Rotation center confusion

asked 2016-01-07 19:46:50 -0500

gruben gravatar image

Can someone please verify my understanding or correct my misunderstanding? If I rotate an image using any one of the many online examples (mainly Stackoverflow), I get an unexpected offset in the rotated image. The examples I've found online all use center=(cols/2.0, rows/2.0) for the affine transform getRotationMatrix2D() call. I believe this is incorrect. I think this should instead be center=(cols/2.0 - 0.5, rows/2.0 - 0.5). Since the online concensus seems against me, I'm really just hoping someone here will verify that I'm not incorrect in my understanding.

Specifically, in Python, I need to do this to get what I believe is correct behavior:

def rotate_opencv(image, angle):
    image_center = tuple(np.array(image.shape)/2.0-0.5)
    # Note: -0.5 offset; see
    rot_mat = cv2.getRotationMatrix2D(image_center, angle, 1.0)
    result = cv2.warpAffine(image, rot_mat, image.shape, flags=cv2.INTER_LINEAR)
    return result

I verified this by comparing the result of rotation by 90 degrees with a direct transpose-and-flip-based rotation (numpy.rot90) function call.

I think it is related to this:

If I understand that correctly, the pixel-coordinate-system and affine-transform-coordinate-system are offset by 0.5 pixels, leading to the common error.

edit retag flag offensive close merge delete


Hmm there will be no influence of doing a -0.5 since point coordinates are stored as integers , and thus rounding errors occur. This happens whenever one of the dimensions is not dividable by a factor of 2. This is no bug, but simply a integer data type story.

StevenPuttemans gravatar imageStevenPuttemans ( 2016-01-08 03:02:47 -0500 )edit

Thanks for the reply @StevenPuttemans. I checked; shifting the center in the getRotationMatrix2D() call by 0.5 does influence the result for both odd- and even-side-length images. If I understand how this works, the destination image pixel coordinates will be integers but the source image coordinates will be computed based on the value of center. The resulting pixel value is then (in this case) linearly interpolated from the neighboring pixel offsets and values in the source image. This is what I expect, but I was surprised that there seems to be a 0.5 pixel offset between the coordinate systems used for the images and the transform so the mapping takes you a coordinate in the source image that differs by 0.5 from what you expect.

gruben gravatar imagegruben ( 2016-01-10 18:02:45 -0500 )edit