A blog about anything a software engineer might encounter during his programming efforts.

28 November 2012

Rotation in 3D using OpenCV's warpPerspective

In order to easily rotate an image in 3D space, I have written a simple method that will do just that. It accepts rotations (in degrees) along each of the three axis (x, y and z), with 90 degrees being the "normal" position.
It also supports translations along each of the axis, and a variable focal distance (you would usually want the focal distance to be the same as your dz).

The parameters are:
input: the image that you want rotated.
output: the Mat object to put the resulting file in.
alpha: the rotation around the x axis
beta: the rotation around the y axis
gamma: the rotation around the z axis (basically a 2D rotation)
dx: translation along the x axis
dy: translation along the y axis
dz: translation along the z axis (distance to the image)
f: focal distance (distance between camera and image, a smaller number exaggerates the effect)

Also, there is a very strange effect. If the output image is bigger than the source size you must to control it because, by default, if you pass the right border opencv draw (follow) in the left border and you get a "mirror" effect very odd.

I don't know... i only want to rotate a picture in the center with x,y,z axis in a loop.... but... may be the next time.

This code works for me but I don't know you the Roll and Pitch angles are exchanged. When I change "alpha", the image is warped in pitch and when I change "beta" the image in warped in roll. Does someone know why it happens? Thanks

Hi! Awesome work! I am trying to use your code. When rotating on the z axis it works fine, but on x and y I have to pass in extremely small values for it to work (I removed the radians calculation in your code and so the minus 90 degrees too) the rotations looks exaggerated (like, np.radians(0.01) for the y axis yields a pretty noticeable rotation, looks like 20 degrees to me. Maybe I am misunderstanding something or misusing dz and f values? I am setting a value of 5 there as the pic I am trying with states a focal length of 5 mm. I am setting dx=dy=0.Also, the projection matrices confuse me a bit, Am I rotating around the center of the image or around a corner? I find it difficult to realize on x and y rotations.

One more detail, if I change f and dz to 500 or 5000 instead of 5 starts yielding better results. In what units am I supposed to send those values? The pic says 5mm for focal length. Thanks! I am really excited I am seeing my pic rotate! :)

dz = translation in z direction (translation as part of the whole operation)f = focal distance of the camera, e.g. the distance between camera and picture. If this is too small, rotations will look exaggerated. I usually use f = 200 or 250. You'll usually want the same value for these, so you have approx. the whole image in view after the operation.Rotation is always around the centre of the image, hence the translation of half the width and half the height in the 2D -> 3D and vice versa matrices.

Did you use the example values for alpha, beta, gamma, dx, etc?I know that if the image is at 90 degrees to the virtual camera (i.e. alpha or beta = 0), you won't see anything. Also, when the camera is too close (dz too small) it won't show either.Please try my example values and see if they work for you. Then you can work from there. Please note that you have to pass 90 degree as alpha to make it appear straight towards the camera.