"Diferenciar" uma imagem usando o ImageMagick

178

Como posso obter a diferença entre duas imagens? Eu tenho a imagem original. Alguém escreveu uma cópia exata da imagem original. Agora, preciso comparar o original com o escrito na imagem e extrair apenas a escrita no formato de imagem.

Exemplo: Eu tenho uma foto de uma casa. Alguém pegou uma cópia e escreveu "Olá!" na cópia. Quero, de alguma forma, comparar as duas figuras, remover a casa e ficar com uma imagem das palavras "Olá!".

Isso é possível com o ImageMagick? Eu sei que existem maneiras de obter a diferença estatística entre as imagens, mas não é isso que estou procurando.

Justin Noel
fonte
8
Experimente esta seção do guia de uso do ImageMagick!
Benoit
1
Eu sei que esta pergunta é sobre o ImageMagick, mas eu apenas precisei incluir um link para o Resemble.js para o pesquisador "causal" que pode estar atrás de uma solução agnóstica.
Brichins
Alguém conhece uma ferramenta que compara duas imagens subtraindo os pixels da segunda imagem da primeira? Prefiro não escrever o meu.
MarcusJ
O Imagemagick 7 possui hash perceptivo, uma técnica que utiliza momentos de imagem invariantes. É bom no sentido de que hashes a mesma, mesmo após a rotação, distorção barril, redimensionamento, mudança de gama, a introdução de ruído, marca d'água ...
v.oddou
1
@ v.oddou, obrigado. Eu li documentos e fiz mais alguns testes. Parece ter um desempenho ruim com desenhos de linhas muito escassamente povoados e com densidade de pixels extremamente baixa. Parece que a densidade de pixels é a chave no PHASH para identificar semelhanças.
BReddy

Respostas:

320

Meus favoritos são esses dois:

 compare image1 image2 -compose src diff.png
 compare image1 image2 -compose src diff.pdf

A única diferença entre os 2 comandos acima: o primeiro mostra a diferença visual entre as duas imagens como um arquivo PNG, a segunda como um PDF.

O arquivo diff resultante exibe todos os pixels diferentes na cor vermelha. Os que não mudam parecem brancos.

Curto e grosso.

Observe que suas imagens não precisam ser do mesmo tipo. Você pode até misturar JPEG, TIFF, PNG - sob uma condição: as imagens devem ter o mesmo tamanho (dimensão da imagem em pixels). O formato de saída é determinado pela extensão do nome do arquivo de saída.

Por algum motivo, se você precisar de uma resolução maior que a padrão (72 dpi) - adicione apenas uma -density parâmetro :

 compare -density 300 image1 image2 -compose src diff.jpeg

Exemplos ilustrados

Aqui estão algumas ilustrações dos resultados para variações do comando acima. Nota: os dois arquivos comparados eram arquivos PDF , por isso também funciona com eles (desde que sejam pagers 1)!


Esquerda: Imagem com texto       Centro: Imagem original       Direita: Diferenças (= texto) em pixels vermelhos. Somente pixels com diferença de vermelho;  pixels idênticos são brancos

compare \
        porsche-with-scratch.pdf  porsche-original.pdf \
       -compose src \
        diff-compose-default.pdf

Este é o mesmo comando que sugeri anteriormente.


Esquerda: Imagem com texto       Centro: Imagem original       Direita: Diferenças em pixels 'verdes'. Somente pixels de diferença de fundo marinho;  pixels idênticos são brancos

compare \
        porsche-with-scratch.pdf  porsche-original.pdf \
       -compose src \
       -highlight-color seagreen \
        diff-compose-default.pdf

Este comando adiciona um parâmetro para fazer com que os pixels da diferença sejam 'seagreen', em vez do vermelho padrão.


Esquerda: Imagem com texto       Centro: Imagem original       Direita: Diferenças azuis (mas com algum contexto de contexto) Somente pixels de diferença em azul;  primeira das imagens comparadas como um fundo iluminado l

compare \
        porsche-with-scratch.pdf  porsche-original.pdf \
       -highlight-color blue \
        diff-compose-default.pdf

Este comando remove a -compose srcpeça - o resultado é o comportamento padrão compareque mantém como plano de fundo iluminado a primeira das 2 imagens diferentes. (Desta vez, com o parâmetro adicionado para fazer com que os pixels do diff apareçam em azul.)

