【问题标题】:How to check if a file is a valid image file?如何检查文件是否是有效的图像文件?
【发布时间】:2010-10-27 17:20:06
【问题描述】:

我目前正在使用 PIL。

from PIL import Image
try:
    im=Image.open(filename)
    # do stuff
except IOError:
    # filename not an image file

但是,虽然这足以涵盖大多数情况,但某些图像文件(如 xcf、svg 和 psd)并未被检测到。 Psd 文件会引发 OverflowError 异常。

有没有什么方法可以包含它们?

【问题讨论】:

  • 嗯,我不知道 psd 的内部情况,但我当然知道,事实上,svg 本身并不是一个图像文件,它是基于 xml ,所以它本质上是一个纯文本文件。
  • 关闭跨不同语言的重复项并不是特别常见的做法。如果您找不到任何其他 Python 问题,请将其打开,因为可能存在人们想要发布的特定于 Python 的解决方案,但这些解决方案并未包含在您发布的问题中。
  • 是的,首先我真的希望有一个我不知道的python库:P然后正如本指出的那样,只是神奇的数字并不能验证整个图像。
  • @Sujoy,验证整个图像几乎是不可能的,除非您已经拥有它的副本,因为计算机无法区分正确的颜色像素和乱码的 1 和0s,只要所有的控制(幻数)都是正确的。
  • @devinb,同意,我会得到神奇的数字并完成它,除非其他人想出更好的东西来要求重构:)

标签: python image identification imghdr


【解决方案1】:

很多时候,前几个字符对于各种文件格式都是一个神奇的数字。除了上面的异常检查之外,您还可以检查这一点。

【讨论】:

  • 如果他真的在测试“有效”图像,那是不够的;例如,幻数的存在并不能保证文件没有被截断。
  • 很好的建议,现在我只需要弄清楚这些数字是多少。谢谢:)
  • @ben,哎呀我还没想到。这确实是一个好点
  • @Ben,您希望库如何推断文件已被截断?
  • @Ben Blank:没错,但解决问题的 99% 通常比根本不解决要好。
【解决方案2】:

在 Linux 上,您可以使用 python-magic,它使用 libmagic 来识别文件格式。

据我所知,libmagic 会查看文件并试图告诉你更多关于它的信息,而不仅仅是格式,比如位图尺寸、格式版本等。所以你可能会认为这是对“有效性”的肤浅测试。

对于“有效”的其他定义,您可能需要编写自己的测试。

