41

我有以下情况:

  • 我正在从 iPhone 向我的 Pyhon 套接字服务器发送图像以及 EXIF 信息。
  • 我需要根据拍摄图像时的实际方向正确定位图像。我知道IOS总是将图像保存为横向左并将实际方向添加为EXIF字段(EXIF.Image.Orientation)。
  • 我正在阅读 EXIF 字段以查看实际方向。然后我使用 wxpython 将图像旋转到正确的方向。

我正在使用 pyexiv2 进行 EXIF 操作。

问题:使用 wxpython 旋转图像时,包括缩略图在内的 EXIF 信息丢失。

我做了什么:我在旋转图像之前阅读 EXIF。我重置了 EXIF 中的方向字段。然后我在旋转后把它放回去。

问题:

EXIF 内的缩略图不旋转。因此,图像和缩略图具有不同的方向。

问题?

除了 PIL 之外,还有其他模块可以旋转图像并保留其 EXIF 信息吗?

缩略图方向是否有单独的 EXIF 字段?

有没有办法我可以单独旋转缩略图?

谢谢你的帮助...

4

6 回答 6

105

此解决方案适用于我: PIL 缩略图正在旋转我的图像?

不需要检查它是 iPhone 还是 iPad:如果照片有方向标签 - 旋转它。

from PIL import Image, ExifTags

try:
    image=Image.open(filepath)

    for orientation in ExifTags.TAGS.keys():
        if ExifTags.TAGS[orientation]=='Orientation':
            break
    
    exif = image._getexif()

    if exif[orientation] == 3:
        image=image.rotate(180, expand=True)
    elif exif[orientation] == 6:
        image=image.rotate(270, expand=True)
    elif exif[orientation] == 8:
        image=image.rotate(90, expand=True)

    image.save(filepath)
    image.close()
except (AttributeError, KeyError, IndexError):
    # cases: image don't have getexif
    pass

前:

前

后: 后

于 2014-11-14T10:42:17.497 回答
59

如果您使用的是Pillow >= 6.0.0,则可以使用内置ImageOps.exif_transpose函数根据其 exif 标签正确旋转图像:

from PIL import ImageOps

image = ImageOps.exif_transpose(image)
于 2019-09-26T12:30:57.647 回答
3

与@scabbiaza 的答案几乎相同,但使用转置而不是旋转(出于性能目的)。

from PIL import Image, ExifTags

try:
    image=Image.open(filepath)
    for orientation in ExifTags.TAGS.keys():
        if ExifTags.TAGS[orientation]=='Orientation':
            break
    exif=dict(image._getexif().items())

    if exif[orientation] == 3:
        image=image.transpose(Image.ROTATE_180)
    elif exif[orientation] == 6:
        image=image.transpose(Image.ROTATE_270)
    elif exif[orientation] == 8:
        image=image.transpose(Image.ROTATE_90)
    image.save(filepath)
    image.close()

except (AttributeError, KeyError, IndexError):
    # cases: image don't have getexif
    pass
于 2020-04-03T11:40:32.310 回答
0

https://medium.com/@giovanni_cortes/rotate-image-in-django-when-saved-in-a-model-8fd98aac8f2a

这篇博文解释得很清楚。只要确保您尝试保留@receiver..代码forms.pymodels.py当我遇到cannot import model/view错误时。

rotate_image方法保留在models.py& @receiver..代码中models.py

我也得到了像没有这样的目录这样的错误。只需确保full_path正确设置为媒体文件夹即可。

我用了这条线

fullpath = os.path.join(os.path.dirname(BASE_DIR)) + instance.fimage.url

于 2018-02-06T07:16:25.673 回答
0

由于这是“python exif rotate”的最佳答案,我想添加一个附录,以防您只需要旋转值而不需要 PIL 旋转图像- 在我的情况下,我使用 QPixmap 在 QGraphicsView 上旋转图像,所以我只需要 QPixmap 变换的角度。上面使用PIL 获取 exif
答案相当慢。在我的测试中,它花费了piexif库的 6 倍时间(6 毫秒 vs 1 毫秒),因为创建/打开 PIL.Image 需要很多时间。所以我建议在这种情况下使用。piexif

import piexif

def get_exif_rotation_angle(picture)

    exif_dict = piexif.load(picture)
    if piexif.ImageIFD.Orientation in exif_dict["0th"]:
        orientation = exif_dict["0th"][piexif.ImageIFD.Orientation]
        if orientation == 3:
            return 180
        elif orientation == 6:
            return 90
        elif orientation == 8:
            return 270
        else:
            return None
    else:
        return None

picture 可以是文件路径或字节对象。

参考:https ://piexif.readthedocs.io/en/latest/sample.html#rotate-image-by-exif-orientation

于 2020-02-11T21:22:21.940 回答
0
from PIL import Image

def reorient_img(pil_img):
    img_exif = pil_img.getexif()

    if len(img_exif):
        if img_exif[274] == 3:
            pil_img = pil_img.transpose(Image.ROTATE_180)
        elif img_exif[274] == 6:
            pil_img = pil_img.transpose(Image.ROTATE_270)
        elif img_exif[274] == 8:
            pil_img = pil_img.transpose(Image.ROTATE_90)

    return pil_img
于 2021-12-12T11:31:23.760 回答