EXIF信息真好,EXIF信息真烦
工作中经常碰到带有旋转信息的图片,读出来之后整个图片被旋转了,标注信息和图片对不上。之前旋转图片一直是个老大难的问题,后来下定决心给解决掉了。
首先,「正确」的图片是什么样子的?
有几个判断方法:
- Mac:在Finder里面直接看图片,看到的样子
- Windows:在资源管理器里面直接看图片,看到的样子
- 将图片直接拖进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 = PIL.ImageOps.exif_transpose(image)
如果你只想得到长宽的话……
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 Value | Row #0 is: | Column #0 is: |
---|---|---|
1 | Top | Left side |
2* | Top | Right side |
3 | Bottom | Right side |
4* | Bottom | Left side |
5* | Left side | Top |
6 | Right side | Top |
7* | Right side | Bottom |
8 | Left side | Bottom |
如果你喜欢使用Scikit-image
对不起哈,这个暂时无解……它封装得比较多,我不能直接深入底层改读取函数。
嗯,大致就这样啦。祝各位食用愉快~
发表回复