3d rotation on the image

I am trying to get code that will perform a perspective transformation (in this case a 3D rotation) on an image.

import os.path import numpy as np import cv def rotation(angle, axis): return np.eye(3) + np.sin(angle) * skew(axis) \ + (1 - np.cos(angle)) * skew(axis).dot(skew(axis)) def skew(vec): return np.array([[0, -vec[2], vec[1]], [vec[2], 0, -vec[0]], [-vec[1], vec[0], 0]]) def rotate_image(imgname_in, angle, axis, imgname_out=None): if imgname_out is None: base, ext = os.path.splitext(imgname_in) imgname_out = base + '-out' + ext img_in = cv.LoadImage(imgname_in) img_size = cv.GetSize(img_in) img_out = cv.CreateImage(img_size, img_in.depth, img_in.nChannels) transform = rotation(angle, axis) cv.WarpPerspective(img_in, img_out, cv.fromarray(transform)) cv.SaveImage(imgname_out, img_out) 

When I rotate around the z axis, everything works as expected, but the rotation around the x or y axis seems to be completely off. I need to rotate angles the size of pi / 200 before I start getting results that seem completely reasonable. Any idea what could be wrong?

+7
source share
2 answers

First, we construct a rotation matrix of the form

  [cos(theta) -sin(theta) 0] R = [sin(theta) cos(theta) 0] [0 0 1] 

Applying this coordinate transformation gives you a rotation around the origin.

If instead you want to rotate around the center of the image, you need to first shift the center of the image to the origin, then apply the rotation, and then move everything back. You can do this using the translation matrix:

  [1 0 -image_width/2] T = [0 1 -image_height/2] [0 0 1] 

The transformation matrix for translation, rotation and inverse transformation then becomes:

 H = inv(T) * R * T 

I need to think a bit about how to relate the skew matrix to 3D transformation. I expect the easiest route is to create a 4D transformation matrix and then project it back into 2D homogeneous coordinates. But at the moment, the general view of the oblique matrix:

  [x_scale 0 0] S = [0 y_scale 0] [x_skew y_skew 1] 

The values ​​of x_skew and y_skew are usually tiny (1e-3 or less).

Here is the code:

 from skimage import data, transform import numpy as np import matplotlib.pyplot as plt img = data.camera() theta = np.deg2rad(10) tx = 0 ty = 0 S, C = np.sin(theta), np.cos(theta) # Rotation matrix, angle theta, translation tx, ty H = np.array([[C, -S, tx], [S, C, ty], [0, 0, 1]]) # Translation matrix to shift the image center to the origin r, c = img.shape T = np.array([[1, 0, -c / 2.], [0, 1, -r / 2.], [0, 0, 1]]) # Skew, for perspective S = np.array([[1, 0, 0], [0, 1.3, 0], [0, 1e-3, 1]]) img_rot = transform.homography(img, H) img_rot_center_skew = transform.homography(img, S.dot(np.linalg.inv(T).dot(H).dot(T))) f, (ax0, ax1, ax2) = plt.subplots(1, 3) ax0.imshow(img, cmap=plt.cm.gray, interpolation='nearest') ax1.imshow(img_rot, cmap=plt.cm.gray, interpolation='nearest') ax2.imshow(img_rot_center_skew, cmap=plt.cm.gray, interpolation='nearest') plt.show() 

And the conclusion:

Rotations of cameraman around origin and center + skew

+21
source

I don’t understand how you build your rotation matrix. It seems rather complicated to me. Usually it is built by constructing a zero matrix, placing 1 on the unnecessary axes and the common sin , cos , -cos , sin in the two dimensions used. Then we multiply everything together.

Where did you get the construction np.eye(3) + np.sin(angle) * skew(axis) + (1 - np.cos(angle)) * skew(axis).dot(skew(axis)) from?

Try building a projection matrix from the main building blocks. Building a rotation matrix is ​​pretty easy, and "rotmatrix dot skewmatrix" should work.

Perhaps you should pay attention to the center of rotation. Your image is likely to be placed in virtual position 1 on the z axis, so by rotating it on x or y, it moves a bit. Therefore, you will need to use the translation so that z becomes 0, then rotates, and then translates back. (Affinity translation matrices are also quite simple. See Wikipedia: https://en.wikipedia.org/wiki/Transformation_matrix )

0
source

All Articles