This technical report provides an overview of an image rotation. The implementation uses Inverse Warping and two interpolation methods: Nearest Neighbor Interpolation and Bilinear Interpolation. The objective of this code is to rotate an image by a specified angle.
The overview of key steps of the code:
Detailed explanation of the code:
float sq_row = ceil(row * sin(radian) + col * cos(radian));
float sq_col = ceil(col * sin(radian) + row * cos(radian));
→ ‘row’ and ‘col’ respectively indicates height and width of the original image, and ‘radian‘ indicates rotation angle. This code ensures that the rotated image has a bounding box that is large enough to contain all transformed pixels. The reason why we use the ceil function here is that new bounding box might have fractional pixel values, but since images are discrete domain, we should round up to ensure the rotated image is included in the new bounding box.
float x = (j - sq_col / 2) * cos(radian) - (i - sq_row / 2) * sin(radian) + col / 2;
float y = (j - sq_col / 2) * sin(radian) + (i - sq_row / 2) * cos(radian) + row / 2;
→ Rotation transformation is fundamentally performed around the origin. However, in digital images, the origin is located at the top-left corner (0,0). To perform rotation based on the center of the image, we need to shift the reference point to the center of the image. Therefore, we first move the center of the output image to the origin (0,0), apply transformation, and then restore the original center using a translation process.
(1) Rotation should occur in center. To accomplish this, we first translate each pixel (i, j) in the output image so that the center of the output image becomes the new origin (0,0).
⇒ j - sq_col / 2, i - sq_col / 2 This effectively shifts every pixel so that the center of the output image is now at (0,0).
(2) Apply the rotation matrix to rotate the point by an angle θ.
(3) After rotation, (x′,y′) must be shifted back to the original image center. This could be done by adding back the original center of the input image col2, row2.
if (!strcmp(opt, "nearest")) {
int x1 = round(x);
int y1 = round(y);
output.at<T>(i, j) = input.at<T>(y1, x1);
}
else if (!strcmp(opt, "bilinear")) {
int x1 = floor(x), x2 = ceil(x);
int y1 = floor(y), y2 = ceil(y);
if (x1 < 0) x1 = 0;
if (x2 >= col) x2 = col - 1;
if (y1 < 0) y1 = 0;
if (y2 >= row) y2 = row - 1;
T P11 = input.at<T>(y1, x1); // (x1, y1)
T P21 = input.at<T>(y1, x2); // (x2, y1)
T P12 = input.at<T>(y2, x1); // (x1, y2)
T P22 = input.at<T>(y2, x2); // (x2, y2)
float dx = x - x1;
float dy = y - y1;
output.at<T>(i, j) = (P11 * (1 - dx) * (1 - dy)) +
(P21 * dx * (1 - dy)) +
(P12 * (1 - dx) * dy) +
(P22 * dx * dy);
}
(1) First, it defines the four surrounding pixels by floor and ceil function, which respectively finds the lower bound and upper bound of (x, y).
(2) Each value should not be outside of the image, so we need to ensure that it is included in the range of [0, col-1] for x and [0, row-1] for y.
(3) We can define four surrounding pixels:
(4) Interpolation weights can be computed:
(5) Mathematical formula for bilinear interpolation can be written:
→ Now, f(x1,y) and f(x2,y) in equation (3) can be substituted with equation (1) and (2).
This is why the final code is :
(P11 * (1 - dx) * (1 - dy)) +(P21 * dx * (1 - dy)) +(P12 * (1 - dx) * dy) +(P22 * dx * dy);
[Computer Vision] _ Image Stitching (0) | 2025.06.21 |
---|---|
[RL] _ Intro to RL (0) | 2024.09.02 |
Computer Vision 2 _ Chap 07 (0) | 2024.09.02 |
Computer Vision 2 _ Chap 06 (0) | 2024.09.02 |
Computer Vision 2 _ Chap 05 (0) | 2024.09.02 |
댓글 영역