我想使用 imageMagick 转换函数调整一堆图像(大约 100 万张)的大小。我使用的是Ubuntu 16.04
这比我想象的要长(运行了大约 5 个小时 - 我可以再给它 5 个小时,但后来我想停止它)
我的问题是:如果我停止该程序,我是否需要担心图像损坏?或者该程序会以安全的方式停止吗?
这是我的脚本:
find . -name "*.JPEG" | xargs -I {} convert {} -resize "256^>" {}
(基本上我正在调整 imagenet 数据集的大小)
按 Ctrl-C 会损坏某些图像吗?
答案1
从理论上讲,不,它不应该导致图像损坏。根据记忆,我认为imagemagick
可以使用临时文件,处理完成后,临时文件将被重命名为所选的目标文件。
顺便说一句,按照您所做的方式转换图像是一种单向操作,我想您已经注意到了这一点,因此我想您的问题。
要查找最后转换的图像,请按时间顺序列出文件,较新的文件在前。如果文件大小存在明显差异,您将轻松知道下次从哪里开始。否则你将不得不使用检索图像尺寸imagemagick 的标识。
另请注意,对于一百万张图像,如果每张图像在一秒钟内处理,仍然需要大约280小时去完成!我希望你有一台快速、强大的机器......
编辑:如果你想展示一些进展,这是我能想到的,基于马丁的回答:
mkdir -p thumbs; \
COUNT=$(find -name "*.JPEG" | wc -l); \
find -name "*.JPEG" | while read IMG; do \
printf "\n$(( ++i )) / $COUNT\n" && \
[ -s "thumbs/${IMG%.JPEG}-small.jpg" ] || \
convert "$IMG" -resize "256^>" "thumbs/${IMG%.JPEG}-small.jpg"; \
done
这是做什么的:
- 创建缩略图目录...
- 计算图像总数
.JPEG
... - 对于每个图像...
- 打印当前图像文件索引与总索引...
- 如果图像尚未转换...
- 制作它的缩略图。
假设所有要调整大小的图像都在同一目录中,我使用一个子目录来保存缩略图,以避免主目录与相应的缩略图混乱。否则,您可以删除第一行以及thumbs/
第五行和第六行中的子目录。
如果图像分散到子目录中:
COUNT=$(find -name "*.JPEG" | wc -l); \
find -name "*.JPEG" | while read IMG; do \
printf "\n$(( ++i )) / $COUNT\n" && \
[ -s "${IMG%.JPEG}-small.jpg" ] || \
convert "$IMG" -resize "256^>" "${IMG%.JPEG}-small.jpg"; \
done
请注意,此脚本会考虑文件名中的空格,因为读取会在换行符处停止。
答案2
以这种方式组合find
和并不是一个好主意。xargs
带有空格和其他在命令行上具有特殊含义的字符的文件名可能会造成混乱。最好使用
find . -name '.JPEG' -print -exec convert '{}' -resize "256^>" '{}-small.jpg' \;
在你的命令中,你似乎覆盖了图像,这是正确的吗?问题是这convert
并不一定是原子操作。如果你这样做会好得多:
shopt -s extglob
for i in **/*.jpg; do
convert "$i" -resize "256^>" tmp.jpg
mv tmp.jpg "$i"
done
该mv
命令很可能是原子的。如果你在任何地方中断这个过程,唯一的损害可能是在某个地方的流浪tmp.jpg
。
如果你CtrlC现在按下,你可能会取消convert
命令。如果捕获到中断信号,它可能会完成图像的写入,但也可能会停止写入。
您也许可以将整个目录结构移动到其他地方,如果幸运的话,写入将完成,但任何新的convert
调用都将失败。
你为什么不试着检查一下这个过程进展到了什么程度呢?find
不提供有序输出,因此您必须扫描目录中图像的大小并检查有多少图像已经调整大小。
答案3
据我了解(如果有任何错误,我确信会有足够多的人参与纠正我) Ctrl+C 发送SIGINT
到 bash 以及任何正在运行的脚本和子进程/线程。
Bash 在下一个重新获得控制权的点处中断脚本(例如循环的下一次迭代,或者通过管道进行调用时),其他进程会收到信号通知并根据自己的策略退出,如果他们有一个。
是否存在任何真正的数据丢失风险取决于如何优雅地convert
捕获和处理SIGINT
.一段写得好的代码(并且convert
已经存在了一段时间)可以优雅地处理这个问题并在没有损坏的情况下退出。
ps -eT | grep -i convert
应该显示有多少线程正在运行以及有多少图像处于“风险”状态,尽管考虑到写入周期比每个图像的处理时间要短得多,但即使只是convert
简单地损坏超过一两个图像,您也会很不幸。当信号到达时,所有东西都掉了。