原标题:
来源:AI 研习社 链接:https://www.yanxishe.com/TextTranslation/2187
我已经写了很多关于计算机视觉和机器学习相关的项目,比如物体识别系统和人脸识别项目。同时,我有一个开源的人脸识别库,目前是github上前10最受欢迎的库。综上,这意味着我经常被新学习python和计算机视觉的人问一系列的问题。
在我个人的经验中,有一个技术问题与比任何其他问题都烦人。不,这并不是一个复杂的理论问题,或者是一个与昂贵GPU有关的问题。事实上,几乎所有人都在不经意间把他们的图片以横向加载到内存中。同时,电脑在横向的图片中探测物体和识别人脸时候表现并不出色。
数码相机是如何自动旋转图像的?
当你拍摄一张照片后,相机会感知到你朝哪一端倾斜。这就是为什么当你用另外一个程序看图片的时候,它会展现出正确的方向。
但是,复杂的部分在于,相机实际上并不是在保存到磁盘中的文件里旋转图像数据。因为数码相机内部的图像传感器是以连续流逐行读取像素中的信息,所以无论相机怎么放置,在相机中把像素数据用同样的顺序存放会更容易一点。
实际上,在展示图片之前进行正确的旋转是取决于图像显示应用。除了图像数据,你的相机也保存了关于每张图片——焦距设置,地点数据,当然也包括相机的旋转角度的元数据。图像显示应用应该用这些信息来正确地显示图片。
下面这个是用exiftool展示的我们谷歌jpeg图像中的exif元数据:
注意‘方向’这个数据元素。这个告诉了显示程序,图片应该在显示到屏幕上之前顺时针旋转90度。 如果程序忘记做这个工作了,图片就会是横向的!
为什么exif破坏了如此多的Python计算机视觉应用?
exif 元数据并不是Jepg文件格式中本来的一部分。它是事后人们从TIFF文件格式中获取,然后附加到了Jpeg文件格式中。这个对旧的图像显示器保持了后向兼容性,但同时也意味着有些程序从没有费心去处理Exif数据。
大部分用于图像数据处理的Python库,比如numpy,scipy,TensorFLow,Keras等等,认为它们是给专业人士处理一般数组数据的科学工具。它们不考虑消费者级别的问题,比如自动图像旋转,即便几乎世界上所有现代相机捕获的图像都需要该功能。
这意味着,当你用几乎任何Python库加载图片,你得到的就是原始的,未旋转的图像数据。猜测一下当你试图给一个横向或者倒立的图像给人脸识别器或者物体识别的模型会发生什么?检测器会失败因为你给了一个不好的数据。
你可能觉得这个问题仅限于初学者和学生写的Python脚本,但事实上不是这样!即便是谷歌的flagship Vision API例子也没有正确的处理Exif的方向:
谷歌的视觉API例子没能成功旋转一个用标准手机拍摄的横向图片
尽管谷歌的视觉成功在横向图像中检测到了一些动物,它把他们检测为了一个非具体的‘动物’标签。这是因为让模型检测横向的鹅比直立的鹅要困难的多。下面是当一个图像在送入模型前正确旋转情况下,谷歌视觉检测的表现:
有了正确的图像方向,谷歌检测到的鸟有了更具体的标签‘鹅’,并且有更高的置信结果。结果远远好了!
这是一个非常明显的问题,如果你能够像这个示例中一样看到图像是横向的。但是这就是有时候问题会潜伏,因为通常你看不见!你电脑上大部分正常的程序会以正确的旋转方向来展示图像,而不是图像实际在硬盘中横向存储的样子。所以,当你想要看一下图像来查看为什么你的模型没有奏效,图像会正确的展示出来,所以你不会知道为什么你的模型不奏效!
Mac上的Finder通常显示图片应用了Exif旋转。我们完全没有办法看到图像数据实际上是在文件中横向存储的。
这个不可避免的问题使得人们在Github上发布问题来抱怨那些他们使用的开源程序是坏的或者模型并不是十分准确。但问题其实非常简单,它们给进的时候是横向的或者是倒向的图片。
解决问题
解决方法是当你需要在你的Python 程序中加载图片时,你应该检查它们的Exif 方向元数据并且在需要的时候旋转图片。这个做起来很简单,但是网上很难找到正确旋转所有方向的代码例子。
这里是以正确旋转方式将任何图片加载到一个numpy数组中的代码:
从这里,你可以把图像数据数组给到任何标准的Python 机器学习库,那些以图像数据数组作为输入的库,比如Keras或者TensorFlow。
既然这个经常用到,我把这个功能发布为一个pip 库,叫做image_to_numpy。你可以用这样的方式安装:
pip3 install image_to_numpy
你可以用它在任何Python程序中正确的加载图像,比如这样:
import matplotlib.pyplot as pltimport image_to_numpy# Load your image fileimg = image_to_numpy.load_image_file("my_file.jpg")# Show it on the screen (or whatever you want to do)plt.imshow(img)
plt.show()
检查下面链接里面的readme来获取更多细节:
https://github.com/ageitgey/image_to_numpy#image_to_numpy
玩的开心!
一THE END一
免责声明:本文来自互联网新闻客户端自媒体,不代表本网的观点和立场。
合作及投稿邮箱:E-mail:editor@tusaishared.com