Por que o comando 'compare' do ImageMagick é tão lento e existe uma alternativa?

3

Eu tenho um shell script rodando em uma pequena caixa Micro-ATX baseada em Atom que está fazendo algumas funções semelhantes a watchdog para vários dispositivos em uma rede local. Uma das coisas que está fazendo é monitorar algumas fontes de vídeo (capturas de tela de VMs e um feed de câmera de segurança) para mudanças significativas. Capturar os dados não parece ser um problema, mas comparar as imagens para decidir se a mudança é importante está matando a caixa.

A única coisa que me leva a qualquer momento na minha configuração atual é o comando compare do ImageMagick, que estou executando assim:

compare -metric PHASH previous.png current.png null:

Isso fornece um número razoavelmente utilizável avaliando a similaridade das imagens, mas é preciso sempre para ser executado. Eu tentei outras métricas como AE com diferentes configurações de -fuzz , mas a diferença de tempo de execução parece ser insignificante.

Eu estava brincando com um par de imagens de 60K 640x480 e estava recebendo tempos de execução ~ 30 segundos nesse comando. Há alguns shows de RAM livre, o desligamento foi definitivamente CPU. Todos os 4 núcleos foram indexados pela duração do comando. Para comparação, eu tentei as mesmas imagens na minha área de trabalho e estava demorando quase 2 segundos para rodar, o que é uma quantidade absurda de tempo de CPU para o que estou tentando realizar.

Eu tive a brilhante ideia de poder gerar miniaturas e verificar o quanto elas mudaram. Isso foi bastante fácil e eu criei miniaturas 64x48 correspondentes e executei compare nelas. O resultado foi pouco diferente, com uma média de cerca de 25 segundos. Amassando ainda mais para imagens de 6x4 pixels não acelerou muito o processo, eu ainda estava recebendo ~ 25 segundos para rodar.

Eu poderia ter algo mal configurado? Por que essa operação é tão intensiva em recursos e por que o tamanho da imagem não parece importar? Existe uma maneira alternativa de descobrir se duas imagens divulgaram mais do que um certo limite? (Os dados da captura de tela são mais fáceis, já que uma contagem de pixels muito alterada faz o truque, mas os dados de vídeo têm estática e precisam de processamento difuso para descobrir um número de diferença.)

    
por Caleb 23.10.2014 / 17:39

1 resposta

2

Não é um problema do S / W, e não parece ser um problema com o Atom. Eu tenho um Atom 330 como minha máquina principal (D945GCLF2), executando o Arch Linux - e acabei de fazer este teste:

ttsiod@home ~/tmp
$ wget i.stack.imgur.com/fWwyu.png
--2014-10-29 14:30:08--  http://i.stack.imgur.com/fWwyu.png
Resolving i.stack.imgur.com (i.stack.imgur.com)... 103.31.7.31...
Connecting to i.stack.imgur.com (i.stack.imgur.com)|103.31.7.31|:80...
HTTP request sent, awaiting response... 200 OK
Length: 28576 (28K) [image/png]
Saving to: 'fWwyu.png'

100%[==============================>] 28,576   --.-K/s   in 0.06s   

2014-10-29 14:30:09 (446 KB/s) - 'fWwyu.png' saved [28576/28576]

ttsiod@home ~/tmp
$ wget http://i.stack.imgur.com/KQiJX.png
--2014-10-29 14:30:16--  http://i.stack.imgur.com/KQiJX.png
Resolving i.stack.imgur.com (i.stack.imgur.com)... 103.31.6.184
Connecting to i.stack.imgur.com (i.stack.imgur.com)|103.31.6.184|:80...
HTTP request sent, awaiting response... 200 OK
Length: 28212 (28K) [image/png]
Saving to: 'KQiJX.png'

100%[==============================>] 28,212  --.-K/s   in 0.06s   

2014-10-29 14:30:17 (431 KB/s) - 'KQiJX.png' saved [28212/28212]


ttsiod@home ~/tmp
$ identify KQiJX.png 
KQiJX.png PNG 640x400 640x400+0+0 8-bit sRGB 28.2KB 0.000u 0:00.000

ttsiod@home ~/tmp
$ time compare -metric PHASH fWwyu.png KQiJX.png null:
0.191664
real    0m1.029s
user    0m2.863s
sys     0m0.177s

ttsiod@home ~/tmp
$ time compare -metric PHASH fWwyu.png fWwyu.png null:
0
real    0m1.027s
user    0m2.843s
sys     0m0.190s

Assim, o tempo que leva para as imagens compare two 640x400 em um Atom330 é de 1 segundo - muito mais rápido que seus 25 segundos.

Na ausência de uma saída de strace -f log de sua execução, a única coisa que posso imaginar é ... hardware ruim (talvez um CPU passivamente resfriado que reduz sua velocidade para evitar pegar fogo?) ou binários mal compilados ( por exemplo, não usar extensões MMX / SSE).

BTW, para ter certeza de que o kernel não está diminuindo sua velocidade, faça isso primeiro (como root):

for i in /sys/devices/system/cpu/cpu?/cpufreq/scaling_governor ; do
    echo performance > $i
done

Eu, então, tentaria monitorar a temperatura / frequência da CPU durante o teste - eu estou supondo que isso reduza ao esquecimento ...

Por questões de integridade, estas são as versões do kernel e compare que usei no teste acima:

ttsiod@home ~/tmp
$ egrep '^model.na|^flags'  /proc/cpuinfo   | sort -u
model name      : Intel(R) Atom(TM) CPU  330   @ 1.60GHz
flags           : fpu vme de tsc msr pae mce cx8 apic sep 
                  mtrr pge mca cmov pat clflush dts acpi
                  mmx fxsr sse sse2 ss ht tm pbe syscall
                  nx lm constant_tsc arch_perfmon pebs
                  bts nopl aperfmperf pni dtes64 monitor
                  ds_cpl tm2 ssse3 cx16 xtpr pdcm movbe
                  lahf_lm dtherm

ttsiod@home ~/tmp
$ uname -a
Linux home 3.16.3-1-ARCH #1 SMP PREEMPT Wed Sep 17 21:54:13
                                CEST 2014 x86_64 GNU/Linux

ttsiod@home ~/tmp
$ compare --version
Version: ImageMagick 6.8.9-9 Q16 x86_64 2014-10-26 http://www.imagemagick.o
Copyright: Copyright (C) 1999-2014 ImageMagick Studio LLC
Features: DPC HDRI Modules OpenCL OpenMP
Delegates: bzlib cairo fontconfig freetype gslib jng jp2 jpeg lcms lqr ltdl
           lzma pangocairo png ps rsvg tiff webp wmf x xml zlib
    
por 29.10.2014 / 13:53