⚠️ Este é um site de tradução não oficial, sem relação com a ImageMagick Studio LLC. Para informações oficiais, consulte a página original (https://usage.imagemagick.org/convolve/index.html).

Exemplos de ImageMagick -- Convolução de Imagens

Exemplos de ImageMagick: Prefácio e Índice
Introdução à Convolução

A convolução usa a «vizinhança» local de pixels para modificar imagens. Ela faz isso combinando e calculando a média de todos os valores de cor ao redor de cada pixel, para desfocar imagens, realçar bordas e limites e aguçar imagens. A variação da convolução, a «correlação», também é usada para varrer e buscar padrões específicos, produzindo uma imagem que indica o quão próximas as imagens correspondem.


Introdução à Convolução

Os métodos «Convolve» e o intimamente relacionado «Correlate» são, de muitas maneiras, muito semelhantes à Morfologia. Na verdade, funcionam quase exatamente da mesma forma, associando um «núcleo» de vizinhança em cada posição, o que faz deles apenas mais um «método» especial da morfologia. De fato, também usam grande parte do mesmo código e até as mesmas definições de núcleo apresentadas em Núcleos Básicos e Núcleos Definidos pelo Usuário. Para núcleos mais específicos projetados para uso por este operador (e há muitos), remetemos a Núcleos de Desfoque e Núcleos de Detecção de Bordas. O núcleo mais importante é o «[Gaussian](../static/img/convolve/gaussian)». No entanto, a convolução é muito mais antiga que a morfologia e gera mais efeitos de gradiente em escala de cinza, em vez dos efeitos de estudo de formas binárias que a morfologia costuma gerar. É por isso que ela é frequentemente considerada uma operação bem distinta ou separada da morfologia, e mais central para o processamento de imagens. Basicamente, uma convolução ou correlação realiza uma «média ponderada» de todos os pixels na vizinhança especificada. Ou seja, multiplica o valor de cada pixel próximo pela quantidade dada no núcleo e depois soma todos esses valores para produzir o resultado final. Assim, cada pixel da imagem final conterá, em geral, pelo menos uma pequena parte de todos os demais pixels que o cercam localmente na imagem de origem. Visto de outra forma, a cor de cada pixel da imagem será somada (desfoque) ou subtraída (aguçamento/detecção de bordas) às cores de todos os seus vizinhos próximos, conforme definido pelo núcleo usado. Tanto «convolve» quanto «correlate» são a mesma operação, exceto por uma diferença muito pequena, porém importante; e para os exemplos e controles que veremos agora, é possível tratá-los como basicamente a mesma coisa. Mais adiante (ver Convolução vs Correlação) examinaremos exatamente como os dois operadores realmente diferem e por que diferem de forma tão sutil. Mas, na maioria das circunstâncias, são o mesmo método.

Convolve ( )

Como mencionado acima, o método «Convolve» funciona ponderando cada um dos pixels da vizinhança local, de acordo com os valores em ponto flutuante do núcleo. Os valores ponderados são então simplesmente somados para produzir o novo pixel de substituição na imagem resultante. Por exemplo, vamos aplicar a convolução a um único pixel, usando um núcleo de convolução Definido pelo Usuário bem pequeno. Também definimos a Configuração Show Kernel especial, para que se possam ver os detalhes do núcleo sendo definido e usado (as imagens exibidas foram ampliadas).

  magick xc: -bordercolor black -border 5x5 pixel.gif
  magick pixel.gif -define morphology:showKernel=1 \
         -morphology Convolve '3x3: 0.0, 0.5, 0.0
                                    0.5, 1.0, 0.5
                                    0.0, 0.5, 0.0' pixel_spread.gif

[IM Text]

[IM Output] [IM Output] [IM Output]

Como se pode ver, o único pixel da imagem agora se expandiu, produzindo pixels 50% cinza ao seu redor. Ou seja, quando a «origem» do núcleo (seu centro, neste caso) é posicionada ao lado do único pixel da imagem original, apenas esse pixel tem valor diferente de zero. Esse valor de pixel é então ponderado pelo valor «0.5» do núcleo, e o pixel «com meio brilho» resultante é adicionado à imagem resultante. De modo semelhante, quando a origem do núcleo é posicionada exatamente sobre o pixel original, ele recebe um valor de «1.0», reproduzindo o pixel original, sem que nenhum outro valor (preto) na vizinhança ao redor contribua com qualquer componente para o resultado. Observe que qualquer valor de núcleo igual a «0.0» não participa do cálculo final. Os valores zero efetivamente não fazem parte da «vizinhança», assim como qualquer valor «Nan» nos núcleos de morfologia não participa. Assim, este núcleo consiste em uma vizinhança de 5 elementos. De muitas maneiras, um método «[Convolve](#convolve)» é muito semelhante a um método morfológico «[Dilate](morphology.html#dilate)»; no entanto, «[Dilate](morphology.html#dilate)» trata o núcleo apenas como um tipo de máscara de bitmap, localizando o maior valor dentro da vizinhança. Por outro lado, «[Convolve](#convolve)» é uma soma ponderada de todos os valores da vizinhança, de modo que o valor de cada elemento do núcleo influi no resultado geral. A sintaxe de uma operação de convolução é...

**-morphology Convolve {_convolution_kernel_}
**

Mas você também pode usar um operador mais antigo e mais direto...

**-convolve {_convolution_kernel_}
**

| _Antes do IM v6.5.9, o antigo "[-convolve](https://imagemagick.org/command-line-options/#convolve)" não entendia as definições de núcleo da morfologia. Ele só aceitava o «estilo antigo» de núcleos definidos pelo usuário, que consiste apenas em uma sequência de valores separados por vírgulas para produzir um núcleo quadrado de tamanho ímpar. Agora ele aceita as definições de núcleo de convolução no «novo estilo».

No entanto, ele ainda se restringe a núcleos quadrados de «tamanho ímpar». E permanecerá assim até que passe a usar o novo método de convolução da «morfologia».

_
---|---
| _O antigo operador "[-convolve](https://imagemagick.org/command-line-options/#convolve)" não é exatamente igual ao método de morfologia mais recente «[Convolve](#convolve)». A seguir, uma lista de como as duas operações diferem...

_

  • _O antigo operador é implementado como uma Correlação em vez de uma verdadeira convolução. Isso significa que o núcleo não é sobreposto à imagem de origem em sua forma refletida. Veja Convolve vs Correlate para os efeitos que isso tem nos resultados.

_ * _Ele só aceita núcleos quadrados de tamanho ímpar. O da morfologia permite qualquer arranjo retangular, com qualquer ponto do arranjo declarado como a origem.

_ * _O antigo operador sempre Normaliza os Núcleos sem qualquer controle do usuário sobre o Escalonamento do Núcleo. O novo não normaliza automaticamente; é preciso solicitá-lo. No entanto, a maioria dos núcleos gerados já vem pré-normalizada.

_ * Não é possível usar nenhuma forma de Mistura com o Núcleo Identidade, embora o Viés de Saída seja aplicado normalmente. * _Ele, porém, fará uso de código «GPU» rápido, se o computador anfitrião dispuser desses recursos. A morfologia ainda não tem isso habilitado.

_ * _Atualmente, outros operadores relacionados à convolução, como "[-gaussian_blur](https://imagemagick.org/command-line-options/#gaussian_blur)", "[-blur](https://imagemagick.org/command-line-options/#blur)", "[-sharpen](https://imagemagick.org/command-line-options/#sharpen)", "[-unsharp](https://imagemagick.org/command-line-options/#unsharpen)", usam a versão antiga do operador.

_ * _Por padrão, o comando antigo só aplica a convolução aos canais de cor (conforme definido pela configuração "[-channel](https://imagemagick.org/command-line-options/#channel)"). Se você aplicar a convolução com uma configuração "[-channel](https://imagemagick.org/command-line-options/#channel) RGBA", ele também ponderará os valores do núcleo pelo canal alfa, para garantir um desfoque correto no que diz respeito à transparência.

O método «convolve» da Morfologia lida automaticamente, por padrão, com a ponderação de transparência dos canais de cor. Ou seja, o desfoque de imagem que o usa tratará as cores transparentes como transparentes, evitando assim, por padrão, o Bug de Transparência do Desfoque.

No entanto, se o usuário modificar a configuração padrão "[-channel](https://imagemagick.org/command-line-options/#channel)" (não incluindo a flag «Sync» especial), então ele tratará a convolução como um operador puramente por canal, em escala de cinza.

Veja a documentação da configuração "[-channel](https://imagemagick.org/command-line-options/#channel)", ou consulte a Matemática de Canais de Imagem, que usa a mesma flag da mesma maneira, para mais informações.

_

_

Com o tempo, a maioria das diferenças acima mudará, à medida que as coisas se fundirem com o método de morfologia mais recente «[Convolve](#convolve)».

_
---|---
Se você quiser ver ótimos exemplos de como o «[Convolve](#convolve)» realmente funciona, recomendo também dar uma olhada em EECE \ CS 253 Image Processing, Lecture 7, Spatial Convolution. O artigo Wikipedia, Convolve tem boas animações 1D do processo de convolução.

Escalonamento do Núcleo de Convolução

O exemplo acima funciona bem para uma imagem majoritariamente preta, como um único pixel, mas se você o aplicasse a uma imagem real, teria um problema...

  magick logo: -resize 50% -crop 80x80+150+60 +repage  face.png

  magick face.png \
         -morphology Convolve '3x3: 0.0,0.5,0.0  0.5,1.0,0.5   0.0,0.5,0.0' \
         face_spread.png

[IM Output] [IM Output] [IM Output]

Como se pode ver, a imagem resultante fica muito clara (na verdade, 3 vezes mais clara) que a imagem original. O que aconteceu é que cada pixel está sendo compartilhado 3 vezes: 4 × «0.5» nas laterais, mais uma cópia completa do pixel original. Ou seja, a soma de todos os valores do núcleo é 3, tornando a imagem resultante três vezes mais clara! Se você voltar e olhar a saída do «showKernel» acima, verá que ele listou este núcleo como tendo uma "faixa de saída da convolução de 0 a 3". Isso mostra que, em geral, este núcleo clareia uma imagem 3 vezes. Para corrigir isso, seria preciso dividir todos os valores do núcleo por 3. Ou seja, um valor de «0.5» deveria realmente ter sido cerca de «0.1667», enquanto o valor central de «1.0» deveria ter sido «0.3333». Esse é um processo conhecido como «Normalização do Núcleo ». Por exemplo, aqui está o resultado «normalizado» manualmente e a definição do núcleo...

magick face.png -define morphology:showKernel=1 \
       -morphology Convolve \
       '3x3: 0.0,.1667,0.0  .1667,.3333,.1667  0.0,.1667,0.0' \
       face_spread_norm.png

[IM Text]

[IM Output] [IM Output] [IM Output]

Como se pode ver, obtém-se uma versão levemente desfocada da imagem do rosto, pois cada pixel foi espalhado para cada um de seus vizinhos imediatos. | _A «imagem do núcleo» mostrada acima (gerada com um Script Kernel 2 Image especial) também mostra o núcleo normalizado resultante. Como se pode ver, o próprio núcleo agora é bem escuro, pois todos os seus valores também são escuros, embora todos somem um valor de «1.0».

Deste ponto em diante, todas as imagens de núcleo de convolução mostradas serão sempre ajustadas para que o valor máximo fique branco; caso contrário, geralmente só se veria uma «Imagem do Núcleo» escura e basicamente inútil.

_
---|---
Normalizar o núcleo manualmente não é agradável e, como se viu, torna a definição do núcleo resultante muito mais difícil de entender. Por isso, são fornecidas alternativas. A partir do IM v6.5.9-2, a opção avançada especial "[-define](https://imagemagick.org/command-line-options/#define) convolve:scale={_kernel_scale_}» permite especificar um fator de escala global para o núcleo e, assim, ajustar o brilho do resultado geral. |

magick face.png -define convolve:scale=0.33333 \
       -morphology Convolve '3x3: 0.0,0.5,0.0  0.5,1.0,0.5  0.0,0.5,0.0' \
       face_spread_scale.png

[IM Output]
Na verdade, o que isso faz é ajustar a intensidade geral dos resultados do núcleo. Como você verá em exemplos posteriores, provavelmente vai querer tornar o resultado da convolução mais ou menos intenso. Esse fator «kernel_scale » permite fazer isso.

Normalização do Núcleo (escalonamento automático)

Em vez de calcular o fator de escala (como acima), você pode simplesmente pedir ao IM para determinar internamente esse «fator de escala de normalização», fornecendo a flag de normalização «!» especial. |

magick face.png -define convolve:scale=\! \
       -morphology Convolve  '3x3: 0,1,0  1,2,1  0,1,0' \
       face_spread_normalize.png

[IM Output]
| O caractere «!» também é às vezes usado para fins especiais por vários shells de linha de comando UNIX. Portanto, pode ser necessário escapar o caractere com uma barra invertida, mesmo entre aspas. Recomenda-se cautela.
---|---
Observe que, como o núcleo agora está normalizado, é possível defini-lo de forma mais simples usando números inteiros. O núcleo normalizado ainda será o mesmo que o núcleo «escalonado» anterior. Normalmente, você sempre vai querer normalizar o núcleo e, por isso, a variante mais simples "[-convolve](https://imagemagick.org/command-line-options/#convolve)" fará essa normalização automaticamente. Você pode fazer o IM normalizar o núcleo e depois escaloná-lo novamente por uma quantidade dada para ajustar sua faixa de saída. Para facilitar ainda mais, é possível especificar o fator de escala como uma porcentagem. Por exemplo, aqui normalizo o núcleo, mas depois reescalono os valores para 50% do tamanho calculado, de modo a produzir um resultado mais escuro. |

  magick face.png -define convolve:scale=50%\! \
         -morphology Convolve  '3x3: 0,1,0  1,2,1  0,1,0' \
         face_spread_norm_half.png

[IM Output]
Observe que usar um valor de «!» é, na verdade, equivalente a usar «1!» ou mesmo «100%!». Você pode até usar um fator de escala negativo se quiser inverter os valores positivos e negativos dentro do núcleo. Para um exemplo disso, veja «Un-Sharpen» de Imagens usando Desfoques. Se o núcleo tiver sido normalizado dessa forma, a saída Show Kernel indicará que ele está normalizado.

Como Funciona a Normalização

A forma como a «Normalização do Núcleo » realmente funciona é que todos os valores do núcleo são somados (incluindo quaisquer valores negativos, o que também é possível). Se o resultado for diferente de zero, escalonam-se todos os valores para que seu valor combinado some um («1.0»). Observe que, se houver valores negativos, isso pode, na verdade, criar um núcleo com um valor maior que um, tipicamente na origem. Isso ocorre especificamente com núcleos Un-Sharp. O ponto importante, porém, é que o núcleo como um todo soma «1.0», de modo que a imagem final não é escurecida nem clareada pela operação de Convolução. Se o resultado da soma for zero («0.0»), então o núcleo é considerado um Núcleo de Soma Zero especial. Nesse caso, o núcleo é escalonado para tornar todos os valores positivos iguais a «1.0» e, do mesmo modo, todos os valores negativos passam a somar «-1.0». Esses núcleos são especialmente comuns nas técnicas de Detecção de Bordas. A saída Show Kernel também especificará que ele é de soma zero, se o núcleo estiver nessa forma, mesmo que não seja de fato um núcleo de soma zero normalizado, embora isso também seja facilmente percebido pelos demais números exibidos. A maioria dos núcleos determinados matematicamente já vem pré-normalizada. Isso inclui os núcleos derivados matematicamente: «[Unity](#unity)», «[Gaussian](#gaussian)», «[LoG](#log)», «[DoG](#dog)», «[Blur](#blur)», «[Comet](#comet)». Os Núcleos Constantes Discretos, porém, não são pré-normalizados, de modo que você terá de fazê-lo usando a Configuração de Normalização do Núcleo (acima). Isso inclui os núcleos: «[Laplacian](#laplacian)», «[Sobel](#sobel)», «[Roberts](#roberts)», «[Prewitt](#prewitt)», «[Compass](#compass)», «[Kirsch](#kirsch)», «[FreiChen](#freichen)». Observe que o núcleo «[FreiChen](#freichen)» tem subtipos que são especialmente pré-ponderados para fins mais específicos. Os núcleos FreiChen não devem ser normalizados, e sim usados como estão.

Normalização de Soma Zero

Nem todos os núcleos de convolução usam apenas valores positivos. Também é possível ter núcleos que usam uma mistura de valores positivos e negativos e, com frequência, os valores desses núcleos devem somar zero para produzir um Núcleo de Soma Zero. Tais núcleos são muito importantes para Convoluções de Imagem mais avançadas, pois fornecem técnicas de Detecção de Bordas e Aguçamento de Imagens. Como mencionei na seção anterior, a flag de normalização usual «!» funciona com esses núcleos. Mas, às vezes, por situações especiais, você quer garantir que o núcleo permaneça «de soma zero». O método de normalização «^» especial apenas oferece uma forma de garantir que o núcleo seja «de soma zero» em situações como...

  1. Se a definição de núcleo do usuário não for precisa o suficiente para garantir a soma zero. Por exemplo, não é possível especificar «1/3» ou qualquer outro fator fracionário de 3 como um número decimal em ponto flutuante exato.
  2. A curva matemática é «cortada» pelo tamanho (raio) do núcleo, de modo que ele pode deixar de ser de soma zero. Por exemplo, isso ocorre em núcleos «[LoG](#log)» ou «[DoG](#dog")», que se baseiam em curvas de resposta infinita. O IM, na verdade, usa internamente essa normalização especial nesses núcleos justamente por essa razão.
  3. Garantir que uma «máscara de forma» de Correlação seja de soma zero, para que, na busca, o IM possa procurar por correspondências positivas e negativas de forma equânime. Veja Busca de Formas por Correlação abaixo.

O que acontece é que ele normaliza todos os valores positivos e negativos do núcleo como entidades separadas. Ou seja, todos os valores negativos são escalonados para somar «-1.0» e todos os valores positivos, para somar «+1.0». O resultado é que o núcleo, como um todo, terá soma zero garantida. Observe que, se você usar esse método de normalização em um núcleo totalmente positivo, como o «Gaussian», ainda obterá um núcleo devidamente normalizado. Assim, essa forma de normalização também pode ser usada com Núcleos de Desfoque. No entanto, ela não deve ser usada para normalizar núcleos de Aguçamento ou até de Un-Sharpen definidos diretamente, pois estes podem conter valores negativos, mas precisam somar um (usando o método de normalização normal).

Mistura do Núcleo com o Núcleo Identidade

A sintaxe completa da Configuração de Escalonamento do Núcleo é uma das seguintes...

**-define convolve:scale='{_kernel_scale_}[!^] [,{_origin_addition_}] [%]' -set option:convolve:scale '{_kernel_scale_}[!^] [,{_origin_addition_}] [%%]'**

Observe a duplicação do caractere de porcentagem ao usar "[-set](https://imagemagick.org/command-line-options/#set)". As flags de normalização opcionais «!» ou «^" são aplicadas primeiro ao núcleo definido pelo usuário ou embutido (se solicitado). Depois disso, o núcleo é escalonado pelo fator «kernel_scale », aumentando ou diminuindo a «força» efetiva da convolução sobre os resultados. O fator de escala padrão é «1.0». Por fim, o valor da «origem» do núcleo recebe a soma do número que vem depois de uma vírgula. O «origin_addition » padrão é «0.0». Esse último passo, na prática, «adiciona» um Núcleo Identidade do «escalonamento» dado ao núcleo normalizado e escalonado gerado anteriormente. Isso gera núcleos que podem...

Observe que, se você fornecer a flag de porcentagem («%»), essa porcentagem será aplicada TANTO ao fator «kernel_scale » QUANTO ao «origin_addition ». Isso pode tornar a escala mais fácil de ler e entender quando há frações envolvidas. Exemplo de uso do define de escalonamento do núcleo...

  -define convolve:scale='!50%,100%'  -morphology Convolve Laplacian:2

Gerará o núcleo «[Laplacian:2](#laplacian_2)» solicitado...

0 -1 0
-1 4 -1
0 -1 0

Normaliza-o (flag «!»)

0 -0.25 0
-0.25 1 -0.25
0 -0.25 0

Escalona em 50%

0 -0.125 0
-0.125 0.5 -0.125
0 -0.125 0

Adiciona um núcleo Unity (adiciona 100% ao valor da origem)

0 -0.125 0
-0.125 1.5 -0.125
0 -0.125 0

E agora você pode aplicar a convolução usando «[Laplacian:2](#laplacian_2)» como núcleo de aguçamento, mas com apenas «50% de força de aguçamento. Lembre-se de que qualquer flag «%» fornecida em qualquer ponto da configuração de escala tornará ambos os valores porcentagens. Se não estiver presente, ambos os valores são apenas multiplicadores diretos simples. Por exemplo, todas estas opções de escala são equivalentes

     50,100%     50%,100    %50,100      .5,1      0.5,1.0

O mesmo vale para as duas flags de normalização. Elas podem aparecer em qualquer ponto da configuração de escala da convolução, mas serão sempre aplicadas primeiro, antes de qualquer outro escalonamento.

Controle de Viés do Resultado de Saída

Quando se lida com um núcleo que contém valores negativos, alguns pixels da imagem resultante deveriam receber um valor negativo. Esse é especialmente o caso dos Núcleos de Soma Zero (ver abaixo). Infelizmente, a menos que você tenha uma Versão HDRI do ImageMagick especialmente compilada para preservar os valores negativos gerados, qualquer resultado negativo será cortado para zero (preto). Você obterá apenas os resultados positivos da convolução. Ele simplesmente não pode ser armazenado em um formato de imagem normal, deixando-o com metade do resultado. Você poderia compilar a Versão HDRI do ImageMagick para preservar os valores negativos gerados e então extrair a informação desejada. Como alternativa, é possível negar o núcleo usando um fator de escala negativo. Por exemplo, usando...

-define convolve:scale='-1'

Mas então você obtém apenas os resultados negativos, com os resultados positivos sendo cortados. No entanto, usando a configuração "[-bias](https://imagemagick.org/command-line-options/#bias)" do IM, você ainda pode preservar tanto os resultados positivos quanto os negativos. As configurações a usar na versão não HDRI do IM são...

     -define convolve:scale=50%\!  -bias 50%

A primeira configuração escalona a saída para metade do tamanho que você normalmente obteria (após a normalização), de modo a abrir espaço para os resultados tanto positivos quanto negativos. Em seguida, adiciona um cinza de 50% à saída de pixels antes de salvar o resultado de volta em uma imagem. Com essas configurações, qualquer resultado «zero» se tornará cinza puro, com os resultados negativos mais escuros que isso e os positivos mais claros que isso. O preto representará «-1.0» e o branco significará «+1.0». Um exemplo disso é mostrado nos exemplos de Busca de Formas por Correlação abaixo.


Desfoque de Imagens (filtragem passa-baixa)

Outra seção dos exemplos do IM, especificamente Desfoque e Nitidez de Imagens, trata dos aspectos práticos deste assunto. Aqui, examinamos detalhes mais específicos. Primeiro, porém, descreveremos os núcleos básicos e como usá-los diretamente, sem modificação. Mais adiante, veremos formas de modificar o desfoque para gerar outros efeitos.

Núcleos de Desfoque

[IM Output]

Unity

Este é um núcleo especial que, na verdade, não faz nada. Apenas um elemento do núcleo é especificado e, como resultado, cada pixel é substituído por si mesmo, sem alteração. Por exemplo, aqui está uma Convolução sem efeito...

  magick face.png -morphology Convolve Unity face_unity.png

[IM Output] [IM Output] [IM Output]

A partir do IM v 6.6.9-4, o núcleo pode receber um único argumento, como um argumento de escala específico do núcleo. Isso permite usá-lo para multiplicar os valores de uma imagem, por exemplo, para tornar uma imagem mais clara ou mais escura. |

  magick face.png -morphology Convolve Unity:0.5 face_dimmed.png

[IM Output]
Isso pode não parecer muito útil, mas pode ser usado para gerar efeitos de Desfoques Suaves e de Unsharpen, ou em sequências de múltiplos núcleos onde talvez você não possa usar o Escalonamento do Núcleo ou a Mistura de Identidade do Núcleo. O mesmo núcleo de elemento único também pode ser gerado usando «[Disk:0.5](morphology.html#disk)», que também permite especificar um argumento de escala extra como parte da geração do núcleo. (POR EXEMPLO: «Disk:0.5,0.5» para o último exemplo). Um núcleo semelhante (para Convolução) também pode ser gerado pelo gerador de núcleo «[Gaussian](#gaussian)» com um «sigma » de «0.0». No entanto, isso só pode produzir um pequeno núcleo 3x3, consistindo em um valor central «1.0» cercado por 8 valores «0.0». [IM Output]

Filtragem por Média usando Núcleos de Forma

Embora a maioria dos núcleos de convolução definidos abaixo geralmente envolva o uso de uma Curva Gaussiana de alguma forma, você ainda pode usar um dos Núcleos de Forma da Morfologia anteriores para simplesmente calcular a média dos pixels sobre uma dada (grande) área. É claro que você precisará Normalizar o núcleo para de fato gerar uma média, em vez de apenas uma soma da vizinhança. Por exemplo, aqui uso um núcleo menor em forma de «[Octagon](morphology.html#octagon)» para calcular a média de todos os valores de pixel encontrados dentro de uma área circular ao redor de cada pixel.

  magick face.png -define convolve:scale=! \
         -morphology Convolve Octagon:2 face_mean.png

[IM Output] [IM Output] [IM Output]

O resultado é que o valor de cada pixel é distribuído igualmente por todos os 25 pixels da vizinhança definida. Ou seja, é equivalente a um filtro de «média» sobre a forma dada. Se você quiser excluir o pixel original dessa média, usando apenas os pixels ao redor, então pode usar um núcleo «[Ring](morphology.html#ring)» (fornecendo apenas um raio). Os demais Núcleos de Forma também podem ser usados da mesma maneira para, digamos, calcular a média dos valores de pixel sobre uma forma «[Diamond](morphology.html#diamond)», «[Square](morphology.html#square)» ou um grande «[Disk](morphology.html#disk)», e do tamanho que você quiser. No entanto, embora uma média constante sobre uma área com forma de fato desfoque imagens, ela tende a produzir efeitos incomuns (especificamente Artefatos de Aliasing) na imagem resultante. Mais especificamente, usar um núcleo de média «plano» tende a converter bordas nítidas em uma inclinação linear mais espessa, com uma mudança abrupta na inclinação nas bordas espessadas. A espessura do resultado é «radius*2-1» do núcleo. Como diferentes ângulos de borda afetam a espessura e a linearidade da inclinação depende da forma do núcleo «plano» ou de média.

  magick -size 80x80 xc: -draw 'polygon 15,15 15,65 60,15' shape.png
  magick shape.png \
         -define convolve:scale=! -morphology Convolve Square:5 \
         shape_mean_square.png
  magick shape.png \
         -define convolve:scale=! -morphology Convolve Disk:5 \
         shape_mean_disk.png

[IM Output] [IM Output] [IM Output]

Observe que o desfoque diagonal acima é diferente para um núcleo quadrado do que para um núcleo de disco. Outra forma de gerar um desfoque quadrado de «inclinação linear» é usar um sigma muito grande com um raio específico. A convolução com núcleo quadrado acima também pode, por exemplo, ser obtida usando -blur 5x65535. Isso era comumente usado por Fred Wienhaus em seus scripts, antes de a morfologia estar disponível. [IM Output]

Núcleo Gaussian (desfoque gaussiano 2D)

Como você já deve ter percebido, o núcleo «Gaussian» é o mais usado para aplicar a Convolução a uma imagem. Este é o núcleo matematicamente ideal para efeitos de desfoque. Aqui, por exemplo, está o Show Kernel de um pequeno núcleo «Gaussian» (eles podem ficar muito grandes muito rapidamente)...

  magick xc: -define morphology:showKernel=1 \
         -morphology Convolve:0 Gaussian:0x0.8 null:

[IM Text]

Na verdade, eu não queria aplicar uma convolução ao caso acima, pois só queria mostrar o núcleo que ele iria usar. Por isso, usei uma Contagem de Iterações de «:0», de modo que ele não faz nada. Da mesma forma, descarto a imagem de saída resultante usando o formato de arquivo «[null:](files.html#null)» especial. Como se pode ver pela faixa de saída da convolução, um núcleo «Gaussian» já vem normalizado (escalonado) para você. No entanto, você também notará que ainda é um núcleo bastante grande, repleto de pequenos valores fracionários. Se olhar mais de perto, verá que o maior valor (2.48678, que também está listado na primeira linha) fica no centro, com os menores valores em direção às bordas e aos cantos (um valor de cerca de .000000194). Aqui está um desfoque gaussiano típico usando uma convolução...

  magick face.png -morphology Convolve Gaussian:0x2 face_gaussian.png

[IM Output] [IM Output] [IM Output]

A sintaxe do núcleo é direta...

   Gaussian:[{_radius_}]x{_sigma_}

Esses argumentos são, na verdade, exatamente os mesmos usados pelo operador "[-gaussian-blur](https://imagemagick.org/command-line-options/#gaussian-blur)", que na prática realiza uma Convolução usando este núcleo. O primeiro número, como na maioria dos Núcleos de Morfologia, é o «radius » ou tamanho do núcleo. É apenas um inteiro, com valor mínimo de 1, de modo que o menor núcleo possível tem 3x3 elementos. O melhor é sempre especificar zero, o que permite ao ImageMagick calcular um raio apropriado para o valor «sigma » fornecido. O segundo argumento, mais importante, é «sigma », que define o quanto cada pixel deve ficar desfocado ou «espalhado». Quanto maior o valor, mais desfocada a imagem ficará. É um valor em ponto flutuante. O valor sigma DEVE ser fornecido. Se for dado um valor de sigma «0.0», você acabará com um núcleo «[Unity](#unity)» bastante inútil (do raio dado, ou de raio 1, produzindo assim um núcleo 3x3 de um único valor «1.0» cercado por valores «0.0».). Como você viu acima, aplicar a convolução com qualquer tipo de núcleo «[Unity](#unity)» não faz nada com a imagem! Se você especificar um «radius », geralmente é boa ideia torná-lo pelo menos duas vezes maior que o «sigma »; o IM normalmente calcula um raio cerca de 3 vezes maior (na verdade, o maior raio que fornecerá resultados significativos), embora isso dependa da Qualidade de Compilação da sua instalação específica do IM. Para mais informações sobre o efeito dos argumentos do núcleo «Gaussian» e sobre o desfoque de imagens em geral, veja... Desfoque de Imagens. [IM Output]

Núcleo Blur (desfoque gaussiano 1D)

O núcleo «Blur» é muito semelhante ao Núcleo Gaussian e até recebe os mesmos argumentos (ver abaixo). Mas, enquanto o gaussiano é uma curva bidimensional, o núcleo «Blur» produz uma curva unidimensional. Ou seja, gera uma única fileira longa e fina de valores. Aqui está a saída Show Kernel de um pequeno núcleo «Blur». | |

  magick xc: -define morphology:showKernel=1 \
         -morphology Convolve:0 Blur:0x0.8 null:

[IM Output]
| [IM Text]


O gráfico mostrado acima é um perfil real do núcleo «Blur» padrão. Ele foi criado usando o script Kernel Image "[kernel2image](../static/img/scripts/kernel2image)", e essa imagem foi então plotada usando o script "[im_profile](../static/img/scripts/im_profile)". Ele mostra claramente a «Curva de Sino Gaussiana» que este núcleo representa. Aqui está um exemplo de uso deste núcleo para desfocar uma imagem horizontalmente. |

  magick face.png -morphology Convolve Blur:0x4 face_blur.png

[IM Output]
A sintaxe do núcleo é exatamente como a de «[Gaussian](#gaussian)», mas com um ângulo de rotação opcional adicional.

   Blur:[{_radius_}]x{_sigma_}[,{_angle_}]

Como antes, o segundo valor «sigma » é obrigatório e, se definido como zero, você obterá o equivalente linear de um núcleo «[Unity](#unity)». O «angle » permite rotacionar o núcleo em 90 graus, possibilitando desfocar uma imagem verticalmente. |

  magick face.png -morphology Convolve Blur:0x4,90 face_blur_vert.png

[IM Output]
No momento, só é possível uma rotação de 90 graus. Isso pode mudar em uma versão posterior do ImageMagick. O propósito deste núcleo é, na verdade, criar uma forma mais rápida de desfoque bidimensional de imagem do que a que o núcleo «[Gaussian](#gaussian)» produz. Veja Núcleos Gaussian vs Blur abaixo para detalhes de como isso é feito. [IM Output]

Núcleo Comet (meio desfoque gaussiano 1D)

O núcleo «Comet» é quase exatamente igual a um núcleo «[Blur](#blur)», mas, na verdade, é apenas meio núcleo de desfoque.

  magick xc: -define morphology:showKernel=1 \
         -morphology Convolve:0 Comet:0x1.0 null:

[IM Text]

Observe como a posição definida da origem fica na borda esquerda, e não no centro do núcleo. Isso é muito incomum para um núcleo de convolução e, por isso, produz um resultado muito incomum. Ele desfoca a imagem em uma direção, como se um dedo tivesse borrado a superfície de uma pintura molhada, deixando um rastro de cor. É um pouco como a cauda de um cometa, ou o rastro deixado por um meteoro ou estrela cadente. |

  magick face.png -morphology Convolve Comet:0x5 face_comet.png

[IM Output]
Observe que tanto as cores de primeiro plano quanto as de fundo foram «borradas». Se você quiser desfocar apenas as cores de primeiro plano, torne o fundo transparente e adicione-o depois que o primeiro plano tiver sido desfocado. Você também pode fornecer um terceiro argumento angle para rotacionar o núcleo em qualquer múltiplo de 90 graus em torno de sua «origem». |

  magick face.png -morphology Convolve comet:0x5+90 face_comet_vert.png

[IM Output]
Na verdade, este núcleo é o mesmo usado pelo operador especializado de Desfoque de Movimento, embora esse operador também faça um tratamento bastante sofisticado de busca de coordenadas para permitir que o desfoque funcione em qualquer ângulo. Ainda que o faça mal, produzindo «aglomerados» de cor em ângulos grandes, como 45 graus. Espera-se que uma rotação de núcleo adequada seja implementada para criar melhores efeitos do tipo desfoque de movimento em ângulos fora dos incrementos de 90 graus. [IM Output]

Núcleos Gaussian vs Blur

Como mencionado, os núcleos «[Gaussian](#gaussian)» e «[Blur](#blur)» estão intimamente relacionados e podem, de fato, fazer o mesmo trabalho. Ambos são representações da Curva Gaussiana, sendo o primeiro uma representação bidimensional, enquanto o outro é uma representação unidimensional. Por exemplo, aqui está uma repetição da operação "-gaussian-blur 0x2", que é equivalente a "-morphology Convolve Gaussian:0x2". |

  magick face.png -gaussian-blur 0x2 face_gaussian-blur.png

[IM Output]
Isso pode ser substituído pelo uso de duas operações de desfoque lineares (ou unidimensionais) separadas, rotacionadas noventa graus entre si (a ordem também não importa muito)... |

  magick face.png -morphology Convolve Blur:0x2 \
         -morphology Convolve Blur:0x2+90 face_blur_x2.png

[IM Output]
Em vez de especificar duas convoluções separadas, você pode fornecer ambos os núcleos como uma lista de núcleos. Por exemplo

  magick face.png -morphology Convolve 'Blur:0x2;Blur:0x2+90' face_blur_x2.png

Por padrão, o IM «re-itera» o resultado do primeiro núcleo de convolução com o segundo (e os seguintes) núcleo de convolução, conforme definido pela configuração de Composição de Múltiplos Núcleos. Você pode até simplificar ainda mais o acima, pedindo ao IM para expandir um núcleo em uma Lista de Núcleos Rotacionados, usando um «>» para fazer uma lista de rotações de 90 graus (dois núcleos, neste caso). Por exemplo...

  magick face.png -morphology Convolve 'Blur:0x2>' face_blur_x2.png

Todos os exemplos acima são equivalentes entre si e é assim que o operador "[-blur](https://imagemagick.org/command-line-options/#blur)" funciona. |

  magick face.png -blur 0x2 face_blurred.png

[IM Output]
Isso representa a real diferença entre os operadores "[-blur](https://imagemagick.org/command-line-options/#blur)" e "[-gaussian-blur](https://imagemagick.org/command-line-options/#gaussian-blur)". No último, é usado um único núcleo bidimensional grande, enquanto o primeiro usa dois núcleos unidimensionais pequenos. Em termos de velocidade, porém, o operador "[-blur](https://imagemagick.org/command-line-options/#blur)" costuma ser uma ordem de magnitude mais rápido, pois usa dois núcleos muito menores, em vez de um único muito grande. Quanto maior o argumento de desfoque (o tamanho do argumento sigma), maiores os núcleos se tornam e maior a diferença de velocidade entre as duas operações. Assim, o operador "[-blur](https://imagemagick.org/command-line-options/#blur)" é geralmente o recomendado. A única diferença nos resultados entre os dois operadores são pequenos efeitos de arredondamento de quantum (a menos que você use HDRI) e efeitos de borda (dependendo da Configuração de Pixel Virtual). Ambos são causados por uma perda de informação gerada ao salvar uma imagem intermediária entre os dois passos separados das convoluções de «desfoque». Essa diferença costuma ser tão pequena a ponto de ser invisível e sem importância para qualquer uso prático.

Desfoque Suavizado (mistura com a imagem original)

Você pode suavizar o impacto de qualquer tipo de desfoque misturando-o com parte da imagem original. Especialmente ao aplicar um desfoque muito forte. Por exemplo...

  magick face.png -morphology Convolve Gaussian:0x3 face_strong_blur.png
  magick face.png face_strong_blur.png \
         -compose Blend -define compose:args=60,40% -composite \
         face_soft_blur.png

[IM Output] [IM Output] [IM Output]

Isso usou o método de composição «[Blend](compose.html#blend)» para misturar «60%» da imagem desfocada (imagem de origem da composição) com «40%» da imagem original (imagem de destino da composição), a fim de dar um efeito de «desfoque suave» à imagem final. No entanto, você pode fazer o mesmo diretamente Misturando o Núcleo com o Núcleo Identidade, usando a mesma proporção. |

  magick face.png -define convolve:scale=60,40% \
         -morphology Convolve 'Gaussian:0x3' face_soft_blur2.png

[IM Output]
Observe que a ordem dos números de escala é a mesma. O primeiro número («60%») escalona o núcleo dado de modo a reduzir seu efeito na saída, enquanto o segundo número («40%») adiciona uma quantidade suficiente do núcleo «[Unity](#unity)» (ou «Identidade») para evitar que o resultado fique mais escuro. O ponto importante é que, para os Núcleos de Desfoque, os dois números somam «100%», assim como você faria para a Mistura por Composição. Você também pode usar o desfoque de 2 passos mais rápido, mas, neste caso, não podemos incorporar um «Blend» diretamente no núcleo, pois as duas convoluções separadas não se «separam» de forma limpa. Assim, precisaremos novamente fazer a Composição Blend depois. |

  magick face.png \( +clone -blur 0x3 \) \
         -compose Blend -define compose:args=60 -composite \
         face_soft_blur3.png

[IM Output]
Observe que você só precisa fornecer a quantidade da imagem desfocada (de origem) que deseja misturar com a imagem original. Assim, valores de «100» darão a imagem desfocada, enquanto «0» dará a imagem original. | Lembre-se de que o operador "[-blur](https://imagemagick.org/command-line-options/#blur)" é exatamente equivalente ao uso dos Núcleos de Desfoque de 2 passos mais rápidos.
---|---

«Un-sharpen» de Imagens usando Desfoques (subtração da imagem original)

Levando essa mistura de núcleos adiante, de modo a começar a usar um escalonamento negativo, você pode subtrair os efeitos de desfoque da imagem original. O resultado é uma técnica chamada «unsharp». Veja Unsharp, Wikipedia para saber como ela acabou ganhando um nome tão infeliz. |

  magick face.png -define convolve:scale=-100,200% \
         -morphology Convolve 'Gaussian:0x2' face_unsharp.png

[IM Output]
Observe que, mesmo usando um fator de escala de núcleo negativo, os dois números ainda somam «100%», exatamente como acima. Você também pode fazer isso com a Mistura por Composição. O exemplo acima é, na verdade, exatamente como funciona o operador de nome enganoso "[-sharpen](https://imagemagick.org/command-line-options/#sharpen)", mas com apenas o controle de desfoque «sigma ». No entanto, nenhum outro controle da operação é fornecido. A mistura é exatamente como dada acima. Você pode usar os Núcleos de Desfoque unidimensionais de 2 passos mais rápidos, mas, novamente, precisará fazer a operação de mistura como um passo separado. |

  magick face.png \( +clone -blur 0x2 \) \
         -compose Blend -define compose:args=-100,200 -composite \
         face_unsharp_fast.png

[IM Output]
Como você já deve ter percebido, isto é quase idêntico ao Desfoque Suavizado, mas com a imagem desfocada sendo subtraída da imagem original em vez de somada. Um método de mistura conhecido como Mistura Extrapolada, ou mistura além da faixa normal de 0 a 100 por cento. Novamente, você pode simplesmente especificar quanto da imagem desfocada deseja subtrair da imagem original. Por exemplo, vamos exagerar no unsharpen da imagem, causando algum aliasing e distorções de cor. |

  magick face.png \( +clone -blur 0x2 \) \
         -compose Blend -define compose:args=-200 -composite \
         face_unsharp_200.png

[IM Output]
O operador completo "[-unsharp](https://imagemagick.org/command-line-options/#unsharp)" fornece outro tipo de controle. Especificamente, um limiar de diferença, de modo que o aguçamento só seja aplicado quando a diferença dada for maior, como perto de uma borda real dentro da imagem. Esse limiar pode ser usado para evitar o «aguçamento» de pequenos defeitos, como rugas ou ruído de câmera. O unsharpen de uma imagem é tipicamente usado com desfoques muito pequenos (da ordem de sigma=0.75) após redimensionar ou distorcer a imagem, para melhorar o resultado final. Veja Aguçar Imagens Redimensionadas para alguns exemplos disso. A alternativa ao uso de uma técnica «unsharp» para aguçar imagens é, de fato, localizar as bordas da imagem e usá-las para aguçá-la. Veja Aguçamento de Imagens com Detecção de Bordas abaixo para detalhes. No entanto, ela é geralmente considerada mais lenta, embora não muito.


Convoluções de Detecção de Bordas (filtragem passa-alta)

A Detecção de Bordas é outra área em que as convoluções são muito usadas. A tarefa aqui é realçar ou enfatizar as bordas de uma imagem de várias formas. Isso pode ser para localizar uma borda com a maior precisão possível ou para determinar o ângulo ou a direção da inclinação de cada uma das bordas. No entanto, a tarefa pode ser bastante dificultada pela presença de ruído na imagem, como o produzido por scanners, câmeras digitais ou mesmo o causado pela compressão com perdas do formato de arquivo JPEG. Em geral, porém, núcleos maiores lidam melhor com o ruído, mas ao custo de localizar a borda de forma adequada, enquanto núcleos menores produzem resultados de localização de borda nítidos, porém com mais resultados espúrios causados pelo ruído na imagem. Há muitos núcleos pequenos e bem conhecidos que foram desenvolvidos e estudados para a detecção de bordas. A maioria deles recebe o «nome» do matemático que estudou a matemática ou desenvolveu aquele tipo específico de núcleo. Assim, você tem núcleos como «[Laplacian](#laplacian)», «[Sobel](#sobel)» e «[Prewitt](#prewitt)». Esses núcleos «nomeados» geralmente são muito pequenos e são definidos com números inteiros, de modo que podem ser embutidos em software e hardware otimizados e especialmente projetados para velocidade. Ou seja, diz-se que são núcleos «discretos». Por causa disso, você precisará Escalonar ou Normalizar o núcleo como parte de seu uso. A detecção de bordas também tem o efeito colateral de oferecer formas de aguçar as bordas de uma imagem.

Núcleos de Soma Zero

Todos os núcleos de detecção de bordas têm uma característica em comum: são todos de soma zero. Isso significa que contêm valores negativos, mas com a soma de todos os valores do núcleo igual a zero. Para uma imagem de cor lisa e uniforme, uma Convolução usando tal núcleo produzirá uma imagem «zero» ou preta. No entanto, para qualquer outra imagem, você terá resultados que contêm valores tanto negativos quanto positivos. Por exemplo, aqui aplico um detector de bordas «[Sobel](#sobel)» discreto a uma imagem que contém algumas formas básicas...

  magick -size 80x80 xc:black \
         -fill white -draw 'rectangle 15,15 65,65' \
         -fill black -draw 'circle 40,40 40,20' shapes.gif
  magick shapes.gif -define convolve:scale='!' \
         -morphology Convolve Sobel shapes_sobel.gif

[IM Output] [IM Output]

Se você olhar os resultados, verá que o núcleo é direcional, no sentido de que apenas as bordas verticais são encontradas (conforme definido pelo núcleo «[Sobel](#sobel)» com ângulo zero). No entanto, ele encontrou apenas um conjunto de bordas: as inclinações «positivas» da esquerda para a direita, de preto para branco. Para obter as inclinações «negativas», você precisará negar o núcleo, usando a Configuração de Escalonamento do Núcleo. Por exemplo... |

  magick shapes.gif -define convolve:scale='-1!' \
         -morphology Convolve Sobel shapes_sobel_neg.gif

[IM Output]
Com um núcleo «[Sobel](#sobel)», você também pode rotacioná-lo 180 graus para obter o mesmo resultado que a «negação por escala», mas nem todos os núcleos são simétricos dessa forma. A outra solução é adicionar um Viés de Saída ao resultado. Ou seja, adicionar 50% de cinza à imagem resultante, de modo que os valores negativos fiquem mais claros que isso e os positivos, mais brilhantes. No entanto, você também precisará Escalonar o Núcleo para garantir que os resultados não sejam «cortados» pelos limites de «preto» e «branco» da imagem. |

  magick shapes.gif -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Sobel shapes_sobel_bias.gif

[IM Output]
Se você não se importa com a polaridade, pode obter um valor absoluto dos resultados com um pequeno truque.. |

  magick shapes.gif -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Sobel -solarize 50% -level 50,0% \
         shapes_sobel_abs.gif

[IM Output]
Veja o núcleo «[Sobel](#sobel)» para mais técnicas de tratamento de resultados, especialmente técnicas que envolvem a determinação de direção. A outra alternativa ao uso de um Viés de Saída é compilar uma versão HDRI especial do ImageMagick. Ela armazena as imagens na memória usando valores em ponto flutuante e significa que os valores da imagem não serão «cortados» nem «arredondados» pelo uso de inteiros. No entanto, mesmo que você use essa versão especial do IM, ainda precisará pós-processar os resultados antes de salvar em um formato de arquivo de imagem normal, ou precisará usar um formato de arquivo de imagem com suporte a ponto flutuante. Por outro lado, você não precisará se preocupar com efeitos de corte ou arredondamento nos resultados de imagem intermediários, tornando as coisas mais fáceis de lidar.

Núcleos de Detecção de Bordas

[IM Output]

LoG: Laplaciano de Gaussianas

   LoG:{_radius_},{_sigma_}

O «LoG», ou "Laplaciano de uma Gaussiana", é um dos melhores núcleos de detecção de bordas disponíveis. Também é conhecido como núcleo «Chapéu Mexicano». Basicamente, é um operador diferencial (de inclinação) «[Laplacian](#laplacian)» que foi suavizado pela adição de um desfoque gaussiano. Isso, por sua vez, remove a maior parte do impacto do ruído em uma imagem, o que pode ser ajustado pela configuração «sigma ». O núcleo contém valores negativos que formam um anel ao redor de um forte pico central. Na «Imagem do Núcleo» mostrada acima, os negativos aparecem como as cores escuras (quase pretas), com as bordas decaindo para zero (cinza-escuro) em direção às extremidades. E aqui está seu efeito.. mostrando como ele realça as bordas da imagem.

  magick face.png -bias 50% -morphology Convolve LoG:0x2 face_log.png

[IM Output] [IM Output] [IM Output]

Um núcleo laplaciano não tem direção, mas produz tanto uma crista positiva quanto uma negativa de valores em cada lado de uma borda. Para localizar a borda, você procuraria os pontos de cruzamento por zero, entre as cristas positiva e negativa, uma técnica conhecida como Detecção de Bordas de Marr e Hildreth. Este núcleo também é ideal para Aguçar Imagens.
[IM Output]

DoG: Diferença de Gaussianas

   DoG:{_radius_},{_sigma1_}[,{_sigma2_}]

Isso gerará um núcleo «DoG», ou "Diferença de Gaussianas", em que a gaussiana gerada por «sigma1 » tem subtraída dela a gaussiana gerada por «sigma2 ». Normalmente, «sigma2 » é o maior, de modo que o «pico central» do núcleo seja positivo. Inverter os dois números na prática nega o núcleo resultante. Uma das principais críticas ao Laplaciano de uma Gaussiana é que ele é difícil de implementar, por ser uma curva matemática tão incomum. Também é uma curva pouco documentada. O outro aspecto é que ele não pode ser «separado» em uma solução de 2 passos mais rápida, como se pode com uma Gaussiana (ver Núcleos Gaussian vs Blur). No entanto, ao gerar dois núcleos «[Gaussian](#gaussian)» com valores de sigma ligeiramente diferentes (em uma proporção de aproximadamente 1.6) e subtraí-los um do outro, você pode, na verdade, gerar uma aproximação próxima de um Laplaciano de uma Gaussiana. O resultado é que um «[DoG](#dog)» é gerado em hardware com muito mais facilidade do que um núcleo «[LoG](#log)». Por exemplo, aqui coloquei lado a lado as Imagens de Núcleo de um «[LoG](#log)» e de um «[DoG](#dog)» para comparação.

[IM Output] [IM Output]

Se você olhar a página da web Difference of Gaussian, Wikipedia, verá alguns gráficos em que também se compara o perfil de um «[LoG](#log)» (ou «Chapéu Mexicano») com um «[DoG](#dog)», mostrando a diferença muito sutil entre as curvas correspondentes. Gostaríamos de mais informações sobre como mapear um sigma de um LoG para gerar um «DoG» quase equivalente. Se você souber, por favor escreva para o endereço no rodapé. Os resultados aplicados também são muito semelhantes. |

  magick face.png -bias 50% -morphology Convolve DoG:0,1.8,2.4 face_dog.png

[IM Output]
Observe que ambos os valores «sigma » devem ser definidos e pelo menos um deve ser diferente de zero. Um valor zero para qualquer componente sigma equivalerá a um núcleo «[Unity](#unity)», ou seja, mantém a imagem inalterada. Se ambos os valores forem zero, as duas Gaussianas seriam núcleos «[Unity](#unity)», que, quando subtraídos, produziriam um resultado perfeitamente zero ou preto (mais qualquer valor de viés). Quando os argumentos são «Dog:0,0,_non-zero_, o DoG torna-se um simples filtro passa-alta, definido como o núcleo «Unity» (que produz a imagem original) menos um núcleo de filtro passa-baixa (imagem desfocada). Nesse caso, sigma1=0 é apenas o núcleo «Unity» e sigma2=non-zero é um núcleo de filtro passa-baixa (desfoque) gaussiano. O seguinte, portanto, produz uma imagem filtrada passa-alta com valor de filtro sigma2=2 |

  magick face.png -bias 50% -morphology Convolve DoG:0,0,2 face_dog_unity.png

[IM Output]
Um filtro passa-alta do Photoshop com valor de filtro raio=2 produz o mesmo resultado. Observe que usar «DoG:0,2,0» retornará uma imagem que é basicamente a versão negada (em torno do Viés de Saída) da imagem anterior. Essa técnica também pode ser usada para gerar um núcleo «Laplaciano Isotrópico» 3x3, ou seja, um núcleo «[Laplacian](#laplacian)» que produz resultados iguais em todas as direções, em vez de ter um viés diagonal desigual. Por exemplo, raio=1 (para um núcleo 3x3) e um sigma de 1 gerarão... | |

  magick face.png -define morphology:showKernel=1 -bias 50% \
          -morphology Convolve DoG:1,0,1 face_laplacian_isotropic.png

[IM Text]
| [IM Text]


O outro ponto sobre usar uma "Diferença de Gaussianas" é que você pode usar o operador "[-blur](https://imagemagick.org/command-line-options/#blur)" muito mais rápido (que internamente usa os núcleos «[Blur](#blur)») para gerar os mesmos resultados. No entanto, para isso, você precisará gerar cada uma das duas imagens «desfocadas» separadamente e, então, subtrair os resultados, com a adição de um escalonamento e um viés apropriados. Por exemplo... |

  magick face.png \
         \( -clone 0 -blur 0x1.8 \) \( -clone 0 -blur 0x2.4 \) -delete 0 \
         -compose Mathematics -define compose:args=0,-4,4,0.5 -composite \
         face_diff_of_blurs.png

[IM Output]
O acima usa o Método de Composição Mathematics especial para evitar problemas com «corte» durante a subtração das imagens em uma versão não HDRI do IM. Para mais detalhes, veja Adicionando Gradientes com Viés. O único outro fator é o uso de um fator de escala maior durante a subtração (os dois «4» no argumento de Composição Mathematics). Isso porque subtrair dois desfoques normalizados não produz a mesma magnitude (aumentada) de resultados que você obtém ao normalizar juntas as duas curvas gaussianas subtraídas em um núcleo «[DoG](#dog)». No entanto, além da magnitude, a imagem de exemplo acima é equivalente ao primeiro resultado do núcleo «[DoG](#dog)», apenas mais rápida de gerar, especialmente para valores de sigma maiores. E esse é o ponto: embora dê mais trabalho, esse método complexo é mais rápido do que usar um núcleo «[DoG](#dog)» ou «[LoG](#log)» diretamente.

Núcleos Laplacianos Discretos

   Laplacian:{_type_}

Foram publicadas muitas formas de pequenos "Núcleos Laplacianos" em diversos artigos de pesquisa científica. Aqui, forneço versões embutidas das mais comuns que consegui encontrar na literatura acadêmica. Esses núcleos são basicamente calculados usando um núcleo «[LoG](#log)», mas escalonados de modo a usar valores inteiros discretos em um pequeno arranjo de núcleo. Isso permite usar filtros de imagem rápidos e dedicados, gerados, que usam apenas aritmética de inteiros para processar os dados da imagem. No entanto, o ImageMagick é um processador de imagens mais generalizado e, por isso, não fornece um filtro dedicado tão ultrarrápido. Mas as pessoas gostam de usá-los por serem mais simples de entender, então muitos deles foram embutidos no IM. Nenhum dos núcleos fornecidos aqui é rotacionável, e a maioria é «anisotrópica», ou seja, não é perfeitamente circular, especialmente nas direções diagonais. No entanto, veja a seção anterior (núcleos «[DoG](#dog)») para uma forma de gerar um verdadeiro "Núcleo Laplaciano Isotrópico 3x3". Os dois primeiros núcleos, «Laplacian:0» e «Laplacian:1», são a forma mais comum de "Núcleo Laplaciano Discreto" em uso. São muito pequenos, o que significa que localizam bordas com muita precisão, mas também são propensos a realçar o ruído da imagem. Observe que nem todos os números de «type » foram definidos, deixando espaços para que mais núcleos discretos sejam definidos no futuro. Os números usados foram selecionados para melhor corresponder ao núcleo definido por aquele número.

Laplacian:0 (padrão)

O Laplaciano de 8 vizinhos. Provavelmente o núcleo de detecção de bordas laplaciano discreto mais comum. Aqui uso o Show Kernel para extrair o núcleo «discreto» e «não normalizado», antes de mostrar o resultado do núcleo normalizado com um Viés de Saída. | |

  magick xc: -define morphology:showKernel=1 -precision 2 \
         -morphology Convolve:0 Laplacian:0 null:
  magick face.png -define convolve:scale='!' -bias 50% \
         -morphology Convolve Laplacian:0 face_laplacian_0.png

[IM Text]
| [IM Text]


Às vezes, um Laplaciano — seja um Laplaciano discreto, como no último exemplo, seja um «[LoG](#log)» ou «[DoG](#dog)» gerado — produz um resultado mais complexo do que o desejado. Nesses casos, gerar uma imagem sem viés (sem qualquer Viés de Saída) funcionará melhor. Então, vamos repetir o acima sem um viés, de modo a manter apenas as bordas «positivas» mais claras. |

  magick face.png -define convolve:scale='!' \
         -morphology Convolve Laplacian:0 \
         -auto-level face_laplacian_positives.png

[IM Output]
Neste caso, temos linhas escuras (pretas) sobre cores mais claras (brancas). Isso, por sua vez, faz com que o filtro «duplique» as bordas, o que pode ser visto nos resultados exibidos. Para esta imagem, usar um fator de escala negativo (para manter as bordas negativas, em vez das positivas) pareceu funcionar melhor na nossa imagem de teste. |

  magick face.png -define convolve:scale='-1!' \
         -morphology Convolve Laplacian:0 \
         -auto-level face_laplacian_negatives.png

[IM Output]
Como se pode ver, para esta imagem, usar o lado negativo produz bordas mais fortes, sem os efeitos de «duplicação» que os resultados positivos produziram. Isso se deve ao uso de linhas de contorno «pretas» sobre um fundo branco na imagem utilizada. À PARTE: a razão de você obter uma borda azul ao redor da estrela amarela é que a diferença entre a estrela «amarela» e o fundo «branco» é uma subtração da cor azul. Se o fundo fosse preto, você obteria uma cor de borda amarela.

Laplacian:1

O Laplaciano de 4 vizinhos. Também muito usado. | |

  magick xc: -define morphology:showKernel=1 -precision 2 \
         -morphology Convolve:0 Laplacian:1 null:
  magick face.png -define convolve:scale='!' -bias 50% \
         -morphology Convolve Laplacian:1 face_laplacian_1.png

[IM Text]
| [IM Text]


Os resultados não são tão fortes, mas frequentemente são mais nítidos que o laplaciano de 8 vizinhos.

Laplacian:2

Laplaciano 3x3, com centro:4 borda:1 canto:-2 | |

  magick xc: -define morphology:showKernel=1 -precision 2 \
        -morphology Convolve:0 Laplacian:2 null:
  magick face.png -define convolve:scale='!' -bias 50% \
         -morphology Convolve Laplacian:2 face_laplacian_2.png

[IM Text]
| [IM Text]


Laplacian:3

Laplaciano 3x3, com centro:4 borda:-2 canto:1 | |

  magick xc: -define morphology:showKernel=1 -precision 2 \
             -morphology Convolve:0 Laplacian:3 null:
  magick face.png -define convolve:scale='400%!' -bias 50% \
         -morphology Convolve Laplacian:3  face_laplacian_3.png

[IM Text]
| [IM Text]


Este núcleo realça as bordas diagonais e tende a fazer as bordas verticais e horizontais desaparecerem. No entanto, pode ser necessário escalonar os resultados (como fiz acima) para tornar qualquer resultado visível.

Laplacian:5

Laplaciano 5x5 | |

  magick xc: -define morphology:showKernel=1 -precision 2 \
         -morphology Convolve:0 Laplacian:5 null:
  magick face.png -define convolve:scale='!' -bias 50% \
         -morphology Convolve Laplacian:5 face_laplacian_5.png

[IM Text]
| [IM Text]


A regra prática com os núcleos laplacianos é: quanto maiores, mais limpo o resultado, especialmente quando há erros envolvidos. No entanto, você também obtém menos detalhe.

Laplacian:7

Laplaciano 7x7 | |

  magick xc: -define morphology:showKernel=1 -precision 2 \
         -morphology Convolve:0 Laplacian:7 null:
  magick face.png -define convolve:scale='!' -bias 50% \
         -morphology Convolve Laplacian:7 face_laplacian_7.png

[IM Text]
| [IM Text]


Laplacian:15

Um LoG 5x5 Discreto (Sigma de aproximadamente 1.4) | |

  magick xc: -define morphology:showKernel=1 -precision 2 \
         -morphology Convolve:0 Laplacian:15 null:
  magick face.png -define convolve:scale='!' -bias 50% \
         -morphology Convolve Laplacian:15 face_laplacian_15.png

[IM Text]
| [IM Text]


Laplacian:19

Um LoG 9x9 Discreto (Sigma de aproximadamente 1.4) | |

  magick xc: -define morphology:showKernel=1 -precision 2 \
         -morphology Convolve:0 Laplacian:19 null:
  magick face.png -define convolve:scale='!' -bias 50% \
         -morphology Convolve Laplacian:19 face_laplacian_19.png

[IM Text]
| [IM Text]


Aguçamento de Imagens com Detecção de Bordas (realce das bordas da imagem original)

Os núcleos «[LoG](#log)» e «[DoG](#dog)» também podem ser usados para aguçar imagens, em contraste com Aplicar «Un-sharpen» a Imagens usando Desfoques. Basicamente, tudo o que você precisa fazer é adicionar os resultados do núcleo (incluindo os resultados negativos) à imagem original. Fazer isso é fácil: basta adicionar aos fatores de escala um núcleo «[Unity](#unity)» (ou «Identidade») com peso de 100%. Foi para isso que ele foi fornecido. Por exemplo... |

  magick face.png -define convolve:scale='100,100%' \
         -morphology Convolve 'Log:0x2' face_sharpen.png

[IM Output]
Este é um aguçamento da imagem muito mais amplo e suave do que o gerado pela Técnica de Unsharpen (resultado mostrado à direita). Isso porque é um aguçamento de fato, real, da imagem, e não um simulado pela subtração de um desfoque. | [IM Output]
---|---
Como antes, quando apenas uma convolução de passo único está sendo realizada, você pode fazer uso direto de um Núcleo Misturado. Por exemplo, menos nítido... |

  magick face.png -define convolve:scale='50,100%' \
         -morphology Convolve 'Log:0x2' face_sharpen_50.png

[IM Output]
Ou mais nítido... |

  magick face.png -define convolve:scale='150,100%' \
         -morphology Convolve 'Log:0x2' face_sharpen_150.png

[IM Output]
Você pode usar métodos de 2 passos da Diferença de Gaussianas para produzir uma operação de aguçamento em múltiplas etapas mais rápida, mas, como mostrado acima, tal esquema requer 4 convoluções e uma operação de mistura separada para alcançar o mesmo resultado. FUTURO: adicionar um exemplo disso É essa complexidade a razão de o uso do Unsharpen ser, com mais frequência, o método preferido para aguçar imagens. Mas, como se pode ver, para um processo de aguçamento intenso, usar um núcleo de aguçamento adequado é preferível a um Aguçamento por Unsharp. No entanto, para aguçamentos menores, como Aguçar Imagens Redimensionadas, não há problema em usar o unsharp.


Convoluções Direcionais (Inclinações e Bússola)

Como as anteriores, estes núcleos procuram inclinações na intensidade de cor da imagem, mas, em vez de qualquer inclinação, procuram inclinações em uma direção específica. Matematicamente, isso é conhecido como uma «derivada», que é apenas uma forma sofisticada de dizer «inclinação». Mas conhecer as informações de inclinação para diferentes direções também pode ser útil como meio de determinar o ângulo ou a direção da «bússola» de uma inclinação ou borda de imagem. Ou seja, a direção bidimensional da inclinação em uma imagem em algum ponto específico. As inclinações também são usadas em técnicas de processamento de imagem conhecidas como «relevo» (embossing) e «sombreamento» (shading) de imagens. No momento, não há núcleos «gerados» disponíveis, apenas núcleos «nomeados» predefinidos, como Sobel e Roberts. No entanto, tenho certeza de que as funções de geração de núcleos de relevo e sombreamento serão movidas para o conjunto de núcleos de morfologia/convolução em algum momento no futuro. Então, vamos dar uma olhada em alguns dos núcleos direcionais «nomeados».

Núcleos Direcionais

Sobel

   Sobel:{_angle_}

[IM Text]

Já vimos o núcleo «Sobel » acima, na discussão sobre Núcleos de Soma Zero. Este núcleo é um núcleo direcional bruto (de primeira derivada) projetado para retornar a inclinação de uma borda em alguma direção ortogonal específica. Por padrão, é projetado para a detecção de inclinação da esquerda para a direita, usando uma operação «convolve». O resultado é, essencialmente, uma derivada em X (inclinação) da imagem.

  magick -size 60x60 xc:black xc:white +append slope_positive.gif
  magick slope_positive.gif -morphology Convolve Sobel slope_sobel.gif

[IM Output] [IM Output] [IM Output]

| _Se você olhar o núcleo, pode achar que ele está declarado de forma invertida. Em certo sentido, você está realmente correto. No entanto, isso se deve à forma como o «Convolve» de fato funciona.

Você pode saber mais sobre essa «inversão» com mais detalhes em Convolve vs Correlate abaixo.

_
---|---
Observe que este núcleo também pode produzir uma indicação de «inclinação negativa», mas isso não pode ser visto a menos que um Viés de «50%» também seja usado com esta operação de convolução. Embora não haja inclinação negativa no exemplo anterior, este próximo exemplo tem uma, então também adicionei uma Configuração de Viés para que você possa vê-la.

  magick -size 40x60 xc:black xc:white xc:black +append slope_both.gif
  magick slope_both.gif -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Sobel slope_sobel_bias.gif

[IM Output] [IM Output] [IM Output]

| _Se você usar este núcleo com «Correlate», encontrará inclinações que «correspondem» à forma como o núcleo é definido. Nesse caso, você obteria um resultado positivo para uma inclinação que vai de alto (valor branco) à esquerda a baixo (valor preto) à direita. No exemplo acima, as duas linhas então seriam trocadas.

No entanto, o acima é «Convolução», e não uma «Correlação» (ou seja, corresponder ao núcleo). Novamente, veja Convolve vs Correlate para mais detalhes sobre a diferença._
---|---
Como se pode ver, agora obtemos uma linha branca (inclinação positiva) à medida que subimos a inclinação de preto para branco, e uma linha preta (inclinação negativa) à medida que descemos de branco para preto. Aqui está o resultado do uso do núcleo «Sobel» padrão na imagem do rosto.

  magick face.png -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Sobel face_sobel.png

[IM Output] [IM Output] [IM Output]

Observe que o sobel, e a maioria dos outros núcleos de detecção de bordas, tende a produzir uma resposta de 2 pixels de espessura ao longo de uma borda muito forte, e uma resposta de 3 pixels sobre uma linha de um único pixel de largura. Isso é muito mais forte que um detector de bordas laplaciano. Você pode rotacionar este núcleo usando o argumento «angle », geralmente em múltiplos de 90 graus. No entanto, você também pode rotacioná-lo em múltiplos de 45 graus, ainda que ele não tenha sido projetado para isso. Isso é útil para obter derivadas direcionais quantizadas em 45 graus, ou a magnitude do gradiente a partir do máximo de todos os resultados de derivada rotacionados em 45 graus. Aqui está ele de novo, mas rotacionado 90 graus (de cima para baixo). |

  magick face.png -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Sobel:90 face_sobel_90.png

[IM Output]

Uma forma de coletar todas as bordas de uma imagem usando um núcleo «[Sobel](#sobel)» é aplicar o núcleo 4 vezes em todas as direções e coletar o valor máximo observado (usando uma Composição Matemática Lighten). Esta é uma aproximação da magnitude do gradiente. |

   magick face.png -define convolve:scale='!' \
          \( -clone 0 -morphology Convolve Sobel:0 \) \
          \( -clone 0 -morphology Convolve Sobel:90 \) \
          \( -clone 0 -morphology Convolve Sobel:180 \) \
          \( -clone 0 -morphology Convolve Sobel:270 \) \
          -delete 0 -background Black -compose Lighten -flatten \
          face_sobel_maximum.png

[IM Output]
Você pode simplificar o acima fazendo uso dos recursos de Manuseio de Múltiplos Núcleos da morfologia do IM. Ou seja, você pode criar uma lista rotacionada de todas as rotações de 90 graus do núcleo «[Sobel](#sobel)». |

   magick face.png -define convolve:scale='!' \
          -define morphology:compose=Lighten \
          -morphology Convolve 'Sobel:>' face_sobel_maximum_2.png

[IM Output]
Se você quiser ver exatamente o que o acima está fazendo, adicione a configuração Show Kernel e a configuração Verbose. Uma técnica mais eficiente para gerar uma magnitude de gradiente seria usar o fato de que uma rotação de 180 graus simplesmente produz o mesmo resultado que negar o núcleo e, portanto, negar os resultados. Assim, as derivadas em X e Y (convoluções rotacionadas em 90 graus), com um pouco de truque para obter os valores absolutos da convolução, podem alcançar tal resultado com menos processamento. |

   magick face.png -define convolve:scale='50%!' -bias 50% \
          \( -clone 0 -morphology Convolve Sobel:0 \) \
          \( -clone 0 -morphology Convolve Sobel:90 \) \
          -delete 0 -solarize 50% -level 50,0% \
          -compose Lighten -composite face_sobel_maximum_3.png

[IM Output]
Isso costuma ser suficiente para a maioria dos propósitos. Uma magnitude mais exata de todas as inclinações pode ser extraída fazendo uma adição vetorial das duas derivadas X e Y (conforme o Teorema de Pitágoras). |

   magick face.png -define convolve:scale='50%!' -bias 50% \
          \( -clone 0 -morphology Convolve Sobel:0 \) \
          \( -clone 0 -morphology Convolve Sobel:90 \) \
          -delete 0 -solarize 50% -level 50,0% \
          +level 0,70% -gamma 0.5 -compose plus -composite -gamma 2 \
          -auto-level face_sobel_magnitude.png

[IM Output]
| _A função "[-gamma](https://imagemagick.org/command-line-options/#gamma)" no uso acima está sendo empregada para realizar um «Quadrado» e uma «Raiz Quadrada» matemáticos dos valores retornados pelos resultados «[Sobel](#sobel)». Para mais detalhes, veja Função Matemática de Potência.

O "[+level](https://imagemagick.org/command-line-options/#level)" extra garante que a Composição Plus não estoure a faixa de quantum da imagem. Veja Efeitos de Quantum, não HDRI vs HDRI para detalhes._
---|---
Em vez da magnitude, você pode extrair a direção da inclinação a partir dos dois resultados de detecção de bordas.

  magick -size 30x600 xc:'#0F0' -colorspace HSB \
         gradient: -compose CopyRed -composite \
         -colorspace RGB -rotate 90  rainbow.jpg
  magick shapes.gif -define convolve:scale='50%!' -bias 50% \
         \( -clone 0 -morphology Convolve Sobel:0 \) \
         \( -clone 0 -morphology Convolve Sobel:90 \) \
         -delete 0 \
         \( -clone 0,1 -fx '0.5+atan2(v-0.5,0.5-u)/pi/2' rainbow.jpg -clut \) \
         \( -clone 0,1 -fx 'u>0.48&&u<0.52&&v>0.48&&v<0.52 ? 0.0 : 1.0' \) \
         -delete 0,1 -alpha off -compose CopyOpacity -composite \
         face_sobel_direction.png

[IM Output] [IM Output]

A primeira expressão "[-fx](https://imagemagick.org/command-line-options/#fx)" é a que usa uma função «atan()» para transformar um vetor X,Y em um ângulo. Isso é então colorido com uma Imagem de Gradiente Arco-Íris externa, como uma Tabela de Consulta de Cores. A segunda expressão "[-fx](https://imagemagick.org/command-line-options/#fx)" cria uma máscara de transparência com limiar para tornar transparentes quaisquer áreas sem inclinação. No entanto, a técnica acima tende a produzir uma enorme confusão de informação para imagens reais, pois não leva em conta a magnitude da inclinação. Aqui está outra versão mais complexa. Ela faz quase todos os cálculos no canal verde «G», de modo a reduzir a quantidade de processamento de imagem necessário por um fator de três. Em seguida, usa o espaço de cor HSB para criar direção (matiz) e magnitude (brilho). |

  magick face.png -colorspace Gray    -channel G \
         -define convolve:scale='50%!' -bias 50% \
         \( -clone 0 -morphology Convolve Sobel:0 \) \
         \( -clone 0 -morphology Convolve Sobel:90 \) \
         -delete 0 \
         \( -clone 0,1 -fx '0.5 + atan2(v-0.5,0.5-u)/pi/2' \) \
         \( -clone 0   -fill white -colorize 100% \) \
         \( -clone 0,1 -fx 'hypot(u-0.5,v-0.5)*2' \) \
         -delete 0,1 -separate +channel \
         -set colorspace HSB -combine -colorspace RGB \
         face_sobel_magnitude_n_direction.png

[IM Output]

Roberts

   Roberts:{_angle_}

[IM Text]

O núcleo «Roberts» é muito mais simples que o núcleo «[Sobel](#sobel)» anterior e produz uma localização de borda ainda mais estreita (até 2 pixels). Claro que isso também o torna mais propenso a efeitos de ruído. Normalmente, este núcleo é representado por um núcleo bem menor, 2x1 ou mesmo 2x2; no entanto, implementando-o como um núcleo 3x3, posso rotacionar o núcleo «ciclicamente» em incrementos de 45 graus. Por exemplo, aqui está um resultado de 45 graus, mais comumente conhecido como núcleo «Roberts-Cross». |

  magick face.png -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Roberts:45 face_roberts.png

[IM Output]
Assim como com «[Sobel](#sobel)», você também pode usar o Manuseio de Múltiplos Núcleos para gerar uma inclinação máxima a partir de todas as direções. Mas, desta vez, obteremos 8 direções de 45 graus, em vez de apenas 4. |

   magick face.png -define morphology:compose=Lighten \
          -morphology Convolve 'Roberts:@' face_roberts_maximum.png

[IM Output]
Observe que, como rotacionar este núcleo em 180 graus não gera um resultado negado (devido a um deslocamento), você não pode simplesmente mesclar metade do número de convoluções, como pode com «[Sobel](#sobel)». Basicamente, a inclinação gerada por apenas uma convolução «[Roberts](#roberts)» está deslocada meio pixel em relação ao alinhamento com a imagem real. Ou seja, a inclinação calculada localiza-se para um ponto entre os valores «+1» e «-1», entre os pixels, mas armazenada no pixel central «-1». No entanto, isso também significa que, salvando todas as inclinações ao redor de um pixel e somando-as, você obtém uma detecção de bordas muito menor e mais nítida, com apenas 2 pixels (em vez de 4 pixels) realçando os limites nítidos das bordas.

Prewitt

   Prewitt:{_angle_}

[IM Text]

O núcleo «Prewitt» é muito semelhante a um «[Sobel](#sobel)», embora bem mais frouxo quanto à direção exata da detecção de bordas específica. O resultado é, portanto, um pouco mais difuso. |

  magick face.png -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Prewitt face_prewitt.png

[IM Output]

Compass

   Compass:{_angle_}

[IM Text]

Este é o núcleo «Prewitt Compass», que supostamente tem um senso direcional mais forte que «[Sobel](#sobel)». |

  magick face.png -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Compass face_compass.png

[IM Output]

Kirsch

   Kirsch:{_angle_}

[IM Text]

Este é outro detector de bordas com forte sensibilidade à direção. |

  magick face.png -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Kirsch face_kirsch.png

[IM Output]

Frei-Chen

Este recurso embutido fornece três conjuntos de núcleos. O primeiro é uma variante «Isotrópica» (direção uniforme) de «[Sobel](#sobel)», em que os valores «2» foram substituídos por uma Raiz Quadrada de 2.

   Frei-Chen:[{_type_},][{_angle_}]

[IM Text]

O núcleo acima é o núcleo padrão, sem ponderação, que é o coração do núcleo «Frei-Chen». |

  magick face.png -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Frei-Chen face_freichen.png

[IM Output]
Assim como «[Sobel](#sobel)», este núcleo deve ser aplicado usando um ângulo em múltiplos de 90 graus. Para facilitar, dois núcleos (com a mesma ponderação) foram fornecidos: um como o acima, para uso ortogonal, e o outro para uso diagonal.

Frei-Chen:1

[IM Text]
Frei-Chen:2
[IM Text]

O terceiro conjunto de tipos consiste em 9 núcleos especialmente projetados e ponderados, usados não apenas para a detecção de bordas em uma direção específica, mas também para determinar o ângulo real de uma borda nítida. O «type » neste caso é um número de «11» a «19», permitindo extrair qualquer um dos 9 núcleos do conjunto. No entanto, se você fornecer um valor de «type » de «10», obterá uma lista de múltiplos núcleos com todos os 9 núcleos pré-ponderados.

Cada um dos núcleos é aplicado à imagem original, e depois os resultados são
somados para gerar o resultado da detecção de bordas.

Isso é feito melhor usando uma versão [HDRI](basics.html#hdri) do
ImageMagick.




   magick image.png \
          \( -clone 0 -morphology Convolve FreiChen:11 \) \
          \( -clone 0 -morphology Convolve FreiChen:12 \) \
          \( -clone 0 -morphology Convolve FreiChen:13 \) \
          \( -clone 0 -morphology Convolve FreiChen:14 \) \
          \( -clone 0 -morphology Convolve FreiChen:15 \) \
          \( -clone 0 -morphology Convolve FreiChen:16 \) \
          \( -clone 0 -morphology Convolve FreiChen:17 \) \
          \( -clone 0 -morphology Convolve FreiChen:18 \) \
          \( -clone 0 -morphology Convolve FreiChen:19 \) \
          -delete 0 -background Black -compose Plus -flatten \
          result.pfm




Se for dado um type de 10, então é gerada uma lista de múltiplos núcleos com todos os 9
núcleos ponderados mostrados acima. Isso permite usar a composição de múltiplos núcleos para
fazer o acima de forma muito mais simples...




    magick image.png -define morphology:compose=Plus \
           -morphology Convolve FreiChen:10 \
           result.pfm




No entanto, não descobri qual é o suposto significado dos resultados.  Se
alguém tiver experiência ou conhecimento sobre como isso é de fato usado, por favor
me avise, para que eu possa incluí-lo aqui para outros usarem.

Correlate ( )

Enquanto o método «[Convolve](#convolve)» é basicamente usado para processamento de imagens, o método «Correlate» é projetado mais para a correspondência de padrões. Ou seja, ele realiza uma «Correlação Cruzada» de uma imagem com seu núcleo, buscando uma correspondência da forma dada dentro da imagem. Na realidade, tanto «[Convolve](#convolve)» quanto «Correlate» são a mesma operação. A única diferença entre eles é, na verdade, muito pequena: uma reflexão em x e y (equivalente a uma rotação de 180 graus) do núcleo. O melhor guia que encontrei sobre como a correlação e a convolução funcionam e como diferem entre si é Class Notes for CMSC 426, Fall 2005, by David Jacobs.

Convolução vs Correlação (efeitos de núcleos assimétricos)

Como mencionei acima, os dois operadores «[Convolve](#convolve)» e «[Correlate](#correlate)» são essencialmente iguais. Na verdade, os usuários costumam dizer convolução quando o que realmente querem dizer é correlação. Além disso, a correlação é, na verdade, o método mais simples de entender. Para núcleos simétricos em torno de uma «origem» central, o que é bem típico, os dois métodos são de fato iguais. A diferença só se torna aparente quando se usa um núcleo assimétrico ou irregular. Por exemplo, aqui uso um núcleo «plano» em forma de «L» sobre a nossa imagem de «pixel único».

  magick pixel.gif  \
         -morphology Convolve '3: 1,0,0
                                  1,0,0
                                  1,1,0' convolve_shape.gif

[IM Output] [IM Output] [IM Output]

Como se pode ver, uma «[Convolve](#convolve)» expandiu o pixel único no centro para formar a forma de «L» ao seu redor. Mesmo quando a própria origem não fazia parte da «vizinhança». Agora, vamos repetir este exemplo, mas usando «[Correlate](#correlate)» em vez disso.

  magick pixel.gif  \
         -morphology Correlate '3: 1,0,0
                                   1,0,0
                                   1,1,0' correlate_shape.gif

[IM Output] [IM Output] [IM Output]

Como se pode ver, «[Correlate](#correlate)» também expandiu o pixel único, formando uma forma de «L», mas era uma forma de «L» «rotacionada». Essa é, essencialmente, a única diferença entre esses dois métodos. O método «[Correlate](#correlate)» aplica o núcleo «TAL COMO ESTÁ», o que resulta na expansão do pixel único em uma forma «rotacionada». Por outro lado, «[Convolve](#convolve)» na verdade usa uma forma «rotacionada» em 180 graus do núcleo, de modo que cada pixel seja expandido na mesma forma não rotacionada. Se você quiser ver ótimos exemplos de como «[Convolve](#convolve)» de fato funciona, recomendo também dar uma olhada em EECE \ CS 253 Image Processing, Lecture 7, Spatial Convolution. O diagrama na página 22, onde ele de fato aplica o núcleo «refletido» a um único pixel, exatamente como fiz acima.
Essa diferença de rotação pode não parecer grande coisa, mas significa que, em termos da matemática, uma operação de convolução (representada por um símbolo de asterisco («*»)) é Comutativa, no sentido de que, se tanto o núcleo quanto a imagem fossem tratados apenas como um arranjo de valores (ou duas imagens), então F * G == G * F. Também significa que a convolução é Associativa, no sentido de que ( F * G ) * H == F * ( G * H ). Veja Propriedades da Convolução, Wikipedia para mais informações sobre isso. A operação «[Correlate](#correlate)» não é nem Comutativa nem Associativa, embora esteja intimamente relacionada (por rotação do núcleo). Basicamente, «[Convolve](#convolve)» age mais como uma «multiplicação» matemática, enquanto «[Correlate](#correlate)» não. A exceção a toda essa complicação é quando o núcleo usado é idêntico ao ser rotacionado 180 graus. Ou seja, o núcleo é simétrico em torno da «origem». Nesse caso especial, ambas as operações geram resultados equivalentes. O que confunde as pessoas é que a maioria dos núcleos usados para convolução, como Desfoques Gaussianos, Laplacianos e assim por diante, é simétrica, caso em que não importa muito se você está de fato fazendo uma convolução ou uma correlação. Então as pessoas ficam relaxadas e imprecisas quanto aos significados. É apenas quando eles não são simétricos, como no caso da Busca de Formas (ver a seguir), ou com núcleos direcionais como Sobel, que a diferença realmente se torna importante.

Correlação e Busca de Formas

O verdadeiro uso do método «Correlate» (aplicando a vizinhança do núcleo «tal como está», sem rotação) é um método antigo, mas simples, de localizar objetos com forma que correspondem aproximadamente à forma encontrada no núcleo fornecido. Por exemplo, se usássemos «Correlate» com um núcleo em forma de «L» e tentássemos buscar na imagem que criamos com o exemplo do método de convolução acima, obteríamos...

  magick convolve_shape.gif -define convolve:scale='1!' \
         -morphology Correlate '3: 1,0,0
                                   1,0,0
                                   1,1,0' correlate.gif

[IM Output] [IM Output] [IM Output] _À PARTE: observe que as áreas «pretas» na imagem do núcleo acima representam um valor de zero. Não há valores negativos neste núcleo, apenas valores positivos para a forma sendo correspondida.

_

Observe que usei a Normalização do Núcleo do IM para evitar que os resultados finais ficassem brilhantes demais e afogassem o «pico» em um mar de pontos brancos. Como se pode ver, o método «[Correlate](#correlate)» produziu um brilho máximo no ponto em que a «origem» do núcleo corresponde exatamente à mesma forma na imagem. Mas ele também produz resultados menos brilhantes onde há apenas uma correspondência parcial da forma. Quanto mais da forma corresponde, mais brilhante o pixel se torna. Eu, porém, o alertaria de que, embora «[Correlate](#correlate)» tenha tido sucesso neste caso, não é realmente uma ótima forma de fazê-lo. Por exemplo, ele pode gerar um número muito grande de falsas correspondências em áreas de brilho muito alto. Esse problema pode ser mitigado usando valores negativos para as áreas que deveriam, em vez disso, corresponder ao fundo escuro da imagem. Ou seja, áreas que não correspondem ao fundo deveriam tornar o pixel resultante menos brilhante.

  magick convolve_shape.gif -define convolve:scale='1^'  \
         -morphology Correlate '4x5+2+2:  0 -1  0  0
                                         -1 +1 -1  0
                                         -1 +1 -1  0
                                         -1 +1 +1 -1
                                          0 -1 -1  0 ' correlate_pattern.gif

[IM Output] [IM Output] [IM Output] _À PARTE: para tornar a imagem do núcleo mais clara, gerei a imagem do núcleo de modo que os valores positivos (primeiro plano) sejam brancos, os valores negativos (fundo) sejam pretos e os valores zero (não importa) sejam transparentes. No entanto, o núcleo que é de fato usado está completamente definido, em termos de números, e sua «vizinhança» é um retângulo completo.

_

Como se pode ver, o pico de correspondência é muito mais pronunciado, pois agora você não corresponde apenas os pixels de primeiro plano, mas também os pixels de fundo. Observe o uso da flag de normalização «^» especial acima. Isso é importante, pois normalizará os valores positivos e negativos do núcleo separadamente. Ou seja, você quer buscar os pixels de primeiro plano de forma equânime com os pixels de fundo. Isso significa que você pode buscar correspondências tanto positivas quanto negativas da forma dada usando uma versão HDRI do IM ou com o uso apropriado de Viés de Saída (ver acima). Por exemplo, aqui aplico a busca da forma «L» a uma imagem de teste que contém formas «L» tanto positivas quanto negativas. (as imagens exibidas foram ampliadas)

  magick test_morphology.gif  -bias 50% -define convolve:scale='50%^' \
         -morphology Correlate '4x5+2+2:  0 -1  0  0
                                         -1  1 -1  0
                                         -1  1 -1  0
                                         -1  1  1 -1
                                          0 -1 -1  0 ' correlate_bias.gif

[IM Output] [IM Output] [IM Output]

O Viés de Saída tornou a saída normal da busca um cinza de tom médio, enquanto as formas correspondentes recebem cores mais claras ou mais escuras, dependendo do número de pixels que de fato correspondem ao «núcleo de forma». Se você examinar apenas os valores reais da imagem de saída, são produzidos um pixel branco puro e um pixel preto puro, indicando correspondências perfeitas. No entanto, há também um bom número de correspondências aproximadas. Se eu não estivesse interessado nas correspondências negativas ou «pretas», poderia remover o Viés de Saída e o fator de escala «50%», de modo que os pixels sem correspondência fiquem pretos e as correspondências perfeitas fiquem brancas. Uma vez que você tenha uma imagem de correspondência «[Correlate](#correlate)», precisa tentar encontrar os «picos» de correspondência. Isso pode ser feito usando outra Correlação, mas nem sempre funciona muito bem. O método melhor é usar o método de correspondência de padrões mais exato, a morfologia «[HitAndMiss](morphology.html#hitmiss)», com o «[Peaks](morphology.html#peaks)» especial, criado para esse fim. Ele encontra qualquer pixel único que esteja cercado apenas por pixels de cor mais escura. Outros núcleos «[Peaks](morphology.html#peaks)» podem ser usados para encontrar correspondências mais «frouxas».

  magick correlate_bias.gif  -morphology hitandmiss peaks:1.9 \
         -auto-level correlate_peaks.gif

[IM Output] [IM Output] [IM Output]

E aqui você pode encontrar facilmente a localização onde a melhor correspondência da forma foi encontrada, embora o grau da correspondência tenha se perdido. Talvez você queira consultar a seção de «localização de picos» de Comparar e Buscar Sub-Imagens. Mas veja também o script «[maxima](http://www.fmwconcepts.com/imagemagick/maxima/)» de Fred Weinhaus. FUTURO: Correlação Cruzada Normalizada com a Transformada Rápida de Fourier, para gerar Correlações de imagem muito rápidas com imagens muito grandes (tanto a imagem de origem quanto a sub-imagem).

Correlação vs Morfologia HitAndMiss

Se você comparar a imagem do núcleo, como a representei, com os núcleos usados pelo Método de Morfologia Hit-And-Miss, verá que eles de fato representam a mesma coisa. «[HitAndMiss](morphology.html#hitmiss)» «[Correlate](#correlate)»
Primeiro plano Um valor de «1.0» Um valor de «1.0» (antes da normalização)
Não importa Um valor de «Nan» ou «0.5» Um valor de «Nan» ou «0.0»
Fundo Um valor de «0.0» Um valor de «-1.0» (antes da normalização)
Resultados Subtrai o mínimo do primeiro plano do máximo do fundo. Assim, apenas correspondências exatas produzirão resultados positivos, e a limiarização produzirá uma imagem de correspondência binária. Gera uma faixa de quão próximo a imagem corresponde a uma forma. É possível que alguns pixels de fundo tenham valor maior que os pixels de primeiro plano, desde que o padrão geral esteja presente. Pode ser difícil localizar «picos» de correspondência específicos. Você também pode encontrar correspondências negativas.
Como se pode ver, eles correspondem um ao outro. Assim, um núcleo para um poderia ser transformado em um núcleo para o outro. No entanto, «[Hit-And-Miss](morphology.html#hitmiss)» só encontrará correspondências perfeitas e exatas, com uma diferença definida entre primeiro plano e fundo. Por isso, ele é muito menos tolerante a ruído e a quase-correspondências do que «[Correlate](#correlate)». Por outro lado, «[Correlate](#correlate)» pode ser realizado usando processamento de imagem linear e, mais especificamente, usando uma Transformada Rápida de Fourier. Isso pode tornar a correspondência de padrões com padrões e núcleos maiores muito mais rápida, especialmente quando múltiplos padrões estão envolvidos, poupando-lhe o custo de transformar imagens e padrões para o domínio da frequência. Também funciona com imagens reais, embora algum pré-processamento e o uso de HDRI também possam ser necessários. Qual usar depende realmente de você e dos resultados que busca: apenas correspondências perfeitas, ou correspondências aproximadas com muito mais erros e o possível uso de um algoritmo mais rápido. Observe que, para encontrar correspondências exatas de pequenas imagens coloridas dentro de imagens maiores, o Recurso de Localização de Sub-Imagem do programa «magick compare» fornecerá um método muito melhor do que os métodos «[Hit-And-Miss](morphology.html#hmt)» ou «[Correlate](#correlate)». Isso porque ele usa «mínimos quadrados das diferenças de vetores de cor» para fazer a correspondência de sub-imagem, o que pode produzir uma métrica melhor para os resultados de correspondência. No entanto, é igualmente lento, especialmente para imagens grandes.

Contagem de Vizinhos

Uma das aplicações mais incomuns da convolução é conhecida como contagem de vizinhos. Ou seja, descobrir quantos pixels existem em uma determinada área que cerca cada ponto de pixel em uma imagem.

Contando Vizinhos

Basicamente, usando um núcleo de convolução muito simples, você pode criar uma imagem que contém uma contagem do número de vizinhos que cercam um determinado ponto em uma imagem binária. Aplicando a convolução com um Núcleo Ring de tamanho «1.5», você obtém uma contagem de vizinhos. Aqui está uma contagem dos vizinhos de cada pixel em uma pequena área, mostrando a ampliação de pixels individuais antes e depois (gerada usando o Script Enlarge Image)...

  magick area.gif -define convolve:scale=\! \
         -morphology Convolve Ring:1.5 neighbour.gif

[IM Output] [IM Output]

Como se pode ver, o nível de cinza de todos os pixels mostra quantos vizinhos eles têm, incluindo quaisquer vizinhos de Pixel Virtual ao longo das bordas. Se você quiser incluir o pixel atual na contagem, pode usar um Núcleo Square em vez disso. Com as conversões apropriadas (incluindo ajustes de nível) e usando o Formato de Arquivo PbmPlus, você pode transformar os níveis de cinza acima em números reais, se for isso o que você quer.

  magick neighbour.gif +depth +level 0,8 pgm: | pnmnoraw | tail -n +4

[IM Text]

Se você quiser excluir os pixels que ficam dentro da própria forma, pode usar um núcleo com um forte pixel central negativo e então Limitar (Clamp) quaisquer resultados negativos (se estiver usando a versão HDRI do IM). Um método simples de gerar justamente esse núcleo de 1s positivos cercando um grande centro negativo é escalonar negativamente um Núcleo Laplaciano Discreto padrão.

  magick area.gif -define convolve:scale=-1\! \
         -morphology Convolve Laplacian:0 -clamp neigh_edge.gif

[IM Output] [IM Output]

É claro que também poderíamos ter usado a imagem original como máscara para remover os pixels desinteressantes.

O Jogo da Vida

Em 1970, um matemático britânico, John Horton Conway, publicou na Scientific American uma simulação especial que se tornou muito popular. Ela é agora conhecida como Jogo da Vida de Conway. Baseava-se em uma grade de pontos, em que cada ponto estava «vivo» ou «morto». Quais «células» eram então classificadas como «vivas» ou «mortas» na «geração» seguinte dependia de um conjunto de regras muito simples, baseadas puramente no número de células vizinhas vivas ao seu redor.

  • A vizinhança são os 8 pixels que cercam cada «célula».
  • Uma célula «viva» continua viva se tiver 2 ou 3 vizinhos.
  • Uma célula «morta» torna-se «viva» (nasce) se tiver exatamente 3 vizinhos.
  • Caso contrário, a célula torna-se ou permanece «morta».

Os resultados dessas regras sobre padrões binários foram notáveis, no sentido de que se obtêm aglomerados de «células» que parecem expandir-se, encolher, oscilar ou até mesmo mover-se lentamente pela grade. Tornou-se um grande ponto de pesquisa teórica, para ver se seria possível até gerar uma replicação de «padrões de vida» maiores, ao estilo do «DNA». À PARTE: parece que era possível, mas tão frágil a ponto de ser impraticável, o que torna a vida de DNA atual ainda mais notável. Também despertou grande interesse no estudo e na implementação de outras formas de Autômato Celular, como método de gerar e estudar grandes efeitos usando regras muito simples em escalas muito pequenas. Muito parecido com o que acontece na química nos níveis atômico e molecular, mas com maior complexidade. Então, vamos implementar a «Vida» usando o ImageMagick. Primeiro, para facilitar, faremos as células «vivas» brancas e as «mortas» pretas. Dessa forma, contamos apenas os pixels «brancos» que cercam cada célula, em uma vizinhança de 8 pixels. No entanto, também poderíamos implementá-lo com preto e branco trocados, embora fosse mais difícil acompanhar como é feito. Contudo, as regras têm forte dependência de a célula central estar viva ou morta. Então, precisamos separar as contagens de vizinhança de uma célula «morta» das de uma célula «viva». Isso pode ser feito simplesmente dando à célula central um valor maior que a soma de todos os seus vizinhos. Um valor de «10» serve bem para isso. É um número redondo e agradável, maior que a contagem máxima de vizinhança, que é 8. Isso torna o núcleo de Convolução do «Jogo da Vida» equivalente a..

    '3: 1,  1,  1
        1, 10,  1
        1,  1,  1'

O resultado disso será uma contagem dos 8 vizinhos ao redor de cada pixel (que seja «branco»), mais um valor de 10 se o pixel central estiver «vivo» ou «branco». Assim, o valor deste núcleo será de «0» a «8» para pixels mortos ou de «10» a «18» para pixels vivos. Se escalonarmos este núcleo por um valor de 20 (na verdade, escalonando por «0.05» para gerar um gradiente, ver abaixo), você gerará uma imagem com 21 níveis de cinza possíveis. Ou seja, você obterá um «preto» para o valor do nível de cinza «0» e um valor branco para o nível de cinza «21», ainda que o núcleo não possa, de fato, gerar tal valor. Agora podemos codificar as regras do «Jogo da Vida » em uma Imagem de Tabela de Consulta de Cores, de modo a transformar o «nível de cinza» da contagem de vizinhos resultante, gerado pelo núcleo acima, no resultado apropriado de «vida e morte», segundo as «Regras da Vida».

  magick -size 21x1 xc:black -fill white \
          -draw 'point 3,0  point 12,0  point 13,0' \
          life_clut.gif
  enlarge_image -25.3 -ml 'Life Rules' life_clut.gif life_clut_enlarged.png

[IM Output]

A imagem é muito pequena, então usei um Script Enlarge Image para gerar uma versão maior para exibir acima, com cada pixel claramente separado. Basicamente, os primeiros 10 pixels são o que fazer para uma «célula morta», e os 10 pixels seguintes, o que fazer para uma «célula viva». O primeiro pixel branco no lado esquerdo (contagem de vizinhos = 3 em torno de uma célula morta) é um «nascimento», enquanto os dois pixels brancos no lado direito (contagens de vizinhos 2 e 3 ao lado de uma célula viva) permitem que uma «célula viva» existente continue a viver. Qualquer outro resultado deixa o resultado como preto (morto). A Tabela de Consulta de Cores tem 21 pixels de comprimento porque estarei dividindo por um fator de escala de 20, o que significa que poderíamos gerar um valor na faixa de 0 a 20, ou 21 níveis distintos de escala de cinza. Na verdade, poderíamos usar um valor diferente de 10 para o centro (estado anterior da célula) e de 20 para o escalonamento, mas esses valores são números fáceis de trabalhar. Em resumo, dividimos o núcleo de convolução por 20 e usamos uma CLUT de 21 pixels de comprimento (com Interpolação de Inteiros) para associar os resultados da convolução (níveis de cinza) ao valor de cor de saída correto. À PARTE: esta CLUT de «Regras da Vida» pode ser considerada uma Tabela de Regras de Autômato Celular geral. O padrão de vizinhança usado para a contagem de vizinhos também faz parte do autômato celular. Essa técnica também é descrita no Léxico de Regras de Autômatos Celulares, na seção Tabelas de Regras, como uma forma de definir formas gerais «sem limites» dos autômatos celulares que ele lista. Basicamente, quase qualquer autômato pode ser definido usando tal combinação de vizinhança/tabela, embora a maioria seja definida usando formas mais simplificadas. Então, vamos aplicar isso a uma imagem que contém um padrão de «vida», várias vezes, para ver como o padrão muda de uma geração para a seguinte e para verificar que está funcionando como esperado.

  magick -size 15x15 xc:black -fill white \
         -draw 'line  3,2 3,4  line 10,10 12,10  point 10,11  point 11,12' \
         life_gen_000.gif
  magick life_gen_000.gif -define convolve:scale=0.05 \
         -morphology Convolve '3:1,1,1 1,10,1 1,1,1' \
         life_clut.gif -interpolate integer -clut \
         life_gen_001.gif
  magick life_gen_001.gif -define convolve:scale=0.05 \
         -morphology Convolve '3:1,1,1 1,10,1 1,1,1' \
         life_clut.gif -interpolate integer -clut \
         life_gen_002.gif
  magick life_gen_002.gif -define convolve:scale=0.05 \
         -morphology Convolve '3:1,1,1 1,10,1 1,1,1' \
         life_clut.gif -interpolate integer -clut \
         life_gen_003.gif
  magick life_gen_003.gif -define convolve:scale=0.05 \
         -morphology Convolve '3:1,1,1 1,10,1 1,1,1' \
         life_clut.gif -interpolate integer -clut \
         life_gen_004.gif

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

Lembre-se de que as imagens acima foram ampliadas; para ver a imagem «minúscula» original gerada, clique na imagem ampliada. Como se pode ver, os padrões de «Vida» se comportam como deveriam (se você conhece os padrões). O «blinker» no canto superior esquerdo alterna para frente e para trás, enquanto o «glider» na parte inferior avançou 1 passo na diagonal em direção a ele, ao longo das 4 «gerações» em que iteramos as regras da vida. [IM Output] E aqui está um exemplo maior, conhecido como Canhão de Planadores de Gosper, em que gero uma animação de 60 quadros a partir de um padrão de vida especial. O tamanho real da imagem usada é mostrado à direita, mas eu escalono a animação resultante para melhor visualização.

  magick glider_gun.gif life_pattern.gif
  for i in `seq 59`; do
    magick life_pattern.gif -define convolve:scale=0.05 \
           -morphology Convolve '3:1,1,1 1,10,1 1,1,1' \
           life_clut.gif -interpolate integer -clut \
           -write life_pattern.gif miff:-
  done | magick - -scale 500% \
                -set delay 10 -layers Optimize -loop 0  glider_gun_anim.gif
  magick glider_gun.gif -scale 500% life_pattern.gif

[IM Output] [IM Output]

Observe que a razão de o glider «explodir» na borda inferior é o tratamento de «Pixel Virtual» padrão que a convolução usa, e a perda das informações de vida à medida que ele ultrapassa os limites da imagem. Mais imagens de padrões de vida podem ser encontradas no Catálogo de Padrões de Vida, embora você precise recolorir (negar) as imagens para uso no processador de vida acima. Deixarei como exercício para alguém colocar o acima em um script, capaz de gerar uma sequência de vida para alguma imagem de entrada específica.
Este é apenas um exemplo de toda uma gama de «Autômatos Celulares » que o IM poderia processar. É claro que há muitos programas dedicados e mais rápidos para «Vida» e «Autômatos Celulares», que geralmente fazem exatamente a mesma coisa, mas eu quis mostrar que o IM é flexível o suficiente para fazê-lo também. Como os resultados são simples imagens binárias, você também pode usar os métodos de Morfologia do IM, como a Busca de Padrões Hit and Miss ou a Correlação Cruzada, para buscar padrões de vida específicos, tornando o uso do IM para pesquisa de vida mais prático, ainda que lento.