One day, my friend sent me some images to test my algorithm on. The algorithm worked just fine, and I got everything running through. When analyzing the results, however, I saw that some images had been rotated!
I really couldn't understand the reason. Nothing in my algorithm performed any rotations, and it was a bit weird. I fortunately got a hold of the reason why this happened after all, and in this post I will walk you through the steps you can perform to analyze images that get rotated weirdly using Python.
Let's get started!
Did you ever think about what happens when you take an image using your mobile phone camera? In this case, the camera would write the image to an image file, while at the same time including other information in the image called metadata; in brief, this is data about data. For instance, our image is considered data. Metadata could be the time when the image was taken.
Metadata is written to the image file using the Exchangeable image file format (Exif). Many interesting metadata tags will be included in your image, such as the make and model of the phone used to take the photo, in addition to more interesting tags! Thus, metadata could include valuable information about your image.
If you want to dig deeper into Exif data, the Camera and Imaging Products Association (CIPA) and Information Technology Industries Association (JEITA) have jointly formulated the standard: CIPA DC- 008-Translation Exchangeable image file format for digital still cameras: Exif Version 2.3.
Now that we know what we mean by metadata, let's go ahead and read some metadata tags in our image. For the purpose of this tutorial, I'm using the image below, which has been taken using a mobile phone camera. The original image can be downloaded from toy.jpg.
As mentioned above, different metadata tags will be included in the image. Let's write a Python script that would extract the information of some metadata tags from the above image. As for the information, let's say we want to know more about the make and model of the mobile phone with which the photo was taken, and the flash status at the time of taking the photo. For that, we are going to be using the ExifTags module, which is part of the Python Imaging Library (PIL).
I will list the Python script first, and then go through the code step by step:
from PIL import Image from PIL.ExifTags import TAGS image = Image.open('toy.jpg') info = image._getexif() for tag, value in info.items(): key = TAGS.get(tag) if key == 'Make': print(key + ': ' + str(value)) elif key == 'Model': print(key + ': ' + str(value)) elif key == 'Flash': print(key + ': ' + str(value))
The first thing we did is import the
TAGS classes. The
Image class is used to represent a PIL image, while the
TAGS class, as mentioned in the documentation, maps 16-bit integer EXIF tag enumerations to descriptive string names.
We then move on by reading our image,
toy.jpg, and using the
._getexif() function which returns a dictionary of tags and their values. After that, before printing the value of the tag (key), we check if that key exists in the image as a tag at all or not.
If you would like to have a list of the available tags in the image, you can simply add the statement
print key under the key variable in the for-loop. What other tags could you see after running this statement?
Checking the output of the above script, this is what you would get if you used
Flash: 0 Make: samsung Model: SAMSUNG-SM-N920A
From the output, we know that the mobile phone used to take the photo we saw was of type
samsung and model
SAMSUNG-SM-N920A. What about the value
0 for the tag
Flash? If we refer to the standard document linked in the Exif Data section above, we will see that the value
0 means that the flash did not fire at the time of taking the photo.
Why Is the Image Rotated on My Desktop?
Let's come to our main topic: the reason why you might sometimes find the image you transferred from a mobile phone camera being rotated, or with the wrong orientation. We can discover the reason for this issue by analyzing the Exif data of the image.
A metadata tag we can use for this purpose is
Orientation, which, based on the standard document linked above, shows the image orientation viewed in terms of rows and columns. In order to check the Orientation tag value for our image, we can add the following statements at the end of the above script:
elif key == 'Orientation': print(key + ': ' + str(value))
The above statements would return
Orientation: 1. Referring back to the Exif standards document, the value
The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side.
To make this clearer, as described in Exif Orientation Tag, the above description can be read as follows: 0th row in the stored image is the top of the captured scene, and the 0th column in the stored image is the left side of the captured scene. In other words, the image has not been rotated in essence, so we wouldn't have any orientation issues when transferring the image from our mobile phone to the desktop. The JPEG Rotation and EXIF Orientation document gives a nice explanation of the Exif orientation tag and its different values.
Thus, when you notice that an image that's been transferred from your mobile phone has an unexpected rotation or has the wrong orientation, you just need to go back to the Exif Orientation tag and check its value for a particular image, based on which you could correct the orientation of your transferred image, or any other image you received from someone else.
This is particularly beneficial when you're applying an algorithm on a batch of images retrieved from a mobile phone camera, and you'd like to make sure that each image has been saved with the correct orientation.