OpenCV Python rotate image by X degrees around specific point
Solution 1
import numpy as np
import cv2
def rotate_image(image, angle):
image_center = tuple(np.array(image.shape[1::-1]) / 2)
rot_mat = cv2.getRotationMatrix2D(image_center, angle, 1.0)
result = cv2.warpAffine(image, rot_mat, image.shape[1::-1], flags=cv2.INTER_LINEAR)
return result
Assuming you're using the cv2 version, that code finds the center of the image you want to rotate, calculates the transformation matrix and applies to the image.
Solution 2
Or much easier use SciPy
from scipy import ndimage
#rotation angle in degree
rotated = ndimage.rotate(image_to_rotate, 45)
see here for more usage info.
Solution 3
def rotate(image, angle, center = None, scale = 1.0):
(h, w) = image.shape[:2]
if center is None:
center = (w / 2, h / 2)
# Perform the rotation
M = cv2.getRotationMatrix2D(center, angle, scale)
rotated = cv2.warpAffine(image, M, (w, h))
return rotated
Solution 4
The cv2.warpAffine function takes the shape parameter in reverse order: (col,row) which the answers above do not mention. Here is what worked for me:
import numpy as np
def rotateImage(image, angle):
row,col = image.shape
center=tuple(np.array([row,col])/2)
rot_mat = cv2.getRotationMatrix2D(center,angle,1.0)
new_image = cv2.warpAffine(image, rot_mat, (col,row))
return new_image
Solution 5
I had issues with some of the above solutions, with getting the correct "bounding_box" or new size of the image. Therefore here is my version
def rotation(image, angleInDegrees):
h, w = image.shape[:2]
img_c = (w / 2, h / 2)
rot = cv2.getRotationMatrix2D(img_c, angleInDegrees, 1)
rad = math.radians(angleInDegrees)
sin = math.sin(rad)
cos = math.cos(rad)
b_w = int((h * abs(sin)) + (w * abs(cos)))
b_h = int((h * abs(cos)) + (w * abs(sin)))
rot[0, 2] += ((b_w / 2) - img_c[0])
rot[1, 2] += ((b_h / 2) - img_c[1])
outImg = cv2.warpAffine(image, rot, (b_w, b_h), flags=cv2.INTER_LINEAR)
return outImg
Mike
Updated on July 05, 2022Comments
-
Mike almost 2 years
I'm having a hard time finding examples for rotating an image around a specific point by a specific (often very small) angle in Python using OpenCV.
This is what I have so far, but it produces a very strange resulting image, but it is rotated somewhat:
def rotateImage( image, angle ): if image != None: dst_image = cv.CloneImage( image ) rotate_around = (0,0) transl = cv.CreateMat(2, 3, cv.CV_32FC1 ) matrix = cv.GetRotationMatrix2D( rotate_around, angle, 1.0, transl ) cv.GetQuadrangleSubPix( image, dst_image, transl ) cv.GetRectSubPix( dst_image, image, rotate_around ) return dst_image
-
Mike over 12 yearsThanks for the help, however I'm using the "cv" module and you are using "cv2", so its complaining specifically about "image.shape" not existing. I have only been using the "cv" module up until now, so I don't quite get all the changes with "cv2" yet. I know my image is (140,140), so I tried hard coding that in place of image.shape, but it didn't like that at all either.
-
Mike over 12 yearsI think I may have made some progress, but still running into a problem. Here is the latest code: result = cv2.warpAffine(image, rot_mat, cv.GetSize(image), flags=cv2.INTER_LINEAR) Traceback (most recent call last): result = cv2.warpAffine(image, rot_mat, cv.GetSize(image), flags=cv2.INTER_LINEAR) TypeError: <unknown> is not a numpy array
-
Hani about 12 yearsI have a problem running cv2.getRotationMatrix2D(center=image_center ,angle=angle,scale=1) TypeError: function takes exactly 2 arguments (3 given)
-
Treper over 11 yearsimage.shape include the width,height and channel
-
sreemanth pulagam over 10 years@Hani try cv2.getRotationMatrix2D((imagecenter[0],imagecenter[1]),angle,1.0)
-
Graydyn Young almost 8 yearsThis solution changes the image dimensions. See nicodjimenez's answer below.
-
Teodorico Levoff over 7 yearsI am looping through a directory of png and doing this but I get a RuntimeError: invalid rotation plane specified. Any fixes?
-
fivef over 7 yearsdo you pass in a open cv image? like from: img = cv2.imread('messi5.jpg',0)
-
Ali Momen Sani almost 7 yearsthis is quite slow for me
-
Ali Momen Sani almost 7 yearsthis one wont cut any of the image:
imutils.rotate_bound(frame, 90)
-
AljoSt over 5 yearsNice, it's easier to use and you have an easy way to decide if you want to keep the image size (
reshape=True
) or the image content (reshape=False
) -
Eduardo Pignatelli about 5 years
angle
is in degrees. docs.opencv.org/2.4/modules/imgproc/doc/… -
mLstudent33 over 4 yearswas this for face detection? I want to rotate video frames by 90 degrees and run MTCNN because it won't detect frontal faces lying sideways (person lying on the ground)
-
mLstudent33 over 4 yearscan I run face detection on the rotated frame? MTCNN does not detect frontal faces lying sideways.
-
JTIM over 4 years@mLstudent33 No I used it for a different purpose, but this is just rotating an image. So if you have the angle then it should be fine?
-
mLstudent33 over 4 yearsI think so. I can rotate, run detection, then draw
cv2.rectangle()
and then rotate it back. Thanks for replying. -
erwaman over 4 yearsgetRotationMatrix2D seems to require (col,row), too.
center
should use (col,row) as well, as is done in @Omnipresent's answer. -
Keithel almost 3 yearsI agree that it wasn't clear. @alex-rodrigues ' answer does some slicing to the image.shape to get the width and height in the right order for warpAffine: image.shape[1::-1] does this. What this does is takes a slice starting at the 1st element, with a step value of -1, so proceeding left, so you end up with a slice with [1][0], which is the width (columns), followed by height (rows).
-
MuadDev over 2 yearsI believe there might be an error in this answer. I think the correct image center to rotate around is off by 0.5 pixel. The correct code would be
image_center = tuple((np.array(image.shape[1::-1])-1) / 2)
. To check this I encourage you to create a small image with a single line in the middle and rotate it with 45 degrees. Like thisim = np.zeros(shape=(3, 3), dtype=np.uint8); im[:, 1] = 1; im_rot = rotate_image(im, 45)
. Using the original code, the line is not correctly rotated, with the adjusted center it is correctly rotated. Please correct me if I am mistaken.