Search code examples
pythonopencvimage-processingtransformationscikit-image

rotation matrix in openCV


I am creating a rotation matrix in python as follows:

import numpy as np
def make_rot(angle):
    cost = np.cos(np.deg2rad(angle))
    sint = np.sin(np.deg2rad(angle))
    rot = np.array([[cost, -sint, 0],
                   [sint, cost, 0],
                   [0, 0, 1]])
    return rot

This is as defined in the wikipedia page here: http://en.wikipedia.org/wiki/Rotation_matrix

I run it with the angle parameter as 45 degrees and I get something like:

[[ 0.70710678 -0.70710678  0.        ]
 [ 0.70710678  0.70710678  0.        ]
 [ 0.          0.          1.        ]]

Now, I use the OpenCV getRotationMatrix2D API as follows:

import cv2
M = cv2.getRotationMatrix2D((0, 0), 45, 1)

The matrix I get is the inverse of the matrix (the transpose as it is a rotation matrix). The result is as follows:

[[ 0.70710678  0.70710678  0.        ]
 [-0.70710678  0.70710678  0.        ]]

As you can see it is the inverse. I have not found anything in the OpenCV documentation which says anything about this behaviour.

Now, I can use this matrix in OpenCV and skimage to transform an image as follows:

# openCV
M = cv2.getRotationMatrix2D((0, 0), 45, 1)
dst = cv2.warpAffine(image2, M, (coumns, rows))

# skimage
from skimage import transform as tf
tform = tf.AffineTransform(matrix=make_rot(45))
dst = tf.warp(image_2, tform)

The surprising thing is that the result from using my matrix and OpenCV matrix is the same.

My question is why is OpenCV working with the inverse of the transformation? I am wondering if this is something they are not mentioning in the documentation or if I am using this wrong somehow.


Solution

  • I think the problem is that in a traditional right-handed coordinate system the rotation matrix looks exactly like the one you are using.

    Whereas in images (and OpenCV works with images) the origin is in the top-left corner, the x-axis goes to the right (as usual), but y-axis goes down rather than up, which means that the coordinate system is left-handed and the rotation matrix is different.

    Let's build the rotation matrix in this coordinate system. If we denote:

    A - linear transformation (rotation in our case)

    then we get

    A(i) = (cos(angle), -sin(angle))

    where i - is the base vector corresponding to x-axis

    A(j) = (sin(angle), cos(angle))

    where j- is the base vector for y-axis.

    Consequently, rotation matrix looks exactly like in OpenCV:

    A(i) is its first column,

    A(j) is the second one.