Title: OpenCV Image Translation - PyImageSearch

URL Source: https://pyimagesearch.com/2021/02/03/opencv-image-translation/

Published Time: 2021-02-04T01:18:00+00:00

Markdown Content:
In this tutorial, you will learn how to translate and shift images using OpenCV.

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

Translation is the shifting of an image along the _x-_ and _y-_axis. To translate an image using OpenCV, we must:

1.  Load an image from disk
2.  Define an affine transformation matrix
3.  Apply the `cv2.warpAffine` function to perform the translation

This sounds like a complicated process, but as you will see, _it can all be done in only two lines of code!_

**To learn how to translate images with OpenCV, _just keep reading._**

![Image 2](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 will discuss what a translation matrix is and how we can define it using OpenCV and NumPy.

From there, we will configure our development environment and review our project directory structure.

With our project directory structure reviewed, we will move on to implement a Python script to perform translation with OpenCV, `opencv_translate.py`.

We will review this script in detail, along with our results generated by the script.

By the end of this guide, you will understand how to perform image translation using OpenCV.

### **Defining a translation matrix with OpenCV**

To perform image translation with OpenCV, we first need to define a _2 x 3_ matrix called an **affine transformation matrix:**

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

**Figure 1:** To translate an image with OpenCV, we must first construct an affine transformation matrix.

For the purposes of translation, all we care about are the ![Image 4: t_{x}](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2013%2013'%3E%3C/svg%3E) and ![Image 5: t_y](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2012%2015'%3E%3C/svg%3E) values:

For example, let’s suppose we want to shift an image 25 pixels to the _right_ and 50 pixels _down_. Our translation matrix would look like the following (implemented as a NumPy array):

M = np.float32(\[
	\[1, 0, 25\],
	\[0, 1, 50\]
\])

Now, if we want to shift an image 7 pixels to the _left_ and 23 pixels _up_, our translation matrix would look like the following:

M = np.float32(\[
	\[1, 0, -7\],
	\[0, 1, -23\]
\])

And as a final example, let’s suppose we want to translate our image 30 pixels to the _left_ and 12 pixels _down_:

M = np.float32(\[
	\[1, 0, -30\],
	\[0, 1, 12\]
\])

As you can see, defining our affine transformation matrix for image translation is quite easy!

And once our transformation matrix is defined, we can simply perform the image translation using the `cv2.warpAffine` function, like so:

shifted = cv2.warpAffine(image, M, (image.shape\[1\], image.shape\[0\]))

We will see a complete example of defining our image translation matrix and applying the `cv2.warpAffine` function later in this guide.

### **Configuring your development environment**

To follow along with 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 6](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 2:** 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 system?**

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 perform image translation with OpenCV, let’s first review our project directory structure:

$ tree . --dirsfirst
.
├── opencv\_logo.png
└── opencv\_translate.py

0 directories, 2 files

We have a single Python script, `opencv_translate.py`, which we will be reviewing in detail.

This script will load the `opencv_logo.png` image from disk and then translate/shift it using the OpenCV library.

### **Image translation with OpenCV**

Translation is the shifting of an image along the _x-_ and _y-_axis. Using translation, we can shift an image _up_, _down_, _left_, or _right_, along with any combination of the above.

**Mathematically, we define a translation matrix, _M,_ that we can use to translate an image:**

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

**Figure 3:** Defining an image translation matrix with OpenCV.

This concept is better explained through some code:

\# import the necessary packages
import numpy as np
import argparse
import imutils
import cv2

On **Lines 2-5,** we simply import the packages we will make use of. At this point, using NumPy, `argparse`, and `cv2` should feel commonplace.

However, I am introducing a new package here: [imutils](https://github.com/jrosebr1/imutils). This isn’t a package included in NumPy or OpenCV. Rather, it’s a library that I personally wrote containing a handful of “convenience” methods to more easily perform common tasks like translation, rotation, and resizing (and with less code).

If you don’t already have `imutils` installed on your machine, you can install it with `pip`:

$ pip install imutils

Let’s now parse our command line arguments:

\# 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())

We only need a single argument, `--image`, which points to the input image we want to load from disk and apply OpenCV translation operations to. By default, we will set the `--image` argument to be `opencv_logo.png`.

Let’s now load our image from disk and perform our first translation:

\# load the image and display it to our screen
image = cv2.imread(args\["image"\])
cv2.imshow("Original", image)

# shift the image 25 pixels to the right and 50 pixels down
M = np.float32(\[\[1, 0, 25\], \[0, 1, 50\]\])
shifted = cv2.warpAffine(image, M, (image.shape\[1\], image.shape\[0\]))
cv2.imshow("Shifted Down and Right", shifted)

**Lines 14 and 15** load our input `image` from disk and then display it to our screen:

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

**Figure 4:** Our example input image that we will be applying translation to with OpenCV.

The first actual translation takes place on **Lines 18-20**, where we start by defining our translation matrix, `M`.

This matrix tells us how many pixels to the _left_ or _right_ our image will be shifted, and then how many pixels _up_ or _down_ the image will be shifted, again keeping in mind that the translation matrix has the form:

M = np.float32(\[
	\[1, 0, shiftX\],
	\[0, 1, shiftY\]
\])

Our translation matrix M is defined as a floating point array — this is important because OpenCV expects this matrix to be of floating point type. The first row of the matrix is ![Image 9: [1, 0, t_{x}]](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2050%2018'%3E%3C/svg%3E), where ![Image 10: t_{x}](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2013%2013'%3E%3C/svg%3E) is the number of pixels we will shift the image _left_ or _right_. Negative values of ![Image 11: t_{x}](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2013%2013'%3E%3C/svg%3E) will shift the image to the _left,_ and positive values will shift the image to the _right_.

Then, we define the second row of the matrix as ![Image 12: [0, 1, t_{y}]](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2050%2018'%3E%3C/svg%3E), where ![Image 13: t_{y}](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2012%2015'%3E%3C/svg%3E) is the number of pixels we will shift the image _up_ or _down_. Negative values of ![Image 14: t_{y}](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2012%2015'%3E%3C/svg%3E) will shift the image _up_, and positive values will shift the image _down_.

Using this notation, on **Line 18,** we can see that ![Image 15: t_{x}=25](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2051%2016'%3E%3C/svg%3E) and ![Image 16: t_{y}=50](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2051%2018'%3E%3C/svg%3E), indicating that we are shifting the image 25 pixels to the _right_ and 50 pixels _down_.

Now that we have our translation matrix defined, the actual translation takes place on **Line 19** using the `cv2.warpAffine` function. The first argument is the image we wish to shift, and the second argument is our translation matrix, `M`. Finally, we manually supply the image’s dimensions (width and height) as the third argument.

**Line 20** displays the results of the translation, which we can see below:

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

**Figure 5:** Using OpenCV to translate an image 25 pixels to the _right_ and 50 pixels _down_.

Notice how the image has clearly been “shifted” _down_ and to the _right_.

Let’s examine another example of image translation with OpenCV.

\# now, let's shift the image 50 pixels to the left and 90 pixels
# up by specifying negative values for the x and y directions,
# respectively
M = np.float32(\[\[1, 0, -50\], \[0, 1, -90\]\])
shifted = cv2.warpAffine(image, M, (image.shape\[1\], image.shape\[0\]))
cv2.imshow("Shifted Up and Left", shifted)

**Line 25** sets ![Image 18: t_{x} = -50](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2064%2016'%3E%3C/svg%3E) and ![Image 19: t_{y} = -90](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2064%2017'%3E%3C/svg%3E), implying that we are shifting the image 50 pixels to the _left_ and 90 pixels _up_. The image is shifted _left_ and _up_ rather than _right_ and _down_ because we are providing negative values for both ![Image 20: t_{x}](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2013%2013'%3E%3C/svg%3E) and ![Image 21: t_{y}](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2012%2015'%3E%3C/svg%3E).

**Figure 6** shows the output of supplying negative values for both ![Image 22: t_{x}](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2013%2013'%3E%3C/svg%3E) and ![Image 23: t_{y}](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2012%2015'%3E%3C/svg%3E):

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

**Figure 6:** Applying translation with OpenCV to shift an image 50 pixels to the _left_ and 90 pixels _up_.

Again, notice how our image is “shifted” to the _left_ 50 pixels and _up_ 90 pixels.

However, manually constructing this translation matrix and calling the `cv2.warpAffine` method takes a bit of effort — and it’s not necessarily pretty code either!

This is where my `imutils` package comes in. Instead of having to define our matrix `M` and make a call to `cv2.warpAffine` each time we want to translate an image, we can instead call `imutils.translate` to take care of the operation for us:

\# use the imutils helper function to translate the image 100 pixels
# down in a single function call
shifted = imutils.translate(image, 0, 100)
cv2.imshow("Shifted Down", shifted)
cv2.waitKey(0)

The output of the translation operation can be seen in **Figure 7**:

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

**Figure 7:** Translating an image 100 pixels _down_ using OpenCV.

The benefit of using `imutils.translate` is cleaner code — the output of `imutils.translate` versus `cv2.warpAffine` will be the same, regardless.

**_Note:_** _If you are interested in seeing the implementation of the `imutils.translate` function,_ [_simply refer to my GitHub repo_.](https://github.com/jrosebr1/imutils/blob/master/imutils/convenience.py#L17)

### **OpenCV image translation results**

To perform image translation with OpenCV, be sure to access the **_“Downloads”_** section of this tutorial to retrieve the source code and example image.

You can then execute the following command:

$ python opencv\_translate.py

Your results should look like 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 perform image translation using OpenCV.

You accomplished this task by first defining an affine transformation matrix:

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

**Figure 9:** To translate an image with OpenCV, we must first construct an affine transformation matrix.

You then specified how you wanted to shift the image:

While performing image translation with OpenCV requires only two lines of code, it’s not exactly the most “pretty” code in the world. For convenience, you can use the `imutils.translate` function to perform image translation in a single, concise, and readable function call.

**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 27](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!