MediumComputer Vision

Image Rotation (Nearest Neighbor)

Computer Vision

Medium

Problem

Rotate a two-dimensional image counterclockwise around its center using nearest-neighbor sampling. The output must have the same height and width as the input image.

For an image with H rows and W columns, define the center row coordinate:

c_y = \frac{H - 1}{2}

Define the center column coordinate:

c_x = \frac{W - 1}{2}

Let a be the supplied angle in degrees. Convert it to radians:

\theta = a\frac{\pi}{180}

For each output position with row i and column j, subtract the image center to obtain dy = i - c_y and dx = j - c_x. Use inverse rotation to locate the corresponding source row:

s_y = c_y + dy\cos(\theta) + dx\sin(\theta)

Compute the corresponding source column:

s_x = c_x - dy\sin(\theta) + dx\cos(\theta)

Round s_y and s_x to the nearest integers using Python round. If both rounded coordinates are inside the input image, copy that source pixel. Otherwise, place 0 at the output position.

Here, i and j are output coordinates, s_y and s_x are source coordinates, and theta is the counterclockwise rotation angle in radians.

Return the rotated image as a two-dimensional list with the same dimensions as the input image.

Theory

Rotating an image by an arbitrary angle requires:

  1. Computing where each output pixel maps to in the input
  2. Sampling the input at that (usually non-integer) location
  3. Filling the output with the sampled values

The rotation is performed around the image center.


Rotation Mathematics

To rotate a point (x, y) by angle \theta around the origin:

x' = x \cos\theta - y \sin\theta

y' = x \sin\theta + y \cos\theta

For rotation around the image center (c_x, c_y):

  1. Translate to origin: (x - c_x, y - c_y)
  2. Rotate
  3. Translate back: add (c_x, c_y)

Inverse Mapping

For each output pixel, we need to find which input pixel it comes from. This requires the inverse rotation (rotate by -\theta):

For output pixel (i, j):

  1. Compute offset from center: dx = j - c_x, dy = i - c_y
  2. Apply inverse rotation:

\text{src}_x = c_x + dx \cos\theta + dy \sin\theta

\text{src}_y = c_y - dx \sin\theta + dy \cos\theta 3. Sample the input at (\text{src}_y, \text{src}_x)


Nearest Neighbor Interpolation

The source coordinates are usually not integers. Nearest neighbor interpolation simply rounds to the closest pixel:

i_{\text{src}} = \text{round}(\text{src}_y)

j_{\text{src}} = \text{round}(\text{src}_x)

If the rounded coordinates are within bounds, copy that pixel. Otherwise, fill with 0 (or another background value).


Step-by-Step Example

Image (3x3):

1 2 3 4 5 6 7 8 9

Rotation: 90 degrees counterclockwise

Center: (1, 1)

For output pixel (0, 0):

For output pixel (0, 2):

Result:

3 6 9 2 5 8 1 4 7

(This is the expected 90-degree CCW rotation)


Why Inverse Mapping?

Forward mapping:

Inverse mapping:

Inverse mapping is the standard approach for image transformations.


Nearest Neighbor vs. Other Methods

Nearest neighbor:

Bilinear interpolation:

Bicubic interpolation:


Handling Out-of-Bounds

When the source coordinates fall outside the input image:

Zero fill:

Border replication:

Wrap around:

This problem uses zero fill.


Rotation Angle Convention

Counterclockwise (positive angle):

Clockwise (positive angle):

This problem uses counterclockwise rotation.


Image Center

The center of rotation affects the result:

Pixel center convention:

c_x = \frac{W - 1}{2}, \quad c_y = \frac{H - 1}{2}

For a 5x5 image: center is (2, 2) For a 4x4 image: center is (1.5, 1.5)

This places the center at the middle pixel (or between pixels for even sizes).


Aliasing Artifacts

Nearest neighbor rotation produces visible artifacts:

These artifacts are worse for:

For better quality, use bilinear or bicubic interpolation.

Examples

Example 1

Input
image = [[1, 2, 3], [4, 5, 6], [7, 8, 9]], angle_degrees = 0
Output
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Explanation
A zero-degree inverse mapping selects every original pixel.

Example 2

Input
image = [[1, 2, 3], [4, 5, 6], [7, 8, 9]], angle_degrees = 180
Output
[[9, 8, 7], [6, 5, 4], [3, 2, 1]]

Hints

  1. Map each output coordinate backward through the inverse rotation.
  2. Round the source coordinates and use zero when they fall outside the image.

Requirements

Constraints

Starter Code

import math

def rotate_image(image: list, angle_degrees: float) -> list:
    """
    Returns the counterclockwise nearest-neighbor rotation.
    """
    # Write code here
    pass

Test Cases

CaseMatches
0 degreespublic
180 degreespublic