2016-10-07 3 views
0

Я использую скрипт bash для обработки кучи изображений для видеоролика с временным разрешением. Метод называется затвором, и я создаю скользящее среднее для всех изображений. Следующий скрипт работает отлично:Как повысить производительность интенсивного сценария imagemagick для чтения и записи?

#! /bin/bash 
totnum=10000 
seqnum=40 
skip=1 
num=$(((totnum-seqnum)/1)) 
i=1 
j=1 
while [ $i -le $num ]; do 
    echo $i 
    i1=$i 
    i2=$((i+1)) 
    i3=$((i+2)) 
    i4=$((i+3)) 
    i5=$((i+4)) 
    ... 
    i37=$((i+36)) 
    i38=$((i+37)) 
    i39=$((i+38)) 
    i40=$((i+39)) 
    convert $i1.jpg $i2.jpg $i3.jpg $i4.jpg $i5.jpg ... \ 
      $i37.jpg $i38.jpg $i39.jpg $i40.jpg \ 
      -evaluate-sequence mean ~/timelapse/Images/Shutterdrag/$j.jpg 
    i=$((i+$skip)) 
    j=$((j+1)) 
done 

Однако я заметил, что этот сценарий занимает очень много времени, чтобы обработать много изображений с большим средним окном (1S на изображение). Наверное, это вызвано большим количеством чтения и записи в фоновом режиме.

Возможно ли увеличить скорость этого скрипта? Например, сохраняя изображения в памяти и каждую итерацию удаляя первый, и загружая только последнее изображение.

Я обнаружил функцию imagemagick mpr:{label}, но я думаю, что это неправильный подход, поскольку память очищается после команды convert?

+1

Как вы, кажется, читаете каждое изображение много раз, вам стоит подумать о создании RAMdisk (какую ОС вы используете?) И преобразовании всех ваших JPEG в файлы формата MPC в RAMdisk спереди, чтобы минимизировать нагрузку на декодирование - возможно, используйте GNU Parallel для этого тоже. –

+0

Ubuntu 15.10 - это ОС, которую я использую. Есть ли простой способ настроить и использовать RAMdisk? – Markus

+0

Вот пример http://www.hecticgeek.com/2015/12/create-ram-disk-ubuntu-linux/ –

ответ

3

Предложение 1 - RAMdisk

Если вы хотите поместить все свои файлы в RAMdisk перед запуском, это должно значительно увеличить скорость ввода-вывода.

Таким образом, чтобы сделать 1GB Ramdisk, использование:

sudo mkdir /RAMdisk 
sudo mount -t tmpfs -o size=1024m tmpfs /RAMdisk 

Предложение 2 - Использовать формат MPC

Итак, если вы сделали предыдущий шаг, конвертировать все ваши изображения в формате JPEG в формате MPC файлов в RAMdisk. Файл MPC может быть удален в память без вашего процессора, нуждающегося в дорогостоящем декодировании JPEG, поскольку MPC - это тот же формат, что и . ImageMagick использует в памяти, но на диске.

Я хотел бы сделать это с GNU Parallel так:

parallel -X mogrify -path /RAMdisk -fmt MPC ::: *.jpg 

-X проходит как много файлов, как можно mogrify без создания нагрузки convert процессов. В документе -path указано, куда должны идти выходные файлы. -fmt MPC делает mogrify конвертирует входные файлы в формат MPC (Magick Pixel Cache), которые ваши последующие команды convert в цикле могут считываться чистым DMA, а не дорогим декодированием JPEG.

Если у вас нет, или не нравится, GNU Parallel, просто опускаем ведущий parallel -X и :::.

Предложение 3 - Использование GNU Parallel

Можно также запустить @ код chepner в параллель ...

for ...; do 
    echo convert ... 
done | parallel 

По существу, я вторя все команды, вместо того, чтобы запускать их и список эховых команд затем выполняется GNU Parallel. Это может быть особенно полезно, если вы не можете скомпилировать ImageMagick с OpenMP, как предложил Эрик.

Вы можете поиграть с такими переключателями, как --eta, после parallel, чтобы узнать, сколько времени займет до конца, или --progress. Кроме того, экспериментируйте с -j 2 или -j4 в зависимости от того, как большой ваша машина.


Я сделал несколько тестов, просто для удовольствия. Во-первых, я сделал 250 изображений JPEG случайного шума на 640x480, и пробежал код чекнера «как есть» - это заняло 2 минуты 27 секунд.


Затем я использовал тот же набор изображений, но изменил петлю на это:

for ((i=1, j=1; i <= num; i+=skip, j+=1)); do 
    echo convert "${files[@]:i:seqnum}" -evaluate-sequence mean ~/timelapse/Images/Shutterdrag/$j.jpg 
done | parallel 

время спускался до 35 секунд.


Тогда я поставил петлю назад, как это было, и изменил все входные файлы в MPC вместо JPEG, время снизилось до 36 секунд.


Наконец, я использовал формат MPC и GNU параллельно, как выше, и время сократилось до 19 секунд.

Я не использовал RAMdisk, поскольку я нахожусь на другой ОС от вас (и у вас очень быстрые диски NVME), но это тоже должно помочь вам. Вы также можете записывать выходные файлы в RAMdisk, а также в формате MPC.

Удачи вам и дайте нам знать, как вы справляетесь!

+0

Эй, у меня наконец было время, чтобы изучить тему. Я использовал ваши предложения и улучшил обработку. Я выбираю RAMdisk 4 ГБ, однако, это всего лишь около 150 изображений с разрешением 2 МП. Поэтому я использую цикл, который загружает кучу изображений, обрабатывает их и удаляет из RAMdisk. Ранее 1,11s/img (SSD), теперь 0,42 с/img (MPC в ОЗУ) (40 img windows). Mogrify использует '-format MPC'.Большое вам спасибо за ваше время и помощь! – Markus

+0

Отлично! Я рад, что это сработало для вас. Удачи с вашим проектом. –

2

В bash ничего не найдено, чтобы ускорить это; все, кроме фактического ввода-вывода, которое должно выполнять convert, довольно тривиально. Тем не менее, вы можете упростить сценарий значительно:

#! /bin/bash 
totnum=10000 
seqnum=40 
skip=1 
num=$(((totnum-seqnum)/1)) 


# Could use files=(*.jpg), but they probably won't be sorted correctly 
for ((i=1; i<=totnum; i++)); do 
    files+=($i.jpg) 
done 

for ((i=1, j=1; i <= num; i+=skip, j+=1)); do 
    convert "${files[@]:i:seqnum}" -evaluate-sequence mean ~/timelapse/Images/Shutterdrag/$j.jpg 
done 

Сохранение файлов в диске RAM, безусловно, поможет, но это выходит за рамки данного сайта. (Конечно, если у вас достаточно ОЗУ, возможно, ОС должна хранить файл в кеше диска после его первого чтения, чтобы последующие чтения были намного быстрее без предварительной загрузки RAM-диска.)

+0

Спасибо, это выглядит лучше! – Markus