Resize Image (Nearest Neighbor)
Implement an image resizing algorithm using the nearest neighbor interpolation technique. This task involves increasing or decreasing the dimensions of a given image while maintaining its visual content.
The concept of image resizing is fundamental in computer vision, as it enables images to be adapted for various applications, such as display on different devices or use in specific algorithms. Nearest neighbor interpolation is a simple, yet effective method for resizing images, which works by mapping each pixel in the output image to the nearest pixel in the input image. This process can be mathematically represented as finding the corresponding position in the input image for each output pixel position.
Here are the steps to achieve this:
- Calculate the source x and y coordinates for each output pixel.
- Use these coordinates to find the nearest source pixel. The calculation of source coordinates can be expressed as srcxβ=βxβ WdstβWsrcβββ,srcyβ=βyβ HdstβHsrcβββ.
This technique is widely used in image processing applications.
Example:
resize_nn([[1,2],[3,4]], 4, 4)
[[1,1,2,2],[1,1,2,2],[3,3,4,4],[3,3,4,4]]
2x2 image scaled to 4x4 by duplicating pixels
Constraints:
- Output dimensions new_h, new_w are positive integers
- Input is a 2D grayscale image
More from CV: Introduction to Computer Vision
- Background Knowledge
Image resizing is an example of image interpolation: you want to create a new image with different width/height, and for each pixel in the new (destination) image you must decide what value it should take based on the original (source) image. Nearest neighbor interpolation is the simplest method: instead of computing a weighted average of surrounding pixels (like bilinear or bicubic), you just copy the value of the single closest source pixel. This makes it fast but can produce blocky or jagged results compared to more advanced methods.
Conceptually, you can think of the source image as a continuous function sampled on a grid. Resizing involves resampling that function on a new grid. The formulas srcxβ=βxβ WdstβWsrcβββ,srcyβ=βyβ HdstβHsrcβββ tell you how to map a destination pixel coordinate (x,y) back to the corresponding source coordinate by scaling with the ratio of sizes, then taking the floor to choose the nearest pixel index on the left/top.
- Algorithm/Approach
The general pattern is:
- Loop over all pixels in the destination image (height Γ width).
- For each destination pixel (x,y), compute the corresponding source coordinates using the given scaling formula.
- Clamp these source coordinates to valid integer indices (0 to Wsrcββ1, 0 to Hsrcββ1) if needed.
- Copy the pixel value from src[src_y][src_x] (and all channels, if color) into dst[y][x].
This is a forward-mapping from destination to source: each destination pixel pulls its value from the source (often called βbackward warpingβ in vision).
-
Step-by-Step Strategy
-
Get dimensions
- Let H_src, W_src be the source height and width.
- Let H_dst, W_dst be the desired destination height and width.
- Precompute scale factors (optional but useful)
- scale_x = W_src / W_dst
- scale_y = H_src / H_dst
- Create an empty destination image
- Shape: [H_dst][W_dst] for grayscale or [H_dst][W_dst][C] for color.
- Loop over destination pixels
for y in range(H_dst):
for x in range(W_dst):
src_x = int(x * scale_x) # floor implicitly
src_y = int(y * scale_y)
- Clamp indices (if needed)
- Ensure 0 <= src_x < W_src and 0 <= src_y < H_src.
- Often the floor formula guarantees this, but clamping is a safe guard.
- Copy pixel value
dst[y][x] = src[src_y][src_x] # copy all channels if color
- Return the resized image
- Common Pitfalls
- Off-by-one errors:
- If you accidentally use WsrcβWdstββ instead of WdstβWsrcββ, or mix up src/dst width/height, youβll sample from wrong positions.
- Using wrong rounding:
- The formula specifies floor. Using round() can shift sampling and create artifacts or index errors at the borders.
- Out-of-bounds indices:
- For the last pixel (e.g., x = W_dst - 1), make sure src_x never becomes W_src (must be at most W_src - 1).
- Channel handling:
- For RGB images, ensure you copy all channels from the same source coordinate; donβt treat channels as separate images with mismatched indexing.
- Integer division in some languages:
- In languages where / between integers truncates, precompute scale as float to avoid division mistakes.
- Time & Space Complexity
-
Time complexity:
-
You visit each destination pixel exactly once and do O(1) work per pixel.
-
O(Wdstββ Hdstβ).
-
Space complexity:
-
You need space for the output image plus the input image.
-
Extra working memory is O(Wdstββ Hdstβ) for the destination (input is given).