In this tutorial, you will learn how to rotate an image using OpenCV. Additionally, I’ll also show you how to rotate an image using my two convenience functions from the imutils library, imutils.rotate
and imutils.rotate_bound
, which make rotating images with OpenCV easier (and requires less code).
Previously, we learned how to translate (i.e., shift) an image, up, down, left, and right (or any combination). We are now moving on to our next image processing topic — rotation.
Rotation is exactly what it sounds like: rotating an image by some angle, . We’ll use to represent how many degrees (not radians) we are rotating an image.
I’ll also show you some techniques that will make rotating images with OpenCV easier.
To learn how to rotate images with OpenCV, just keep reading.
Looking for the source code to this post?
Jump Right To The Downloads SectionOpenCV Rotate Image
In the first part of this tutorial, we’ll discuss how OpenCV rotates images and the functions available for rotation.
From there, we’ll configure our development environment and review our project directory structure.
I’ll then show you three ways to rotate an image with OpenCV:
- Use the
cv2.rotate
function: Built into OpenCV, but requires constructing a rotation matrix and explicitly applying an affine warp, making the code more verbose. - Use the
imutils.rotate
function: Part of my imutils library. Makes it possible to rotate an image with OpenCV in a single function call. - Use the
imutils.rotate_bound
function: Also part of my imutils library. Ensures that no part of the image is cut off during rotation.
We’ll wrap up this tutorial by reviewing our OpenCV rotation results.
How does OpenCV rotate images?
Similar to translation, and perhaps unsurprisingly, rotation by an angle can be defined by constructing a matrix, M, in the form:
Given an (x, y)-Cartesian plane, this matrix can be used to rotate a vector degrees (counterclockwise) about the origin. In this case, the origin is normally the center of the image; however, in practice, we can define any arbitrary (x, y)-coordinate as our rotation center.
From the original image, I, the rotated image, R, is then obtained by simple matrix multiplication:
However, OpenCV also provides the ability to (1) scale (i.e., resize) an image and (2) provide an arbitrary rotation center around which to perform the rotation.
Our modified rotation matrix, M, is thus:
where and and and are the respective (x, y)-coordinates around which the rotation is performed.
If the mathematics is starting to get a bit overwhelming, no worries — we’ll jump into some code that will make these concepts much clearer.
Configuring your development environment
To follow this guide, you need to have the OpenCV library installed on your system.
Luckily, OpenCV is pip-installable:
$ pip install opencv-contrib-python
If you need help configuring your development environment for OpenCV, I highly recommend that you read my pip install OpenCV guide — it will have you up and running in a matter of minutes.
Having problems configuring your development environment?
All that said, are you:
- Short on time?
- Learning on your employer’s administratively locked system?
- Wanting to skip the hassle of fighting with the command line, package managers, and virtual environments?
- Ready to run the code right now on your Windows, macOS, or Linux systems?
Then join PyImageSearch Plus today!
Gain access to Jupyter Notebooks for this tutorial and other PyImageSearch guides that are pre-configured to run on Google Colab’s ecosystem right in your web browser! No installation required.
And best of all, these Jupyter Notebooks will run on Windows, macOS, and Linux!
Project structure
Before we can implement rotation with OpenCV, let’s first review our project directory structure.
Be sure you access the “Downloads” section of this tutorial to retrieve the source code and example images, and from there, take a peek inside:
$ tree . --dirsfirst . ├── opencv_logo.png └── opencv_rotate.py 0 directories, 2 files
Here, we have opencv_rotate.py
. This script will load opencv_logo.png
(or any other image you choose) and then apply a series of rotations to it, thereby demonstrating how to perform rotation with OpenCV.
Implementing image rotation with OpenCV
We are now ready to implement image rotation with OpenCV.
Open the opencv_rotate.py
file in your project directory structure and insert the following code:
# import the necessary packages import argparse import imutils import cv2 # construct the argument parser and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", type=str, default="opencv_logo.png", help="path to the input image") args = vars(ap.parse_args())
Lines 2-4 import our required Python packages. We’ll use argparse
for command line arguments, imutils for my set of OpenCV convenience functions (namely the imutils.rotate
and imutils.rotate_bound
methods), and cv2
for our OpenCV bindings.
We only have a single command line argument, --image
, which is the path to the input image we want to rotate (which we default to opencv_logo.png
).
Next, let’s load our input image from disk and do some basic resizing:
# load the image and show it image = cv2.imread(args["image"]) cv2.imshow("Original", image) # grab the dimensions of the image and calculate the center of the # image (h, w) = image.shape[:2] (cX, cY) = (w // 2, h // 2) # rotate our image by 45 degrees around the center of the image M = cv2.getRotationMatrix2D((cX, cY), 45, 1.0) rotated = cv2.warpAffine(image, M, (w, h)) cv2.imshow("Rotated by 45 Degrees", rotated) # rotate our image by -90 degrees around the image M = cv2.getRotationMatrix2D((cX, cY), -90, 1.0) rotated = cv2.warpAffine(image, M, (w, h)) cv2.imshow("Rotated by -90 Degrees", rotated)
We start by loading our input image and displaying it on our screen:
When we rotate an image, we need to specify around which point we want to rotate. In most cases, you will want to rotate around the center of an image; however, OpenCV allows you to specify any arbitrary point you want to rotate around (as detailed above).
Let’s just go ahead and rotate about the center of the image. Lines 18 and 19 grab the width and height of the image and then divide each component by 2
to determine the center of the image.
Just as we define a matrix to translate an image, we also define a matrix to rotate the image. Instead of manually constructing the matrix using NumPy (which can be a bit tedious), we’ll just make a call to the cv2.getRotationMatrix2D
method on Line 22.
The cv2.getRotationMatrix2D
function takes three arguments. The first argument is the point where we rotate the image (in this case, the center cX
and cY
of the image).
We then specify , the number of (counterclockwise) degrees by which we will rotate the image. In this case, we are going to rotate the image 45 degrees.
The last argument is the scale of the image. We haven’t discussed resizing an image yet, but here you can specify a floating-point value, where 1.0 means the same, original dimensions of the image are used. However, if you specified a value of 2.0, the image doubles in size — similarly, a value of 0.5 halves the image size.
Once we have our rotation matrix M
from the cv2.getRotationMatrix2D
function, we can apply the rotation to our image using the cv2.warpAffine
method on Line 23.
The first argument to this function is the image
we want to rotate. We then specify our rotation matrix M
and the output dimensions (width and height) of our image. Line 24 then shows our image rotated by 45 degrees:
Lines 27-29 do the same, but this time rotating an image -90
degrees (clockwise) about the center cX
and cY
coordinates.
Note: Remember that in OpenCV, positive degrees specify counterclockwise rotation while negative degrees indicate clockwise rotation. Keep this in mind; otherwise, you may be confused when applying rotation to your own images!
Figure 4 displays the output of these resizing operations:
As you can see, our image has been rotated. Take a second to note that OpenCV does not automatically allocate space for our entire rotated image to fit into the frame.
This is the intended behavior! If you want the entire image to fit into view after the rotation, you’ll need to modify the width and height, denoted as (w, h)
in the cv2.warpAffine
function. As we’ll see later in this script, the imutils.rotate_bound
function takes care of all that for us.
Until this point, we have only rotated an image about the center of the image. But what if we wanted to rotate the image about some arbitrary point?
Let’s go ahead and see how this can be accomplished:
# rotate our image around an arbitrary point rather than the center M = cv2.getRotationMatrix2D((10, 10), 45, 1.0) rotated = cv2.warpAffine(image, M, (w, h)) cv2.imshow("Rotated by Arbitrary Point", rotated)
By now, this code should look fairly standard for performing a rotation. However, take note of the first argument of the cv2.getRotationMatrix2D
function. Here, we indicate that we want to rotate the image around x = 10, y = 10, or approximately the top-left corner of the image.
When we apply this rotation, our output image looks like this:
We can see that the center of the rotation is no longer the center of the image.
However, just like translating an image, making calls to both cv2.getRotationMatrix2D
and cv2.warpAffine
can become quite tedious — not to mention it also makes our code substantially more verbose.
Let’s reduce the amount of code we need to write by calling imutils.rotate
, a convenience function that wraps calls to cv2.getRotationMatrix2D
and cv2.warpAffine
:
# use our imutils function to rotate an image 180 degrees rotated = imutils.rotate(image, 180) cv2.imshow("Rotated by 180 Degrees", rotated)
Here, we rotate our image by 180 degrees, but we could make our code substantially less verbose by using the rotate
method.
Figure 6 displays the output of our rotation:
As you saw in previous examples, OpenCV does not allocate enough space to store the entire image if part of the image is cut off during the rotation process.
The way around that is to use the imutils.rotate_bound
function:
# rotate our image by 33 degrees counterclockwise, ensuring the # entire rotated image still renders within the viewing area rotated = imutils.rotate_bound(image, -33) cv2.imshow("Rotated Without Cropping", rotated) cv2.waitKey(0)
This function will automatically expand the image array such that the entire rotated image fits within it.
The results of applying the rotate_bound
function can be seen in Figure 7, where we rotate an image 33 degrees counterclockwise:
And that’s all there is to it!
Note: The imutils.rotate_bound
function inverts the relationship between positive/negative values and clockwise/counterclockwise rotation. Here, negative values will rotate counterclockwise while positive values will rotate clockwise.
When applying image rotation with OpenCV, you have three options:
cv2.getRotationMatrix2D
andcv2.warpAffine
imutils.rotate
imutils.rotate_bound
Mix and match them as you see fit for your own applications.
OpenCV image rotation results
To rotate images with OpenCV, be sure to access the “Downloads” section of this tutorial to retrieve the source code and example images.
We’ve already reviewed the results of this script in the previous section, but when you’re ready to run the script for yourself, you can use the following command:
$ python opencv_rotate.py
Your OpenCV rotation results should match mine from the previous section.
What's next? I recommend PyImageSearch University.
30+ total classes • 39h 44m video • Last updated: 12/2021
★★★★★ 4.84 (128 Ratings) • 3,000+ Students Enrolled
I strongly believe that if you had the right teacher you could master computer vision and deep learning.
Do you think learning computer vision and deep learning has to be time-consuming, overwhelming, and complicated? Or has to involve complex mathematics and equations? Or requires a degree in computer science?
That’s not the case.
All you need to master computer vision and deep learning is for someone to explain things to you in simple, intuitive terms. And that’s exactly what I do. My mission is to change education and how complex Artificial Intelligence topics are taught.
If you're serious about learning computer vision, your next stop should be PyImageSearch University, the most comprehensive computer vision, deep learning, and OpenCV course online today. Here you’ll learn how to successfully and confidently apply computer vision to your work, research, and projects. Join me in computer vision mastery.
Inside PyImageSearch University you'll find:
- ✓ 30+ courses on essential computer vision, deep learning, and OpenCV topics
- ✓ 30+ Certificates of Completion
- ✓ 39h 44m on-demand video
- ✓ Brand new courses released every month, ensuring you can keep up with state-of-the-art techniques
- ✓ Pre-configured Jupyter Notebooks in Google Colab
- ✓ Run all code examples in your web browser — works on Windows, macOS, and Linux (no dev environment configuration required!)
- ✓ Access to centralized code repos for all 500+ tutorials on PyImageSearch
- ✓ Easy one-click downloads for code, datasets, pre-trained models, etc.
- ✓ Access on mobile, laptop, desktop, etc.
Summary
In this tutorial, you learned how to rotate an image using OpenCV. To rotate an image by an arbitrary angle with OpenCV, we need to:
- Construct a 2D rotation matrix using the
cv2.getRotationMatrix2D
function - Perform an affine warp using the
cv2.warpAffine
function, supplying our input image and computed rotation matrix,M
The result is an image that has been rotated degrees.
The problem with using OpenCV’s functions to rotate an image is that they require two lines of code — one to construct the rotation matrix and then another to perform the transform.
To help make image rotation with OpenCV easier, I’ve implemented two methods in my imutils library:
imutils.rotate
: Performs OpenCV image rotation in a single line of code.imutils.rotate_bound
: Also performs image rotation with OpenCV but ensures the image (after rotation) is still viewable, and no parts of the image are cut off.
I suggest you get familiar with all three rotation techniques as you’ll likely use each of them when developing your own respective image processing pipelines.
To download the source code to this post (and be notified when future tutorials are published here on PyImageSearch), simply enter your email address in the form below!
Download the Source Code and FREE 17-page Resource Guide
Enter your email address below to get a .zip of the code and a FREE 17-page Resource Guide on Computer Vision, OpenCV, and Deep Learning. Inside you'll find my hand-picked tutorials, books, courses, and libraries to help you master CV and DL!
Comment section
Hey, Adrian Rosebrock here, author and creator of PyImageSearch. While I love hearing from readers, a couple years ago I made the tough decision to no longer offer 1:1 help over blog post comments.
At the time I was receiving 200+ emails per day and another 100+ blog post comments. I simply did not have the time to moderate and respond to them all, and the sheer volume of requests was taking a toll on me.
Instead, my goal is to do the most good for the computer vision, deep learning, and OpenCV community at large by focusing my time on authoring high-quality blog posts, tutorials, and books/courses.
If you need help learning computer vision and deep learning, I suggest you refer to my full catalog of books and courses — they have helped tens of thousands of developers, students, and researchers just like yourself learn Computer Vision, Deep Learning, and OpenCV.
Click here to browse my full catalog.