

John Fremlin's blog: Rotating an image with OpenCV and Python
source link: http://john.freml.in/opencv-rotation
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

John Fremlin's blog: Rotating an image with OpenCV and Python
Waiting for updates: connected
Posted 2014-04-05 19:07:00 GMT
OpenCV is the most widely used open-source vision library. It lets you detect faces in photographs or video feeds with very little code.
There are a few tutorials on the Internet explaining how to use an affine transform to rotate an image with OpenCV -- they don't at all handle the issue that rotating a rectangle inside its own bounds will generally cut off the corners, so the shape of the destination image needs to be changed. That's a bit sad, as doing it properly is very little code:
def rotate_about_center(src, angle, scale=1.): w = src.shape[1] h = src.shape[0] rangle = np.deg2rad(angle) # angle in radians # now calculate new image width and height nw = (abs(np.sin(rangle)*h) + abs(np.cos(rangle)*w))*scale nh = (abs(np.cos(rangle)*h) + abs(np.sin(rangle)*w))*scale # ask OpenCV for the rotation matrix rot_mat = cv2.getRotationMatrix2D((nw*0.5, nh*0.5), angle, scale) # calculate the move from the old center to the new center combined # with the rotation rot_move = np.dot(rot_mat, np.array([(nw-w)*0.5, (nh-h)*0.5,0])) # the move only affects the translation, so update the translation # part of the transform rot_mat[0,2] += rot_move[0] rot_mat[1,2] += rot_move[1] return cv2.warpAffine(src, rot_mat, (int(math.ceil(nw)), int(math.ceil(nh))), flags=cv2.INTER_LANCZOS4)
The affine transformation of the rotation has to be combined with the affine transformation of translation, from the center of the original image to the center of the destination image. An affine transformation in 2D is a 2x2 matrix A and a translation 2x1 vector a - it takes a source point p = (x,y) to a destination: Ap + a. Combining two transforms Ap + a and Bp + b, doing A first then B, one gets B(Ap + a) + b - another affine transform with matrix BA and vector Ba + b.
In this case, we are combining a rotation with a translation; A translation as an affine transform has the identity 2x2 matrix I and a movement vector m, so is represented by Ip + m, and we want to first translate to the new center, then rotate about that, so we take the rotation Rp + r after applying Ip + m, which gives Rp + Rm + r, which explains why we have to only add two coefficients.
PS. Sadly, numpy interprets the multiplication operator * not as matrix multiplication if it considers the inputs to be vectors of vectors rather than matrices, so we have to explicitly write np.dot.
PPS. We use the Lanczos interpolation which is generally good for scaling up but not for scaling down very small; that should be adapted given the application.
PPPS. The interaction with Python is much improved with the cv2 module, but there are inescapably some rough edges as numpy has a different co-ordinate ordering than OpenCV. Also, for some reason OpenCV persists in using units like degrees instead of radians, and so on. In numpy, the co-ordinates in an image array are accessed in [y,x] order, as in vertical increasing downwards first, followed by horizontal increasing rightwards second. In OpenCV, sizes are given as (width, height), the opposite order.
from skimage.transform import rotate
rotate(image, angle)
Posted 2014-04-06 01:56:10 GMT by Anonymous from 66.57.39.23
thanks that was very helpful and well explained
Posted 2014-04-14 11:56:38 GMT by Anonymous from 89.211.118.229
rotation offset should be 1 pixel closer to the origin so in the resulting picture no pixels are lost
a constant '2' is added to one of the lines to avoid the problem
rot_move = np.dot(rot_mat, np.array([(nw-w)*0.5, (nh-h+2)*0.5,0]))
Posted 2019-05-05 15:24:05 GMT by Anonymous from 138.38.229.118
Post a comment
Recommend
-
16
John Fremlin's blog: Testing systems at scaleWaiting for updates: connectedPosted 2020-04-04 22:00:00 GMTTest driven development is trendy. Interview loops and promotion...
-
26
John Fremlin's blog: Exactly-Once in multithreaded async PythonWaiting for updates: connectedPosted 2020-07-31 22:00:00 GMTPython's builtin greenlets with asyncio are com...
-
15
John Fremlin's blog: Recruiting software engineers and their CVsWaiting for updates: connectedPosted 2017-03-03 23:00:00 GMTHaving conducted hundreds of software and othe...
-
15
John Fremlin's blog: A single point of failure is okWaiting for updates: connectedPosted 2016-10-05 01:11:00 GMTMaking big systems out of many computers, people often end...
-
13
John Fremlin's blog: Nothing was a billion dollar mistakeWaiting for updates: connectedPosted 2018-01-19 23:00:00 GMTTony Hoare, inventor of quicksort and many other foun...
-
16
John Fremlin's blog: Kotlin is a better JavaWaiting for updates: connectedPosted 2017-03-12 23:00:00 GMTThe Kotlin programming langu...
-
12
John Fremlin's blog: Curse of business logicWaiting for updates: connectedPosted 2019-05-18 22:00:00 GMTPeople complain that a piece of software is bogged down in te...
-
9
John Fremlin's blog: Square CTF 2017 Grace HopperWaiting for updates: connectedPosted 2017-10-18 22:00:00 GMTSquare put on a great compet...
-
15
John Fremlin's blog: Against equality in Lisp: eq, eql, equal and equalpWaiting for updates: connectedPosted 2009-02-19 23:00:00 GMTThe mess of options for testing whethe...
-
8
John Fremlin's blog: HTML image maps don't scaleWaiting for updates: connectedPosted 2012-08-15 13:37:00 GMTOn a webpage you can mark part of an image as clickable b...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK