MediumComputer Vision

Bilinear Interpolation

Computer Vision

Medium

Problem

Resize a two-dimensional grid with corner-aligned bilinear interpolation. Map each output coordinate to the source grid:

y=i\frac{H-1}{H_{\mathrm{new}}-1}

x=j\frac{W-1}{W_{\mathrm{new}}-1}

Use source coordinate zero when the corresponding output dimension is one. Let y_0=\lfloor y\rfloor, x_0=\lfloor x\rfloor, d_y=y-y_0, and d_x=x-x_0. Clamp y_1=y_0+1 and x_1=x_0+1 to the source boundary. Then compute:

V_0=I_{y_0,x_0}(1-d_x)+I_{y_0,x_1}d_x

V_1=I_{y_1,x_0}(1-d_x)+I_{y_1,x_1}d_x

O_{i,j}=V_0(1-d_y)+V_1d_y

Return the resized two-dimensional list.

Theory

Interpolation estimates values at positions between known data points. In image processing, it is used when:

The input is a grid of known pixel values. The output needs values at non-integer positions.


The Bilinear Idea

Bilinear interpolation uses the four nearest pixels to estimate a value at any point. It performs:

  1. Linear interpolation in the x-direction (horizontal)
  2. Linear interpolation in the y-direction (vertical)

The result is a smooth blend of the four neighbors.


The Formula

For a point (x, y) where (x_0, y_0) is the floor (top-left neighbor):

Let dx = x - x_0 and dy = y - y_0 be the fractional parts.

The four neighbors are:

The interpolated value:

v = I[y_0][x_0](1-dx)(1-dy) + I[y_0][x_1] \cdot dx(1-dy)

$$


Understanding the Weights

Each neighbor contributes based on distance:

Top-left weight: (1-dx)(1-dy)

Top-right weight: dx(1-dy)

Bottom-left weight: (1-dx) \cdot dy

Bottom-right weight: dx \cdot dy

The weights always sum to 1.


Numerical Example

Known pixels (2x2 grid):

10 30 20 40

Query point: (0.25, 0.75)

Neighbors:

Weights:

Result: 10 * 0.1875 + 30 * 0.0625 + 20 * 0.5625 + 40 * 0.1875 = 1.875 + 1.875 + 11.25 + 7.5 = 22.5

The point is closer to the bottom-left (20), and the result (22.5) reflects that.


Image Resizing with Bilinear

To resize from (H, W) to (H_new, W_new):

For each output pixel (i, j):

  1. Map to source coordinates:

\text{src}_y = i \cdot \frac{H - 1}{H_{new} - 1}

\text{src}_x = j \cdot \frac{W - 1}{W_{new} - 1}

  1. Apply bilinear interpolation at (src_y, src_x)
  2. Store result in output[i][j]

Coordinate Mapping Details

Why (H-1)/(H_new-1)?

This maps corners to corners:

Alternative: (H)/(H_new)

Edge case: H_new = 1


Boundary Handling

When the interpolation point is at the image edge:

Problem: x_1 = x_0 + 1 or y_1 = y_0 + 1 may be out of bounds

Solution: Clamp to valid range

This effectively replicates the edge pixel.


Bilinear vs. Nearest Neighbor

Nearest neighbor:

Bilinear:

When to use nearest neighbor:


Bilinear vs. Bicubic

Bilinear:

Bicubic:

For most applications, bilinear is good enough. Bicubic is used when quality matters (photo editing, print).


Separability

Bilinear interpolation is separable:

  1. Interpolate horizontally to get two values
  2. Interpolate vertically between those two values

This is mathematically equivalent to the 4-point formula and can be slightly faster.

Horizontal first:


Applications

Examples

Example 1

Input
image = [[0, 10], [20, 30]], new_h = 3, new_w = 3
Output
[[0, 5, 10], [10, 15, 20], [20, 25, 30]]
Explanation
Corners remain fixed and every middle value is the linear blend of neighboring pixels.

Example 2

Input
image = [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]], new_h = 2, new_w = 2
Output
[[0, 3], [12, 15]]

Hints

  1. Compute source coordinates before taking their floor and fractional parts.
  2. Interpolate horizontally twice, then interpolate those two values vertically.

Requirements

Constraints

Starter Code

def bilinear_resize(image: list, new_h: int, new_w: int) -> list:
    """
    Returns a two-dimensional list with shape (new_h, new_w).
    """
    # Write code here
    pass

Test Cases

CaseMatches
Upscale 2x2 to 3x3public
Downscale 4x4 to 2x2public