【讨论】:

    【解决方案3】:

    除了 Brian 建议的内容之外,您还可以使用 PIL 的 verify 方法来检查文件是否损坏。

    im.verify()

    尝试确定文件是否为 坏了,没有实际解码 图像数据。如果此方法发现任何 问题,它提出了合适的 例外。此方法仅适用于 新打开的图像;如果图像有 已经加载,结果是 不明确的。此外,如果您需要加载 使用此方法后的图像,您 必须重新打开图像文件。属性

    【讨论】:

    • 主要问题是 svg、xcf 和 psd 文件无法使用 Image.open() 打开,因此无法使用 im.verify() 进行验证
    • 天哪,PIL 文档太糟糕了。究竟什么是“合适的例外”?
    • 这是Pillow documentation for Image.verify() 的链接。不幸的是,这也好不到哪里去,看起来他们只是取消了上面的段落,没有添加任何内容。
    • 我已经看到为损坏的 png 文件验证引发 SyntaxError
    • mmh 源代码似乎可以验证......什么都没有! pillow.readthedocs.io/en/latest/_modules/PIL/…
    【解决方案4】:

    您可以使用 Python 绑定到 libmagic,python-magic,然后检查 mime 类型。这不会告诉您文件是否损坏或完好无损,但它应该能够确定它是什么类型的图像。

    【讨论】:

      【解决方案5】:

      我刚刚找到了内置的imghdr 模块。来自python文档:

      imghdr 模块确定类型 包含在文件或字节中的图像 流。

      这就是它的工作原理:

      >>> import imghdr
      >>> imghdr.what('/tmp/bass')
      'gif'
      

      使用模块比重新实现类似功能要好得多

      【讨论】:

      • 是的,imghdr 适用于大多数图像格式,但不是全部。根据我对 svg、xcf 和 psd 文件的原始问题,在 imghdr 中也没有检测到这些文件
      • 您的回答实际上更好,谢谢。就像上面有人说的那样...但是解决99%的问题通常比根本不解决要好..
      • 值得注意的是:imghdr.what(path) 返回None 如果给定的path 是无法识别的图像文件类型。 List 当前识别的图像类型:rgbgifpbmpgmppm、tiffrastxbmjpegbmp、pngwebpexr.
      • 我发现偶尔imghdr.what(path)会返回None,即使文件是有效的图像,尤其是对于jpegs。
      • 小心!有效的 hdr 并不意味着有效的图像(例如,图像字节可能已被打乱!)
      【解决方案6】:

      更新

      我还在我的 Python 脚本 here on GitHub 中实现了以下解决方案。

      我还验证了损坏的文件 (jpg) 通常不是“损坏”的图像,即损坏的图片文件有时仍然是合法的图片文件,原始图像丢失或更改,但您仍然可以毫无错误地加载它.但是,文件截断总是会导致错误。

      结束更新

      您可以使用 Python Pillow(PIL) 模块和大多数图像格式来检查文件是否是有效且完整的图像文件。

      如果您还打算检测损坏的图像,@Nadia Alramli 会正确建议 im.verify() 方法,但这不会检测到所有可能的图像缺陷,例如,im.verify 不会检测截断的图像(大多数观看者加载时通常带有灰色区域)。

      Pillow 也能够检测到这些类型的缺陷,但您必须应用图像处理或图像解码/重新编码或触发检查。最后我建议使用这段代码:

      from PIL import Image
      
      try:
        im = Image.load(filename)
        im.verify() #I perform also verify, don't know if he sees other types o defects
        im.close() #reload is necessary in my case
        im = Image.load(filename) 
        im.transpose(Image.FLIP_LEFT_RIGHT)
        im.close()
      except: 
        #manage excetions here
      

      如果出现图像缺陷,此代码将引发异常。 请考虑 im.verify 比执行图像处理快大约 100 倍(我认为翻转是更便宜的转换之一)。 使用此代码,您将以大约 10 MBytes/sec 的标准 Pillow 或 40 MBytes/sec 的 Pillow-SIMD 模块(现代 2.5Ghz x86_64 CPU)验证一组图像。

      对于其他格式psd,xcf,..可以使用Imagemagick包装器Wand,代码如下: 检查 Wand 文档:here,安装:here

      im = wand.image.Image(filename=filename)
      temp = im.flip;
      im.close()
      

      但是,根据我的实验,Wand 没有检测到截断的图像,我认为它会在没有提示的情况下将缺少的部分加载为灰色区域。

      我认为 Imagemagick 有一个外部命令 identify 可以 完成这项工作,但我还没有找到调用该函数的方法以编程方式,我还没有测试过这条路线。

      我建议始终进行初步检查,检查文件大小不为零(或非常小),这是一个非常便宜的想法:

      import os
      
      statfile = os.stat(filename)
      filesize = statfile.st_size
      if filesize == 0:
        #manage here the 'faulty image' case
      

      【讨论】:

        【解决方案7】:

        除了PIL 图像检查,您还可以像这样添加文件扩展名检查:

        filename.lower().endswith(('.png', '.jpg', '.jpeg', '.tiff', '.bmp', '.gif'))
        

        请注意,这仅检查文件名是否具有有效的图像扩展名,它不会实际打开图像以查看它是否是有效图像,这就是为什么您需要另外使用 PIL 或建议的库之一其他答案。

        【讨论】:

        • 如果文件中的扩展名不正确怎么办?例如,文本文件以 .jpg 扩展名保存,反之亦然。
        • @hafiz031 要获得实际格式,您可以执行from PIL import Image img = Image.open(filename) print(img.format),然后像这样检查:img.format.lower() in ['png', 'jpg', 'jpeg', 'tiff', 'bmp', 'gif']
        • 不幸的是,这对我不起作用。它仍在将损坏的图像识别为 JPEG 图像。最后我设法以这种方式处理了这种情况(我正在使用 OpenCv):stackoverflow.com/a/63421847/6907424
        【解决方案8】:
        format = [".jpg",".png",".jpeg"]
         for (path,dirs,files) in os.walk(path):
             for file in files:
                 if file.endswith(tuple(format)):
                     print(path)
                     print ("Valid",file)
                 else:
                     print(path)
                     print("InValid",file)
        

        【讨论】:

        • 您的代码存在缩进问题,无法正常运行。此外,请考虑添加一些解释,说明您的代码为何以及如何解决问题。纯代码的答案对未来的读者没有太大帮助。
        • 这里我们使用了Agrparser方法。
        【解决方案9】:

        一种选择是使用filetype 包。

        安装

        python -m pip install filetype

        优势

        1. 快速:仅加载图像的前几个字节即可工作(检查幻数
        2. 支持不同的 mime 类型:图像、视频、字体、音频、档案。

        示例

        文件类型 >= 1.0.7

        import filetype
        
        filename = "/path/to/file.jpg"
        
        if filetype.is_image(filename):
            print(f"{filename} is a valid image...")
        elif filetype.is_video(filename):
            print(f"{filename} is a valid video...")
        

        文件类型

        import filetype
        
        filename = "/path/to/file.jpg"
        
        if filetype.image(filename):
            print(f"{filename} is a valid image...")
        elif filetype.video(filename):
            print(f"{filename} is a valid video...")
        

        官方repo补充信息:https://github.com/h2non/filetype.py

        【讨论】:

        • 文件类型程序也支持webp格式。不错!
        猜你喜欢
        • 2014-11-15
        • 2020-12-04
        • 2017-08-31
        • 2013-12-07
        • 1970-01-01
        • 1970-01-01
        • 2015-09-30
        相关资源
        最近更新 更多