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.
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.