Whether you are capturing an image from a camera or scanner, images tend to misalign, resulting in sideways or upside-down images. That’s where manual rotating is required. Designers may rotate the image to achieve the desired effects and fit them into a specific layout.
But the main question is what does it take to rotate an image?
Rotating images involves transforming an image by shifting its pixel positions around a specific point based on an angel. In most cases, that specific point is the center and angles are in degrees (e.g., 90°, 180°, 270°, or custom angles like 45°).
A positive angle represents a counter-clockwise direction.
A negative angle represents a clockwise direction.
By default, images rotate around their center point. However, you can change the rotating point to any point. For example, you can rotate the image around top-left or bottom-right corner.
How does the rotation work in digital images?
Digital images are two-dimensional arrays of pixel values represented by rows and columns. You can create a rotation by applying a transformation matrix to each pixel coordinate.
While rotating your image, make sure that you have a proper canvas size to fit the rotated image. If your canvas size is small, then you have to resize the canvas size to make it big by filling the extra space with background color.
Here are two ways to rotate an image in Python:
- Using image.rotate() function from pillow
- Using cv2.getRotationMatrix2D function from opencv-python
Method 1: Using image.rotate() function from pillow
The Pillow library provides the .rotate() function that accepts an angle and expand arguments and rotates the image based on the center point.
Decision Tree Diagram
The above diagram depicts each step of the process to rotate an image and display it to the user. If the image does not load properly, it will print the error or handle the error.
Install the “pillow” library using the command below:
pip install pillow
Code example
Let’s rotate an image to 180° degrees and display it.
from PIL import Image # Replacing 'krunal.png' with the path to your image file image = Image.open('krunal.png') # Rotating the image by 180 degrees counter-clockwise rotated_image = image.rotate(180, expand=True) # Saving the rotated image rotated_image.save('rotated_image.png') # Displaying the rotated image rotated_image.show()
Before rotating an image
After rotating an image
You can see the new image file called “rotated_image.png” being created in your current working directory.
The pillow provides an easy-to-use interface that supports a wider range of image formats and optimized performance. However, it is not as robust as opencv because opencv provides more tools to manipulate images. If you are looking for a simpler approach, I recommend you use the pillow’s “image.rotate()” function.
Method 2: Using the cv2.getRotationMatrix2D function from opencv-python
The opencv-python library provides the cv2.getRotationMatrix2D() function to create the rotation matrix. In the next step, we use the “cv2.warpAffine()” function to apply the rotation.
The above diagram shows each step from reading an image using the cv2.imread() function to get an image dimension, calculate the center, create a rotation matrix, apply a rotation matrix to the image, save the rotated image, and display the rotated image.
Install the “opencv-python” library using the command below:
pip install opencv-python
Code example
Let’s rotate an image to 45° from the center.
import cv2 # Replacing 'krunal.png' with the path to your image file image = cv2.imread('krunal.png') # Get the image dimension (h, w) = image.shape[:2] # Checkout the center of the rotation center = (w // 2, h // 2) # Rotating angle in degrees angle = 45 # Scaling factor scale = 1.0 # Creating a rotation matrix M = cv2.getRotationMatrix2D(center, angle, scale) # Applying a rotation rotated_image = cv2.warpAffine(image, M, (w, h)) # Saving the rotated image cv2.imwrite('./images/cv_rotated_image.png', rotated_image) # Displaying the rotated image cv2.imshow('Rotated Image', rotated_image) cv2.waitKey(0) cv2.destroyAllWindows()
Before rotating an image
After rotating an image
If you are performing large-scale image operations, the OpenCV library is your go-to choice. It is optimized for real-time large-scale image processing applications and supports complex computer vision algorithms.
However, OpenCV uses BGR instead of RGB which can confuse beginners and it requires a steep learning curve.
From my experience, I recommend using the opencv approach when you are already doing image processing in your application. If you are just rotating an image and not doing any other computer vision task, then my suggestion would be to use the PIL approach because the opencv library is too big and it is not feasible to just install it for rotating an image.
Rotating around an arbitrary point
Until now, we rotated an image around the center of the image. In this section, we will rotate an image around a specific arbitrary point.
Code example
# Rotating Around an Arbitrary Point import cv2 # Reading the input image image = cv2.imread('krunal.png') # Rotation angel in degrees angle = 90 # Scaling factor scale = 1.0 # Defining arbitrary point (x, y) center_of_rotation = (100, 200) # Getting the rotation matrix M = cv2.getRotationMatrix2D(center_of_rotation, angle, scale) # Adjusting the Output dimensions (h, w) = image.shape[:2] rotated_image = cv2.warpAffine(image, M, (w, h)) # Saving the rotated image cv2.imwrite('./images/cv_rotated_image_arbitrary.png', rotated_image) # Displaying the rotated image cv2.imshow('Rotated Image', rotated_image) cv2.waitKey(0) cv2.destroyAllWindows()
Before the rotation around an arbitrary point
After the rotation around an arbitrary point
You can see that we rotated an image around (100, 200) arbitrary point of the image. The process is the same as the above opencv section. The only changes are in the arbitrary point and angle which is 90°.
Rotating a Region of Interest (ROI)
In image processing, the Region of Interest (ROI) refers to a specific section of an image that you want to focus on from the rest of the image. For example, in a facial recognition app, you may define the ROI around a person’s face, or in medical imaging, you focus on a specific bone-breaking area to highlight it.
Code example
# Rotating a Region of Interest import cv2 # Reading the input image image = cv2.imread('krunal.png') # Coordinates of the ROI x, y, w, h = 100, 100, 200, 200 roi = image[y:y+h, x:x+w] # Rotating the ROI (h_roi, w_roi) = roi.shape[:2] center_roi = (w_roi // 2, h_roi // 2) # Getting the Rotation matrix M = cv2.getRotationMatrix2D(center_roi, 45, 1.0) rotated_roi = cv2.warpAffine(roi, M, (w_roi, h_roi)) # Placing the rotated ROI back to the image roi_rotated_image = image.copy() roi_rotated_image[y:y+h, x:x+w] = rotated_roi # Saving the rotated image cv2.imwrite('./images/cv_roi_rotated_image.png', roi_rotated_image) # Displaying the rotated image cv2.imshow('Rotated ROI', roi_rotated_image) cv2.waitKey(0) cv2.destroyAllWindows()
Before rotating ROI
After rotating ROI
You can see from the above output image that we rotated the left side of my face to 45°. So, the left side of the face is ROI and we only rotated that portion.
Affine rotation
Affine rotation allows us to perform a combination of linear transformations such as rotation, scaling, shearing, and translation.
To do that, first, we need to have three non-collinear points in both source and destination images. Then, create an affine transformation matrix, and apply it. Finally, display the transformed image.
Code example
# Affine rotation import cv2 import numpy as np # Reading the input image image = cv2.imread('krunal.png') # Defining src and destination points pts_src = np.float32([[50, 50], [200, 50], [50, 200]]) # Points in the transformed image pts_dst = np.float32([[10, 100], [200, 50], [100, 250]]) # Getting affine transformation matrix M = cv2.getAffineTransform(pts_src, pts_dst) # Applying the transformation affine_transformed_image = cv2.warpAffine( image, M, (image.shape[1], image.shape[0])) # Saving the rotated image cv2.imwrite('./images/cv_affine_transformed_image.png', affine_transformed_image) # Displaying the rotated image cv2.imshow('Affine Rotated Image', affine_transformed_image) cv2.waitKey(0) cv2.destroyAllWindows()
Before applying an affine transformation
After applying an affine transformation
That’s all!