【问题标题】:Imagemagick: Optimizing the speed for identification of truncated imagesImagemagick:优化截断图像的识别速度
【发布时间】:2019-05-12 17:20:25
【问题描述】:

我正在使用 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

有没有办法优化我的脚本以提高性能?还是有更快的方法来识别图像的问题?

【问题讨论】:

  • 尝试“magick identify -ping”,这应该会阻止您加载整个图像。在这种情况下它可能对你有用
  • Ping 不会发现截断的图像,不幸的是,它只是加载标题,

标签: c# imagemagick


【解决方案1】:

你可以试试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

这是一张损坏的图片,1000 张正常的图片,全部为 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

现在 1001 张图片只需 11 秒。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-26
    • 1970-01-01
    • 2012-07-10
    • 2012-05-11
    • 1970-01-01
    • 2017-05-18
    • 2017-12-20
    相关资源
    最近更新 更多