Resizing and Interpolation

Enlarging an image means inventing pixels. How you invent them is the difference between blocks and mush.

Overview

Enlarging invents; shrinking discards

Resizing is two different problems wearing one name.

Enlarging asks for pixels that were never measured. A 4×4 image stretched to 8×8 needs 64 values where 16 exist. The extra 48 have to come from a place, and wherever they come from, they're a guess. No interpolation method adds info — the choice is only about which plausible guess to make.

Shrinking has too much data rather than too little, and the risk is throwing away the wrong parts.

Resizing and Interpolation

This module needs JavaScript: the images are computed in the page rather than downloaded.

Worth knowing

Enlarging cannot add information. It can only decide what to put between the pixels that exist.
Nearest neighbour copies the closest pixel. Fast, exact for pixel art, blocky for everything else.
Bilinear takes a weighted average of the four surrounding pixels. Smoother, and softer.
Shrinking has the opposite problem: sampling without averaging first produces aliasing, which is why area averaging exists.

Resizing and Interpolation

What happens between the pixels, and why the answer looks different each time.

Nearest neighbour

For each output pixel, work out where it lands in the input and copy whichever input pixel is closest. That is all.

It's the fastest possible method, and it's exact in one key sense: each output value is a value that truly appeared in the input. Nothing is averaged, so nothing is invented that wasn't there.

The cost is blockiness. Neighbouring output pixels that map to the same input pixel are the same, so enlarging makes flat squares with hard steps between them. Straight edges come out as staircases.

That is often just right. Pixel art must be scaled with nearest neighbour or it stops being pixel art. A segmentation mask where pixel value 3 means "road" must be scaled with nearest neighbour. Blending 3 and 5 gives 4, which might mean "building" — a label is a name, not a quantity, and names do not mean.

Bilinear

For each output pixel, find the four input pixels nearby its spot and take a weighted mean, with weights from how close the spot is to each. Linear in one direction, then linear in the other. Hence bilinear.

Edges become smooth and the staircase goes away. The cost is softness: a blend of nearby pixels is always softer than the originals, so sharp edges turn into ramps. Enlarge by a large factor and the result is blurry, not blocky.

Switch between the two above with the downscale factor set high. The same info is present in both. Only the guessing strategy differs, and it's easy to see that neither is simply better.

Bicubic extends the idea to sixteen nearby pixels with a cubic weight function. It's sharper than bilinear because the cubic curve overshoots slightly at edges, adding a small amount of local contrast. Photo editors default to it for that reason. The overshoot is also its failure mode: it can give faint halos beside high-contrast edges.

MethodReadsSpeedGood forFails at
Nearest1 pixelfastestpixel art, label masksphotographs
Bilinear4 pixelsfastgeneral enlargementlarge factors
Bicubic16 pixelsslowerphotographscan halo
Areaa blockfastshrinkingnot for enlarging

Shrinking is a different failure

To halve an image, it's tempting to keep each second pixel. This is wrong, and wrong in a way that looks like a bug elsewhere in the program.

Consider a pattern of alternating black and white columns. Keep each second column and you may get all the black ones. A solid black image. Shift by one and you get solid white. Detail finer than the new sampling grid doesn't disappear gracefully. It reappears as a fully different, false pattern. This is aliasing, and it's why photos of striped shirts on video develop rainbow moiré.

The fix is to mean before sampling. Area interpolation takes the mean of each input pixel that falls inside each output pixel's footprint, so nothing is silently dropped. Gaussian blurring before downsampling reaches the same end, and is what an image pyramid does at each level.

This matters for machine learning in detail. A dataset resized with a naive-sampling routine has aliased artefacts that vary with the first detail, and a network will happily learn them.

Bilinear, worked, and why masks forbid it

Bilinear interpolation reads the four input pixels around a fractional spot and takes a distance-weighted mean — linear across, then linear down. For an output point landing at fraction (0.25, 0.75) inside a cell whose corners are 10 (top-left), 20 (top-right), 30 (bottom-left), 40 (bottom-right):

stepvalue
top edge: 10·0.75 + 20·0.2512.5
bottom edge: 30·0.75 + 40·0.2532.5
down: 12.5·0.25 + 32.5·0.7527.5

The output 27.5 is a value that never appeared in the input. That is the whole point for a photo: it smooths the staircase that nearest neighbour would leave.

