5

I am loading an image using PIL and OpenCV packages. The height and width are reversed when loading the image using PIL versus when loading using cv2. Following is the code to print height and width of the image loaded using both the packages.

file = 'conceptual_captions/VL-BERT/data/conceptual-captions/val_image/00002725.jpg'
# load image using PIL
import PIL.Image
pil = PIL.Image.open(file).convert('RGB')
w, h = pil.size
print("width: {}, height: {}".format(w, h))

Print output width: 1360, height: 765

# now using cv2
import cv2
im = cv2.imread(file)
print("height, width, channels: {}".format(im.shape)) 

print output height, width, channels: (1360, 765, 3)

I downloaded the image and checked the size of the image using info option on Mac. Info has width = 765 and height = 1360, which is same as reported by cv2 method. Why is PIL giving wrong image dimensions?

The problem occurs with very few images. The image I have linked is one such image. For rest of the images, the height and width reported by PIL and cv2 are the same.

Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
Gaurav Srivastava
  • 505
  • 1
  • 7
  • 17
  • What result do you get when you call `width, height = cv.GetSize(im)`, which is the documented way of getting the width and height? – Frank Yellin Sep 18 '20 at 01:38
  • @FrankYellin I get an error when I run the command `width, height = cv.GetSize(im)`. Also, [OpenCV documentation](https://docs.opencv.org/master/d3/df2/tutorial_py_basic_ops.html) mentions to use `im.shape` under "Accessing Image Properties" section. Can you link to the documentation for using `GetSize()`. – Gaurav Srivastava Sep 18 '20 at 01:58
  • Oh, great. One document I saw mentions GetSize(), another doesn't. Sorry about that. But definitely `pil.size` returns width, height while `im.shape` returns height, width. That's not what you're seeing? (You're not showing the results of the print statement, just your interpretations of the results.) – Frank Yellin Sep 18 '20 at 02:31
  • @FrankYellin I have updated the question with the exact print outputs. – Gaurav Srivastava Sep 18 '20 at 04:25

1 Answers1

10

The image has some EXIF meta data including information about orientation (rotation). I suggest reading this Q&A and subsequent references there.

Nevertheless, the proposed solution there can be simplified nowadays, just use PIL.ImageOps.exif_transpose():

If an image has an EXIF Orientation tag, return a new image that is transposed accordingly. Otherwise, return a copy of the image.

Some code to test:

from PIL import Image, ImageOps

# Read original image, show width and height
file = '...'
pil = Image.open(file).convert('RGB')
w, h = pil.size
print("width: {}, height: {}".format(w, h))

# Transpose with respect to EXIF data
pil = ImageOps.exif_transpose(pil)
w, h = pil.size
print("width: {}, height: {}".format(w, h))

The corresponding output:

width: 1360, height: 765
width: 765, height: 1360
----------------------------------------
System information
----------------------------------------
Platform:     Windows-10-10.0.16299-SP0
Python:       3.8.5
Pillow:       7.2.0
----------------------------------------
HansHirse
  • 18,010
  • 10
  • 38
  • 67
  • The suggested edit worked on `PIllow 7.2.0` and `Python 3.6.8`. It did not work on `Pillow 6.2.0` and `Python 3.7.4`. With the later configuration, I got error when `ImageOps.exif_transpose(pil)` got called. Before I accept the answer, I have a related question. `exif_transpose()` is converting the image to correct orientation, which `cv2.imread` was doing automatically. Is that correct? – Gaurav Srivastava Sep 18 '20 at 16:12