读取带旋转信息的图片

EXIF 信息真好,EXIF 信息真烦

工作中经常碰到带有旋转信息的图片,读出来之后整个图片被旋转了,标注信息和图片对不上。之前旋转图片一直是个老大难的问题,后来下定决心给解决掉了。

首先,「正确」的图片是什么样子的?

有几个判断方法:

  1. Mac:在 Finder 里面直接看图片,看到的样子
  2. Windows:在资源管理器里面直接看图片,看到的样子
  3. 将图片直接拖进 Chrome,显示出来的样子

以上方法都是读取 EXIF 信息并旋转过后的结果,也就是我们希望得到的结果。

如果你喜欢使用 OpenCV……

恭喜你!最简单了!

你只要将你的 OpenCV 升级到 3.1 以上,并且读图片的时候不要使用 IMREAD_UNCHANGED 参数就好了。

这里说一下。仔细看下 IMREAD_常量的定义,会发现其实这些常量是可以组合的,比如 IMREAD_UNCHANGED 就是 1,IMREAD_IGNOREORIENTATION 就是 128。既然我们需要让 OpenCV 自己来处理旋转这个事情,就不能将 128 这一位给置上。然而 IMREAD_UNCHANGED 是 255,自然就不能用啦。最多可以写 127。

如果你喜欢用 PIL/Pillow……

不幸的是,你需要自己将 EXIF 信息找出来,判断旋转方向,并自己进行旋转——不过也不难。

首先我们需要将旋转信息找出来。往上很多方法是再引入一下 PIL 的 EXIF 包,我觉得比较麻烦——明明读出来的图片里面就可以直接取到 EXIF 信息的,为啥非要从头来过。

大致代码如下:

image = Image.open("some_image.png")
# Read orientation info and correct the width and height.
# 274 is Orientation. You can find the index in ExifTags.TAGS
orientation_code = image.getexif().get(274)
if 8 == orientation_code:
    image = image.rotate(90, expand=True)
elif 3 == orientation_code:
    image = image.rotate(180, expand=True)
elif 6 == orientation_code:
    image = image.rotate(-90, expand=True)

如果你只想得到长宽的话……

image = Image.open("some_image.png")
width, height = image.width, image.height
# Read orientation info and correct the width and height.
# 274 is Orientation. You can find the index in ExifTags.TAGS
if image.getexif().get(274) in [6, 8]:
    width, height = height, width

其中旋转代码如下

EXIF Orientation ValueRow #0 is:Column #0 is:
1TopLeft side
2*TopRight side
3BottomRight side
4*BottomLeft side
5*Left sideTop
6Right sideTop
7*Right sideBottom
8Left sideBottom
NOTE: Values with "*" are uncommon since they represent "flipped" orientations.

如果你喜欢使用 Scikit-image

对不起哈,这个暂时无解……它封装得比较多,我不能直接深入底层改读取函数。


嗯,大致就这样啦。祝各位食用愉快~

留下评论