Image Rotation without cropping

Dears, With the below code, I rotate my cv::Mat object (I'm not using any Cv's functions, apart from load/save/convertionColor.., as this is a academic project) and I receive a cropped Image

rotation function:

float rads = angle*3.1415926/180.0;
float _cos = cos(-rads);
float _sin = sin(-rads);
float xcenter = (float)(src.cols)/2.0;
float ycenter = (float)(src.rows)/2.0;

for(int i = 0; i < src.rows; i++)
    for(int j = 0; j < src.cols; j++){

        int x = ycenter + ((float)(i)-ycenter)*_cos - ((float)(j)-xcenter)*_sin;
        int y = xcenter + ((float)(i)-ycenter)*_sin + ((float)(j)-xcenter)*_cos;
        if (x >= 0 && x < src.rows && y >= 0 && y < src.cols) {
                 dst.at<cv::Vec4b>(i ,j) = src.at<cv::Vec4b>(x, y);
              }
        else {
            dst.at<cv::Vec4b>(i ,j)[3] = 0;
        }
    }

before

after

I would like to know, How I can keep my Full image every time I want to rotate it. Am I missing something in my function maybe? thanks in advance

1 answer

  • answered 2019-07-18 15:38 Thomas Sablik

    The rotated image usually has to be large than the old image to store all pixel values.

    Each point (x,y) is translated to

    (x', y') = (x*cos(rads) - y*sin(rads), x*sin(rads) + y*cos(rads))
    

    An image with height h and width w, center at (0,0) and corners at

    (h/2, w/2)
    (h/2, -w/2)
    (-h/2, w/2)
    (-h/2, -w/2)
    

    has a new height of

    h' = 2*y' = 2 * (w/2*sin(rads) + h/2*cos(rads))
    

    and a new width of

    w' = 2*x' = 2 * (w/2*cos(rads) + h/2*sin(rads))
    

    for 0 <= rads <= pi/4. It is x * y <= x' * y' and for rads != k*pi/2 with k = 1, 2, ... it is x * y < x' * y'

    In any case the area of the rotated image is same size as or larger than the area of the old image.

    If you use the old size, you cut off the corners.

    Example:

    Your image has h=1, w=1 and rads=pi/4. You need a new image with h'=sqrt(2)=1.41421356237 and w'=sqrt(2)=1.41421356237 to store all pixel values. The pixel from (1,1) is translated to (0, sqrt(2)).