Title: OpenCV Rotate Image - PyImageSearch

URL Source: https://pyimagesearch.com/2021/01/20/opencv-rotate-image/

Published Time: 2021-01-21T04:55:00+00:00

Markdown Content:
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](https://github.com/jrosebr1/imutils), `imutils.rotate` and `imutils.rotate_bound`, which make rotating images with OpenCV easier (and requires less code).

A varied image dataset is crucial for understanding image rotation techniques. It helps in exploring how different images respond to rotation operations and assists in learning how to manage the issues that arise, like image cutoff.

[Roboflow](https://roboflow.com/?ref=pyimagesearch) has free tools for each stage of the computer vision pipeline that will streamline your workflows and supercharge your productivity.

Sign up or Log in to your [Roboflow account](https://roboflow.com/?ref=pyimagesearch) to access state of the art dataset libaries and revolutionize your computer vision pipeline.

You can start by choosing your own datasets or using our [PyimageSearch’s assorted library of useful datasets](https://universe.roboflow.com/pyimagesearch?ref=pyimagesearch).

Bring data in any of 40+ formats to [Roboflow](https://roboflow.com/?ref=pyimagesearch), train using any state-of-the-art model architectures, deploy across multiple platforms (API, NVIDIA, browser, iOS, etc), and connect to applications or 3rd party tools.

![Image 1](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20450'%3E%3C/svg%3E)

Previously, we learned how to [translate (i.e., shift) an image](https://pyimagesearch.com/2021/02/03/opencv-image-translation/), 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, ![Image 2: \large\theta](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%2011'%3E%3C/svg%3E). We’ll use ![Image 3: \large\theta](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%2011'%3E%3C/svg%3E) 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._**

![Image 4](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20128%20128'%3E%3C/svg%3E)

#### Looking for the source code to this post?

[Jump Right To The Downloads Section](#download-the-code)

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:

1.  **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.
2.  **Use the `imutils.rotate` function:** Part of my [imutils library](https://github.com/jrosebr1/imutils). Makes it possible to rotate an image with OpenCV in a single function call.
3.  **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](https://pyimagesearch.com/2021/02/03/opencv-image-translation/), and perhaps unsurprisingly, rotation by an angle ![Image 5: \theta](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%2011'%3E%3C/svg%3E) can be defined by constructing a matrix, _M_, in the form:

![Image 6: M = \begin{bmatrix}\cos \theta & -\sin \theta \\ \sin \theta & \cos\theta\end{bmatrix}](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20146%2040'%3E%3C/svg%3E)

Given an _(x, y)_\-Cartesian plane, this matrix can be used to rotate a vector ![Image 7: \theta](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%2011'%3E%3C/svg%3E) 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: ![Image 8: R = I \times M](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2080%2011'%3E%3C/svg%3E)

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:

![Image 9: M = \begin{bmatrix}\alpha & \beta & (1 - \alpha) \times c_{x} - \beta \times c_{y} \\-\beta & \alpha & \beta \times c_{x} + (1 - \alpha) \times c_{y}\end{bmatrix}](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20265%2040'%3E%3C/svg%3E)

where ![Image 10: \alpha = \text{scale} \times \cos \theta](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20119%2014'%3E%3C/svg%3E) and ![Image 11: \beta = \text{scale} \times \sin \theta](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20116%2016'%3E%3C/svg%3E) and ![Image 12: c_{x}](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2014%2010'%3E%3C/svg%3E) and ![Image 13: c_{y}](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2013%2012'%3E%3C/svg%3E) 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**](https://pyimagesearch.com/2018/09/19/pip-install-opencv/) — it will have you up and running in a matter of minutes.

### **Having problems configuring your development environment?**

[![Image 14](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20500%20334'%3E%3C/svg%3E)](https://pyimagesearch.com/pyimagesearch-plus/)

**Figure 1:** Having trouble configuring your development environment? Want access to pre-configured Jupyter Notebooks running on Google Colab? Be sure to join [PyImageSearch Plus](https://pyimagesearch.com/pyimagesearch-plus/) — you will be up and running with this tutorial in a matter of minutes.

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](https://pyimagesearch.com/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](https://github.com/jrosebr1/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:

![Image 15](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20380%20500'%3E%3C/svg%3E)

**Figure 2:** Loading our input image.

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](https://pyimagesearch.com/2021/02/03/opencv-image-translation/), 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 ![Image 16: \theta](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%2011'%3E%3C/svg%3E), 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:

![Image 17](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20380%20500'%3E%3C/svg%3E)

**Figure 3:** Rotating an image with OpenCV. Positive degrees rotate the image _counterclockwise._

**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:

![Image 18](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20380%20500'%3E%3C/svg%3E)

**Figure 4:** Using OpenCV to rotate an image _clockwise_ by supplying a negative degree value.

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:

![Image 19](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20380%20500'%3E%3C/svg%3E)

**Figure 5:** Using OpenCV to rotate our image 45 degrees counterclockwise centered around _x = 10_, _y = 10._

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:

![Image 20](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20500%20658'%3E%3C/svg%3E)

**Figure 6:** Rotating our image 180 degrees using OpenCV and imutils.

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:

![Image 21](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20500%20567'%3E%3C/svg%3E)

**Figure 7:** Rotating our image 33 degrees counterclockwise while ensuring the entire rotated image still renders within the viewable area.

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:

1.  `cv2.getRotationMatrix2D` and `cv2.warpAffine`
2.  `imutils.rotate`
3.  `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? We recommend [PyImageSearch University](https://pyimagesearch.com/pyimagesearch-university/?utm_source=blogPost&utm_medium=bottomBanner&utm_campaign=What%27s%20next%3F%20I%20recommend).

**Course information:**  
84 total classes • 114+ hours of on-demand code walkthrough videos • Last updated: February 2024  
★★★★★ 4.84 (128 Ratings) • 16,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:**

*   ✓ **84 courses** on essential computer vision, deep learning, and OpenCV topics
*   ✓ **84 Certificates** of Completion
*   ✓ **114+ hours** of on-demand video
*   ✓ **Brand new courses released _regularly_**, 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_ 536+ tutorials** on PyImageSearch
*   ✓ **Easy one-click downloads** for code, datasets, pre-trained models, etc.
*   ✓ **Access** on mobile, laptop, desktop, etc.

[Click here to join PyImageSearch University](https://pyimagesearch.com/pyimagesearch-university/?utm_source=blogPost&utm_medium=bottomBanner&utm_campaign=What%27s%20next%3F%20I%20recommend)

**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:

1.  Construct a 2D rotation matrix using the `cv2.getRotationMatrix2D` function
2.  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 ![Image 22: \theta](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%2011'%3E%3C/svg%3E) 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](https://github.com/jrosebr1/imutils):

1.  `imutils.rotate`: Performs OpenCV image rotation in a single line of code.
2.  `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!_**

![Image 23](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20410%20567'%3E%3C/svg%3E)

#### 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!