回顾本系列
第 1 部分:使用 Python 为数字艺术家自动化重复性任务
如果您在计算机上处理图像,您迟早会遇到损坏的文件,破坏您的一天。我在动画渲染中遇到这种情况(记住,这里的最佳实践是渲染成图像文件序列,而不是单个视频文件)。然而,动画和视觉效果并不是唯一会看到图像损坏的地方。在其他领域,您也可能很容易遇到这种情况。也许您是一位摄影师,您拍摄了一堆包围曝光 HDRI(高动态范围成像)色调映射,并且在从相机传输文件时出现了一些故障。
问题不在于修复或替换损坏图像所需的工作量,这通常只是重新渲染图像或将好的图像重新复制到您的计算机的问题,而技巧是在流程中尽早找到那些坏图像。您不知道的时间越长,当您确实遇到损坏的图像时,您将面临的麻烦就越大。
那么,您该怎么办?好吧,您可以可以逐个打开每个文件——在您的图像编辑器或查看器中,让该程序告诉您有问题。然而,照片图像很大,并且浏览整个集合以找到一两个坏家伙可能很烦人和耗时。虽然动画渲染通常是较小的文件,但您通常有更多的文件要浏览。就我而言,我经常制作渲染,渲染中包含超过 44,000 帧。(不,这不是拼写错误——四万四千帧。)
解决方案?您猜对了。编写一个脚本。
与本系列之前的文章一样,您将使用 Python 进行脚本编写。第一步:获取文件列表。幸运的是,如果您已经阅读过本系列中的上一篇文章,您就会知道这只是使用 os 模块的问题。假设您要检查的所有图像文件都位于硬盘上的单个目录中。此外,假设您将从该目录中运行此脚本。使用 Python,您可以使用以下代码获取这些文件的列表
import os
for filename in os.listdir('./'):
print(filename)
如果您愿意,您可以缩小图像列表的范围(或至少更清楚地指定它;例如,您不希望将此脚本包含为其中一个文件),只需查找以 PNG 扩展名结尾的文件
import os
for filename in os.listdir('./'):
if filename.endswith('.png'):
print(filename)
您现在在当前工作目录中有一个 PNG 图像文件列表。现在怎么办?好吧,现在您需要弄清楚这些图像中的哪些(如果有)已损坏。在本系列之前的文章中,我们专门使用了 Python 默认附带的模块。不幸的是,在没有任何图像处理能力的情况下发现图像是否损坏是很困难的,Python 2 和 Python 3 都没有任何开箱即用的方法来处理这个问题。您需要获取一个图像处理模块来查看这些文件。令人高兴的是,Python 开发社区让您更容易做到这一点。
事实上,您可以使用整个软件包库来安装。您只需要知道如何获取它们。让我向您介绍 pip,这是安装 Python 软件包的推荐工具。当您安装 Python 时,它默认安装在大多数平台上。
注意: 我正在使用 Python 3,但如果您正在使用 Python 2,那么我在本系列中编写的几乎所有内容都可以在这两种语言变体之间传输。此外,许多 Linux 发行版更希望您使用自己的软件包管理系统而不是使用 pip 来安装 Python 软件包。如果您愿意,可以坚持使用它。这里建议使用 pip 主要是为了在您可以使用 Python 的所有平台上保持一致性。
我将要推荐您安装的特定软件包称为 Pillow。它是原始 PIL(Python 图像库)的“友好分支”,适用于当前版本的 Python 3 和 Python 2。您只需要启动终端窗口并键入 pip install Pillow 即可安装 Pillow。Python 包工具应该从那里为您处理剩下的事情。
一旦您安装了 Pillow,您实际上需要在您的脚本中使用它的方法。因为它已安装,您可以像对待任何 Python 附带的模块一样对待它。您使用 import
——在这种情况下,您可以使用 import PIL
。但是,要查找损坏的图像,您实际上不需要将整个 Pillow 库导入到我们的脚本中。在 Python 中,您可以仅导入模块的单个子组件。这是一个好的做法,因为它减少了脚本的内存占用,而且同样重要的是,它更清楚地说明了您的脚本从一开始就要做什么。此外,当您导入子组件时,当您进入脚本的核心时,您最终需要键入更少的内容。这总是一个不错的奖励。
要导入模块的子组件,您可以在 import
前面加上 from
指令。对于 Pillow,您的脚本实际上只需要使用 Image 类。因此,您的导入行将如下所示:from PIL import Image
。事实上,您可以使用 os 模块做同样的事情。如果您回顾之前的代码,您可能会注意到您只使用了 os 模块中的 listdir 函数。因此,您可以不使用 import os
,而是使用 from os import listdir
。这意味着当您进入脚本时,您不再需要键入 os.listdir
。相反,您只需要键入 listdir
,因为这就是您导入的全部内容。
将所有这些放在一起,您的脚本现在应该如下所示
from os import listdir
from PIL import Image
for filename in listdir('./'):
if filename.endswith('.png'):
print(filename)
您已加载 Pillow 中的 Image 类,但您的脚本仍然没有对它做任何事情。现在是时候进入脚本的功能部分了。您将要做的是打开每个图像文件并检查它是否可读的脚本等效操作。如果出现错误,那么您就找到了一个坏文件。为此,您将使用 try/except 块。简而言之,您的脚本将尝试运行一个打开文件的函数。如果该函数返回错误,也称为异常,那么您就知道该图像有问题。特别是,如果异常类型为 IOError 或 SyntaxError,那么您就知道您遇到了坏图像。
执行 try/except 的语法非常简单。我在下面的代码注释中描述了它
try: # These next functions may produce an exception
# <some function>
except (IOError, SyntaxError) as e: # These are the exceptions we're looking for
# <do something... like print an intelligent error message>
在查找损坏的图像文件的情况下,您需要测试两个函数:Image.open()
和 verify()
。如果您将它们包装在 try/except 块中,您的损坏图像查找脚本应如下所示
from os import listdir
from PIL import Image
for filename in listdir('./'):
if filename.endswith('.png'):
try:
img = Image.open('./'+filename) # open the image file
img.verify() # verify that it is, in fact an image
except (IOError, SyntaxError) as e:
print('Bad file:', filename) # print out the names of corrupt files
就这样。将此脚本保存在您的图像目录中。当您从命令行运行它时,您应该获得其中所有损坏图像文件的列表。如果没有任何内容打印出来,那么您可以假设所有这些图像文件都是好的、有效的文件。
当然,能够在任何任意目录中使用此脚本会很好。如果脚本提示您指示它继续为您删除这些损坏的文件,那就更好了。好消息!您可以使脚本完全做到这一点。我们将在本系列的下一篇文章中介绍这一点。
与此同时,祝您在图像文件夹中发现损坏时玩得愉快。
7 条评论