11

How can I rotate an image file and plot it in matplotlib?

I know I can open it using PIL and rotate it, but this seems way too much for this simple function, that I'm probably not finding.

I found this piece of code around here, but doesn't seems to work:

from matplotlib import pyplot, image, transforms

img = image.imread('filename.png')

pyplot.ion()
fig = pyplot.figure()
ax = fig.add_subplot(111)

for degree in range(360):
    pyplot.clf()
    tr = transforms.Affine2D().rotate_deg(degree)

    ax.imshow(img, transform=tr)
    fig.canvas.draw()
f.rodrigues
  • 3,499
  • 6
  • 26
  • 62

5 Answers5

18

It seems matplotlib has moved on since this question was asked, and it can now natively support affine transformations of images without the user needing to fall back to low-level image manipulation routines.

This is now documented in the form of an example in https://matplotlib.org/gallery/images_contours_and_fields/affine_image.html.

Essentially, this requires specifying the appropriate transform keyword argument. The code provided in the original question would be updated as follows:

import matplotlib.pyplot as plt
from matplotlib import transforms

img = plt.imread('filename.png')

fig = plt.figure()
ax = fig.add_subplot(111)

tr = transforms.Affine2D().rotate_deg(rotation_in_degrees)

ax.imshow(img, transform=tr + ax.transData)
plt.show()
pelson
  • 21,252
  • 4
  • 92
  • 99
17

You could use rotate from scipy.ndimage:

import scipy.misc
from scipy import ndimage
import matplotlib.pyplot as plt

img = scipy.misc.lena()  
# img = scipy.misc.face()  # lena is not included in scipy 0.19.1
plt.figure(figsize=(12, 2))

for degree in range(5):
    plt.subplot(151+degree)
    rotated_img = ndimage.rotate(img, degree*60)
    plt.imshow(rotated_img, cmap=plt.cm.gray)
    plt.axis('off')

plt.show()

This rotates the image around the center (see docs).

lena

Edit:

I you want some kind of animation (I don't how you're going to use the rotating image, so I can only speculate), maybe you're better off using some kind of game/graphics library, e.g. Pygame. Here you can rotate an image with some performance (thanks to the underlying SDL) by using pygame.transform.rotate and blitting that rotated image onto the screen.

Try this (using a picture lena.jpg) to get a smoothly rotating image:

import pygame

pygame.init()
screen = pygame.display.set_mode([400, 400])
pygame.display.set_caption('Rotating image example')
clock = pygame.time.Clock()

img = pygame.image.load('lena.jpg').convert()

img_rect = img.get_rect(center = screen.get_rect().center)
degree = 0

while degree < 360:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

    # rotate image
    rot_img = pygame.transform.rotate(img, degree)
    img_rect = rot_img.get_rect(center = img_rect.center)

    # copy image to screen
    screen.fill((0, 0, 0))
    screen.blit(rot_img, img_rect)
    pygame.display.flip()

    clock.tick(60)
    degree += 1

pygame.quit()
Steven C. Howell
  • 16,902
  • 15
  • 72
  • 97
adrianus
  • 3,141
  • 1
  • 22
  • 41
  • This gives me weird line in the contour, I'm working with alpha png images. Also, this is slow as hell (in the loop with 360 values) it took 90 seconds. I need to rotate this image many times. – f.rodrigues Jul 14 '15 at 09:13
  • Do you want to animate an image that rotates? From your question I just understood that you wanted to rotate and then show it to the user. In this case maybe matplotlib isn't the right library to do that and you're better off with [Pygame](http://www.pygame.org/) (have a look at `pygame.transform.rotate`), which is based on SDL and should provide a better performance regarding animations like rotating etc. – adrianus Jul 14 '15 at 10:45
  • The program I'm making is displaying a series of information about a vehicle (velocity, trajectory, ...) which I get via the gps, including the bearing(angle), I want to displaying a small car image in the top corner behaving like a compass. I thought of using pygame, but it doesn't have most of the neat features of matplotlib to deal with dynamic data. – f.rodrigues Jul 14 '15 at 11:30
4

Another option might be to use numpy's rot90 function. The idea is to convert the image into a numpy array and then rotate the array the number of times needed. Here's an example:

import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import numpy as np

with cbook.get_sample_data('ada.png') as image_file:
    image = plt.imread(image_file)
image_arr = np.array(image)

#plt.show() To view the image

for _ in range(3):#3 to turn the image 90 degrees three times = 270 degrees
    image_arr = np.rot90(image_arr)

plt.imshow(image_arr, aspect="auto", extent=(-14,-4,-2,40), zorder = 2, interpolation="nearest")

plt.show()

However, this is only limited to rotating an image by right angles (multiples of 90).

Abhishek
  • 553
  • 2
  • 9
  • 26
3

you could use the following code, which I found here:

How can I rotate a matplotlib plot through 90 degrees?

import matplotlib.pyplot as plt
import scipy

img = scipy.misc.lena()
tr = scipy.ndimage.rotate(img, 45)
plt.imshow(tr)
Ian Thompson
  • 2,914
  • 2
  • 18
  • 31
Achim
  • 282
  • 4
  • 12
2

I find the following solution quite intuitive. It uses Pillow library to read the image, then, we can use the inbuilt rotate function to rotate the image. The image is rotated in a counter-clockwise manner and stored in a new variable. Finally, we can use matplotlib to create and show the plot.

from PIL import Image
import matplotlib.pyplot as plt

im = Image.open(path-to-file)
im = im.rotate(90) # Rotates counter clock-wise.
implot = plt.imshow(im)
plt.show()
Jayant
  • 346
  • 3
  • 14
  • Hello and welcome to SO! While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. Please read the [tour](https://stackoverflow.com/tour), and [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer) – Tomer Shetah Feb 03 '21 at 10:25