Imagemagick: оптимизация скорости идентификации усеченных изображений - PullRequest
1 голос
/ 07 мая 2019

Я использую imagemagick для определения преждевременного окончания усеченных изображений в папке. Сценарий, который я написал, успешно идентифицирует изображения, однако, он очень медленный. Скорее всего, это связано с загрузкой всего изображения в память, но, учитывая время, которое потребовалось мне, чтобы скопировать мои файлы на диск, это должно добавить не более нескольких часов к операции. Я анализирую более 700 000 изображений, и на текущей скорости операция займет более месяца, не говоря уже о чрезвычайно высокой загрузке ЦП.

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());
}

Вот пример проблемы, которую я пытаюсь определить на изображениях.

Есть ли способ оптимизировать мой сценарий для повышения производительности? или есть более быстрый способ выявить проблему с изображениями?

1 Ответ

3 голосов
/ 08 мая 2019

Вы можете попробовать 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 изображений OK, все 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 1001 изображений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...