현상
1) 핸드폰을 세로로 길게 세운 상태에서 사진을 찍었다 (iPhone 12, iOS: 16.6.1)
2) Python에서 pillow 이용해서 이미지를 열었는데 자동으로 반시계방향으로 90도 회전이 되어 읽어진다
from PIL import Image, ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True # OSError: image file is truncated 에러때문에 추가했다
image_path = 'service_coke.jpeg'
img = Image.open(image_path)
img.show(title='test')
왜 자동으로 이미지를 돌릴까?
해결책은 github pillow repo의 issue에서 찾을 수 있었다. https://github.com/python-pillow/Pillow/issues/4703
I would imagine that the images you are dealing with have an EXIF orientation tag. This means that the image data is saved in one position, and then the image instructs the viewer to rotate it another way.
Pillow does not automatically apply this transformation to the data. However, it has a method to do so - https://pillow.readthedocs.io/en/stable/reference/ImageOps.html#PIL.ImageOps.exif_transpose
Here is an example using it. You can try this and check if it resolves your problem.
from PIL import Image, ImageOps
im = Image.open("file.jpg")
im = ImageOps.exif_transpose(im)
최종 코드
from PIL import Image, ImageFile, ImageOps
ImageFile.LOAD_TRUNCATED_IMAGES = True
image_path = 'service_coke.jpeg'
img = Image.open(image_path)
img = ImageOps.exif_transpose(img)
img.show(title='test')
EXIF orientation tag는 뭘까?
먼저, EXIF는 Exchangeable image file format의 약자로 digital camera로 찍힌 이미지에 대한 다양한 meta 정보를 저장하는 프로토콜이다. EXIF 는 실제 이미지와 함께 저장되는데 shutter speed, focal length, orientation, shooting time 정보들이 있다.
그중 내가 관심있는 orientation tag는 1~8까지의 값을 가진다.
이미지에서 orientation tag를 얻는 방법
from PIL.ExifTags import TAGS
from PIL import Image
image_path = 'service_coke.jpeg'
img = Image.open(image_path)
exif = img.getexif()
for k, v in exif.items():
print('{}: {}'.format(TAGS[k], v))
orientation tag: 6
TileWidth: 512
TileLength: 512
ResolutionUnit: 2
ExifOffset: 240
Make: Apple
Model: iPhone 12
Software: 16.6.1
Orientation: 6
DateTime: 2024:01:14 23:25:06
YCbCrPositioning: 1
XResolution: 72.0
YResolution: 72.0
HostComputer: iPhone 12
이런 정보를 확인할 수 있고 이 중 orientation tag 값은 6을 보여준다.
6은 위 이미지에서 볼 떄 image viewer에서 보여줄 때 이미지를 시계 방향으로 90도 회전해서 보여줘야된다는 의미이고 이를 반영하여 image를 보여주기 위해서는 위의 최종 코드에서 ImageOps.exif_transpose를 사용해야한다.
from PIL import Image, ImageFile, ImageOps
image_path = 'service_coke.jpeg'
img = Image.open(image_path)
img = ImageOps.exif_transpose(img)
img.show(title='test')
exif_transpose 함수 정의
def exif_transpose(image, *, in_place=False):
"""
If an image has an EXIF Orientation tag, other than 1, transpose the image
accordingly, and remove the orientation data.
:param image: The image to transpose.
:param in_place: Boolean. Keyword-only argument.
If ``True``, the original image is modified in-place, and ``None`` is returned.
If ``False`` (default), a new :py:class:`~PIL.Image.Image` object is returned
with the transposition applied. If there is no transposition, a copy of the
image will be returned.
"""
- exif_transpose 함수는 이미지에 EXIF Orientation tag 정보가 있으면 이를 이용하여 image를 보여준다.
'Python' 카테고리의 다른 글
super() (0) | 2024.09.15 |
---|---|
The Walrus Operator: Python's Assignment Expressions (바다코끼리 연산자) (0) | 2024.08.31 |
URL 다루기 위한 python의 built-in 패키지: urllib (0) | 2024.08.25 |
Python을 이용한 Crawling (Feat. arm64, graviton) (0) | 2024.01.06 |
[Python] annotation 과 forward reference (0) | 2022.06.06 |