Kurt Pfeifle
fonte
Não consigo entender de onde veio esse cli de comparação? Faz parte do imagebrick? disponível no windows?
Krishnom 23/05/19
2
@ Krishnom: Não existe tal coisa como 'imagebrick'. Você quer dizer ImageMagick?
Kurt Pfeifle
2
@ Krishnom: A pergunta explicitamente feita sobre uma solução ImageMagick. Parte do pacote de software v6.x do ImageMagick tinha uma ferramenta CLI separada chamada 'compare'. Para a v7.x do ImageMagick, você deve executar 'magick compare'.
Kurt Pfeifle #
Foi mal. Obrigado por corrigir isso (imagebrick -> imageMagick). Vou tentar. Também estou procurando uma ferramenta para comparar imagens em massa. Obrigado pela ajuda novamente
Krishnom 24/05/19
@ Krishnom: Eu não sei o que é uma "imagem em massa". Mas ainda aposto que o conjunto de ferramentas ImageMagick pode fazer o que você deseja.
Kurt Pfeifle
53

Embora comparefaça um bom trabalho para muitas aplicações, descobri que às vezes prefiro uma abordagem diferente, principalmente quando comparamos imagens que são principalmente em escala de cinza:

convert '(' file1.png -flatten -grayscale Rec709Luminance ')' \
        '(' file2.png -flatten -grayscale Rec709Luminance ')' \
        '(' -clone 0-1 -compose darken -composite ')' \
        -channel RGB -combine diff.png

A idéia é a seguinte: converta ambos file1.pnge file2.pngem escala de cinza. Em seguida, trate o primeiro como o canal vermelho da imagem resultante, o segundo como o canal verde. O canal azul é formado a partir desses dois usando o darkenoperador de composição, o que significa essencialmente levar o mínimo.

Portanto, as coisas brancas nas duas imagens permanecem brancas. Coisas pretas nas duas imagens permanecem pretas. Coisas brancas na primeira imagem, mas pretas na segunda ficam vermelhas, e coisas brancas na segunda, mas pretas na primeira ficam verdes.

O resultado fornece uma imagem bem codificada por cores, na qual você pode associar facilmente verde à primeira entrada e vermelho à segunda. Aqui está um exemplo em que estou usando isso para comparar a saída do LaTeX com a do KaTeX (antes de eu corrigir algum bug para melhorar isso):

insira a descrição da imagem aqui

Você pode combinar as abordagens, usando comparepara ver onde algo mudou e, em seguida, usando o acima para ver em mais detalhes como ele mudou.

MvG
fonte
2
Agradável! Eu precisava de alguma interação, então repliquei seu método no Gimp. Para referência: 1) carregue imagens como camadas, 2) Cor -> Desature as duas camadas, 3) remova canais alfa de ambas as camadas na guia Camadas, 4) selecione os canais G + B em uma camada, selecione tudo e limpe os canais com cor preta, o mesmo com os canais R + B na segunda camada, 4) defina o modo Tela para a camada superior na guia Camadas.
Matěj Šmíd 23/02
1
@Palmstrom: Obrigado! Originalmente, fiz essas comparações de imagens usando o Gimp, mas usando o modo de camada "extrato de grão" diretamente nas imagens de entrada, para que as áreas comuns acabassem cinza, enquanto o diff seria preto em uma direção e branco na outra . Mais difícil de ler, mas mais rápido de gerar, e pode conter informações de cores. Eu acho que você corresponderia ao meu comando ainda mais de perto se estivesse usando "apenas escurecer" em vez de "tela" e colorir os canais não utilizados de branco em vez de preto.
MvG 23/02
1
Algumas entradas de PDF resultam em uma imagem invertida após a conversão em escala de cinza por algum motivo. Usar em -colorspace grayvez de -grayscale Rec709Luminancecorrigir isso, mas isso atrapalha a composição. Adicione -respect-parenthesescomo a primeira opção para convertcuidar disso.
Brecht Machiels
Aqui está um script para diferenciar visualmente dois PDFs página por página usando este método: gist.github.com/brechtm/891de9f72516c1b2cbc1 . Ele gera um JPG para cada página dos PDFs em um pdfdiffdiretório e imprime adicionalmente os números das páginas que diferem entre os dois PDFs.
Brecht Machiels 31/03
1
Em ImageMagick v6.7.7-10 parece -grayscalenão é suportado, eu tive que usar -colorspace graycomo @BrechtMachiels sugeriu
austinmarton