But a *label mask* must never be resized this way. If 3 means "road" and 5 means "sky", a blend of 4 might be a class that is neither. Class labels are names, not amounts, and names cannot be mixed. Use nearest neighbour for masks.

Shrinking is a third case. Keeping each second pixel can alias — a striped pattern can vanish or flip — so you need to blur first (area method), not guess between samples.

Bicubic uses sixteen nearby pixels with a cubic weight that overshoots slightly at edges. That adds a little local contrast, which is why photo editors default to it. The overshoot can also leave faint halos beside sharp edges.

Shrinking trips people up in a different way. Keeping each second pixel of a stripe pattern can return a solid block of one colour, because detail finer than the new grid shows up as a false pattern. That is aliasing — the same effect as moirĂ© on a striped shirt on video. The fix is to blur before sampling (area method, or a Gaussian blur, which is what an image pyramid does). It matters for ML too: a dataset resized by naive sampling carries false patterns that vary with the input detail, and a network will learn them.

Where it goes wrong with Resizing and Interpolation

Bilinear on a label mask. Blending class indices makes indices that mean a thing else. Nearest neighbour, always.

Enlarging to fix a low-detail input. Upscaling before feeding a model adds no info and costs work. Learned super-detail is a different thing fully — it hallucinates plausible detail from a prior, which is handy for viewing and dangerous for reading.

Repeated resizes. Each interpolation softens. Resize once from the first rather than in steps.

Skipping aspect ratio. Stretching to a square distorts each shape in the frame. Pad to the target aspect ratio, then resize.

Questions people ask about Resizing and Interpolation

Which interpolation method should I use? Use INTER_AREA when shrinking, INTER_LINEAR as a general default when enlarging, and INTER_CUBIC for higher quality at a higher cost. Use nearest neighbour for labels and masks.

Why does a downscaled image look jagged or show moire? Dropping pixels without filtering causes aliasing. INTER_AREA, or a blur before subsampling, removes the detail that would otherwise fold into false patterns.

Why can't I use bilinear on a segmentation mask? It blends label values, producing classes that do not exist, such as 1.5 between class 1 and class 2. Nearest neighbour copies existing labels only.

Does upscaling add detail? No. Interpolation only estimates values between existing pixels, so the image gets bigger and smoother but not sharper. Recovering detail needs learned super-resolution.

How do I resize while keeping the aspect ratio? Compute one scale factor from the target width or height and apply it to both. Pad or crop afterwards if you need a fixed shape.

Does resizing affect model accuracy? Yes, so use the same method in training and inference. A mismatch between libraries, such as PIL and OpenCV, can shift predictions.

Nearest, bilinear, and why downscaling needs a blur first

Resizing asks for pixel values at coords that don't exist. Each method is a guess. This measures three guesses against a known ground truth. Then shows the failure that catches everyone -- that shrinking an image right isn't an interpolation problem at all.

example_01.pyNumPy
Output

Bicubic interpolation fits a cubic curve through four neighbours instead of blending two. It costs 16 reads per pixel but halves bilinear's error.

example_02.pyNumPy
Output

The next block examines what nearest and bilinear actually produce per-pixel, showing how nearest repeats values while bilinear smooths between them.

example_03.pyNumPy
Output

The next block shows that bilinear interpolation is not truly linear along a diagonal -- it is linear in each axis separately, which makes a curved surface.

example_04.pyNumPy
Output

The next block demonstrates the downscaling failure: subsampling a stripe pattern causes aliasing, while averaging first preserves the correct brightness.

example_05.pyNumPy
Output

Check yourself

0 of 3

Answer without scrolling back up.

  1. Why must a segmentation mask be resized with nearest neighbour?

  2. What causes aliasing when shrinking an image?

  3. Why can bicubic interpolation produce halos near high-contrast edges?

Cheat sheet

Resizing and Interpolation

Resize an image with nearest, bilinear and bicubic interpolation side by side and see exactly where each method invents or drops detail.

COMPUTER VISION · vizlearn.in/computer_vision/resizing_and_interpolation.html

About the author

Ashish Jangra builds and maintains VizLearn. Every module here is written and the visualisation behind it hand-built, so the numbers in a readout come from the same code that draws the picture. Corrections are genuinely welcome and get priority over everything else — if a page states something wrong, or an animation misrepresents what the algorithm does, get in touch.