⚠️ Este es un sitio de traducción no oficial, sin relación con ImageMagick Studio LLC. Para información autorizada, consulte la página original (https://usage.imagemagick.org/convolve/index.html).

ImageMagick Ejemplos -- Convolución de imágenes

ImageMagick Ejemplos: prefacio e índice
Introducción a la convolución

La convolución utiliza el «vecindario» local de píxeles para modificar imágenes. Lo hace combinando y promediando todos los valores de color alrededor de cada píxel para desenfocar imágenes, resaltar bordes y contornos, y enfocar imágenes. La variante de la convolución, la «correlación» (Correlation), también se usa para rastrear y buscar patrones concretos, produciendo una imagen que indica cuán de cerca coinciden las imágenes.


Introducción a la convolución

Los métodos «Convolve» y el estrechamente relacionado «Correlate» son, en muchos aspectos, muy similares a la morfología. De hecho, funcionan casi exactamente de la misma manera, haciendo coincidir un «núcleo» de vecindario en cada posición, lo que los convierte simplemente en otro «método» especial de la morfología. De hecho, también comparten gran parte del mismo código e incluso las mismas definiciones de núcleo que se definieron en Núcleos básicos y Núcleos definidos por el usuario. Para núcleos más específicos diseñados para usarse con este operador (y hay muchos), le remito a Núcleos de desenfoque y Núcleos de detección de bordes. El núcleo más importante es el núcleo «[Gaussian](../static/img/convolve/gaussian)». Sin embargo, la convolución es mucho más antigua que la morfología, y genera más efectos de degradado en escala de grises que los efectos de estudio de formas binarias que la morfología suele producir. Por eso a menudo se considera una operación muy distinta o separada de la morfología, y más central para el procesamiento de imágenes. Básicamente, una convolución o correlación realiza un «promedio ponderado» de todos los píxeles del vecindario especificado. Es decir, multiplica el valor de cada píxel cercano por la cantidad indicada en el núcleo y luego suma todos esos valores para producir el resultado final. Así, cada píxel de la imagen final contendrá en general al menos una pequeña parte de todos los demás píxeles que lo rodean localmente en la imagen de origen. Visto de otro modo, el color de cada píxel de la imagen se sumará a (desenfoque) o se restará de (enfoque/detección de bordes) los colores de todos sus vecinos cercanos, según defina el núcleo utilizado. Tanto «convolve» como «correlate» son la misma operación, salvo en un detalle muy menor pero importante, y para los ejemplos y controles que veremos ahora puede tratarlos como básicamente lo mismo. Más adelante (véase Convolve vs Correlate) examinaremos con exactitud en qué difieren realmente los dos operadores y por qué difieren de forma tan sutil. Pero en la mayoría de los casos son el mismo método.

Convolve ( )

Como se mencionó arriba, el método «Convolve» funciona ponderando cada uno de los píxeles del vecindario local según los valores en coma flotante del núcleo. Los valores ponderados se suman luego simplemente para producir el nuevo píxel de reemplazo en la imagen resultante. Por ejemplo, convolucionemos un único píxel usando un núcleo de convolución definido por el usuario muy pequeño. También activo la opción Mostrar núcleo especial, para que pueda ver los detalles del núcleo que se define y se usa (las imágenes mostradas se han ampliado).

  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 puede ver, el único píxel de la imagen se ha expandido ahora para producir píxeles gris al 50 % a su alrededor. Es decir, cuando el «origen» del núcleo (en este caso, su centro) se sitúa junto al único píxel de la imagen original, solo ese único píxel tiene un valor distinto de cero. Ese valor de píxel se pondera entonces por el valor «0.5» del núcleo, y el píxel «de medio brillo» resultante se añade a la imagen resultante. De forma similar, cuando el origen del núcleo se sitúa exactamente sobre el píxel original, obtiene un valor de «1.0», reproduciendo el píxel original sin que ningún otro valor (negro) del vecindario que lo rodea aporte componente alguno al resultado. Tenga en cuenta que cualquier valor del núcleo igual a «0.0» no participa en absoluto en el cálculo final. Los valores cero no forman parte, en la práctica, del «vecindario», igual que cualquier valor «Nan» en los núcleos de morfología no participa. Así, este núcleo consta de un vecindario de 5 elementos. En muchos sentidos, el método «[Convolve](#convolve)» es muy similar al método morfológico «[Dilate](morphology.html#dilate)»; sin embargo, «[Dilate](morphology.html#dilate)» solo trata el núcleo como una especie de máscara de mapa de bits, localizando el mayor valor dentro del vecindario. En cambio, «[Convolve](#convolve)» es una suma ponderada de todos los valores del vecindario, de modo que el valor de cada elemento del núcleo interviene en el resultado global. La sintaxis de una operación de convolución es...

**-morphology Convolve {_núcleo_de_convolución_}
**

Pero también puede usar un operador más antiguo y más directo...

**-convolve {_núcleo_de_convolución_}
**

| _Antes de IM v6.5.9, el antiguo «[-convolve](https://imagemagick.org/command-line-options/#convolve)» no entendía las definiciones de núcleo de la morfología. Solo aceptaba el «estilo antiguo» de núcleos definidos por el usuario, consistente en una simple cadena de valores separados por comas para producir algún núcleo cuadrado de tamaño impar. Ahora acepta también las definiciones de núcleo de convolución de «estilo nuevo».

Sin embargo, sigue estando restringido a núcleos cuadrados de «tamaño impar». Y seguirá así hasta que empiece a hacer uso del nuevo método de convolución de la «morfología».

_
---|---
| _El antiguo operador «[-convolve](https://imagemagick.org/command-line-options/#convolve)» no es exactamente igual que el más reciente método «[Convolve](#convolve)» de la morfología. La siguiente es una lista de cómo difieren ambas operaciones...

_

* _El operador antiguo está implementado como una [correlación](#correlation) y no como una verdadera convolución. Esto significa que el núcleo no se superpone a la imagen de origen en su forma reflejada. Véase [Convolve vs Correlate](#convolve_vs_correlate) para conocer los efectos que esto tiene en los resultados.
_
  • _Solo acepta núcleos cuadrados de tamaño impar. El de la morfología admite cualquier matriz rectangular, pudiéndose declarar como origen cualquier punto de la matriz.
_
  • _El operador antiguo siempre normaliza los núcleos sin que el usuario tenga control alguno sobre el escalado del núcleo. El nuevo no normaliza automáticamente: hay que solicitarlo. Sin embargo, la mayoría de los núcleos generados ya vienen normalizados.
_
  • _Sin embargo, sí aprovechará el código «GPU» rápido si el equipo anfitrión dispone de tales recursos. La morfología todavía no tiene esto habilitado.
_
  • _Actualmente, otros operadores relacionados con la convolución, 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)», usan la versión antigua del operador.
_
  • _Por defecto, el comando antiguo solo convoluciona contra los canales de color (según defina la opción «[-channel](https://imagemagick.org/command-line-options/#channel)». Si convoluciona con una opción «[-channel](https://imagemagick.org/command-line-options/#channel) RGBA», también ponderará los valores del núcleo por el canal alfa para asegurar un desenfoque correcto en lo relativo a la transparencia.

El método «convolve» de la morfología gestiona automáticamente, por defecto, la ponderación de transparencia de los canales de color. Es decir, el desenfoque de imágenes que lo use tratará los colores transparentes como transparentes, evitando así por defecto el error de transparencia del desenfoque.

Sin embargo, si el usuario modifica la opción «[-channel](https://imagemagick.org/command-line-options/#channel)» por defecto (al no incluir el indicador especial «Sync»), entonces gestionará la convolución como un operador de escala de grises puramente basado en canales.

Véase la documentación de la opción «[-channel](https://imagemagick.org/command-line-options/#channel)», o consulte Matemática de canales de imagen, que usa el mismo indicador de la misma manera, para más información.

_

_

Con el tiempo, la mayoría de las diferencias anteriores cambiarán a medida que las cosas se fusionen con el más reciente método «[Convolve](#convolve)» de la morfología.

_
---|---
Si desea ver algunos buenos ejemplos de cómo funciona realmente «[Convolve](#convolve)», le recomiendo que también eche un vistazo a EECE \ CS 253 Image Processing, Lecture 7, Spatial Convolution. El artículo Wikipedia, Convolve tiene algunas bonitas animaciones 1-D del proceso de convolución.

Escalado del núcleo de convolución

El ejemplo anterior funciona bien con una imagen mayormente negra, como un único píxel, pero si lo aplicara a una imagen real tendría un 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 puede ver, la imagen resultante es muy brillante (de hecho, 3 veces más brillante) que la imagen original. Lo que ocurrió es que cada píxel se reparte 3 veces: 4 × «0.5» en los lados, más una copia completa del píxel original. Es decir, la suma de todos los valores del núcleo es 3, ¡lo que hace que la imagen resultante sea tres veces más brillante! Si vuelve atrás y mira la salida de «showKernel» de arriba, verá que indicaba que este núcleo tenía un «convolution output range from 0 to 3» (rango de salida de convolución de 0 a 3). Esto demuestra que, en general, este núcleo aclara una imagen 3 veces. Para corregirlo, conviene dividir todos los valores del núcleo entre 3. Es decir, un valor de «0.5» debería haber sido en realidad alrededor de «0.1667», mientras que el valor central de «1.0» debería haber sido «0.3333». Este proceso se conoce como «normalización del núcleo». Por ejemplo, aquí está el resultado «normalizado» manualmente y la definición del 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 puede ver, obtiene una versión muy levemente desenfocada de la imagen del rostro, ya que cada píxel se repartió entre cada uno de sus vecinos inmediatos. | _La «imagen del núcleo» que se muestra arriba (generada mediante un Script Núcleo a Imagen especial) también muestra el núcleo normalizado resultante. Como puede ver, el propio núcleo es ahora muy oscuro, ya que todos sus valores también son oscuros, aunque todos suman un valor de «1.0».

A partir de ahora, todas las imágenes de núcleo de convolución que se muestran se ajustarán siempre para que el valor máximo se fije en blanco; de lo contrario, en general solo vería una «imagen del núcleo» oscura y básicamente inútil.

_
---|---
Normalizar el núcleo uno mismo no es agradable y, como ha visto, hace que la definición del núcleo resultante sea mucho más difícil de entender. Por eso se proporcionan formas alternativas. A partir de IM v6.5.9-2, la opción experta especial «[-define](https://imagemagick.org/command-line-options/#define) convolve:scale={_escala_del_núcleo_}» permite especificar un factor de escala global para el núcleo y, así, ajustar el brillo del resultado global. |

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]
En realidad, lo que esto hace es ajustar la intensidad global de los resultados del núcleo. Como verá en ejemplos posteriores, probablemente querrá hacer el resultado de la convolución más o menos potente. Este factor «escala_del_núcleo» le permite hacerlo.

Normalización del núcleo (escalado automático)

En lugar de calcular el factor de escala (como antes), basta con pedir a IM que calcule internamente este «factor de escala de normalización» dándole el indicador de normalización 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]
| El carácter «!» también lo usan a veces para fines especiales diversos intérpretes de la línea de comandos de UNIX. Por eso quizá tenga que escapar el carácter usando una barra invertida, incluso entre comillas. Se aconseja precaución.
---|---
Tenga en cuenta que, como el núcleo ya está normalizado, puedo definirlo de forma más simple usando números enteros. El núcleo normalizado seguirá siendo el mismo que el núcleo «escalado» anterior. Normalmente querrá siempre normalizar el núcleo y, por ello, la variante más simple «[-convolve](https://imagemagick.org/command-line-options/#convolve)» hará esta normalización automáticamente. Puede hacer que IM normalice el núcleo y luego lo escale aún más en una cantidad dada para ajustar su rango de salida. Para facilitarlo todavía más, puede especificar el factor de escala como porcentaje. Por ejemplo, aquí normalizo el núcleo pero luego reescalo los valores al 50 % del tamaño calculado, para producir un resultado más oscuro. |

  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]
Tenga en cuenta que usar un valor de «!» es en realidad equivalente a usar «1!» o incluso «100%!». Incluso puede usar un factor de escala negativo si desea invertir los valores positivos y negativos dentro del núcleo. Para ver un ejemplo de esto, véase «Un-sharpen» de imágenes usando desenfoques. Si el núcleo se ha normalizado de esta forma, la salida de Mostrar núcleo le indicará que está normalizado.

Cómo funciona la normalización

La forma real en que funciona la «normalización del núcleo» es que todos los valores del núcleo se suman (incluidos los valores negativos, que también son posibles). Si el resultado es distinto de cero, se escalan todos los valores para que su valor combinado sume uno («1.0»). Tenga en cuenta que, si hay valores negativos, esto podría crear en realidad un núcleo con un valor mayor que uno, normalmente en el origen. Sucede específicamente con los núcleos Un-Sharp. Lo importante, sin embargo, es que el núcleo en su conjunto suma «1.0», de modo que la imagen final no se oscurece ni se aclara por la operación de convolución. Si el resultado de la suma es cero («0.0»), se asume que el núcleo es un núcleo de suma cero especial. En ese caso, el núcleo se escala para hacer que todos los valores positivos sean iguales a «1.0» y, del mismo modo, todos los valores negativos sumarán «-1.0». Estos núcleos son especialmente frecuentes en las técnicas de detección de bordes. La salida de Mostrar núcleo también especificará que es de suma cero si el núcleo tiene esta forma, aunque no sea en realidad un núcleo de suma cero normalizado, si bien eso también se apreciará fácilmente por los demás números mostrados. La mayoría de los núcleos determinados matemáticamente vienen pre-normalizados. Esto incluye los núcleos derivados matemáticamente: «[Unity](#unity)», «[Gaussian](#gaussian)», «[LoG](#log)», «[DoG](#dog)», «[Blur](#blur)», «[Comet](#comet)». Los núcleos constantes discretos, en cambio, no vienen pre-normalizados, así que tendrá que hacerlo usando la opción de normalización del núcleo (arriba). Esto incluye los núcleos: «[Laplacian](#laplacian)», «[Sobel](#sobel)», «[Roberts](#roberts)», «[Prewitt](#prewitt)», «[Compass](#compass)», «[Kirsch](#kirsch)», «[FreiChen](#freichen)». Tenga en cuenta que el núcleo «[FreiChen](#freichen)» tiene subtipos especialmente preponderados para fines más concretos. Los núcleos FreiChen no deberían normalizarse, sino usarse tal cual.

Normalización de suma cero

No todos los núcleos de convolución usan solo valores positivos. También puede encontrar núcleos que usan una mezcla de valores positivos y negativos, y a menudo los valores de estos núcleos están pensados para sumar cero, produciendo un núcleo de suma cero. Tales núcleos son muy importantes para convoluciones de imagen más avanzadas, ya que proporcionan técnicas de detección de bordes y enfoque de imágenes. Como mencioné en la última sección, el indicador de normalización habitual «!» funciona con tales núcleos. Pero a veces, debido a situaciones especiales, querrá asegurarse de que el núcleo siga siendo «de suma cero». El método de normalización especial «^» proporciona precisamente una forma de garantizar que el núcleo sea «de suma cero» en situaciones como...

1. Si la definición de núcleo del usuario no es lo bastante precisa para garantizar la suma cero. Por ejemplo, no puede especificar «`1/3`» ni ningún otro factor fraccionario de 3 como número decimal en coma flotante exacto.
2. La curva matemática queda «recortada» por el tamaño (radio) del núcleo, de modo que podría dejar de ser de suma cero. Por ejemplo, esto ocurre en los núcleos «`[LoG](#log)`» o «`[DoG](#dog")`», que se basan en curvas de respuesta infinita. IM, de hecho, usa internamente esta normalización especial en estos núcleos por esta misma razón.
3. Asegurar que una «máscara de forma» de [correlación](#correlate) sea de suma cero, de modo que en la búsqueda IM pueda buscar por igual coincidencias positivas y negativas. Véase [Búsqueda de formas por correlación](#correlate) más abajo.

Lo que ocurre es que normalizará todos los valores positivos y negativos del núcleo como entidades separadas. Es decir, todos los valores negativos se escalarán para sumar «-1.0» y todos los positivos para sumar «+1.0». El resultado es que el núcleo, en su conjunto, queda garantizado para sumar cero. Tenga en cuenta que si usa este método de normalización para un núcleo totalmente positivo, como «Gaussian», seguirá obteniendo un núcleo correctamente normalizado. Por ello, esta forma de normalización también puede usarse con núcleos de desenfoque. Sin embargo, no debería usarse para normalizar directamente núcleos de enfoque ni de «un-sharpen» definidos directamente, ya que estos pueden contener valores negativos, pero requieren sumar un valor de uno (usando el método de normalización normal).

Mezcla del núcleo con el núcleo identidad

La sintaxis completa de la opción de escalado del núcleo es...

**-define convolve:scale='{_escala_del_núcleo_}[!^] [,{_adición_al_origen_}] [%]' -set option:convolve:scale '{_escala_del_núcleo_}[!^] [,{_adición_al_origen_}] [%%]'**

Observe el doblado del carácter de porcentaje al usar «[-set](https://imagemagick.org/command-line-options/#set)». Los indicadores de normalización opcionales «!» o «^» se aplicarán primero al núcleo definido por el usuario o integrado (si se solicitan). Después, el núcleo se escalará por el factor «escala_del_núcleo», aumentando o disminuyendo la «potencia» efectiva de la convolución sobre los resultados. El factor de escala por defecto es «1.0». Por último, al valor del «origen» del núcleo se le sumará el número que va tras una coma. La «adición_al_origen» por defecto es «0.0». Este último paso «suma», en la práctica, un núcleo Unity del «escalado» dado al núcleo normalizado y escalado generado previamente. Esto genera núcleos que pueden...

* Suavizar los efectos de un [núcleo de desenfoque](#blurring_kernels). 
* Convertir un [núcleo de desenfoque](#blurring_kernels) en uno que pueda usarse directamente para [«un-sharpen» de una imagen](#unsharpen). 
* También puede permitirle convertir un [núcleo de detección de bordes](#edgedet_kernels) en un [núcleo de enfoque de imagen](#sharpening).

Tenga en cuenta que si proporciona un indicador de porcentaje («%»), ese porcentaje se aplicará TANTO al factor «escala_del_núcleo» COMO a la «adición_al_origen». Esto puede hacer que la escala sea más fácil de leer y entender cuando hay fracciones de por medio. Ejemplo de uso de la opción define de escalado del núcleo...

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

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

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

Lo normaliza (indicador «!»)

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

Lo escala al 50 %

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

Añade un núcleo Unity (suma el 100 % al valor del origen)

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

Y ahora puede convolucionar usando «[Laplacian:2](#laplacian_2)» como núcleo de enfoque, pero con solo un «50%» de potencia de enfoque. Recuerde que cualquier indicador «%» dado en cualquier parte de la opción de escala hará que ambos valores sean porcentajes. Si no está presente, ambos valores son simples multiplicadores directos. Por ejemplo, todas estas opciones de escala son equivalentes

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

Lo mismo ocurre con los dos indicadores de normalización. Pueden aparecer en cualquier parte de la opción de escalado de convolución, pero siempre se aplicarán primero, antes de cualquier otro escalado.

Control del sesgo del resultado de salida

Cuando trabaja con un núcleo que contiene valores negativos, a algunos píxeles de la imagen resultante se les debería asignar un valor negativo. Este es especialmente el caso de los núcleos de suma cero (véase más abajo). Por desgracia, a menos que tenga una versión HDRI de ImageMagick especialmente compilada para preservar los valores negativos generados, cualquier resultado negativo se recortará a cero (negro). Solo obtendrá los resultados positivos de la convolución. Sencillamente, no puede almacenarse en un formato de imagen normal, dejándole con la mitad del resultado. Podría compilar una versión HDRI de ImageMagick para preservar los valores negativos generados y luego extraer la información que desee. Como alternativa, puede negar el núcleo usando un factor de escala negativo. Por ejemplo, usando...

-define convolve:scale='-1'

Sin embargo, entonces solo obtiene los resultados negativos, recortándose los resultados positivos. No obstante, usando la opción «[-bias](https://imagemagick.org/command-line-options/#bias)» de IM aún puede preservar tanto los resultados positivos como los negativos. Las opciones a usar para la versión no HDRI de IM son...

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

La primera opción escala la salida a la mitad del tamaño que normalmente obtendría (después de normalizarse), para dejar sitio tanto a los resultados positivos como a los negativos. Luego añadirá un gris al 50 % a la salida del píxel antes de guardar el resultado de vuelta en una imagen. Con estas opciones, cualquier resultado «cero» se convertirá en gris puro, con los resultados negativos más oscuros que esto y los positivos más claros. El negro representará «-1.0» y el blanco significará «+1.0». Un ejemplo de cómo hacer esto se muestra en los ejemplos de Búsqueda de formas con Correlate más abajo.


Desenfoque de imágenes (filtrado de paso bajo)

Otra sección de los ejemplos de IM, concretamente Desenfoque y enfoque de imágenes, trata en realidad los aspectos prácticos de este tema. Aquí veremos detalles más concretos. Primero, sin embargo, describiremos los núcleos básicos y cómo puede usarlos directamente sin modificación. Más tarde veremos formas de modificar el desenfoque para generar otros efectos.

Núcleos de desenfoque

[IM Output]

Unity

Este es un núcleo especial que en realidad no hace nada. Solo se especifica un elemento del núcleo y, como resultado, cada píxel se reemplaza por sí mismo sin cambio. Por ejemplo, aquí hay una convolución que no hace nada (no-op)...

  magick face.png -morphology Convolve Unity face_unity.png

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

A partir de IM v6.6.9-4, el núcleo puede tomar un único argumento, como argumento de escala específico del núcleo. Esto le permite usarlo para multiplicar los valores de una imagen, por ejemplo para aclararla u oscurecerla. |

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

[IM Output]
Esto puede no parecer muy útil, pero puede usarse para generar efectos de desenfoque suave y de un-sharpen, o en secuencias de múltiples núcleos donde quizá no pueda usar el escalado del núcleo ni la mezcla con el núcleo identidad. El mismo núcleo de un solo elemento también puede generarse usando «[Disk:0.5](morphology.html#disk)», que además le permite especificar un argumento de escala adicional como parte de la generación de los núcleos. (P. ej.: «Disk:0.5,0.5» para el último ejemplo). Un núcleo similar (para convolución) también puede generarse con el generador de núcleos «[Gaussian](#gaussian)» con un «sigma» de «0.0». Sin embargo, eso solo puede producir un pequeño núcleo de 3x3, consistente en un valor central «1.0» rodeado de 8 valores «0.0». [IM Output]

Filtrado de media o promedio usando núcleos de forma

Aunque la mayoría de los núcleos de convolución definidos a continuación suelen implicar el uso de una curva gaussiana de algún modo, también puede usar uno de los anteriores núcleos de forma de la morfología para simplemente promediar los píxeles sobre un área (grande) dada. Por supuesto, tendrá que normalizar el núcleo para generar realmente un promedio, en lugar de una mera suma del vecindario. Por ejemplo, aquí uso un núcleo más pequeño con forma de «[Octagon](morphology.html#octagon)» para promediar todos los valores de píxel hallados dentro de un área circular que rodea cada píxel.

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

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

El resultado es que el valor de cada píxel se reparte por igual entre los 25 píxeles del vecindario definido. Es decir, equivale a un filtro de «media» o «promedio» sobre la forma dada. Si quiere excluir el píxel original de ese promedio, usando solo los píxeles circundantes, puede usar un núcleo «[Ring](morphology.html#ring)» (proporcionando solo un radio). Los demás núcleos de forma también pueden usarse de la misma manera para, por ejemplo, promediar los valores de píxel sobre una forma de «[Diamond](morphology.html#diamond)», «[Square](morphology.html#square)» o un «[Disk](morphology.html#disk)» grande, y del tamaño que desee. Sin embargo, aunque un promedio constante sobre un área con forma sí desenfoca las imágenes, tiende a producir efectos inusuales (concretamente artefactos de aliasing) en la imagen resultante. Más concretamente, usar un núcleo de promediado «plano» tiende a convertir los bordes nítidos en una pendiente lineal más gruesa con un cambio brusco en la pendiente en los bordes engrosados. El grosor del resultado es «radius*2-1» del núcleo. El modo en que los distintos ángulos de borde afectan al grosor y a la linealidad de la pendiente depende de la forma del núcleo «plano» o de promediado.

  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]

Tenga en cuenta que el desenfoque diagonal de arriba es distinto para un núcleo cuadrado que para un núcleo de disco. Otra forma de generar un desenfoque de «pendiente lineal» cuadrado es usar un sigma muy grande con un radio concreto. La convolución del núcleo cuadrado anterior puede también, por ejemplo, lograrse usando -blur 5x65535. Fred Wienhaus la usaba comúnmente en sus scripts antes de que la morfología estuviera disponible. [IM Output]

Núcleo Gaussian (desenfoque gaussiano 2d)

Como habrá deducido, el núcleo «Gaussian» es el núcleo más usado para convolucionar una imagen. Es el núcleo matemáticamente ideal para efectos de desenfoque. Aquí, por ejemplo, está la salida de Mostrar núcleo de un pequeño núcleo «Gaussian» (pueden hacerse muy grandes muy rápidamente)...

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

[IM Text]

En realidad no quería aplicar una convolución a lo anterior, ya que solo quería mostrar el núcleo que iba a usar. Por ello, usé un recuento de iteraciones de «:0», de modo que no hace nada. De forma similar, descarto la salida de imagen resultante usando el formato de archivo especial «[null:](files.html#null)». Como puede ver por el rango de salida de la convolución, un núcleo «Gaussian» ya viene normalizado (escalado) para usted. Sin embargo, también notará que sigue siendo un núcleo bastante grande, lleno de pequeños valores fraccionarios. Si mira más de cerca, encontrará que el mayor valor (2.48678, que también aparece en la primera línea) está en el centro, con los valores más pequeños hacia los bordes y las esquinas (un valor de aproximadamente .000000194). Aquí hay un desenfoque gaussiano típico usando una convolución...

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

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

La sintaxis de los núcleos es sencilla...

   Gaussian:[{_radius_}]x{_sigma_}

Estos argumentos son, de hecho, exactamente los mismos que usa el operador «[-gaussian-blur](https://imagemagick.org/command-line-options/#gaussian-blur)», que en realidad realiza una convolución usando este núcleo. El primer número, como en la mayoría de los núcleos de la morfología, es el «radio» o tamaño del núcleo. Es solo un entero, con un valor mínimo de 1, lo que hace que el núcleo más pequeño posible tenga 3x3 elementos. Lo mejor es especificar siempre cero, lo que permite a ImageMagick calcular un radio adecuado para el valor «sigma» proporcionado. El segundo argumento, más importante, es «sigma», que define cuán desenfocado o «extendido» debe quedar cada píxel. Cuanto mayor sea el valor, más borrosa quedará la imagen. Es un valor en coma flotante. El valor de sigma DEBE proporcionarse. Si se da un valor de sigma de «0.0», acabará con un núcleo «[Unity](#unity)» bastante inútil (del radio dado, o de radio 1, produciendo así un núcleo de 3x3 de un único valor «1.0» rodeado de valores «0.0»). Como vio arriba, ¡convolucionar con cualquier tipo de núcleo «[Unity](#unity)» no hace nada a la imagen! Si especifica un «radio», en general es buena idea hacerlo al menos el doble de grande que el «sigma»; IM normalmente calcula un radio aproximadamente 3 veces mayor (en realidad, el mayor radio que dará resultados significativos), aunque depende de la calidad en tiempo de compilación de su instalación concreta de IM. Para más información sobre el efecto de los argumentos del núcleo «Gaussian» y sobre el desenfoque de imágenes en general, véase... Desenfoque de imágenes. [IM Output]

Núcleo Blur (desenfoque gaussiano 1d)

El núcleo «Blur» es muy similar al núcleo Gaussian y toma incluso los mismos argumentos (véase más abajo). Pero, mientras que el gaussiano es una curva bidimensional, el núcleo «Blur» produce una curva unidimensional. Es decir, genera una única fila larga y delgada de valores. Aquí está la salida de Mostrar núcleo de un pequeño núcleo «Blur». | |

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

[IM Output]
| [IM Text]


El gráfico mostrado arriba es un perfil real del núcleo «Blur» por defecto. Se creó usando el script Imagen del núcleo «[kernel2image](../static/img/scripts/kernel2image)», y esa imagen se graficó luego usando el script «[im_profile](../static/img/scripts/im_profile)». Muestra claramente la «curva de campana gaussiana» que representa este núcleo. Aquí hay un ejemplo de uso de este núcleo para desenfocar una imagen horizontalmente. |

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

[IM Output]
La sintaxis del núcleo es exactamente como la de «[Gaussian](#gaussian)», pero con un ángulo de rotación opcional adicional.

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

Como antes, el segundo valor «sigma» es obligatorio y, si se establece a cero, obtendrá el equivalente lineal de un núcleo «[Unity](#unity)». El «ángulo» le permite rotar el núcleo 90 grados, lo que le permite desenfocar una imagen verticalmente. |

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

[IM Output]
Por ahora solo es posible una rotación de 90 grados. Esto puede cambiar en una versión posterior de ImageMagick. El propósito de este núcleo es, en realidad, crear una forma más rápida del desenfoque de imagen bidimensional que produce el núcleo «[Gaussian](#gaussian)». Véase Núcleos Gaussian vs Blur más abajo para más detalles de cómo se hace esto. [IM Output]

Núcleo Comet (media de desenfoque gaussiano 1d)

El núcleo «Comet» es casi exactamente igual que un núcleo «[Blur](#blur)», pero en realidad es solo medio núcleo de desenfoque.

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

[IM Text]

Observe cómo la ubicación definida del origen está en el borde izquierdo, y no en el centro del núcleo. Esto es muy inusual para un núcleo de convolución y, como tal, produce un resultado muy inusual. Desenfoca la imagen en una dirección, como si un dedo hubiera emborronado la superficie de una pintura húmeda, dejando un rastro de color. Es un poco como la cola de un cometa, o el rastro que deja un meteoro o una estrella fugaz. |

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

[IM Output]
Tenga en cuenta que tanto los colores de primer plano como los de fondo se «emborronaron». Si solo quiere desenfocar los colores de primer plano, haga el fondo transparente y añádalo después de haber desenfocado el primer plano. También puede dar un tercer argumento ángulo para rotar el núcleo en cualquier múltiplo de 90 grados alrededor de su «origen». |

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

[IM Output]
Este núcleo es en realidad el mismo que usa el operador especializado de desenfoque de movimiento, aunque ese operador también hace un manejo muy elaborado de búsqueda de coordenadas para permitir que el desenfoque funcione en cualquier ángulo. Aunque lo hace mal, produciendo «grumos» de color en ángulos grandes, como 45 grados. Es de esperar que se implemente una rotación de núcleo adecuada para crear mejores efectos de tipo desenfoque de movimiento en ángulos fuera de los incrementos de 90 grados. [IM Output]

Núcleos Gaussian vs Blur

Como se mencionó, los núcleos «[Gaussian](#gaussian)» y «[Blur](#blur)» están muy estrechamente relacionados y, de hecho, pueden hacer el mismo trabajo. Ambos son representaciones de la curva gaussiana, siendo el primero una representación bidimensional y el otro una representación unidimensional. Por ejemplo, aquí está repetido el «-gaussian-blur 0x2», que es equivalente a la operación «-morphology Convolve Gaussian:0x2». |

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

[IM Output]
Esto puede sustituirse usando dos operaciones de desenfoque lineales o unidimensionales separadas, rotadas noventa grados una respecto a la otra (el orden tampoco importa mucho)... |

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

[IM Output]
En lugar de especificar dos convoluciones separadas, puede dar ambos núcleos como una lista de núcleos. Por ejemplo

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

IM, por defecto, «reiterará» el resultado del primer núcleo de convolución con el segundo (y posteriores) núcleo de convolución, según defina la opción Composición de múltiples núcleos. Puede incluso simplificar lo anterior aún más pidiendo a IM que expanda un núcleo en una lista de núcleos rotados, usando un «>» para hacer una lista de rotaciones de 90 grados (dos núcleos en este caso). Por ejemplo...

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

Todos los ejemplos anteriores son equivalentes entre sí, y es así como funciona el operador «[-blur](https://imagemagick.org/command-line-options/#blur)». |

  magick face.png -blur 0x2 face_blurred.png

[IM Output]
Esto representa la diferencia real entre los operadores «[-blur](https://imagemagick.org/command-line-options/#blur)» y «[-gaussian-blur](https://imagemagick.org/command-line-options/#gaussian-blur)». En el último se usa un único núcleo bidimensional grande, mientras que el primero usa dos núcleos unidimensionales pequeños. En términos de velocidad, sin embargo, el operador «[-blur](https://imagemagick.org/command-line-options/#blur)» suele ser un orden de magnitud más rápido, ya que usa dos núcleos mucho más pequeños en lugar de uno muy grande. Cuanto mayor sea el argumento de desenfoque (el tamaño del argumento sigma), más grandes se vuelven los núcleos, y mayor es la diferencia de velocidad entre las dos operaciones. Por ello, el operador «[-blur](https://imagemagick.org/command-line-options/#blur)» es, en general, el recomendado. La única diferencia en los resultados entre los dos operadores son pequeños efectos de redondeo de cuanto (a menos que use HDRI) y efectos de borde (según la opción de píxel virtual). Ambos están causados por una pérdida de información generada al guardar una imagen intermedia entre las dos pasadas separadas de las convoluciones de «desenfoque». Esta diferencia suele ser tan pequeña que resulta invisible y carece de importancia para cualquier uso práctico.

Desenfoque suavizado (mezcla con la imagen original)

Puede suavizar el impacto de cualquier tipo de desenfoque mezclándolo con algo de la imagen original. Especialmente al aplicar un desenfoque muy fuerte. Por ejemplo...

  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]

Esto usó el método de composición «[Blend](compose.html#blend)» para mezclar el «60%» de la imagen desenfocada (imagen de origen de la composición) con el «40%» de la imagen original (imagen de destino de la composición) para dar un efecto de «desenfoque suave» en la imagen final. Sin embargo, puede hacer lo mismo directamente mezclando el núcleo con el núcleo identidad, usando la misma proporción. |

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

[IM Output]
Tenga en cuenta que el orden de los números de escala es el mismo. El primer número («60%») escala el núcleo dado para reducir su efecto en la salida, mientras que el segundo número («40%») añade suficiente del núcleo «[Unity](#unity)» (o «identidad») para evitar que el resultado se oscurezca. Lo importante es que, para los núcleos de desenfoque, los dos números suman «100%», igual que haría para la mezcla por composición. También puede usar el desenfoque de 2 pasadas, más rápido, pero en este caso no podemos incorporar una «Blend» directamente en el núcleo, ya que las dos convoluciones separadas no se «separarán» limpiamente. Por ello, tendremos que volver a hacer la composición Blend después. |

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

[IM Output]
Tenga en cuenta que solo necesita dar la cantidad de la imagen desenfocada (origen) que quiere mezclar con la imagen original. Por ello, valores de «100» darán la imagen desenfocada, mientras que «0» dará la imagen original. | Recuerde que el operador «[-blur](https://imagemagick.org/command-line-options/#blur)» es exactamente equivalente a usar los núcleos de desenfoque de 2 pasadas, más rápidos.
---|---

«Un-sharpen» de imágenes usando desenfoques (restando de la imagen original)

Llevando esta mezcla de núcleos más lejos, de modo que empiece a usar un escalado negativo, puede restar los efectos de desenfoque de la imagen original. El resultado es una técnica llamada «unsharp». Véase Unsharp, Wikipedia para saber cómo llegó a tener un nombre tan desafortunado. |

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

[IM Output]
Tenga en cuenta que, aunque se usa un factor de escala de núcleo negativo, los dos números siguen sumando «100%», exactamente como antes. También puede hacer esto con la mezcla por composición. El ejemplo anterior es en realidad exactamente cómo funciona el mal llamado operador «[-sharpen](https://imagemagick.org/command-line-options/#sharpen)», pero solo con el control de desenfoque «sigma». Sin embargo, no se proporciona ningún otro control de la operación. La mezcla es exactamente como se dio arriba. Puede usar los núcleos de desenfoque unidimensionales de 2 pasadas, más rápidos, pero de nuevo tendrá que hacer la operación de mezcla como paso separado. |

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

[IM Output]
Esto, como habrá deducido, es casi idéntico al desenfoque suavizado, pero restando la imagen desenfocada de la original en lugar de sumarla. Un método de mezcla conocido como mezcla extrapolada, o mezcla más allá del rango normal del 0 al 100 por ciento. De nuevo, igual que antes, puede simplemente especificar cuánto de la imagen desenfocada quiere restar de la imagen original. Por ejemplo, exageremos el «un-sharpen» de la imagen, causando algo de aliasing y distorsiones de color. |

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

[IM Output]
El operador «[-unsharp](https://imagemagick.org/command-line-options/#unsharp)» completo proporciona otro tipo de control. Concretamente, un umbral de diferencia, de modo que el enfoque solo se aplica cuando la diferencia dada es mayor, como cerca de un borde real dentro de la imagen. Ese umbral puede usarse para evitar el «enfoque» de pequeños defectos, como arrugas o ruido de cámara. El «un-sharpen» de una imagen se usa típicamente con desenfoques muy pequeños (del orden de sigma=0.75) tras redimensionar o distorsionar la imagen, para mejorar el resultado final. Véase Enfocar imágenes redimensionadas para algunos ejemplos de esto. La alternativa a usar una técnica «unsharp» para el enfoque de imágenes es localizar realmente los bordes de la imagen y usarlos para enfocarlas. Véase Enfoque de imágenes con detección de bordes más abajo para más detalles. Sin embargo, se considera en general más lento, aunque en realidad no por mucho.


Convoluciones de detección de bordes (filtrado de paso alto)

La detección de bordes es otra área en la que las convoluciones se usan mucho. La tarea aquí es resaltar o realzar los bordes de una imagen de diversas formas. Esto puede ser para localizar un borde con la mayor precisión posible o para determinar el ángulo o la dirección de la pendiente de cada uno de los bordes. Sin embargo, el trabajo puede complicarse bastante por la presencia de ruido en la imagen, como el que producen los escáneres, las cámaras digitales o, simplemente, el causado por la compresión con pérdida del formato de archivo de imagen JPEG. En general, no obstante, los núcleos más grandes gestionan mejor el ruido, pero a costa de localizar el borde con precisión, mientras que los núcleos más pequeños producen resultados de localización de bordes nítidos, pero con más resultados espurios causados por el ruido de la imagen. Hay muchos núcleos pequeños y bien conocidos que se han desarrollado y estudiado para la detección de bordes. La mayoría de ellos llevan el «nombre» del matemático que estudió la matemática o que desarrolló ese tipo concreto de núcleo. Así, tiene núcleos como «[Laplacian](#laplacian)», «[Sobel](#sobel)» y «[Prewitt](#prewitt)». Estos núcleos «con nombre» suelen ser muy pequeños y se definen usando números enteros, de modo que puedan incorporarse a software y hardware optimizados y diseñados específicamente para la velocidad. Es decir, se dice que son núcleos «discretos». Por eso, tendrá que escalar o normalizar el núcleo como parte de su uso. La detección de bordes también tiene el efecto secundario de proporcionar formas de enfocar los bordes de una imagen.

Núcleos de suma cero

Todos los núcleos de detección de bordes tienen una característica en común. Todos son de suma cero. Eso significa que contienen valores negativos, pero con todos los valores del núcleo sumando cero. Para una imagen de color liso y plano, una convolución usando tal núcleo producirá una imagen «cero» o negra. Sin embargo, para cualquier otra imagen, tendrá resultados que contienen valores tanto negativos como positivos. Por ejemplo, aquí aplico un detector de bordes «[Sobel](#sobel)» discreto sobre una imagen que contiene algunas 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]

Si observa los resultados, verá que el núcleo es direccional, en el sentido de que solo se encuentran los bordes verticales (según defina el núcleo «[Sobel](#sobel)» con ángulo cero). Sin embargo, solo encontró un conjunto de bordes, las pendientes «positivas» de izquierda a derecha, de negro a blanco. Para obtener las pendientes «negativas», tendrá que negar el núcleo usando la opción de escalado del núcleo. Por ejemplo... |

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

[IM Output]
Con un núcleo «[Sobel](#sobel)», también puede rotarlo 180 grados para obtener el mismo resultado que la «negación por escala», pero no todos los núcleos son simétricos de esta forma. La otra solución es añadir un sesgo de salida al resultado. Es decir, añadir un gris al 50 % a la imagen resultante de modo que los valores negativos sean más claros que esto y los positivos más brillantes. Sin embargo, también tendrá que escalar el núcleo para asegurar que los resultados permanezcan «sin recortar» por los límites de «negro» y «blanco» de la imagen. |

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

[IM Output]
Si no le importa la polaridad, puede obtener un valor absoluto de los resultados con un pequeño truco... |

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

[IM Output]
Véase el núcleo «[Sobel](#sobel)» para más técnicas de manejo de resultados, especialmente técnicas que implican la determinación de la dirección. La otra alternativa a usar un sesgo de salida es compilar una versión HDRI especial de Imagemagick. Esta almacena las imágenes en memoria usando valores en coma flotante y hace que los valores de la imagen no sean «recortados» ni «redondeados» por el uso de enteros. Sin embargo, incluso si usa esta versión especial de IM, todavía tendrá que postprocesar los resultados antes de guardarlos en un formato de archivo de imagen normal, o necesitará usar un formato de archivo de imagen especial habilitado para coma flotante. No obstante, no tendrá que preocuparse por los efectos de recorte o redondeo en los resultados de imagen intermedios, lo que facilita el manejo de las cosas.

Núcleos de detección de bordes

[IM Output]

LoG: laplaciano de gaussianas

   LoG:{_radius_},{_sigma_}

El «LoG» o «laplaciano de una gaussiana» es uno de los mejores núcleos de detección de bordes que puede conseguir. También se le conoce como núcleo «sombrero mexicano». Básicamente es un operador diferencial (de pendiente) «[Laplacian](#laplacian)» que se ha suavizado mediante la adición de un desenfoque gaussiano. Esto, a su vez, elimina la mayor parte del impacto del ruido en una imagen, que puede ajustarse con la opción «sigma». El núcleo contiene valores negativos que forman un anillo alrededor de un fuerte pico central. En la «imagen del núcleo» mostrada arriba, los negativos aparecen como los colores oscuros (casi negros), con los bordes decayendo a cero (gris oscuro) hacia los bordes. Y aquí está su efecto... mostrando cómo resalta los bordes de la imagen.

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

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

Un núcleo laplaciano carece de dirección, pero produce una cresta tanto positiva como negativa de valores a cada lado de un borde. Para localizar el borde, buscaría los puntos de cruce por cero entre las crestas positiva y negativa, una técnica conocida como detección de bordes de Marr y Hildreth. Este núcleo también es ideal para enfocar imágenes.
[IM Output]

DoG: diferencia de gaussianas

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

Esto generará un núcleo «DoG» o «diferencia de gaussianas» en el que a la gaussiana generada por «sigma1» se le restará la gaussiana generada por «sigma2». Normalmente «sigma2» es la mayor, de modo que el «pico central» del núcleo es positivo. Invertir los dos números, en la práctica, negará el núcleo resultante. Una de las principales críticas a un laplaciano de una gaussiana es que es difícil de implementar, al ser una curva matemática tan inusual. Tampoco es una curva muy bien documentada. El otro aspecto es que no puede «separarse» en una solución de 2 pasadas más rápida, como sí puede con una gaussiana (véase Núcleos Gaussian vs Blur). Sin embargo, generando dos núcleos «[Gaussian](#gaussian)» de valores sigma ligeramente distintos (en una proporción de aproximadamente 1.6) y restándolos entre sí, puede generar en realidad una aproximación cercana a un laplaciano de una gaussiana. El resultado es que un «[DoG](#dog)» se genera mucho más fácilmente en hardware que un núcleo «[LoG](#log)». Por ejemplo, aquí he colocado las imágenes del núcleo de un «[LoG](#log)» y de un «[DoG](#dog)» una al lado de la otra para compararlas.

[IM Output] [IM Output]

Si mira en la página web Diferencia de gaussianas, Wikipedia, verá algunos gráficos en los que también comparan el perfil de un «[LoG](#log)» (o «sombrero mexicano») con un «[DoG](#dog)», mostrando la diferencia muy muy leve entre las curvas correspondientes. Se desea más información sobre cómo mapear un sigma de un LoG para generar un «DoG» casi equivalente. Si lo sabe, por favor, escríbame a la dirección que figura en el pie de página. Los resultados aplicados también son muy similares. |

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

[IM Output]
Tenga en cuenta que ambos valores «sigma» deberían definirse y al menos uno debería ser distinto de cero. Un valor cero para cualquiera de los componentes sigma equivaldrá a un núcleo «[Unity](#unity)», es decir, mantiene la imagen sin cambios. Si ambos valores son cero, las dos gaussianas serían núcleos «[Unity](#unity)» que, al restarse, producirían un resultado perfectamente cero o negro (más cualquier valor de sesgo). Cuando los argumentos son «Dog:0,0,_distinto-de-cero_», el DoG se convierte en un simple filtro de paso alto, que se define como el núcleo «Unity» (que produce la imagen original) menos un núcleo de filtro de paso bajo (imagen desenfocada). En este caso, sigma1=0 es solo el núcleo «Unity» y sigma2=distinto-de-cero es un núcleo de filtro de paso bajo (desenfoque) gaussiano. Lo siguiente, por tanto, produce una imagen filtrada por paso alto con un valor de filtro de sigma2=2 |

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

[IM Output]
Un filtro de paso alto de Photoshop con un valor de filtro de radio=2 produce el mismo resultado. Tenga en cuenta que usar «DoG:0,2,0» devolverá una imagen que es básicamente la versión negada (en torno al sesgo de salida) de la imagen anterior. Esta técnica también puede usarse para generar un núcleo «laplaciano isótropo» de 3x3, es decir, un núcleo «[Laplacian](#laplacian)» que produce resultados iguales en todas las direcciones, en lugar de tener un sesgo diagonal desigual. Por ejemplo, radio=1 (para un núcleo de 3x3) y un sigma de 1 generarán... | |

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

[IM Text]
| [IM Text]


El otro punto sobre usar una «diferencia de gaussianas» es que puede usar el operador «[-blur](https://imagemagick.org/command-line-options/#blur)», mucho más rápido (que internamente usa los núcleos «[Blur](#blur)»), para generar los mismos resultados. Sin embargo, para hacer esto tendrá que generar cada una de las dos imágenes «desenfocadas» por separado y luego restar los resultados, con la adición de un escalado y un sesgo adecuados. Por ejemplo... |

  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]
Lo anterior usa el método de composición Mathematics especial para evitar problemas de «recorte» durante la resta de las imágenes en una versión no HDRI de IM. Para más detalles, véase Añadir degradados sesgados. El único otro factor es el uso de un factor de escala mayor durante la resta (los dos «4» del argumento de Mathematics Compose). Esto se debe a que restar dos desenfoques normalizados no produce la misma magnitud (aumentada) de resultados que se obtiene al normalizar conjuntamente las dos curvas gaussianas restadas en un núcleo «[DoG](#dog)». No obstante, aparte de la magnitud, la imagen del ejemplo anterior es equivalente al primer resultado del núcleo «[DoG](#dog)», solo que más rápida de generar, especialmente para valores de sigma grandes. Y ese es el punto: aunque supone más trabajo, ese método complejo es más rápido que usar directamente un núcleo «[DoG](#dog)» o «[LoG](#log)».

Núcleos Laplacian discretos

   Laplacian:{_type_}

Se han publicado muchas formas de pequeño «núcleo laplaciano» en numerosos artículos de investigación científica. Aquí proporciono versiones integradas de los más comunes que he podido encontrar en la literatura académica. Estos núcleos se calculan básicamente usando un núcleo «[LoG](#log)», pero escalado para usar valores enteros discretos en una pequeña matriz de núcleo. Esto permite usar filtros de imagen rápidos y dedicados, generados de modo que solo usen matemática de enteros para procesar los datos de la imagen. Sin embargo, ImageMagick es un procesador de imágenes más generalizado y, como tal, no proporciona un filtro dedicado tan ultrarrápido. Pero a la gente le gusta usar estos por ser más fáciles de entender, así que muchos de ellos se han incorporado a IM. Ninguno de los núcleos aquí proporcionados es rotable, y la mayoría son «anisótropos», es decir, no son perfectamente circulares, especialmente en las direcciones diagonales. No obstante, véase la sección anterior (núcleos «[DoG](#dog)») para una forma de generar un verdadero «núcleo laplaciano isótropo de 3x3». Los dos primeros núcleos, «Laplacian:0» y «Laplacian:1», son la forma más común de «núcleo laplaciano discreto» en uso. Son muy pequeños, lo que significa que localizarán los bordes con mucha precisión, pero también tienden a realzar el ruido de la imagen. Tenga en cuenta que no se han definido todos los números de «tipo», dejando huecos para definir más núcleos discretos en el futuro. Los números usados se eligieron para corresponder mejor con el núcleo definido por ese número.

Laplacian:0 (por defecto)

El laplaciano de 8 vecinos. Probablemente el núcleo de detección de bordes laplaciano discreto más común. Aquí uso Mostrar núcleo para extraer el núcleo «discreto» y «sin normalizar», antes de mostrarle el resultado del núcleo normalizado con un sesgo de salida. | |

  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]


A veces un laplaciano, ya sea un laplaciano discreto, como en el último ejemplo, o un «[LoG](#log)» o «[DoG](#dog)» generado, produce un resultado más complejo de lo deseado. En tales casos, generar una imagen sin sesgo (sin ningún sesgo de salida) funcionará mejor. Así que repitamos lo anterior sin un sesgo, para quedarnos solo con los bordes «positivos» más brillantes. |

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

[IM Output]
En este caso tenemos líneas oscuras (negras) sobre colores más claros (blancos). Esto, a su vez, hace que el filtro «duplique» los bordes, lo que puede verse en los resultados mostrados. Para esta imagen, usar un factor de escala negativo (para quedarse con los bordes negativos, en lugar de los positivos) pareció funcionar mejor en nuestra imagen de prueba. |

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

[IM Output]
Como puede ver, para esta imagen usar el tamaño negativo produce bordes más fuertes sin los efectos de «duplicación» que produjeron los resultados positivos. Esto se debe al uso de líneas de borde «negras» sobre un fondo blanco en la imagen empleada. NOTA APARTE: La razón por la que se obtiene un borde azul alrededor de la estrella amarilla es que la diferencia entre la estrella «amarilla» y el fondo «blanco» es una resta de color azul. Si el fondo fuera negro, obtendría un color de borde amarillo.

Laplacian:1

El laplaciano de 4 vecinos. También muy 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]


Los resultados no son tan fuertes, pero a menudo son más claros que los del laplaciano de 8 vecinos.

Laplacian:2

Laplaciano 3x3, con centro:4 borde:1 esquina:-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, con centro:4 borde:-2 esquina: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 resalta los bordes diagonales y tiende a hacer desaparecer los bordes verticales y horizontales. Sin embargo, quizá tenga que escalar los resultados (como hice arriba) para que cualquier resultado sea visible.

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]


La regla general con los núcleos laplacianos es que cuanto más grandes son, más limpio es el resultado, especialmente cuando hay errores de por medio. Sin embargo, también se obtiene menos detalle.

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

Un LoG discreto de 5x5 (sigma 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

Un LoG discreto de 9x9 (sigma 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]


Enfoque de imágenes con detección de bordes (realzando los bordes de la imagen original)

Los núcleos «[LoG](#log)» y «[DoG](#dog)» también pueden usarse para enfocar imágenes, en contraposición a «un-sharpen» de imágenes usando desenfoques. Básicamente, todo lo que necesita hacer es sumar los resultados del núcleo (incluidos los resultados negativos) a la imagen original. Hacer esto es fácil: simplemente sume el núcleo «[Unity](#unity)» o «identidad» ponderado al 100 % a los factores de escala. Por eso se proporcionó. Por ejemplo... |

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

[IM Output]
Este es un enfoque de la imagen mucho más amplio y suave que el que generó la técnica unsharpen (resultado mostrado a la derecha). Es decir, porque es un verdadero enfoque real de la imagen, y no uno fingido mediante la resta de un desenfoque. | [IM Output]
---|---
Como antes, cuando solo se realiza una convolución de una sola pasada, puede hacer uso directo de un núcleo mezclado. Por ejemplo, menos enfocado... |

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

[IM Output]
O más enfocado... |

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

[IM Output]
Puede usar métodos de 2 pasadas de la diferencia de gaussianas para producir una operación de enfoque multipaso más rápida pero, como se mostró arriba, tal esquema requiere 4 convoluciones y una operación de mezcla separada para lograr el mismo resultado. FUTURO: añadir un ejemplo de esto Es esta complejidad la razón de que usar unsharpen sea, más a menudo, el método preferido para enfocar imágenes. Pero, como puede ver, para un proceso de enfoque intenso, usar un núcleo de enfoque adecuado es preferible a un enfoque unsharp. No obstante, para un enfoque menor, como enfocar imágenes redimensionadas, no hay problema en usar unsharp.


Convoluciones direccionales (pendientes y brújula)

Como en los casos anteriores, estos núcleos buscan pendientes en la intensidad de color de la imagen pero, en lugar de cualquier pendiente, estos buscan pendientes en una dirección concreta. Matemáticamente, esto se conoce como «derivada», que en realidad es solo una forma elegante de decir «pendiente». Pero conocer la información de pendiente para distintas direcciones también puede ser útil como medio para determinar el ángulo o la dirección de «brújula» de una pendiente o borde de imagen. Es decir, la dirección bidimensional de la pendiente en una imagen en un punto concreto. Las pendientes también se usan en técnicas de procesamiento de imágenes conocidas como «relieve» (embossing) y «sombreado» (shading) de imágenes. Por ahora no hay núcleos «generados» disponibles, solo núcleos predefinidos «con nombre», como Sobel y Roberts. Sin embargo, estoy seguro de que las funciones de generación de núcleos de relieve y sombreado se trasladarán al conjunto de núcleos de morfología/convolución en algún momento del futuro. Así que echemos un vistazo a algunos de los núcleos direccionales «con nombre».

Núcleos direccionales

Sobel

   Sobel:{_angle_}

[IM Text]

Ya vimos el núcleo «Sobel» arriba, en la discusión sobre núcleos de suma cero. Este núcleo es un núcleo direccional puro (primera derivada) diseñado para devolver la pendiente de un borde en alguna dirección ortogonal concreta. Por defecto está diseñado para la detección de pendientes de izquierda a derecha, usando una operación «convolve». El resultado es, en esencia, una derivada en X (pendiente) de la imagen.

  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]

| _Si observa el núcleo, podría pensar que está declarado al revés. En cierto sentido, tiene razón. Sin embargo, esto se debe a la forma en que «Convolve» funciona en realidad.

Puede saber más sobre esta «inversión» con más detalle en Convolve vs Correlate más abajo.

_
---|---
Tenga en cuenta que este núcleo también puede producir una indicación de «pendiente negativa», pero esto no puede verse a menos que se use además un sesgo de «50%» con esta operación de convolución. Aunque no hay pendiente negativa en el ejemplo anterior, este siguiente ejemplo sí tiene una, así que también añadí una opción de sesgo para que pueda verla.

  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]

| _Si usa este núcleo con «Correlate», encontrará pendientes que «coinciden» con la forma en que está definido el núcleo. En ese caso, obtendría un resultado positivo para una pendiente que va de un valor alto (blanco) a la izquierda y un valor bajo (negro) a la derecha. En el ejemplo anterior, las dos líneas quedarían entonces intercambiadas.

Sin embargo, lo anterior es una «convolución», y no una «correlación» (es decir, coincidir con el núcleo). De nuevo, véase Convolve vs Correlate para más detalle de la diferencia._
---|---
Como puede ver, ahora obtenemos una línea blanca (pendiente positiva) al subir la pendiente de negro a blanco, y una línea negra (pendiente negativa) al volver a bajar de blanco a negro. Aquí está el resultado de usar el núcleo «Sobel» por defecto sobre la imagen del rostro.

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

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

Tenga en cuenta que sobel, y la mayoría de los demás núcleos de detección de bordes, tienden a producir una respuesta de 2 píxeles de grosor a lo largo de un borde muy fuerte, y una respuesta de 3 píxeles sobre una línea de un solo píxel de ancho. Esto es mucho más fuerte que un detector de bordes laplaciano. Puede rotar este núcleo usando el argumento «ángulo», generalmente en múltiplos de 90 grados. Sin embargo, también puede rotarlo en múltiplos de 45 grados, aunque no se diseñó para esto. Esto es útil para obtener derivadas direccionales cuantizadas a 45 grados o la magnitud del gradiente a partir del máximo de todos los resultados de derivadas rotadas 45 grados. Aquí está de nuevo, pero rotado 90 grados (de arriba abajo). |

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

[IM Output]

Una forma de recopilar todos los bordes de una imagen usando un núcleo «[Sobel](#sobel)» es aplicar el núcleo 4 veces en todas las direcciones y recopilar el valor máximo observado (usando una composición matemática Lighten). Esta es una aproximación a la magnitud del 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]
Puede simplificar lo anterior haciendo uso de las funciones de manejo de múltiples núcleos de la morfología de IM. Es decir, puede crear una lista rotada de todas las rotaciones de 90 grados del núcleo «[Sobel](#sobel)». |

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

[IM Output]
Si quiere ver exactamente qué hace lo anterior, añada la opción Mostrar núcleo y la opción Verbose. Una técnica más eficiente para generar una magnitud de gradiente sería aprovechar el hecho de que una rotación de 180 grados simplemente produce el mismo resultado que negar el núcleo y, por tanto, negar los resultados. Así, las derivadas en X e Y (convoluciones rotadas 90 grados), con cierto truco para obtener los valores absolutos de la convolución, pueden lograr tal resultado con menos procesamiento. |

   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]
Esto suele ser suficiente para la mayoría de los propósitos. Puede extraerse una magnitud más exacta de todas las pendientes haciendo una suma vectorial de las dos derivadas en X e Y (según el 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]
| _La función «[-gamma](https://imagemagick.org/command-line-options/#gamma)» en el uso anterior se emplea para realizar un «cuadrado» y una «raíz cuadrada» matemáticos de los valores devueltos por los resultados de «[Sobel](#sobel)». Para más detalle, véase Función de potencia de las matemáticas.

El «[+level](https://imagemagick.org/command-line-options/#level)» adicional asegura que la composición Plus no desborde el rango de cuanto de la imagen. Véase Efectos de cuanto, no-HDRI vs HDRI para más detalles._
---|---
En lugar de la magnitud, puede extraer la dirección de la pendiente a partir de los dos resultados de detección de bordes.

  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]

La primera expresión «[-fx](https://imagemagick.org/command-line-options/#fx)» es la que usa una función «atan()» para convertir un vector X,Y en un ángulo. Esto se colorea luego con una imagen de degradado arcoíris externa, como una tabla de búsqueda de color. La segunda expresión «[-fx](https://imagemagick.org/command-line-options/#fx)» crea una máscara de transparencia con umbral para hacer transparente cualquier área sin pendiente. Sin embargo, la técnica anterior tiende a producir un enorme lío de información para imágenes reales, ya que no tiene en cuenta la magnitud de la pendiente. Aquí hay otra versión más compleja. Esta hace casi todos los cálculos en el canal verde «G», para reducir en un factor de tres la cantidad de procesamiento de imagen necesario. Luego usa el espacio de color HSB para crear la dirección (matiz) y la magnitud (brillo). |

  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]

El núcleo «Roberts» es mucho más simple que el anterior núcleo «[Sobel](#sobel)» y producirá una localización de bordes aún más ajustada (hasta 2 píxeles). Por supuesto, eso también lo hace más propenso a los efectos del ruido. Normalmente este núcleo se representa con un núcleo mucho más pequeño de 2x1 o incluso de 2x2; sin embargo, al implementarlo como un núcleo de 3x3 puedo rotar el núcleo «cíclicamente» en incrementos de 45 grados. Por ejemplo, aquí hay un resultado a 45 grados, más comúnmente conocido como núcleo «Roberts-Cross». |

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

[IM Output]
Como con «[Sobel](#sobel)», también puede usar el manejo de múltiples núcleos para generar una pendiente máxima desde todas las direcciones. Pero esta vez obtendremos 8 direcciones de 45 grados, en lugar de solo 4. |

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

[IM Output]
Tenga en cuenta que rotar este núcleo 180 grados no genera un resultado negado (debido a un desplazamiento). Por ello no puede simplemente combinar la mitad del número de convoluciones, como sí puede con «[Sobel](#sobel)». Básicamente, la pendiente generada por una sola convolución «[Roberts](#roberts)» está desplazada medio píxel respecto a la alineación con la imagen real. Es decir, la pendiente calculada se localiza para un punto entre los valores «+1» y «-1», entre los píxeles, pero se almacena en el píxel central «-1». No obstante, esto también significa que, guardando todas las pendientes alrededor de un píxel y sumándolas, se obtiene una detección de bordes mucho más pequeña y nítida, con solo 2 píxeles (en lugar de 4 píxeles) resaltando los límites de borde nítidos.

Prewitt

   Prewitt:{_angle_}

[IM Text]

El núcleo «Prewitt» es muy similar a un «[Sobel](#sobel)», aunque mucho menos estricto en cuanto a la dirección exacta de la detección de bordes concreta. El resultado es, por tanto, un poco más difuso. |

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

[IM Output]

Compass

   Compass:{_angle_}

[IM Text]

Este es el núcleo «brújula de Prewitt» (Prewitt Compass), que supuestamente tiene un sentido direccional más fuerte 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 es otro detector de bordes con fuerte detección de dirección. |

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

[IM Output]

Frei-Chen

Este integrado proporciona tres conjuntos de núcleos. El primero es una variante «isótropa» (dirección uniforme) de «[Sobel](#sobel)», donde los valores «2» se han reemplazado por una raíz cuadrada de 2.

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

[IM Text]

El núcleo de arriba es el núcleo por defecto sin ponderar que constituye el corazón del núcleo «Frei-Chen». |

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

[IM Output]
Como «[Sobel](#sobel)», este núcleo debería aplicarse usando un ángulo en múltiplos de 90 grados. Para facilitar las cosas, se han proporcionado dos núcleos (con la misma ponderación): uno como el anterior para uso ortogonal y el otro para uso diagonal.

Frei-Chen:1

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

El tercer conjunto de tipos consta de 9 núcleos especialmente diseñados y ponderados que se usan no solo para la detección de bordes en una dirección concreta, sino también para determinar el ángulo real de un borde nítido. El «tipo» en este caso es un número del «11» al «19», que le permite extraer cualquiera de los 9 núcleos del conjunto. Sin embargo, si da un valor de «tipo» de «10», obtendrá una lista de múltiples núcleos con los 9 núcleos pre-ponderados.

Cada uno de los núcleos se aplica a la imagen original, luego los resultados se suman
para generar el resultado de la detección de bordes.

Esto se hace mejor usando una versión [HDRI](basics.html#hdri) de
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




Si se da un tipo de 10, se genera una lista de múltiples núcleos con los 9 núcleos ponderados
mostrados arriba. Esto le permite usar la composición de múltiples núcleos para hacer lo
anterior de forma mucho más sencilla...




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




Sin embargo, no he averiguado cuál se supone que es el significado de los resultados.  Si
alguien tiene experiencia o conocimiento sobre cómo se usa esto realmente, por favor,
hágamelo saber para poder incluirlo aquí y que otros lo aprovechen.

Correlate ( )

Mientras que el método «[Convolve](#convolve)» se usa básicamente para el procesamiento de imágenes, el método «Correlate» está diseñado más para la coincidencia de patrones. Es decir, realiza una «correlación cruzada» de una imagen con su núcleo, buscando una coincidencia de la forma dada dentro de la imagen. En realidad, tanto «[Convolve](#convolve)» como «Correlate» son la misma operación. La única diferencia entre ellos es en realidad muy menor, a saber, una reflexión en x e y (equivalente a una rotación de 180 grados) del núcleo. La mejor guía que he encontrado sobre cómo funcionan la correlación y la convolución y en qué se diferencian entre sí es Class Notes for CMSC 426, Fall 2005, by David Jacobs.

Convolución vs correlación (efectos de núcleos asimétricos)

Como mencioné arriba, los dos operadores «[Convolve](#convolve)» y «[Correlate](#correlate)» son esencialmente lo mismo. De hecho, los usuarios suelen decir convolución cuando lo que realmente quieren decir es correlación. Además, la correlación es en realidad el método más simple de entender. Para núcleos que son simétricos en torno a un «origen» central, lo cual es muy habitual, los dos métodos son en realidad iguales. La diferencia solo se hace evidente cuando se usa un núcleo asimétrico o irregular. Por ejemplo, aquí uso un núcleo «plano» con forma de «L» sobre nuestra imagen de «un solo píxel».

  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 puede ver, un «[Convolve](#convolve)» expandió el único píxel del centro para formar la forma de «L» a su alrededor. Incluso cuando el propio origen no formaba parte del «vecindario». Ahora repitamos este ejemplo pero usando «[Correlate](#correlate)» en su lugar.

  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 puede ver, «[Correlate](#correlate)» también expandió el único píxel para formar una forma de «L», pero era una forma de «L» «rotada». Esta es, en esencia, la única diferencia entre estos dos métodos. El método «[Correlate](#correlate)» aplica el núcleo «TAL CUAL», lo que hace que el único píxel se expanda en una forma «rotada». Por otro lado, «[Convolve](#convolve)» usa en realidad una forma «rotada» 180 grados del núcleo, de modo que cada píxel se expande en la misma forma sin rotar. Si desea ver algunos buenos ejemplos de cómo funciona realmente «[Convolve](#convolve)», le recomiendo que también eche un vistazo a EECE \ CS 253 Image Processing, Lecture 7, Spatial Convolution. El diagrama de la página 22, donde de hecho aplica el núcleo «reflejado» a un único píxel, tal como hice yo arriba.
Esta diferencia de rotación puede no parecer gran cosa, pero significa que, en términos matemáticos, una operación de convolución (representada por un símbolo de asterisco («*»)) es conmutativa, en el sentido de que, si tanto el núcleo como la imagen se trataran como una mera matriz de valores (o dos imágenes), entonces F * G == G * F. También significa que la convolución es asociativa, en el sentido de que ( F * G ) * H == F * ( G * H ). Véase Propiedades de la convolución, Wikipedia para más información al respecto. La operación «[Correlate](#correlate)» no es ni conmutativa ni asociativa. Aunque está estrechamente relacionada (por la rotación del núcleo). Básicamente, «[Convolve](#convolve)» actúa más como una «multiplicación» matemática, mientras que «[Correlate](#correlate)» no. La excepción a todo este lío es cuando el núcleo usado es idéntico al rotarlo 180 grados. Es decir, cuando el núcleo es simétrico respecto al «origen». En ese caso especial, ambas operaciones generan resultados equivalentes. Lo que confunde a la gente es que la mayoría de los núcleos que se usan para la convolución, como los desenfoques gaussianos, los laplacianos, etc., son simétricos, en cuyo caso no importa realmente si está haciendo una convolución o una correlación. Así que la gente se relaja y se vuelve imprecisa con los significados. Solo cuando no son simétricos, como en el caso de la búsqueda de formas (véase a continuación), o con núcleos direccionales como Sobel, la diferencia se vuelve realmente importante.

Correlación y búsqueda de formas

El uso real del método «Correlate» (aplicar el vecindario del núcleo «tal cual», sin rotación) es un método antiguo, pero simple, de localizar objetos con forma que coinciden aproximadamente con la forma hallada en el núcleo proporcionado. Por ejemplo, si usáramos «Correlate» con un núcleo con forma de «L» e intentáramos buscar en la imagen que creamos con el ejemplo del método de convolución anterior, obtenemos...

  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] _NOTA APARTE: observe que las áreas «negras» de la imagen del núcleo de arriba representan un valor de cero. No hay valores negativos en este núcleo, solo valores positivos para la forma que se busca.

_

Tenga en cuenta que usé la normalización del núcleo de IM para evitar que los resultados finales quedaran demasiado brillantes y que el «pico» se ahogara en un mar de puntos blancos. Como puede ver, el método «[Correlate](#correlate)» produjo un brillo máximo en el punto donde el «origen» del núcleo coincide exactamente con la misma forma en la imagen. Pero también produce resultados menos brillantes donde solo se obtiene una coincidencia parcial de la forma. Cuanto más coincide la forma, más brillante se vuelve el píxel. No obstante, le advierto que, aunque «[Correlate](#correlate)» tuvo éxito en este caso, no es realmente una gran forma de hacerlo. Por ejemplo, puede generar un número muy grande de coincidencias falsas en áreas de muy alto brillo. Este problema puede mitigarse usando valores negativos para las áreas que deberían coincidir con el fondo oscuro de la imagen. Es decir, las áreas que no coinciden con el fondo deberían hacer que el píxel resultante sea menos brillante.

  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] _NOTA APARTE: Para hacer más clara la imagen del núcleo, la generé de modo que los valores positivos (primer plano) son blancos, los valores negativos (fondo) son negros y los valores cero (no importa) son transparentes. Sin embargo, el núcleo que se usa en realidad está completamente definido, en términos de números, y su «vecindario» es un rectángulo completo.

_

Como puede ver, el pico de coincidencia es mucho más pronunciado, ya que ahora no solo coincide con los píxeles de primer plano, sino también con los del fondo. Observe el uso del indicador de normalización especial «^» en lo anterior. Esto es importante, ya que normalizará por separado los valores positivos y negativos del núcleo. Es decir, quiere buscar los píxeles de primer plano por igual que los del fondo. Esto significa que puede buscar coincidencias tanto positivas como negativas de la forma dada usando una versión HDRI de IM o con el uso adecuado del sesgo de salida (véase arriba). Por ejemplo, aquí aplico la búsqueda de la forma «L» a una imagen de prueba que contiene formas «L» tanto positivas como negativas. (las imágenes mostradas se han ampliado)

  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]

El sesgo de salida hizo que la salida normal de la búsqueda fuera un gris de tono medio, mientras que a las formas coincidentes se les dan colores más brillantes o más oscuros, según el número de píxeles que realmente coinciden con el «núcleo de forma». Si examina solo los valores reales de la imagen de salida, se producen un píxel blanco puro y un píxel negro puro, indicando coincidencias perfectas. Sin embargo, también hay un buen número de coincidencias aproximadas. Si no me interesaran las coincidencias negativas o «negras», podría quitar el sesgo de salida y el factor de escala «50%», de modo que los píxeles sin coincidencia sean negros y las coincidencias perfectas sean blancas. Una vez que tiene una imagen de coincidencia de «[Correlate](#correlate)», debe intentar encontrar los «picos» de coincidencia. Esto puede hacerse usando otra correlación, pero no siempre funciona muy bien. El mejor método es usar el método de coincidencia de patrones más exacto, la morfología «[HitAndMiss](morphology.html#hitmiss)», con el «[Peaks](morphology.html#peaks)» especial creado para este propósito. Esto encuentra cualquier píxel individual que esté rodeado únicamente por píxeles de color más oscuro. Pueden usarse otros núcleos «[Peaks](morphology.html#peaks)» para encontrar coincidencias más «laxas».

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

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

Y aquí puede encontrar fácilmente la ubicación donde se halló la mejor coincidencia de la forma, aunque el grado de la coincidencia se ha perdido. Quizá quiera mirar la sección de «búsqueda de picos» de Comparación y búsqueda de subimágenes. Pero mire también el script «[maxima](http://www.fmwconcepts.com/imagemagick/maxima/)» de Fred Weinhaus. FUTURO: Correlación cruzada normalizada con la transformada rápida de Fourier, para generar correlaciones de imagen muy rápidas con imágenes muy grandes (tanto la imagen de origen como la subimagen).

Correlación vs morfología HitAndMiss

Si compara la imagen del núcleo tal como yo la representé con los núcleos que usa el método de morfología Hit-And-Miss, verá que en realidad representan lo mismo. «[HitAndMiss](morphology.html#hitmiss)» «[Correlate](#correlate)»
Primer plano Un valor de «1.0» Un valor de «1.0» (antes de la normalización)
No importa Un valor de «Nan» o «0.5» Un valor de «Nan» o «0.0»
Fondo Un valor de «0.0» Un valor de «-1.0» (antes de la normalización)
Resultados Resta el mínimo del primer plano del máximo del fondo. Así, solo las coincidencias exactas producirán resultados positivos, y el umbralizado producirá una imagen de coincidencia binaria. Genera un rango de cuán de cerca coincide la imagen con una forma. Es posible que algunos píxeles del fondo tengan un valor mayor que los de primer plano, siempre que el patrón global esté presente. Puede ser difícil localizar «picos» de coincidencia concretos. También puede encontrar coincidencias negativas.
Como puede ver, se corresponden entre sí. Así, un núcleo para uno podría transformarse en un núcleo para el otro. Sin embargo, «[Hit-And-Miss](morphology.html#hitmiss)» solo encontrará coincidencias exactas perfectas con una diferencia clara entre primer plano y fondo. Por ello, es mucho menos tolerante con el ruido y las casi coincidencias que «[Correlate](#correlate)». Por otro lado, «[Correlate](#correlate)» puede realizarse usando procesamiento de imágenes lineal y, más concretamente, usando una transformada rápida de Fourier. Esto puede hacer que la coincidencia con patrones y núcleos más grandes sea mucho más rápida, especialmente cuando hay varios patrones implicados, ahorrándole el coste de transformar imágenes y patrones al dominio de la frecuencia. También funciona con imágenes reales, aunque también puede ser necesario algo de preprocesamiento y el uso de HDRI. Cuál usar depende realmente de usted y de los resultados que busque. Solo coincidencias perfectas, o coincidencias aproximadas con muchos más errores y el posible uso de un algoritmo más rápido. Tenga en cuenta que, para encontrar coincidencias exactas de imágenes en color pequeñas dentro de imágenes más grandes, la función de localización de subimágenes del programa «magick compare» proporcionará un método mucho mejor que los métodos «[Hit-And-Miss](morphology.html#hmt)» o «[Correlate](#correlate)». Esto se debe a que usa «mínimos cuadrados de diferencias de vectores de color» para hacer la coincidencia de subimágenes, lo que puede producir una mejor métrica para los resultados de coincidencia. Sin embargo, es igual de lento, especialmente para imágenes grandes.

Conteo de vecinos

Una de las cosas más inusuales para las que puede emplearse la convolución se conoce como conteo de vecinos. Es decir, averiguar cuántos píxeles existen en un área concreta que rodea cada punto de píxel de una imagen.

Conteo de vecinos

Básicamente, usando un núcleo de convolución muy simple, puede crear una imagen que contenga un conteo del número de vecinos que rodean un punto concreto en una imagen binaria. Convolucionando con un núcleo Ring de tamaño «1.5», obtiene un conteo de vecinos. Aquí cuento los vecinos de cada píxel en un área pequeña y muestro la ampliación de los píxeles individuales antes y después (generada usando el Script Ampliar imagen)...

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

[IM Output] [IM Output]

Como puede ver, el nivel de gris de todos los píxeles muestra cuántos vecinos tienen, incluidos los vecinos de píxel virtual a lo largo de los bordes. Si quiere incluir el píxel actual en el conteo, puede usar en su lugar un núcleo Square. Con las conversiones adecuadas (incluidos ajustes de nivel) y usando el formato de archivo PbmPlus, puede convertir los niveles de gris anteriores en números reales si eso es lo que desea.

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

[IM Text]

Si quiere excluir los píxeles que se encuentran dentro de la propia forma, puede usar un núcleo con un fuerte píxel central negativo y luego Clamp cualquier resultado negativo (si usa una versión HDRI de IM). Un método simple para generar justamente tal núcleo de unos positivos rodeando un gran centro negativo es escalar negativamente un núcleo laplaciano discreto estándar.

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

[IM Output] [IM Output]

Por supuesto, también podríamos haber usado la imagen original como máscara para eliminar los píxeles sin interés.

El juego de la vida

En 1970, un matemático británico, John Horton Conway, publicó en Scientific American una simulación especial que se hizo muy popular. Ahora se conoce como El juego de la vida de Conway. Se basaba en una cuadrícula de puntos donde cada punto estaba «vivo» o «muerto». Qué «células» se clasificaban como «vivas» o «muertas» en la siguiente «generación» dependía de un conjunto de reglas muy simples basadas únicamente en el número de células vecinas vivas a su alrededor.

* El vecindario son los 8 píxeles que rodean cada «célula».
* Una célula «viva» sigue viva si tiene 2 o 3 vecinos.
* Una célula «muerta» pasa a estar «viva» (nace) si tiene exactamente 3 vecinos.
* En cualquier otro caso, la célula pasa a estar o permanece «muerta».

El resultado de estas reglas sobre patrones binarios fue notable, en el sentido de que se obtienen grupos de «células» que parecen expandirse, encogerse, oscilar o incluso moverse lentamente por la cuadrícula. Se convirtió en un importante punto de investigación teórica, para ver si se podía incluso generar una replicación al estilo del «ADN» de «patrones de vida» más grandes. NOTA APARTE: Parece que era posible, pero era tan frágil como para resultar poco práctico, lo que hace que la vida basada en ADN actual sea mucho más notable. También despertó un gran interés por el estudio y la implementación de otras formas de autómatas celulares, como método para generar y estudiar grandes efectos usando reglas muy muy simples a escalas muy pequeñas. Muy parecido a lo que ocurre en química a nivel atómico y molecular, pero con mayor complejidad. Así que implementemos «Life» usando ImageMagick. Primero, para simplificar, haremos las células «vivas» blancas y las «muertas» negras. De esa forma, solo contamos píxeles «blancos» que rodean cada célula, en un vecindario de 8 píxeles. Sin embargo, también podríamos haberlo implementado con el blanco y el negro intercambiados, aunque sería más difícil seguir cómo se hace. No obstante, las reglas dependen fuertemente de si la célula central está viva o muerta. Por eso necesitamos separar los conteos de vecindario de una célula «muerta» de los de una célula «viva». Eso puede hacerse simplemente dando a la célula central un valor mayor que la suma de todos sus vecinos. Un valor de «10» es bueno para esto. Es un número redondo y agradable, mayor que el conteo máximo de vecindario de 8. Eso hace que el núcleo de convolución del «juego de la vida» equivalga a...

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

El resultado de esto será un conteo de los 8 vecinos alrededor de cada píxel (que sea «blanco»), más un valor de 10 si el píxel central está «vivo» o es «blanco». Así, el valor de este núcleo será de «0» a «8» para los píxeles muertos, o de «10» a «18» para los píxeles vivos. Si escalamos este núcleo por un valor de 20 (en realidad escalando por «0.05» para generar un degradado, véase más abajo), generará una imagen con 21 niveles de gris posibles. Es decir, obtendrá un «negro» para el nivel de gris «0» y un valor blanco para el nivel de gris «21», aunque el núcleo no pueda generar realmente tal valor. Ahora podemos codificar las reglas del «juego de la vida» en una imagen de tabla de búsqueda de color, para convertir el «nivel de gris» del conteo de vecinos resultante, generado por el núcleo anterior, en el resultado de «vida y muerte» adecuado según las «reglas de la 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]

La imagen es muy pequeña, así que usé un Script Ampliar imagen para generar una versión más grande que mostrar arriba, con cada píxel claramente separado. Básicamente, los primeros 10 píxeles indican qué hacer para una «célula muerta», y los siguientes 10 píxeles, qué hacer para una «célula viva». El primer píxel blanco del lado izquierdo (conteo de vecinos = 3 alrededor de una célula muerta) es un «nacimiento», mientras que los dos píxeles blancos del lado derecho (conteos de vecinos 2 y 3 junto a una célula viva) permiten que una «célula viva» existente siga viva. Cualquier otro resultado deja el resultado como negro (muerta). La tabla de búsqueda de color tiene 21 píxeles de largo porque dividiré por un factor de escala de 20, lo que significa que podríamos generar un valor en el rango de 0 a 20, o 21 niveles distintos de escala de grises. En realidad, podríamos usar un valor distinto de 10 para el centro (estado previo de las células) y de 20 para el escalado, pero estos valores son números fáciles de manejar. En resumen, dividimos el núcleo de convolución entre 20 y usamos una CLUT de 21 píxeles de largo (con interpolación de enteros) para hacer corresponder los resultados de la convolución (niveles de gris) con el valor de color de salida correcto. NOTA APARTE: Esta CLUT de «reglas de la vida» puede considerarse una tabla general de reglas de autómatas celulares. El patrón de vecindario usado para el conteo de vecinos también forma parte del autómata celular. Esta técnica también se describe en Cellular Automata Rules Lexicon, en la sección Rules Tables, como forma de definir formas generales «sin límite» de los autómatas celulares que enumera. Básicamente, casi cualquier autómata puede definirse usando tal combinación de vecindario/tabla, aunque la mayoría se definen usando formas más simplificadas. Así que apliquemos esto a una imagen que contiene un patrón de «vida», varias veces, para ver cómo cambia el patrón de una generación a la siguiente y comprobar que funciona como se espera.

  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]

Recuerde que las imágenes anteriores se han ampliado; para ver la imagen «diminuta» original generada, haga clic en la imagen ampliada. Como puede ver, los patrones de «Life» se comportan como deberían (si está familiarizado con los patrones). El «blinker» de la esquina superior izquierda parpadea de un lado a otro, mientras que el «glider» de la parte inferior se movió 1 paso en diagonal hacia él, a lo largo de las 4 «generaciones» que iteramos las reglas de la vida. [IM Output] Y aquí hay un ejemplo más grande conocido como Cañón de planeadores de Gosper, donde genero una animación de 60 fotogramas a partir de un patrón de vida especial. El tamaño real de la imagen usada se muestra a la derecha, pero escalo la animación resultante para verla mejor.

  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]

Tenga en cuenta que la razón por la que el glider «explota» en el borde inferior es el manejo del píxel virtual por defecto que usa convolve, y la pérdida de la información de vida a medida que sale de los límites de la imagen. Pueden encontrarse más imágenes de patrones de vida en el catálogo de patrones de Life, aunque tendrá que recolorear (negar) las imágenes para usarlas en el procesador de vida anterior. Dejaré como ejercicio para alguien convertir lo anterior en un script que pueda generar una secuencia de vida para alguna imagen de entrada concreta.
Este es solo un ejemplo de toda la gama de «autómatas celulares» que IM podría procesar. Por supuesto, hay muchos programas dedicados más rápidos para «Life» y los «autómatas celulares», que en general hacen exactamente lo mismo, pero quería mostrar que IM es lo bastante flexible como para hacerlo también. Como los resultados son simples imágenes binarias, también puede usar los métodos de morfología de IM, como la búsqueda de patrones Hit-and-Miss o la correlación cruzada, para buscar patrones de vida concretos, lo que hace que usar IM para la investigación de la vida sea más práctico, aunque lento.