Imagemagick:优化截断图像的识别速度
Imagemagick: Optimizing the speed for identification of truncated images
我正在使用 imagemagick 来识别文件夹中截断图像的过早结束。我编写的脚本成功识别了图像,但是速度很慢。这可能是因为它必须将整个图像加载到内存中,但考虑到我将文件复制到磁盘所花费的时间,这应该不会增加操作的几个小时。我正在分析超过 700,000 张图像,以目前的速度,该操作将需要一个多月才能完成,更不用说极高的 CPU 使用率了。
foreach (string f in files)
{
Tuple<int, string> result = ImageCorrupt(f);
int exitCode = result.Item1;
if (exitCode != 0)...
}
public static Tuple<int, string> ImageCorrupt(string pathToImage)
{
var cmd = "magick identify -regard-warnings -verbose \"" + pathToImage + "\"";
var startInfo = new ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Hidden,
FileName = "cmd.exe",
Arguments = "/C " + cmd,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true
};
var process = new Process
{
StartInfo = startInfo
};
process.Start();
string output = process.StandardOutput.ReadToEnd();
if (!process.WaitForExit(30000))
{
process.Kill();
}
return Tuple.Create(process.ExitCode, process.StandardError.ReadToEnd());
}
这是我试图在图像中识别的问题的 example。
有没有办法优化我的脚本以提高性能?或者有没有更快的方法来识别图像问题?
你可以试试 net-vips。它不会发现像 imagemagick 那样多的图像格式,但它会做基本的 TIF/JPG/PNG/GIF 等等,而且速度要快得多。
我会通过计算平均像素值来测试图像。这样你就可以保证读取每个像素,而且操作成本低。
我实际上并没有在这里安装 C#,但是在 pyvips 中(Python 绑定到与 net-vips 相同的库),它将是:
import sys
import pyvips
for filename in sys.argv[1:]:
try:
# the fail option makes pyvips throw an exception on a file
# format error
# sequential access means libvips will stream the image rather than
# loading it into memory
image = pyvips.Image.new_from_file(filename,
fail=True, access="sequential")
avg = image.avg()
except pyvips.Error as e:
print("{}: {}".format(filename, e))
我可以运行这样:
$ for i in {1..1000}; do cp ~/pics/k2.jpg $i.jpg; done
$ cp ~/pics/k2_broken.jpg .
$ vipsheader 1.jpg
1.jpg: 1450x2048 uchar, 3 bands, srgb, jpegload
这是一张损坏的图像,1,000 张正常图像,全部为 1450x2048。那么:
$ time ../sanity.py *.jpg
k2_broken.jpg: unable to call avg
VipsJpeg: Premature end of JPEG file
VipsJpeg: out of order read at line 48
real 0m23.424s
所以在这台普通的笔记本电脑上,它在 23 秒内发现了损坏的图像。
你的识别循环(尽管只测试了 100 张图像)将是:
$ time for i in {1..100}; do if ! identify -regard-warnings -verbose $i.jpg > /dev/null; then echo $i: error; fi; done
real 0m21.454s
时间长度大致相同,因此 net-vips 在此测试中快了大约 10 倍。
因为 net-vips 相对节省内存,您也可以 运行 一次使用很多,具体取决于您有多少个内核。这应该提供几乎线性的加速。
我在这台两核四线程的笔记本电脑上看到:
$ time parallel --jobs 10 -m ../sanity.py ::: *.jpg
k2_broken.jpg: unable to call avg
VipsJpeg: Premature end of JPEG file
VipsJpeg: out of order read at line 48
real 0m10.828s
现在 1,001 张图像减少到 11 秒。
我正在使用 imagemagick 来识别文件夹中截断图像的过早结束。我编写的脚本成功识别了图像,但是速度很慢。这可能是因为它必须将整个图像加载到内存中,但考虑到我将文件复制到磁盘所花费的时间,这应该不会增加操作的几个小时。我正在分析超过 700,000 张图像,以目前的速度,该操作将需要一个多月才能完成,更不用说极高的 CPU 使用率了。
foreach (string f in files)
{
Tuple<int, string> result = ImageCorrupt(f);
int exitCode = result.Item1;
if (exitCode != 0)...
}
public static Tuple<int, string> ImageCorrupt(string pathToImage)
{
var cmd = "magick identify -regard-warnings -verbose \"" + pathToImage + "\"";
var startInfo = new ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Hidden,
FileName = "cmd.exe",
Arguments = "/C " + cmd,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true
};
var process = new Process
{
StartInfo = startInfo
};
process.Start();
string output = process.StandardOutput.ReadToEnd();
if (!process.WaitForExit(30000))
{
process.Kill();
}
return Tuple.Create(process.ExitCode, process.StandardError.ReadToEnd());
}
这是我试图在图像中识别的问题的 example。
有没有办法优化我的脚本以提高性能?或者有没有更快的方法来识别图像问题?
你可以试试 net-vips。它不会发现像 imagemagick 那样多的图像格式,但它会做基本的 TIF/JPG/PNG/GIF 等等,而且速度要快得多。
我会通过计算平均像素值来测试图像。这样你就可以保证读取每个像素,而且操作成本低。
我实际上并没有在这里安装 C#,但是在 pyvips 中(Python 绑定到与 net-vips 相同的库),它将是:
import sys
import pyvips
for filename in sys.argv[1:]:
try:
# the fail option makes pyvips throw an exception on a file
# format error
# sequential access means libvips will stream the image rather than
# loading it into memory
image = pyvips.Image.new_from_file(filename,
fail=True, access="sequential")
avg = image.avg()
except pyvips.Error as e:
print("{}: {}".format(filename, e))
我可以运行这样:
$ for i in {1..1000}; do cp ~/pics/k2.jpg $i.jpg; done
$ cp ~/pics/k2_broken.jpg .
$ vipsheader 1.jpg
1.jpg: 1450x2048 uchar, 3 bands, srgb, jpegload
这是一张损坏的图像,1,000 张正常图像,全部为 1450x2048。那么:
$ time ../sanity.py *.jpg
k2_broken.jpg: unable to call avg
VipsJpeg: Premature end of JPEG file
VipsJpeg: out of order read at line 48
real 0m23.424s
所以在这台普通的笔记本电脑上,它在 23 秒内发现了损坏的图像。
你的识别循环(尽管只测试了 100 张图像)将是:
$ time for i in {1..100}; do if ! identify -regard-warnings -verbose $i.jpg > /dev/null; then echo $i: error; fi; done
real 0m21.454s
时间长度大致相同,因此 net-vips 在此测试中快了大约 10 倍。
因为 net-vips 相对节省内存,您也可以 运行 一次使用很多,具体取决于您有多少个内核。这应该提供几乎线性的加速。
我在这台两核四线程的笔记本电脑上看到:
$ time parallel --jobs 10 -m ../sanity.py ::: *.jpg
k2_broken.jpg: unable to call avg
VipsJpeg: Premature end of JPEG file
VipsJpeg: out of order read at line 48
real 0m10.828s
现在 1,001 张图像减少到 11 秒。