专栏首页磐创AI技术团队的专栏计算机视觉模型效果不佳,你可能是被相机的Exif信息坑了

计算机视觉模型效果不佳,你可能是被相机的Exif信息坑了

为何别人用得好好的人脸识别、目标检测开源模型,到了初学者手中,效果却惨不忍睹?其中原因可能很多,有时候这个原因很“愚蠢”。

最近一位Medium上的博主Adam Geitgey给初学者指出了一个极其简单而又容易忽视的关键点:相机的Exif信息。

在开发和使用计算机视觉(CV)模型的过程中,由于NumPy、TensorFlow和电脑上的图片查看器在处理Exif上存在着差异,让这个问题变得十分隐秘。

Adam是一位知名的机器学习课程博主,他的博客内容非常实用,几乎篇篇都能收获上千赞,足见其受欢迎的程度。

他在最新的文章中指出了CV模型在处理Exif存在的缺失,以及补救方法,下面是他文章的主要内容。

Exif信息害死人

普通智能手机或者相机拍照时,如果手持方向发生变化,内部的重力感应器件会告诉设备,照片究竟哪个边是向上的。

当我们在手机、相机或者电脑的Photoshop软件上查看照片时,完全没有问题,就像这样:

然而眼见并非为实,实际图像的像素数据不会旋转。这是由于图像传感器是对连续的像素信息流进行逐行读取,因此你无论纵向和横向握持相机,图像都是按照一个方向进行存储。

那么拍照设备和电脑为什么就能按照正确的方向显示图片呢?这是因为照片里还保存着一组元数据,称之为Exif,即可交换图像文件格式(Exchangeable image file format)。

Exif中包含着照片的像素数、焦距、光圈等信息,其中还有一个方向(Orientation)的数据。

上图中Orientation一项的参数是Rotate 90 CW,意思是图像在显示前需要顺时针旋转90度。如果图片查看程序没有执行此操作,你就只能拧着脖子看了。

Exif原先是用在TIFF图像格式上,后来才加入到JPEG图像格式中,而图像数据集中的图片大多是JPEG格式。

一些程序为了保持向后兼容性,不会去解析Exif数据。大多数用于处理图像数据的Python库(如NumPy、SciPy,TensorFlow,Keras等)就是这样的。

这意味着当你使用这些工具导入图像时,都将获得原始的未旋转图像数据。如果把这些侧躺着或上下颠倒的图像输入到CV模型中,会得到错误的检测结果。

这个问题看起来很愚蠢,似乎初学者会犯这样的低级错误。但事实并非如此!甚至连Google云上的视觉API Demo也无法正确处理Exif方向问题:

如果我们把图像旋转到正确的方向再上传,检测的结果与上图相比将完全改变:

当我们在电脑上查看图片时完全没问题,但是一用到模型中就不正常。因此很难发现问题的所在。

这也导致一些开发者在Github上提问,抱怨他们正在使用的开源项目已损坏,或是模型不够准确。但是实际上问题要简单得多,只是图片的方向错了!

解决方法

解决以上问题的方法就是,在导入图像时检查它们的Exif数据,在必要时旋转图像。Adam已经写好了一段代码:

import PIL.Image
import PIL.ImageOps
import numpy as np


def exif_transpose(img):
    if not img:
        return img

    exif_orientation_tag = 274

    # Check for EXIF data (only present on some files)
    if hasattr(img, "_getexif") and isinstance(img._getexif(), dict) and exif_orientation_tag in img._getexif():
        exif_data = img._getexif()
        orientation = exif_data[exif_orientation_tag]

        # Handle EXIF Orientation
        if orientation == 1:
            # Normal image - nothing to do!
            pass
        elif orientation == 2:
            # Mirrored left to right
            img = img.transpose(PIL.Image.FLIP_LEFT_RIGHT)
        elif orientation == 3:
            # Rotated 180 degrees
            img = img.rotate(180)
        elif orientation == 4:
            # Mirrored top to bottom
            img = img.rotate(180).transpose(PIL.Image.FLIP_LEFT_RIGHT)
        elif orientation == 5:
            # Mirrored along top-left diagonal
            img = img.rotate(-90, expand=True).transpose(PIL.Image.FLIP_LEFT_RIGHT)
        elif orientation == 6:
            # Rotated 90 degrees
            img = img.rotate(-90, expand=True)
        elif orientation == 7:
            # Mirrored along top-right diagonal
            img = img.rotate(90, expand=True).transpose(PIL.Image.FLIP_LEFT_RIGHT)
        elif orientation == 8:
            # Rotated 270 degrees
            img = img.rotate(90, expand=True)

    return img


def load_image_file(file, mode='RGB'):
    # Load the image with PIL
    img = PIL.Image.open(file)

    if hasattr(PIL.ImageOps, 'exif_transpose'):
        # Very recent versions of PIL can do exit transpose internally
        img = PIL.ImageOps.exif_transpose(img)
    else:
        # Otherwise, do the exif transpose ourselves
        img = exif_transpose(img)

    img = img.convert(mode)

    return np.array(img)

加入以上代码后,就可以正确地将图像导入Keras或TensorFlow了。

如果觉得麻烦,Adam还把上面的代码打包好了,在GitHub上这个项目叫做image_to_numpy。一行代码就可以完成安装:

pip3 install image_to_numpy

以后,你在自己的Python代码中加入这样几句即可。

import matplotlib.pyplot as plt
import image_to_numpy
# Load your image file
img = 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()

传送门

原文链接: https://medium.com/@ageitgey/the-dumb-reason-your-fancy-computer-vision-app-isnt-working-exif-orientation-73166c7d39da

快速导入旋转图像的image_to_numpy: https://github.com/ageitgey/image_to_numpy

作者系网易新闻·网易号“各有态度”签约作者

本文分享自微信公众号 - 磐创AI(xunixs)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-10-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 深度学习算法(第25期)----机器翻译中的编码解码器网络

    深度学习算法(第24期)----自然语言处理(NLP)中的Word Embedding 前几期我们一起学习了RNN的很多相关知识,今天我们一起用这些知识,学习下...

    智能算法
  • 智能八段锦 app 中的身体动作识别

    OliveX是一家总部位于香港的公司,致力于健身相关软件的开发,自2018年首次推出以来,已为200万用户提供服务。我们的许多用户都是老年人,智能八段锦应用程序...

    云水木石
  • windows安装tensorflow

    下载可以去官网上下载,直接搜索找与你电脑对应的版本就好,国内清华镜像网站是:https://mirrors.tuna.tsinghua.edu.cn/anaco...

    开发架构二三事
  • 吐血整理!绝不能错过的24个顶级Python库

    事实上,由于Python库种类很多,要跟上其发展速度非常困难。因此,本文介绍了24种涵盖端到端数据科学生命周期的Python库。

    AI算法与图像处理
  • 具有Keras和Tensorflow Eager的功能性RL

    在此博客文章中,探索了用于实现强化学习(RL)算法的功能范例。范例是开发人员将其算法的数值写为独立的纯函数,然后使用库将其编译为可以大规模训练的策略。分享了如何...

    代码医生工作室
  • 《TensorFlow学习指南:深度学习系统构建详解》英文PDF+源代码+部分中文PDF

    TensorFlow学习指南:深度学习系统构建详解英文完整版PDF,242页,带目录书签,彩色配图,文字可以复制粘贴;

    用户6345190
  • 深度学习哪家强?用数据来一较高下吧

    本人现在还是一个初识深度学习的小白。初学者总是会面临选择的纠结,尤其是对看似高深的深度学习,有着众多开源框架可供选择,但自己又没有能力评估。于是我看了许多比较文...

    数据森麟
  • 基于深度神经网络的股票预测,正确率80%!

    股票市场具有高收益与高风险并存的特性,预测股票市场走势一直被普通股民和投资机构所关注。股票市场是一个复杂的动态系统,受多方面因素的影响,例如国家金额正常的调整、...

    沉默的白面书生
  • 教程 | 基于LSTM实现手写数字识别

    基于tensorflow,如何实现一个简单的循环神经网络,完成手写数字识别,附完整演示代码。

    OpenCV学堂
  • 在几分钟内构建强大的可用于生产的深度学习视觉模型

    得益于更快的计算,更好的存储和易于使用的软件,基于深度学习的解决方案绝对可以看到从概念验证隧道进入现实世界的曙光!看到深度学习模型已广泛应用于该行业的各个领域,...

    代码医生工作室

扫码关注云+社区

领取腾讯云代金券