⚠️ Ceci est un site de traduction non officiel, sans lien avec ImageMagick Studio LLC. Pour des informations officielles, consultez la page originale (https://usage.imagemagick.org/convolve/index.html).

Exemples ImageMagick -- Convolution des images

Préface et index des exemples ImageMagick
Introduction à la convolution

La convolution utilise le « voisinage » local des pixels pour modifier les images. Pour cela, elle combine et moyenne toutes les valeurs de couleur autour de chaque pixel afin de flouter les images, de faire ressortir les contours et les frontières, et d'accentuer les images. La variante de la convolution, la « corrélation », sert aussi à balayer et rechercher des motifs particuliers, en produisant une image qui indique à quel point les images correspondent.


Introduction à la convolution

Les méthodes 'Convolve' et 'Correlate', qui lui est étroitement liée, ressemblent à bien des égards à la morphologie. Elles fonctionnent en effet presque exactement de la même manière, en faisant correspondre un « noyau » de voisinage à chaque emplacement, ce qui en fait simplement une autre « méthode » particulière de la morphologie. Elles réutilisent d'ailleurs une grande partie du même code, et même les mêmes définitions de noyaux décrites dans Noyaux de base et Noyaux définis par l'utilisateur. Pour des noyaux plus spécifiques conçus pour cet opérateur (et ils sont nombreux), reportez-vous aux Noyaux de floutage et aux Noyaux de détection de contours. Le noyau le plus important étant le noyau '[Gaussian](../static/img/convolve/gaussian)'. La convolution est cependant bien plus ancienne que la morphologie, et elle produit davantage d'effets de dégradé en niveaux de gris que les effets d'étude de formes binaires que la morphologie génère habituellement. C'est pourquoi elle est souvent considérée comme une opération très différente ou distincte de la morphologie, et plus centrale dans le traitement d'images. Fondamentalement, une convolution ou une corrélation effectue une « moyenne pondérée » de tous les pixels du voisinage indiqué. Autrement dit, elle multiplie la valeur de chaque pixel proche par la quantité donnée dans le noyau, puis additionne toutes ces valeurs pour produire le résultat final. Ainsi, chaque pixel de l'image finale contiendra en général au moins une petite part de tous les autres pixels qui l'entourent localement dans l'image source. Vu autrement, la couleur de chaque pixel de l'image sera soit ajoutée (floutage) soit soustraite (accentuation/détection de contours) aux couleurs de tous ses voisins proches, selon le noyau utilisé. « convolve » et « correlate » sont la même opération, à un détail près, mineur mais important ; pour les exemples et les contrôles que nous allons voir maintenant, vous pouvez les considérer comme fondamentalement identiques. Plus loin (voir Convolution vs corrélation), nous examinerons précisément en quoi les deux opérateurs diffèrent réellement et pourquoi cette différence est si minime. Mais dans la plupart des cas, il s'agit de la même méthode.

Convolve ( )

Comme indiqué plus haut, la méthode 'Convolve' pondère chacun des pixels du voisinage local selon les valeurs à virgule flottante du noyau. Les valeurs pondérées sont ensuite simplement additionnées pour produire le nouveau pixel de remplacement dans l'image résultante. Par exemple, convoluons un pixel unique à l'aide d'un très petit noyau de convolution défini par l'utilisateur. J'active aussi le réglage Show Kernel spécial, afin que vous puissiez voir le détail du noyau défini et utilisé (les images affichées ont été agrandies).

  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]

Comme vous pouvez le voir, le pixel unique de l'image s'est maintenant étendu pour produire des pixels gris à 50 % autour de lui. Autrement dit, lorsque l'« origine » du noyau (son centre dans ce cas) est positionnée à côté du pixel unique de l'image d'origine, seul ce pixel a une valeur non nulle. Cette valeur de pixel est alors pondérée par la valeur '0.5' du noyau, et le pixel « à demi-lumineux » obtenu est ajouté à l'image résultante. De même, lorsque l'origine du noyau est positionnée exactement sur le pixel d'origine, elle reçoit une valeur de '1.0' reproduisant le pixel d'origine, sans qu'aucune autre valeur (noire) du voisinage alentour n'apporte de composante au résultat. Notez que toute valeur de noyau égale à '0.0' ne prend aucune part au calcul final. Les valeurs nulles ne font en fait pas partie du « voisinage », de même que toute valeur 'Nan' dans les noyaux de morphologie n'y prend aucune part. Ce noyau comporte donc un voisinage de 5 éléments. À bien des égards, une méthode '[Convolve](#convolve)' ressemble beaucoup à une méthode morphologique '[Dilate](morphology.html#dilate)' ; cependant '[Dilate](morphology.html#dilate)' traite seulement le noyau comme une sorte de masque bitmap, en repérant la plus grande valeur du voisinage. '[Convolve](#convolve)', en revanche, est une somme pondérée de toutes les valeurs du voisinage, si bien que la valeur de chaque élément du noyau intervient dans le résultat global. La syntaxe d'une opération de convolution est…

**-morphology Convolve {_convolution_kernel_}
**

Mais vous pouvez aussi employer un opérateur plus ancien et plus direct…

**-convolve {_convolution_kernel_}
**

| _Avant IM v6.5.9, l'ancien "[-convolve](https://imagemagick.org/command-line-options/#convolve)" ne comprenait pas les définitions de noyaux de la morphologie. Il n'acceptait que l'« ancien style » de noyaux définis par l'utilisateur, à savoir une simple chaîne de valeurs séparées par des virgules produisant un noyau carré de taille impaire. Il accepte désormais le « nouveau style » de définitions de noyaux de convolution.

Il reste toutefois limité aux noyaux carrés de « taille impaire ». Et il en restera ainsi jusqu'à ce qu'il commence à utiliser la nouvelle méthode de convolution de la « morphologie ».

_
---|---
| _L'ancien opérateur "[-convolve](https://imagemagick.org/command-line-options/#convolve)" n'est pas tout à fait identique à la méthode de morphologie plus récente '[Convolve](#convolve)'. Voici la liste des différences entre les deux opérations…

_

  • _L'ancien opérateur est implémenté comme unecorrélation plutôt qu'une véritable convolution. Cela signifie que le noyau n'est pas superposé à l'image source sous sa forme réfléchie. Voir Convolve vs Correlate pour les effets que cela produit sur les résultats.

_ * _Il n'accepte que des noyaux carrés de taille impaire. Celui de la morphologie autorise n'importe quel tableau rectangulaire, avec la possibilité de déclarer n'importe quel point du tableau comme origine.

_ * _L'ancien opérateur normalise toujours les noyaux sans laisser à l'utilisateur le moindre contrôle sur la mise à l'échelle du noyau. Le nouveau ne normalise pas automatiquement : vous devez le demander. La plupart des noyaux générés sont toutefois pré-normalisés pour vous.

_ * Vous ne pouvez utiliser aucune forme demélange avec le noyau identité, même si le biais de sortie est appliqué normalement. * _Il tirera en revanche parti d'un code « GPU » rapide, si l'ordinateur hôte dispose de telles capacités. La morphologie ne l'a pas encore activé.

_ * _Actuellement, les autres opérateurs liés à la convolution, tels que "[-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)", utilisent l'ancienne version de l'opérateur.

_ * _Par défaut, l'ancienne commande ne convolue que les canaux de couleur (tels que définis par le réglage "[-channel](https://imagemagick.org/command-line-options/#channel)"). Si vous convoluez avec un réglage "[-channel](https://imagemagick.org/command-line-options/#channel) RGBA", elle pondérera aussi les valeurs du noyau par le canal alpha afin d'assurer un floutage correct vis-à-vis de la transparence.

La méthode de morphologie 'convolve' gère automatiquement, par défaut, la pondération de la transparence des canaux de couleur. Autrement dit, un floutage d'image effectué avec elle traite les couleurs transparentes comme transparentes, et évite ainsi par défaut le bug de transparence du flou.

Cependant, si l'utilisateur modifie le réglage "[-channel](https://imagemagick.org/command-line-options/#channel)" par défaut (en n'incluant pas l'indicateur spécial 'Sync'), elle traitera alors la convolution comme un opérateur en niveaux de gris purement par canal.

Consultez la documentation du réglage "[-channel](https://imagemagick.org/command-line-options/#channel)", ou reportez-vous aux Mathématiques sur les canaux d'image, qui utilisent le même indicateur de la même façon, pour plus d'informations.

_

_

La plupart des différences ci-dessus finiront par disparaître à mesure que les choses fusionneront avec la méthode de morphologie plus récente '[Convolve](#convolve)'.

_
---|---
Si vous souhaitez voir d'excellents exemples du fonctionnement réel de '[Convolve](#convolve)', je vous recommande aussi de consulter EECE \ CS 253 Image Processing, Lecture 7, Spatial Convolution. L'article Wikipedia, Convolve propose de belles animations 1D du processus de convolution.

Mise à l'échelle du noyau de convolution

L'exemple ci-dessus fonctionne bien pour une image essentiellement noire, comme un pixel unique, mais si vous l'appliquiez à une image réelle, vous rencontreriez un problème…

  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]

Comme vous pouvez le voir, l'image résultante est très lumineuse (trois fois plus lumineuse, en fait) que l'image d'origine. Ce qui s'est passé, c'est que chaque pixel est partagé trois fois : 4 × '0.5' sur les côtés, plus une copie complète du pixel d'origine. Autrement dit, la somme de toutes les valeurs du noyau vaut 3, ce qui rend l'image résultante trois fois plus lumineuse ! Si vous revenez à la sortie « showKernel » ci-dessus, vous verrez qu'elle indiquait pour ce noyau une « convolution output range from 0 to 3 ». Cela montre que ce noyau éclaircira en général une image d'un facteur 3. Pour corriger cela, il faudrait diviser toutes les valeurs du noyau par 3. C'est-à-dire qu'une valeur de '0.5' aurait dû en réalité valoir environ '0.1667', tandis que la valeur centrale de '1.0' aurait dû être '0.3333'. Ce procédé est connu sous le nom de « normalisation du noyau ». Voici par exemple un résultat « normalisé » manuellement, avec la définition du noyau…

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]

Comme vous pouvez le voir, vous obtenez une version très légèrement floutée de l'image du visage, car chaque pixel a été réparti sur chacun de ses voisins immédiats. | _L'« image du noyau » présentée ci-dessus (générée à l'aide d'un script Kernel 2 Image spécial) montre aussi le noyau normalisé obtenu. Comme vous pouvez le constater, le noyau lui-même est désormais très sombre, car toutes ses valeurs sont également sombres, bien qu'elles totalisent une valeur de '1.0'.

À partir d'ici, toutes les images de noyaux de convolution présentées seront toujours ajustées pour que la valeur maximale soit portée au blanc ; sinon, vous ne verriez en général qu'une « image de noyau » sombre et pour ainsi dire inutile.

_
---|---
Normaliser le noyau soi-même n'est pas agréable et, comme vous l'avez vu, cela rend la définition du noyau obtenue bien plus difficile à comprendre. D'autres moyens sont donc proposés. Depuis IM v6.5.9-2, l'option experte spéciale "[-define](https://imagemagick.org/command-line-options/#define) convolve:scale={_kernel_scale_}' vous permet d'indiquer un facteur d'échelle global pour le noyau, et donc d'ajuster la luminosité du résultat 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 réalité, cela ajuste l'intensité globale des résultats du noyau. Comme vous le verrez dans les exemples suivants, vous voudrez probablement rendre le résultat de la convolution plus ou moins puissant. Ce facteur 'kernel_scale ' vous le permet.

Normalisation du noyau (mise à l'échelle automatique)

Plutôt que de calculer le facteur d'échelle (comme ci-dessus), vous pouvez simplement demander à IM de déterminer ce « facteur d'échelle de normalisation » en interne, en lui fournissant l'indicateur de normalisation spécial '!'. |

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

[IM Output]
| Le caractère '!' est aussi parfois utilisé à des fins particulières par divers shells de ligne de commande UNIX. Vous devrez donc peut-être l'échapper à l'aide d'une barre oblique inverse, même entre guillemets. La prudence est de mise.
---|---
Notez que, le noyau étant désormais normalisé, je peux le définir plus simplement à l'aide de nombres entiers. Le noyau normalisé restera identique au noyau « mis à l'échelle » précédent. En général, vous voudrez toujours normaliser le noyau, et c'est pourquoi la variante plus simple "[-convolve](https://imagemagick.org/command-line-options/#convolve)" effectue automatiquement cette normalisation. Vous pouvez demander à IM de normaliser le noyau, puis de le remettre à l'échelle d'une quantité donnée pour ajuster sa plage de sortie. Pour rendre cela encore plus simple, vous pouvez indiquer le facteur d'échelle sous forme de pourcentage. Par exemple, ici je normalise le noyau, puis je remets les valeurs à 50 % de la taille calculée, afin de produire un résultat plus sombre. |

  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]
Notez qu'utiliser une valeur de '!' équivaut en fait à utiliser '1!' ou même '100%!'. Vous pouvez même employer un facteur d'échelle négatif si vous voulez inverser les valeurs positives et négatives au sein du noyau. Pour un exemple, voir Images « désaccentuées » à l'aide de flous. Si le noyau a été normalisé de cette façon, la sortie Show Kernel vous indiquera qu'il est normalisé.

Fonctionnement de la normalisation

Concrètement, la « normalisation du noyau » consiste à additionner toutes les valeurs du noyau (y compris d'éventuelles valeurs négatives, ce qui est aussi possible). Si le résultat est non nul, toutes les valeurs sont mises à l'échelle de sorte que leur somme totale vaille un ('1.0'). Notez que, si vous avez des valeurs négatives, cela peut en fait créer un noyau dont une valeur est supérieure à un, typiquement à l'origine. Cela se produit notamment avec les noyaux de masque flou. Le point important est cependant que le noyau dans son ensemble totalise '1.0', de sorte que l'image finale n'est ni assombrie ni éclaircie par l'opération de convolution. Si le résultat de l'addition est zéro ('0.0'), le noyau est supposé être un noyau à somme nulle particulier. Dans ce cas, le noyau est mis à l'échelle pour que toutes les valeurs positives soient égales à '1.0' et, de la même manière, toutes les valeurs négatives totalisent alors '-1.0'. Ces noyaux sont particulièrement fréquents dans les techniques de détection de contours. La sortie Show Kernel précisera aussi qu'il est à somme nulle, si le noyau est sous cette forme, même s'il ne s'agit pas réellement d'un noyau à somme nulle normalisé, ce qui se verra d'ailleurs aisément aux autres nombres affichés. La plupart des noyaux déterminés mathématiquement sont pré-normalisés. Cela inclut les noyaux dérivés mathématiquement : '[Unity](#unity)', '[Gaussian](#gaussian)', '[LoG](#log)', '[DoG](#dog)', '[Blur](#blur)', '[Comet](#comet)'. Les noyaux constants discrets, en revanche, ne sont pas pré-normalisés ; vous devrez donc le faire à l'aide du réglage de normalisation du noyau (ci-dessus). Cela inclut les noyaux : '[Laplacian](#laplacian)', '[Sobel](#sobel)', '[Roberts](#roberts)', '[Prewitt](#prewitt)', '[Compass](#compass)', '[Kirsch](#kirsch)', '[FreiChen](#freichen)'. Notez que le noyau '[FreiChen](#freichen)' possède des sous-types spécialement pré-pondérés pour des usages plus spécifiques. Les noyaux FreiChen ne doivent pas être normalisés, mais utilisés tels quels.

Normalisation à somme nulle

Tous les noyaux de convolution n'utilisent pas uniquement des valeurs positives. Vous pouvez aussi rencontrer des noyaux mêlant valeurs positives et négatives, et souvent les valeurs de ces noyaux sont censées totaliser zéro afin de produire un noyau à somme nulle. De tels noyaux sont très importants pour les convolutions d'images plus avancées, car ils fournissent des techniques de détection de contours et d'accentuation des images. Comme je l'ai mentionné dans la section précédente, l'indicateur de normalisation habituel '!' fonctionne avec ces noyaux. Mais parfois, dans des situations particulières, vous voulez garantir que le noyau reste bien « à somme nulle ». La méthode de normalisation spéciale '^' offre simplement un moyen de garantir que le noyau est « à somme nulle » dans des cas tels que…

  1. Si la définition du noyau par l'utilisateur n'est pas assez précise pour garantir la somme nulle. Par exemple, vous ne pouvez pas indiquer '1/3' ou tout autre facteur fractionnaire de 3 sous forme de nombre décimal à virgule flottante exact.
  2. La courbe mathématique se retrouve « rognée » par la taille (le rayon) du noyau, si bien qu'elle peut ne plus être à somme nulle. Cela se produit par exemple pour les noyaux '[LoG](#log)' ou '[DoG](#dog")', qui reposent sur des courbes de réponse infinies. C'est précisément pour cette raison qu'IM applique cette normalisation spéciale en interne sur ces noyaux.
  3. Garantir qu'un « masque de forme » de corrélation est à somme nulle, de sorte que, lors de la recherche, IM puisse rechercher à parts égales les correspondances positives et négatives. Voir Corrélation et recherche de formes ci-dessous.

Ce qui se passe, c'est qu'elle normalise toutes les valeurs positives et négatives du noyau comme des entités distinctes. Autrement dit, toutes les valeurs négatives sont mises à l'échelle pour totaliser '-1.0' et toutes les valeurs positives pour totaliser '+1.0'. Le résultat est que le noyau dans son ensemble est garanti totaliser zéro. Notez que si vous employez cette méthode de normalisation pour un noyau entièrement positif comme « Gaussian », vous obtiendrez tout de même un noyau correctement normalisé. Cette forme de normalisation peut donc encore s'utiliser avec les noyaux de floutage. Elle ne doit toutefois pas servir à normaliser des noyaux d'accentuation définis directement, ni même des noyaux de masque flou, car ceux-ci peuvent contenir des valeurs négatives mais doivent totaliser un (à l'aide de la méthode de normalisation normale).

Mélange du noyau avec le noyau identité

La syntaxe complète du réglage de mise à l'échelle du noyau est soit…

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

Notez le doublement du caractère pour cent lorsqu'on utilise "[-set](https://imagemagick.org/command-line-options/#set)". Les indicateurs de normalisation optionnels '!' ou '^" seront appliqués en premier au noyau défini par l'utilisateur ou intégré (si demandé). Ensuite, le noyau sera mis à l'échelle par le facteur 'kernel_scale ', ce qui augmente ou diminue la « puissance » effective de la convolution sur les résultats. Le facteur d'échelle par défaut est '1.0'. Enfin, le nombre placé après une virgule est ajouté à la valeur d'« origine » du noyau. L'addition 'origin_addition ' par défaut est '0.0'. Cette dernière étape « ajoute » en fait un noyau Unity de l'« échelle » indiquée au noyau normalisé et mis à l'échelle généré précédemment. Cela produit des noyaux capables de…

Notez que si vous indiquez un indicateur pour cent ('%'), ce pourcentage sera appliqué À LA FOIS au facteur 'kernel_scale ' et à 'origin_addition '. Cela peut rendre l'échelle plus facile à lire et à comprendre lorsque des fractions sont en jeu. Exemple d'utilisation du réglage de mise à l'échelle du noyau…

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

Générera le noyau '[Laplacian:2](#laplacian_2)' demandé…

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

Le normalise (indicateur '!')

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

Le met à l'échelle à 50 %

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

Ajoute un noyau Unity (ajoute 100 % à la valeur d'origine)

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

Et vous pouvez désormais convoluer en utilisant '[Laplacian:2](#laplacian_2)' comme noyau d'accentuation, mais avec seulement une puissance d'accentuation de '50%. Rappelez-vous que tout indicateur '%' placé n'importe où dans le réglage d'échelle rendra les deux valeurs des pourcentages. En son absence, les deux valeurs sont de simples multiplicateurs directs. Par exemple, toutes ces options de mise à l'échelle sont équivalentes

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

Il en va de même pour les deux indicateurs de normalisation. Ils peuvent apparaître n'importe où dans le réglage de mise à l'échelle de convolution, mais ils seront toujours appliqués en premier, avant toute autre mise à l'échelle.

Contrôle du biais sur le résultat

Lorsque vous manipulez un noyau contenant des valeurs négatives, certains pixels de l'image résultante devraient recevoir une valeur négative. C'est particulièrement le cas avec les noyaux à somme nulle (voir ci-dessous). Malheureusement, à moins de disposer d'une version HDRI d'ImageMagick spécialement compilée pour préserver les valeurs négatives générées, tout résultat négatif sera écrêté à zéro (noir). Vous n'obtiendrez de la convolution que les résultats positifs. Cela ne peut tout simplement pas être stocké dans un format d'image normal, ce qui vous laisse avec la moitié du résultat. Vous pourriez compiler une version HDRI d'ImageMagick pour préserver les valeurs négatives générées, puis en extraire les informations souhaitées. Vous pouvez aussi, à la place, inverser le noyau en utilisant un facteur d'échelle négatif. Par exemple en utilisant…

-define convolve:scale='-1'

Mais vous n'obtenez alors que les résultats négatifs, les résultats positifs étant écrêtés. En utilisant le réglage IM "[-bias](https://imagemagick.org/command-line-options/#bias)", vous pouvez toutefois préserver à la fois les résultats positifs et négatifs. Les réglages à employer pour une version non-HDRI d'IM sont…

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

Le premier réglage met la sortie à la moitié de la taille que vous obtiendriez normalement (après normalisation), afin de laisser de la place aux résultats positifs comme négatifs. Ensuite, il ajoute un gris à 50 % à la valeur du pixel avant de sauvegarder le résultat dans une image. Avec ces réglages, tout résultat « nul » devient un gris pur, les résultats négatifs étant plus sombres et les résultats positifs plus clairs. Le noir représentera '-1.0' et le blanc signifiera '+1.0'. Un exemple de ce procédé est présenté dans les exemples de recherche de forme par corrélation ci-dessous.


Floutage des images (filtrage passe-bas)

Une autre section des exemples IM, en particulier Floutage et accentuation des images, traite des aspects pratiques de ce sujet. Nous examinons ici des détails plus spécifiques. Mais d'abord, nous décrirons les noyaux de base et la façon de les utiliser directement, sans modification. Plus tard, nous verrons comment modifier le floutage pour produire d'autres effets.

Noyaux de floutage

[IM Output]

Unity

Il s'agit d'un noyau spécial qui, en réalité, ne fait rien. Un seul élément de noyau est indiqué et, par conséquent, chaque pixel est remplacé par lui-même sans changement. Voici par exemple une convolution sans effet…

  magick face.png -morphology Convolve Unity face_unity.png

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

Depuis IM v 6.6.9-4, le noyau peut prendre un seul argument, à savoir un argument d'échelle propre au noyau. Cela vous permet de l'utiliser pour multiplier les valeurs d'une image, par exemple pour la rendre plus claire ou plus sombre. |

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

[IM Output]
Cela peut sembler peu utile, mais on peut s'en servir pour générer des effets de flous doux et de masque flou, ou dans des séquences multi-noyaux où vous ne pourriez peut-être pas utiliser la mise à l'échelle du noyau ni le mélange avec le noyau identité. Le même noyau à un seul élément peut aussi être généré à l'aide de '[Disk:0.5](morphology.html#disk)', qui vous permet également d'indiquer un argument d'échelle supplémentaire lors de la génération du noyau (par exemple 'Disk:0.5,0.5' pour le dernier exemple). Un noyau similaire (pour la convolution) peut aussi être généré par le générateur de noyau '[Gaussian](#gaussian)' avec un 'sigma ' de '0.0'. Mais cela ne peut produire qu'un petit noyau 3x3, constitué d'une valeur centrale '1.0' entourée de 8 valeurs '0.0'. [IM Output]

Filtrage par moyenne à l'aide de noyaux de forme

Alors que la plupart des noyaux de convolution définis plus bas font en général intervenir d'une manière ou d'une autre une courbe gaussienne, vous pouvez tout de même utiliser l'un des noyaux de forme de la morphologie vus précédemment pour simplement moyenner les pixels sur une zone donnée (large). Vous devrez bien sûr normaliser le noyau afin de générer réellement une moyenne, plutôt qu'une simple somme du voisinage. Par exemple, ici j'utilise un noyau plus petit en forme d''[Octagon](morphology.html#octagon)' pour moyenner toutes les valeurs de pixels trouvées dans une zone circulaire entourant chaque pixel.

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

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

Le résultat est que la valeur de chaque pixel est répartie de manière égale sur l'ensemble des 25 pixels du voisinage défini. Autrement dit, cela équivaut à un filtre de « moyenne » sur la forme donnée. Si vous voulez exclure le pixel d'origine de cette moyenne, en n'utilisant que les pixels environnants, vous pouvez employer un noyau '[Ring](morphology.html#ring)' (en ne fournissant qu'un seul rayon). Les autres noyaux de forme peuvent aussi s'utiliser de la même façon pour, par exemple, moyenner les valeurs de pixels sur une forme '[Diamond](morphology.html#diamond)', '[Square](morphology.html#square)' ou un grand '[Disk](morphology.html#disk)', et à la taille que vous voulez. Cependant, si une moyenne constante sur une zone en forme floute bien les images, elle a tendance à produire des effets inhabituels (en particulier des artéfacts de crénelage) dans l'image résultante. Plus précisément, l'usage d'un noyau de moyenne « plat » tend à convertir les contours nets en une pente linéaire plus épaisse, avec un changement brusque de la pente aux contours épaissis. L'épaisseur du résultat est de 'radius*2-1'. La façon dont différents angles de contour influent sur l'épaisseur et la linéarité de la pente dépend de la forme du noyau « plat » ou de moyenne.

  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]

Notez que le flou diagonal ci-dessus est différent pour un noyau carré et pour un noyau en disque. Une autre façon de générer un floutage carré à « pente linéaire » consiste à utiliser un très grand sigma avec un rayon précis. La convolution par noyau carré ci-dessus peut par exemple aussi s'obtenir avec -blur 5x65535. C'est ce qu'employait couramment Fred Wienhaus dans ses scripts avant que la morphologie ne soit disponible. [IM Output]

Noyau Gaussian (flou gaussien 2D)

Comme vous l'avez sans doute deviné, le noyau 'Gaussian' est le noyau le plus couramment utilisé pour convoluer une image. C'est le noyau mathématiquement idéal pour les effets de floutage. Voici par exemple la sortie Show Kernel d'un petit noyau 'Gaussian' (ils peuvent devenir très grands très rapidement)…

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

[IM Text]

Je ne voulais pas réellement appliquer de convolution à ce qui précède, car je souhaitais seulement montrer le noyau qui allait être utilisé. J'ai donc employé un nombre d'itérations ':0', pour qu'il ne fasse rien. De même, je jette l'image de sortie produite à l'aide du format de fichier spécial '[null:](files.html#null)'. Comme le montre la plage de sortie de la convolution, un noyau 'Gaussian' a déjà été normalisé (mis à l'échelle) pour vous. Vous remarquerez cependant aussi qu'il reste un noyau assez grand, rempli de petites valeurs fractionnaires. En regardant de plus près, vous constaterez que la plus grande valeur (2.48678, également indiquée sur la première ligne) se trouve au centre, les plus petites valeurs allant vers les bords et les coins (une valeur d'environ .000000194). Voici un flou gaussien typique à l'aide d'une convolution…

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

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

La syntaxe du noyau est simple…

   Gaussian:[{_radius_}]x{_sigma_}

Ces arguments sont en fait exactement les mêmes que ceux employés par l'opérateur "[-gaussian-blur](https://imagemagick.org/command-line-options/#gaussian-blur)", qui effectue justement une convolution à l'aide de ce noyau. Le premier nombre, comme pour la plupart des noyaux de morphologie, est le 'radius ' ou taille du noyau. Il s'agit simplement d'un entier, dont la valeur minimale est 1, ce qui donne un noyau le plus petit possible de 3x3 éléments. Le mieux est de toujours indiquer zéro, ce qui permet à ImageMagick de calculer un rayon approprié pour la valeur 'sigma ' fournie. Le second argument, plus important, est 'sigma ', qui définit à quel point chaque pixel doit être flouté ou « étalé ». Plus la valeur est grande, plus l'image devient floue. C'est une valeur à virgule flottante. La valeur sigma DOIT être fournie. Si une valeur de sigma de '0.0' est donnée, vous vous retrouverez avec un noyau '[Unity](#unity)' plutôt inutile (du rayon indiqué, ou d'un rayon de 1, produisant donc un noyau 3x3 formé d'une seule valeur '1.0' entourée de valeurs '0.0'). Comme vous l'avez vu plus haut, convoluer avec n'importe quel type de noyau '[Unity](#unity)' ne fait rien à l'image ! Si vous indiquez un 'radius ', il est généralement bon de le faire au moins deux fois plus grand que le 'sigma ' ; IM calcule habituellement un rayon environ 3 fois plus grand (en fait le plus grand rayon qui fournira des résultats significatifs), bien que cela dépende de la qualité à la compilation de votre installation IM particulière. Pour plus d'informations sur l'effet des arguments du noyau 'Gaussian' et sur le floutage des images en général, voir… Floutage des images. [IM Output]

Noyau Blur (flou gaussien 1D)

Le noyau 'Blur' ressemble beaucoup au noyau Gaussian, et prend même les mêmes arguments (voir ci-dessous). Mais là où la gaussienne est une courbe à deux dimensions, le noyau 'Blur' produit une courbe à une dimension. Autrement dit, il génère une longue et fine rangée unique de valeurs. Voici la sortie Show Kernel d'un petit noyau 'Blur'. | |

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

[IM Output]
| [IM Text]


Le graphe présenté ci-dessus est un profil réel du noyau 'Blur' par défaut. Il a été créé à l'aide du script Kernel Image "[kernel2image](../static/img/scripts/kernel2image)", puis cette image a été tracée à l'aide du script "[im_profile](../static/img/scripts/im_profile)". Il montre clairement la « courbe en cloche gaussienne » que représente ce noyau. Voici un exemple d'utilisation de ce noyau pour flouter une image horizontalement. |

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

[IM Output]
La syntaxe du noyau est exactement celle de '[Gaussian](#gaussian)', mais avec un angle de rotation optionnel supplémentaire.

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

Comme précédemment, la deuxième valeur 'sigma ' est requise, et si elle vaut zéro vous obtiendrez l'équivalent linéaire d'un noyau '[Unity](#unity)'. L'angle 'angle ' vous permet de pivoter le noyau de 90 degrés, ce qui permet de flouter une image verticalement. |

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

[IM Output]
Pour l'instant, seule une rotation de 90 degrés est possible. Cela pourra changer dans une version ultérieure d'ImageMagick. L'objet de ce noyau est en réalité de créer une forme plus rapide du floutage d'image à deux dimensions que produit le noyau '[Gaussian](#gaussian)'. Voir Noyaux Gaussian vs Blur ci-dessous pour le détail de la façon dont cela se fait. [IM Output]

Noyau Comet (demi-flou gaussien 1D)

Le noyau 'Comet' est presque exactement identique à un noyau '[Blur](#blur)', mais n'est en réalité qu'un demi-noyau de flou.

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

[IM Text]

Remarquez que l'emplacement défini de l'origine se trouve sur le bord gauche, et non au centre du noyau. C'est très inhabituel pour un noyau de convolution, et cela produit donc un résultat très inhabituel. Il floute l'image dans une seule direction, comme si un doigt avait étalé la surface d'une peinture fraîche, laissant une traînée de couleur. Un peu comme la queue d'une comète, ou la traînée laissée par un météore ou une étoile filante. |

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

[IM Output]
Notez que les couleurs de premier plan comme d'arrière-plan ont été « étalées ». Si vous voulez ne flouter que les couleurs de premier plan, rendez l'arrière-plan transparent et ajoutez-le après avoir flouté le premier plan. Vous pouvez aussi fournir un troisième argument angle pour pivoter le noyau de n'importe quel multiple de 90 degrés autour de son « origine ». |

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

[IM Output]
Ce noyau est en réalité le même que celui utilisé par l'opérateur spécialisé Motion Blur, bien que cet opérateur effectue aussi une gestion très élaborée de recherche de coordonnées pour permettre au flou de fonctionner à n'importe quel angle. Il le fait toutefois mal, produisant des « amas » de couleur aux grands angles, comme 45 degrés. On espère qu'une véritable rotation de noyau sera implémentée pour créer de meilleurs effets de type flou de mouvement à des angles autres que des multiples de 90 degrés. [IM Output]

Noyaux Gaussian vs Blur

Comme indiqué, les noyaux '[Gaussian](#gaussian)' et '[Blur](#blur)' sont très étroitement liés et peuvent en fait faire le même travail. Tous deux sont des représentations de la courbe gaussienne, le premier en étant une représentation à deux dimensions, l'autre une représentation à une dimension. Par exemple, voici une reprise de l'opération "-gaussian-blur 0x2", équivalente à "-morphology Convolve Gaussian:0x2". |

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

[IM Output]
Cela peut être remplacé par deux opérations de floutage linéaires (à une dimension) distinctes, pivotées de quatre-vingt-dix degrés l'une par rapport à l'autre (l'ordre n'a d'ailleurs pas vraiment d'importance)… |

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

[IM Output]
Plutôt que d'indiquer deux convolutions distinctes, vous pouvez fournir les deux noyaux sous forme de liste de noyaux. Par exemple

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

Par défaut, IM « ré-itère » le résultat du premier noyau de convolution avec le deuxième noyau (et les suivants), selon le réglage composition de plusieurs noyaux. Vous pouvez même simplifier davantage ce qui précède en demandant à IM de développer un noyau en une liste de noyaux pivotés, à l'aide d'un '>' pour effectuer une liste de rotations de 90 degrés (deux noyaux dans ce cas). Par exemple…

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

Tous les exemples ci-dessus sont équivalents entre eux, et c'est ainsi que fonctionne l'opérateur "[-blur](https://imagemagick.org/command-line-options/#blur)". |

  magick face.png -blur 0x2 face_blurred.png

[IM Output]
Cela représente la véritable différence entre les opérateurs "[-blur](https://imagemagick.org/command-line-options/#blur)" et "[-gaussian-blur](https://imagemagick.org/command-line-options/#gaussian-blur)". Dans le second, un seul grand noyau à deux dimensions est utilisé, tandis que le premier emploie deux petits noyaux à une dimension. En termes de vitesse, toutefois, l'opérateur "[-blur](https://imagemagick.org/command-line-options/#blur)" est généralement plus rapide d'un ordre de grandeur, car il utilise deux noyaux bien plus petits plutôt qu'un très grand. Plus l'argument de floutage est grand (la taille de l'argument sigma), plus les noyaux deviennent grands, et plus l'écart de vitesse entre les deux opérations est important. C'est pourquoi l'opérateur "[-blur](https://imagemagick.org/command-line-options/#blur)" est en général celui qu'il est recommandé d'utiliser. Les seules différences de résultats entre les deux opérateurs sont de petits effets d'arrondi de quantum (sauf si vous utilisez HDRI) et des effets de bord (selon le réglage Virtual Pixel). Tous deux sont dus à une perte d'information provoquée par la sauvegarde d'une image intermédiaire entre les deux passes distinctes des convolutions de « flou ». Cette différence est en général si faible qu'elle est invisible et sans conséquence pour tout usage pratique.

Floutage adouci (mélange avec l'image d'origine)

Vous pouvez adoucir l'impact de n'importe quel type de flou en le mélangeant à une partie de l'image d'origine. En particulier lorsque vous appliquez un flou très fort. Par exemple…

  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]

Cela a utilisé la méthode de composition '[Blend](compose.html#blend)' pour mélanger '60%' de l'image floutée (image source de la composition) avec '40%' de l'image d'origine (image de destination de la composition), afin de donner un effet de « flou doux » à l'image finale. Vous pouvez toutefois obtenir la même chose directement en mélangeant le noyau avec le noyau identité, en utilisant le même rapport. |

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

[IM Output]
Notez que l'ordre des nombres d'échelle est le même. Le premier nombre ('60%') met à l'échelle le noyau donné afin de réduire son effet sur la sortie, tandis que le second nombre ('40%') ajoute suffisamment de noyau '[Unity](#unity)' (ou « identité ») pour empêcher le résultat de s'assombrir. Le point important est que, pour les noyaux de floutage, les deux nombres totalisent '100%', tout comme vous le feriez pour un mélange par composition. Vous pouvez aussi utiliser le floutage plus rapide à 2 passes, mais dans ce cas nous ne pouvons pas incorporer un « Blend » directement dans le noyau, car les deux convolutions distinctes ne se « sépareront » pas proprement. Nous devrons donc, là encore, effectuer la composition Blend par la suite. |

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

[IM Output]
Notez qu'il vous suffit d'indiquer la quantité d'image floutée (source) que vous voulez mélanger à l'image d'origine. Ainsi, des valeurs de '100' donneront l'image floutée, tandis que '0' donnera l'image d'origine. | Rappelez-vous que l'opérateur "[-blur](https://imagemagick.org/command-line-options/#blur)" est exactement équivalent à l'utilisation des noyaux de floutage à 2 passes, plus rapides.
---|---

Images « désaccentuées » à l'aide de flous (soustraction à l'image d'origine)

En poussant ce mélange de noyaux plus loin, jusqu'à employer une mise à l'échelle négative, vous pouvez soustraire les effets de floutage à l'image d'origine. Le résultat est une technique appelée « masque flou » (unsharp). Voir Masque flou, Wikipedia pour comprendre comment elle a hérité d'un nom aussi malheureux. |

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

[IM Output]
Notez que, même si un facteur d'échelle de noyau négatif est utilisé, les deux nombres totalisent toujours '100%', exactement comme ci-dessus. Vous pouvez aussi faire cela avec un mélange par composition. L'exemple ci-dessus est en fait exactement le fonctionnement de l'opérateur mal nommé "[-sharpen](https://imagemagick.org/command-line-options/#sharpen)", mais avec seulement le contrôle de floutage 'sigma '. Aucun autre contrôle de l'opération n'est cependant fourni. Le mélange est exactement celui donné ci-dessus. Vous pouvez utiliser les noyaux de floutage à 2 passes, à une dimension, plus rapides, mais là encore vous devrez effectuer l'opération de mélange en une étape distincte. |

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

[IM Output]
Vous l'aurez compris, c'est presque identique au floutage adouci, sauf que l'image floutée est soustraite à l'image d'origine au lieu d'y être ajoutée. Une méthode de mélange dite mélange extrapolé, c'est-à-dire un mélange au-delà de la plage normale de 0 à 100 pour cent. Là encore, vous pouvez simplement indiquer quelle quantité de l'image floutée vous voulez soustraire à l'image d'origine. Par exemple, exagérons le masque flou de l'image, ce qui provoque un peu de crénelage et des distorsions de couleur. |

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

[IM Output]
L'opérateur complet "[-unsharp](https://imagemagick.org/command-line-options/#unsharp)" offre un autre type de contrôle. En particulier, un seuil de différence, de sorte que l'accentuation ne s'applique que lorsque la différence donnée est plus grande, par exemple près d'un véritable contour dans l'image. Ce seuil peut servir à empêcher l'« accentuation » de petits défauts, comme des rides ou du bruit d'appareil photo. Le masque flou d'une image s'emploie généralement avec de très petits flous (de l'ordre de sigma=0.75) après un redimensionnement ou une déformation de l'image, afin d'améliorer le résultat final. Voir Accentuer les images redimensionnées pour quelques exemples. L'alternative à l'emploi d'une technique de « masque flou » pour l'accentuation d'image consiste à localiser réellement les contours de l'image et à s'en servir pour l'accentuer. Voir Accentuation des images par détection de contours ci-dessous pour plus de détails. Cette approche est cependant généralement considérée comme plus lente, mais pas vraiment de beaucoup.


Convolutions de détection de contours (filtrage passe-haut)

La détection de contours est un autre domaine où les convolutions sont abondamment utilisées. La tâche consiste ici à faire ressortir ou à renforcer les contours d'une image de diverses manières. Cela peut viser à localiser un contour aussi précisément que possible, ou à déterminer l'angle ou la direction de pente de chacun des contours. La tâche peut cependant être rendue bien plus difficile par la présence de bruit dans l'image, tel que celui produit par les scanners, les appareils photo numériques, ou même simplement causé par la compression avec pertes du format de fichier JPEG. En général, toutefois, les grands noyaux gèrent mieux le bruit, mais au prix d'une localisation moins précise du contour, tandis que les petits noyaux produisent des localisations de contours nettes mais avec davantage de résultats parasites causés par le bruit de l'image. Il existe de nombreux petits noyaux bien connus, développés et étudiés pour la détection de contours. La plupart sont « nommés » d'après le mathématicien qui en a étudié les mathématiques ou développé ce type de noyau. Vous avez ainsi des noyaux tels que '[Laplacian](#laplacian)', '[Sobel](#sobel)' et '[Prewitt](#prewitt)'. Ces noyaux « nommés » sont en général très petits et définis à l'aide de nombres entiers, de sorte qu'ils peuvent être intégrés dans des logiciels et du matériel optimisés spécialement conçus pour la vitesse. Autrement dit, on les qualifie de noyaux « discrets ». De ce fait, vous devrez soit mettre à l'échelle soit normaliser le noyau lors de leur utilisation. La détection de contours a aussi pour effet secondaire de fournir des moyens d'accentuer les contours d'une image.

Noyaux à somme nulle

Tous les noyaux de détection de contours ont une caractéristique commune : ils sont tous à somme nulle. Cela signifie qu'ils contiennent des valeurs négatives, mais que toutes les valeurs du noyau totalisent zéro. Pour une image de couleur unie et lisse, une convolution utilisant un tel noyau produira une image « nulle » ou noire. Pour toute autre image, en revanche, vous obtiendrez des résultats contenant à la fois des valeurs négatives et positives. Par exemple, ici j'applique un détecteur de contours '[Sobel](#sobel)' discret sur une image contenant quelques formes de base…

  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 vous examinez les résultats, vous verrez que le noyau est directionnel, en ce sens que seuls les contours verticaux sont trouvés (tels que définis par le noyau '[Sobel](#sobel)' avec un angle nul). Il n'a cependant trouvé qu'un seul ensemble de contours, les pentes « positives » de gauche à droite, du noir au blanc. Pour obtenir les pentes « négatives », vous devrez inverser le noyau, à l'aide du réglage de mise à l'échelle du noyau. Par exemple… |

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

[IM Output]
Avec un noyau '[Sobel](#sobel)', vous pouvez aussi le pivoter de 180 degrés pour obtenir le même résultat que la « négation par l'échelle », mais tous les noyaux ne sont pas symétriques de cette façon. L'autre solution consiste à ajouter un biais de sortie au résultat. Autrement dit, ajouter un gris à 50 % à l'image résultante, de sorte que les valeurs négatives soient plus claires que ce gris et les valeurs positives plus lumineuses. Vous devrez toutefois aussi mettre le noyau à l'échelle pour garantir que les résultats ne soient pas écrêtés par les limites « noire » et « blanche » de l'image. |

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

[IM Output]
Si la polarité vous importe peu, vous pouvez obtenir une valeur absolue des résultats avec une petite astuce… |

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

[IM Output]
Voir le noyau '[Sobel](#sobel)' pour davantage de techniques de traitement des résultats, en particulier celles impliquant la détermination de la direction. L'autre alternative à l'emploi d'un biais de sortie est de compiler une version HDRI spéciale d'ImageMagick. Celle-ci stocke les images en mémoire à l'aide de valeurs à virgule flottante, ce qui signifie que les valeurs de l'image ne seront pas « écrêtées » ni « arrondies » par l'usage d'entiers. Cependant, même si vous utilisez cette version spéciale d'IM, vous devrez tout de même post-traiter les résultats avant de les enregistrer dans un format de fichier image normal, ou bien utiliser un format de fichier image gérant la virgule flottante. Vous n'aurez toutefois pas à vous soucier des effets d'écrêtage ou d'arrondi dans les résultats intermédiaires, ce qui facilite la manipulation.

Noyaux de détection de contours

[IM Output]

LoG : laplacien de gaussiennes

   LoG:{_radius_},{_sigma_}

Le 'LoG' ou « laplacien d'une gaussienne » est l'un des meilleurs noyaux de détection de contours qui soient. Il est aussi connu sous le nom de noyau « chapeau mexicain ». C'est essentiellement un opérateur différentiel (de pente) '[Laplacian](#laplacian)', qui a été lissé par l'ajout d'un floutage gaussien. Cela supprime à son tour l'essentiel de l'impact du bruit dans une image, ce qui peut être ajusté par le réglage 'sigma '. Le noyau contient des valeurs négatives qui forment un anneau autour d'un fort pic central. Dans l'« image du noyau » présentée ci-dessus, les valeurs négatives apparaissent en couleurs sombres (proches du noir), s'atténuant jusqu'à zéro (gris foncé) vers les bords. Et voici son effet… montrant comment il fait ressortir les contours de l'image.

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

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

Un noyau laplacien est sans direction, mais il produit à la fois une crête de valeurs positive et négative de part et d'autre d'un contour. Pour localiser le contour, on chercherait les points de passage par zéro, entre les crêtes positive et négative, une technique connue sous le nom de détection de contours de Marr et Hildreth. Ce noyau est aussi idéal pour l'accentuation des images.
[IM Output]

DoG : différence de gaussiennes

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

Cela génère un noyau 'DoG' ou « différence de gaussiennes », dans lequel la gaussienne générée par 'sigma1 ' se voit soustraire la gaussienne générée par 'sigma2 '. Normalement, 'sigma2 ' est le plus grand, de sorte que le « pic central » du noyau soit positif. Inverser les deux nombres inversera de fait le noyau obtenu. L'une des principales critiques adressées à un laplacien d'une gaussienne est qu'il est difficile à implémenter, car il s'agit d'une courbe mathématique très inhabituelle. C'est aussi une courbe assez peu documentée. L'autre aspect est qu'il ne peut pas être « séparé » en une solution à 2 passes plus rapide, comme on peut le faire avec une gaussienne (voir Noyaux Gaussian vs Blur). Cependant, en générant deux noyaux '[Gaussian](#gaussian)' de valeurs de sigma légèrement différentes (dans un rapport d'environ 1.6), et en les soustrayant l'un de l'autre, vous pouvez en fait générer une approximation proche d'un laplacien d'une gaussienne. Il en résulte qu'un '[DoG](#dog)' se génère bien plus facilement en matériel qu'un noyau '[LoG](#log)'. Par exemple, ici j'ai placé côte à côte les images de noyaux d'un noyau '[LoG](#log)' et d'un noyau '[DoG](#dog)' pour comparaison.

[IM Output] [IM Output]

Si vous consultez la page web Différence de gaussiennes, Wikipedia, vous verrez des graphes où l'on compare aussi le profil d'un '[LoG](#log)' (ou « chapeau mexicain ») avec un '[DoG](#dog)', montrant la très légère différence entre les courbes correspondantes. Des informations sont souhaitées sur la façon de faire correspondre un sigma d'un LoG pour générer un « DoG » quasi équivalent. Si vous le savez, écrivez-moi à l'adresse indiquée dans le pied de page. Les résultats appliqués sont eux aussi très similaires. |

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

[IM Output]
Notez que les deux valeurs 'sigma ' doivent être définies et qu'au moins une doit être non nulle. Une valeur nulle pour l'une ou l'autre des composantes sigma équivaudra à un noyau '[Unity](#unity)', c'est-à-dire qu'il laisse l'image inchangée. Si les deux valeurs sont nulles, les deux gaussiennes seraient des noyaux '[Unity](#unity)' qui, une fois soustraits, produiraient un résultat parfaitement nul ou noir (plus toute valeur de biais). Lorsque les arguments sont 'Dog:0,0,_non-zero_, le DoG devient un simple filtre passe-haut, défini comme le noyau « Unity » (produisant l'image d'origine) moins un noyau de filtre passe-bas (image floutée). Dans ce cas, sigma1=0 est simplement le noyau « Unity » et sigma2=non-zero est un noyau de filtre passe-bas (flou) gaussien. Ce qui suit produit donc une image filtrée passe-haut avec une valeur de filtre de sigma2=2 |

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

[IM Output]
Un filtre passe-haut de Photoshop avec une valeur de filtre de radius=2 produit le même résultat. Notez qu'utiliser 'DoG:0,2,0' renverra une image qui est essentiellement la version inversée (autour du biais de sortie) de l'image précédente. Cette technique peut aussi servir à générer un noyau « laplacien isotrope » 3x3, c'est-à-dire un noyau '[Laplacian](#laplacian)' qui produit des résultats égaux dans toutes les directions, plutôt que d'avoir un biais diagonal inégal. Par exemple, radius=1 (pour un noyau 3x3) et un sigma de 1 génèrent… | |

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

[IM Text]
| [IM Text]


L'autre intérêt de l'utilisation d'une « différence de gaussiennes » est que vous pouvez employer l'opérateur "[-blur](https://imagemagick.org/command-line-options/#blur)", bien plus rapide (qui utilise en interne les noyaux '[Blur](#blur)'), pour générer les mêmes résultats. Pour cela, vous devrez cependant générer séparément chacune des deux images « floutées », puis soustraire les résultats, avec l'ajout d'une mise à l'échelle et d'un biais appropriés. Par exemple… |

  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]
Ce qui précède utilise la méthode de composition Mathematics spéciale pour éviter les problèmes d'« écrêtage » lors de la soustraction des images dans une version non-HDRI d'IM. Pour plus de détails, voir Ajouter des dégradés biaisés. Le seul autre facteur est l'emploi d'un facteur d'échelle plus grand pendant la soustraction (les deux '4' dans l'argument de Mathematics Compose). Cela vient du fait que soustraire deux flous normalisés ne produit pas la même magnitude (accrue) de résultats que celle obtenue en normalisant ensemble les deux courbes gaussiennes soustraites dans un noyau '[DoG](#dog)'. Toutefois, hormis la magnitude, l'image de l'exemple ci-dessus est équivalente au résultat du premier noyau '[DoG](#dog)', simplement plus rapide à générer, en particulier pour de grandes valeurs de sigma. Et c'est là tout l'intérêt : même si cela demande plus de travail, cette méthode complexe est plus rapide que l'utilisation directe d'un noyau '[DoG](#dog)' ou '[LoG](#log)'.

Noyaux Laplacian discrets

   Laplacian:{_type_}

De nombreuses formes de petits « noyaux laplaciens » ont été publiées dans de nombreux articles de recherche scientifique. Je fournis ici des versions intégrées des plus courantes que j'ai pu trouver dans la littérature universitaire. Ces noyaux sont fondamentalement calculés à l'aide d'un noyau '[LoG](#log)', mais mis à l'échelle pour utiliser des valeurs entières discrètes dans un petit tableau de noyau. Cela permet d'utiliser des filtres d'image dédiés et rapides, générés pour ne recourir qu'à l'arithmétique entière pour traiter les données de l'image. ImageMagick est toutefois un processeur d'images plus généraliste et, à ce titre, ne fournit pas un tel filtre dédié ultra-rapide. Mais comme les gens aiment les utiliser parce qu'ils sont plus simples à comprendre, beaucoup ont été intégrés à IM. Aucun des noyaux fournis ici n'est pivotable, et la plupart sont « anisotropes », c'est-à-dire qu'ils ne sont pas parfaitement circulaires, en particulier dans les directions diagonales. Voir toutefois la section précédente (noyaux '[DoG](#dog)') pour un moyen de générer un véritable « noyau laplacien isotrope 3x3 ». Les deux premiers noyaux 'Laplacian:0' et 'Laplacian:1' sont la forme la plus courante de « noyau laplacien discret » en usage. Ils sont très petits, ce qui signifie qu'ils localiseront les contours très précisément, mais ils sont aussi enclins à renforcer le bruit de l'image. Notez que tous les numéros de 'type ' n'ont pas été définis, laissant des places pour définir d'autres noyaux discrets à l'avenir. Les numéros utilisés ont été choisis pour mieux correspondre au noyau défini par ce numéro.

Laplacian:0 (par défaut)

Le laplacien à 8 voisins. Probablement le noyau laplacien discret de détection de contours le plus courant. Ici j'utilise Show Kernel pour extraire le noyau « discret » et « non normalisé », avant de vous montrer le résultat du noyau normalisé avec un biais de sortie. | |

  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]


Parfois un laplacien, qu'il s'agisse d'un laplacien discret comme dans le dernier exemple, ou d'un '[LoG](#log)' ou '[DoG](#dog)' généré, produit un résultat plus complexe que souhaité. Dans ces cas, générer une image non biaisée (sans aucun biais de sortie) fonctionnera mieux. Reprenons donc ce qui précède sans biais, afin de ne conserver que les contours « positifs » plus lumineux. |

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

[IM Output]
Dans ce cas, nous avons des lignes sombres (noires) sur des couleurs plus claires (blanches). Cela pousse à son tour le filtre à « dédoubler » les contours, ce que l'on peut voir dans les résultats présentés. Pour cette image, l'emploi d'un facteur d'échelle négatif (pour conserver les contours négatifs plutôt que les contours positifs) a semblé mieux fonctionner sur notre image de test. |

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

[IM Output]
Comme vous pouvez le voir, pour cette image, l'emploi de la version négative produit des contours plus forts sans les effets de « dédoublement » qu'ont produits les résultats positifs. Cela vient de l'usage de lignes de bordure « noires » sur fond blanc dans l'image utilisée. À NOTER : la raison pour laquelle vous obtenez un contour bleu autour de l'étoile jaune est que la différence entre l'étoile « jaune » et le fond « blanc » est une soustraction de la couleur bleue. Si le fond était noir, vous obtiendriez une couleur de contour jaune.

Laplacian:1

Le laplacien à 4 voisins. Également très couramment utilisé. | |

  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]


Les résultats ne sont pas aussi forts, mais souvent plus nets que ceux du laplacien à 8 voisins.

Laplacian:2

Laplacien 3x3, avec centre:4 bord:1 coin:-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

Laplacien 3x3, avec centre:4 bord:-2 coin: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]


Ce noyau fait ressortir les contours diagonaux et tend à faire disparaître les contours verticaux et horizontaux. Vous devrez cependant peut-être mettre les résultats à l'échelle (comme je l'ai fait ci-dessus) pour rendre le moindre résultat visible.

Laplacian:5

Laplacien 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 règle générale avec les noyaux laplaciens est que plus ils sont grands, plus le résultat est net, en particulier lorsqu'il y a des erreurs. Vous obtenez cependant aussi moins de détail.

Laplacian:7

Laplacien 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 5x5 discret (sigma d'environ 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 9x9 discret (sigma d'environ 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]


Accentuation des images par détection de contours (renforcement des contours de l'image d'origine)

Les noyaux '[LoG](#log)' et '[DoG](#dog)' peuvent aussi servir à accentuer les images, par opposition à la désaccentuation des images à l'aide de flous. Il suffit essentiellement d'ajouter les résultats du noyau (y compris les résultats négatifs) à l'image d'origine. C'est facile à faire : ajoutez simplement un noyau '[Unity](#unity)' ou « identité » pondéré à 100 % aux facteurs d'échelle. C'est pour cela qu'il a été fourni. Par exemple… |

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

[IM Output]
Il s'agit d'une accentuation de l'image bien plus large et plus douce que celle produite par la technique du masque flou (résultat montré à droite). C'est parce qu'il s'agit d'une véritable accentuation de l'image, et non d'une accentuation simulée par la soustraction d'un flou. | [IM Output]
---|---
Comme précédemment, lorsqu'une seule passe de convolution est effectuée, vous pouvez recourir directement à un noyau mélangé. Par exemple, moins accentué… |

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

[IM Output]
Ou plus accentué… |

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

[IM Output]
Vous pouvez utiliser les méthodes à 2 passes de la différence de gaussiennes pour produire une opération d'accentuation en plusieurs étapes plus rapide, mais comme cela a été montré ci-dessus, un tel schéma requiert 4 convolutions et une opération de mélange distincte pour obtenir le même résultat. À VENIR : ajouter un exemple de ceci C'est cette complexité qui explique que l'emploi du masque flou soit le plus souvent la méthode privilégiée pour accentuer les images. Mais comme vous pouvez le voir, pour un processus d'accentuation intense, l'emploi d'un véritable noyau d'accentuation est préférable à une accentuation par masque flou. Pour une accentuation mineure, en revanche, comme l'accentuation des images redimensionnées, il n'y a aucun problème à utiliser le masque flou.


Convolutions directionnelles (pentes et boussole)

Comme les précédents, ces noyaux recherchent des pentes dans l'intensité de couleur de l'image, mais plutôt que n'importe quelle pente, ils recherchent des pentes dans une direction précise. Mathématiquement, on parle de « dérivée », ce qui n'est en réalité qu'une manière savante de dire « pente ». Mais connaître l'information de pente pour différentes directions peut aussi être utile comme moyen de déterminer l'angle ou la direction « de boussole » d'une pente ou d'un contour d'image. Autrement dit, la direction à deux dimensions de la pente en un point donné d'une image. Les pentes servent aussi dans les techniques de traitement d'images dites de « gaufrage » et d'« ombrage » des images. Pour l'instant, aucun noyau « généré » n'est disponible, seulement des noyaux « nommés » prédéfinis, tels que Sobel et Roberts. Je suis toutefois certain que les fonctions de génération de noyaux de gaufrage et d'ombrage seront intégrées à l'ensemble des noyaux de morphologie/convolution, à un moment donné dans le futur. Examinons donc quelques-uns des noyaux directionnels « nommés ».

Noyaux directionnels

Sobel

   Sobel:{_angle_}

[IM Text]

Nous avons déjà vu le noyau 'Sobel ' plus haut, lors de la discussion sur les noyaux à somme nulle. Ce noyau est un noyau directionnel brut (dérivée première) conçu pour renvoyer la pente d'un contour dans une direction orthogonale précise. Par défaut, il est conçu pour la détection de pente de gauche à droite, à l'aide d'une opération 'convolve'. Le résultat est essentiellement une dérivée en X (pente) de l'image.

  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 vous regardez le noyau, vous pourriez penser qu'il est déclaré à l'envers. En un sens, vous avez raison. Cela tient toutefois à la façon dont 'Convolve' fonctionne réellement.

Vous pouvez en apprendre davantage sur cette « inversion » plus en détail dans Convolve vs Correlate ci-dessous.

_
---|---
Notez que ce noyau peut aussi produire une indication de « pente négative », mais cela ne peut se voir que si un biais de '50%' est également utilisé avec cette opération de convolution. Bien qu'il n'y ait pas de pente négative dans l'exemple précédent, l'exemple suivant en comporte une ; j'ai donc aussi ajouté un réglage de biais pour que vous puissiez la voir.

  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 vous utilisez ce noyau avec 'Correlate', vous trouverez les pentes qui « correspondent » à la façon dont le noyau est défini. Dans ce cas, vous obtiendriez un résultat positif pour une pente allant d'une valeur haute (blanche) à gauche à une valeur basse (noire) à droite. Dans l'exemple ci-dessus, les deux lignes seraient alors permutées.

Mais ce qui précède est une 'convolution', et non une 'corrélation' (c'est-à-dire une correspondance avec le noyau). Là encore, voir Convolve vs Correlate pour plus de détails sur la différence._
---|---
Comme vous pouvez le voir, nous obtenons maintenant une ligne blanche (pente positive) en montant la pente du noir vers le blanc, et une ligne noire (pente négative) en redescendant du blanc vers le noir. Voici le résultat de l'emploi du noyau 'Sobel' par défaut sur l'image du visage.

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

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

Notez que Sobel, comme la plupart des autres noyaux de détection de contours, tend à produire une réponse épaisse de 2 pixels le long d'un contour très marqué, et une réponse de 3 pixels sur une ligne large d'un seul pixel. C'est bien plus fort qu'un détecteur de contours laplacien. Vous pouvez pivoter ce noyau à l'aide de l'argument 'angle ', généralement par multiples de 90 degrés. Vous pouvez toutefois aussi le pivoter par multiples de 45 degrés, même s'il n'a pas été conçu pour cela. C'est utile pour obtenir des dérivées directionnelles quantifiées à 45 degrés, ou la magnitude du gradient à partir du maximum de tous les résultats de dérivées pivotées de 45 degrés. Le revoici, mais pivoté de 90 degrés (de haut en bas). |

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

[IM Output]

Une façon de collecter tous les contours d'une image à l'aide d'un noyau '[Sobel](#sobel)' est d'appliquer le noyau 4 fois dans toutes les directions et de collecter la valeur maximale observée (à l'aide d'une composition mathématique Lighten). C'est une approximation de la magnitude du gradient. |

   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]
Vous pouvez simplifier ce qui précède en tirant parti des fonctionnalités de gestion de plusieurs noyaux de la morphologie IM. Autrement dit, vous pouvez créer une liste pivotée de toutes les rotations à 90 degrés du noyau '[Sobel](#sobel)'. |

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

[IM Output]
Si vous voulez voir exactement ce que fait ce qui précède, ajoutez le réglage Show Kernel et le réglage Verbose. Une technique plus efficace pour générer une magnitude de gradient consisterait à exploiter le fait qu'une rotation de 180 degrés produit simplement le même résultat que la négation du noyau, et donc la négation des résultats. Ainsi, les dérivées en X et en Y (convolutions pivotées de 90 degrés), avec une petite astuce pour obtenir les valeurs absolues de la convolution, permettent d'obtenir un tel résultat avec moins de traitement. |

   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]
C'est en général suffisant pour la plupart des usages. Une magnitude plus exacte de toutes les pentes peut être extraite en effectuant une addition vectorielle des deux dérivées en X et en Y (conformément au théorème de Pythagore). |

   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 fonction "[-gamma](https://imagemagick.org/command-line-options/#gamma)" est utilisée ci-dessus pour effectuer un « carré » et une « racine carrée » mathématiques des valeurs renvoyées par les résultats '[Sobel](#sobel)'. Pour plus de détails, voir Fonction puissance en mathématiques.

Le "[+level](https://imagemagick.org/command-line-options/#level)" supplémentaire garantit que la composition Plus ne dépasse pas la plage de quantum de l'image. Voir Effets de quantum, non-HDRI vs HDRI pour les détails._
---|---
Au lieu de la magnitude, vous pouvez extraire la direction de la pente à partir des deux résultats de détection de contours.

  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 première expression "[-fx](https://imagemagick.org/command-line-options/#fx)" est celle qui utilise une fonction 'atan()' pour transformer un vecteur X,Y en angle. Le résultat est ensuite coloré à l'aide d'une image de dégradé arc-en-ciel externe, servant de table de correspondance de couleurs. La seconde expression "[-fx](https://imagemagick.org/command-line-options/#fx)" crée un masque de transparence à seuil pour rendre transparentes toutes les zones dépourvues de pente. La technique ci-dessus tend cependant à produire un énorme fouillis d'informations pour des images réelles, car elle ne tient pas compte de la magnitude de la pente. Voici une autre version, plus complexe. Elle effectue presque tous les calculs dans le canal vert « G », afin de réduire d'un facteur trois la quantité de traitement d'image nécessaire. Elle utilise ensuite l'espace colorimétrique HSB pour créer la direction (teinte) et la magnitude (luminosité). |

  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]

Le noyau 'Roberts' est bien plus simple que le noyau '[Sobel](#sobel)' précédent, et produira une localisation de contour encore plus resserrée (jusqu'à 2 pixels). Cela le rend bien sûr aussi plus sensible aux effets du bruit. Normalement, ce noyau est représenté par un noyau bien plus petit, 2x1 voire 2x2 ; cependant, en l'implémentant comme un noyau 3x3, je peux le pivoter « cycliquement » par incréments de 45 degrés. Par exemple, voici un résultat à 45 degrés, plus communément appelé noyau « Roberts-Cross ». |

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

[IM Output]
Comme avec '[Sobel](#sobel)', vous pouvez aussi utiliser la gestion de plusieurs noyaux pour générer une pente maximale à partir de toutes les directions. Mais cette fois, nous obtiendrons 8 directions à 45 degrés, plutôt que seulement 4. |

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

[IM Output]
Notez que pivoter ce noyau de 180 degrés ne génère pas un résultat inversé (à cause d'un décalage). Vous ne pouvez donc pas simplement fusionner la moitié des convolutions, comme vous pouvez le faire avec '[Sobel](#sobel)'. Fondamentalement, la pente générée par une seule convolution '[Roberts](#roberts)' est décalée d'un demi-pixel par rapport à l'alignement avec l'image réelle. Autrement dit, la pente calculée est localisée pour un point situé entre les valeurs '+1' et '-1', entre les pixels, mais stockée dans le pixel central '-1'. Cela signifie toutefois aussi qu'en sauvegardant toutes les pentes autour d'un pixel et en les additionnant, vous obtenez une détection de contours bien plus petite et nette, avec seulement 2 pixels (plutôt que 4) faisant ressortir les frontières de contours nettes.

Prewitt

   Prewitt:{_angle_}

[IM Text]

Le noyau 'Prewitt' ressemble beaucoup à un '[Sobel](#sobel)', quoique bien moins précis sur la direction exacte de la détection de contours. Le résultat est donc un peu plus flou. |

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

[IM Output]

Compass

   Compass:{_angle_}

[IM Text]

C'est le noyau « Prewitt Compass », censé avoir un sens directionnel plus marqué 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]

C'est un autre détecteur de contours à forte détection de direction. |

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

[IM Output]

Frei-Chen

Trois jeux de noyaux sont fournis par cette fonction intégrée. Le premier est une variante « isotrope » (direction uniforme) de '[Sobel](#sobel)', où les valeurs '2' ont été remplacées par une racine carrée de 2.

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

[IM Text]

Le noyau ci-dessus est le noyau non pondéré par défaut qui est au cœur du noyau 'Frei-Chen'. |

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

[IM Output]
Comme '[Sobel](#sobel)', ce noyau doit être appliqué avec un angle en multiples de 90 degrés. Pour faciliter les choses, deux noyaux (avec la même pondération) ont été fournis : l'un comme ci-dessus pour un usage orthogonal, l'autre pour un usage diagonal.

Frei-Chen:1

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

Le troisième jeu de types consiste en 9 noyaux spécialement conçus et pondérés, utilisés non seulement pour la détection de contours dans une direction précise, mais aussi pour déterminer l'angle réel d'un contour net. Le 'type ' est ici un nombre de '11' à '19', vous permettant d'extraire n'importe lequel des 9 noyaux du jeu. Si toutefois vous donnez une valeur de 'type ' de '10', vous obtiendrez une liste multi-noyaux des 9 noyaux pré-pondérés.

Chaque noyau est appliqué à l'image d'origine, puis les résultats sont
additionnés pour générer le résultat de détection de contours.

Cela se fait au mieux à l'aide d'une version [HDRI](basics.html#hdri)
d'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 un type de 10 est donné, une liste multi-noyaux des 9 noyaux pondérés
présentés ci-dessus est générée. Cela vous permet d'utiliser la composition
multi-noyaux pour faire ce qui précède, bien plus simplement…




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




Je n'ai toutefois pas découvert ce que les résultats sont censés signifier. Si
quelqu'un a une expérience ou des connaissances sur la façon dont cela s'utilise
réellement, merci de me le faire savoir, afin que je puisse l'inclure ici pour les autres.

Correlate ( )

Là où la méthode '[Convolve](#convolve)' sert essentiellement au traitement d'images, la méthode 'Correlate' est davantage conçue pour la mise en correspondance de motifs. Autrement dit, elle effectue une « corrélation croisée » d'une image avec son noyau, à la recherche d'une correspondance de la forme donnée au sein de l'image. En réalité, '[Convolve](#convolve)' et 'Correlate' sont la même opération. La seule différence entre elles est en fait très mineure, à savoir une réflexion en x et en y (équivalente à une rotation de 180 degrés) du noyau. Le meilleur guide que j'aie trouvé sur le fonctionnement de la corrélation et de la convolution et sur leur différence est Class Notes for CMSC 426, Fall 2005, by David Jacobs.

Convolution vs corrélation (effets des noyaux asymétriques)

Comme je l'ai mentionné plus haut, les deux opérateurs '[Convolve](#convolve)' et '[Correlate](#correlate)' sont essentiellement les mêmes. De fait, les utilisateurs disent souvent convolution alors qu'ils veulent en réalité parler de corrélation. La corrélation est d'ailleurs la méthode la plus simple à comprendre. Pour les noyaux symétriques autour d'une « origine » centrale, ce qui est très souvent le cas, les deux méthodes sont en réalité identiques. La différence n'apparaît que lorsque vous utilisez un noyau asymétrique ou irrégulier. Par exemple, ici j'utilise un noyau « plat » en forme de « L » sur notre image à « pixel unique ».

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

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

Comme vous pouvez le voir, un '[Convolve](#convolve)' a étendu le pixel unique au centre pour former la forme en « L » autour de lui. Même lorsque l'origine elle-même ne faisait pas partie du « voisinage ». Reprenons maintenant cet exemple, mais en utilisant '[Correlate](#correlate)' à la place.

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

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

Comme vous pouvez le voir, '[Correlate](#correlate)' a lui aussi étendu le pixel unique pour former une forme en « L », mais il s'agissait d'une forme en « L » « pivotée ». C'est essentiellement la seule différence entre ces deux méthodes. La méthode '[Correlate](#correlate)' applique le noyau « TEL QUEL », ce qui fait que le pixel unique s'étend en une forme « pivotée ». '[Convolve](#convolve)', en revanche, utilise en réalité une forme « pivotée » de 180 degrés du noyau, de sorte que chaque pixel s'étende en la même forme non pivotée. Si vous souhaitez voir d'excellents exemples du fonctionnement réel de '[Convolve](#convolve)', je vous recommande aussi de consulter EECE \ CS 253 Image Processing, Lecture 7, Spatial Convolution. Le schéma de la page 22, où l'on applique effectivement le noyau « réfléchi » à un pixel unique, exactement comme je l'ai fait ci-dessus.
Cette différence de rotation peut sembler négligeable, mais elle implique que, du point de vue mathématique, une opération de convolution (représentée par le symbole astérisque ('*')) est commutative, en ce sens que si le noyau et l'image étaient traités comme de simples tableaux de valeurs (ou deux images), alors F * G == G * F. Cela signifie aussi que la convolution est associative, en ce sens que ( F * G ) * H == F * ( G * H ). Voir Propriétés de la convolution, Wikipedia pour plus d'informations. L'opération '[Correlate](#correlate)' n'est ni commutative ni associative. Bien qu'elle lui soit étroitement liée (par rotation du noyau). Fondamentalement, '[Convolve](#convolve)' agit davantage comme une « multiplication » mathématique, contrairement à '[Correlate](#correlate)'. L'exception à toute cette affaire est le cas où le noyau utilisé est identique une fois pivoté de 180 degrés. Autrement dit, le noyau est symétrique par rapport à l'« origine ». Dans ce cas particulier, les deux opérations génèrent des résultats équivalents. Ce qui trouble les gens, c'est que la plupart des noyaux utilisés pour la convolution, comme les flous gaussiens, le laplacien, etc., sont symétriques, auquel cas peu importe en réalité que vous fassiez une convolution ou une corrélation. Les gens deviennent donc laxistes et flous sur les significations. Ce n'est que lorsqu'ils ne sont pas symétriques, comme dans le cas de la recherche de formes (voir plus loin), ou avec des noyaux directionnels tels que Sobel, que la différence devient réellement importante.

Corrélation et recherche de formes

Le véritable usage de la méthode 'Correlate' (appliquer le voisinage du noyau « tel quel », sans rotation) est une méthode ancienne mais simple pour localiser des objets dont la forme correspond approximativement à celle du noyau fourni. Par exemple, si nous devions utiliser 'Correlate' avec un noyau en forme de « L » et tenter de rechercher dans l'image que nous avons créée avec l'exemple de méthode de convolution ci-dessus, nous obtenons…

  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] _À NOTER : remarquez que les zones « noires » de l'image de noyau ci-dessus représentent une valeur de zéro. Il n'y a aucune valeur négative dans ce noyau, seulement des valeurs positives pour la forme recherchée.

_

Notez que j'ai utilisé la normalisation du noyau d'IM pour empêcher les résultats finaux de devenir trop lumineux et de noyer le « pic » dans une mer de points blancs. Comme vous pouvez le voir, la méthode '[Correlate](#correlate)' a produit une luminosité maximale au point où l'« origine » du noyau correspond exactement à la même forme dans l'image. Mais elle produit aussi des résultats moins lumineux là où la forme n'est que partiellement retrouvée. Plus la forme correspond, plus le pixel devient lumineux. Je vous préviens toutefois que, même si '[Correlate](#correlate)' a réussi dans ce cas, ce n'est pas vraiment une excellente façon de procéder. Par exemple, elle peut générer un très grand nombre de fausses correspondances dans les zones de très forte luminosité. Ce problème peut être atténué en utilisant plutôt des valeurs négatives pour les zones censées correspondre au fond sombre de l'image. Autrement dit, les zones qui ne correspondent pas au fond doivent rendre le pixel résultant moins lumineux.

  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] _À NOTER : pour rendre l'image de noyau plus claire, je l'ai générée de sorte que les valeurs positives (premier plan) soient blanches, les valeurs négatives (arrière-plan) noires et les valeurs nulles (indifférentes) transparentes. Le noyau réellement utilisé est cependant entièrement défini, en termes de nombres, et son « voisinage » est un rectangle plein.

_

Comme vous pouvez le voir, le pic de correspondance est bien plus prononcé, car vous ne faites plus seulement correspondre les pixels de premier plan, mais aussi ceux d'arrière-plan. Remarquez l'emploi de l'indicateur de normalisation spécial '^' ci-dessus. C'est important, car il normalise séparément les valeurs positives et négatives du noyau. Autrement dit, vous voulez rechercher les pixels de premier plan à parts égales avec les pixels d'arrière-plan. Cela signifie que vous pouvez rechercher à la fois les correspondances positives et négatives de la forme donnée en utilisant une version HDRI d'IM ou avec un usage approprié du biais de sortie (voir ci-dessus). Par exemple, ici j'applique la recherche de forme en « L » à une image de test contenant à la fois des formes en « L » positives et négatives. (les images présentées ont été agrandies)

  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]

Le biais de sortie a rendu la sortie normale de la recherche d'un gris de ton moyen, tandis que les formes correspondantes se voient attribuer des couleurs plus claires ou plus sombres, selon le nombre de pixels qui correspondent réellement au « noyau de forme ». Si vous examinez uniquement les valeurs réelles de l'image de sortie, un pixel blanc pur et un pixel noir pur sont produits, indiquant des correspondances parfaites. Il existe cependant aussi un bon nombre de correspondances approchées. Si les correspondances négatives ou « noires » ne m'intéressaient pas, je pourrais supprimer le biais de sortie et le facteur d'échelle '50%', de sorte que les pixels sans correspondance soient noirs et les correspondances parfaites blanches. Une fois que vous disposez d'une image de correspondance '[Correlate](#correlate)', vous devez essayer de trouver les « pics » de correspondance. Cela peut se faire à l'aide d'une autre corrélation, mais ne fonctionne pas toujours très bien. La meilleure méthode est d'utiliser la méthode de mise en correspondance de motifs plus exacte, la morphologie '[HitAndMiss](morphology.html#hitmiss)', avec le '[Peaks](morphology.html#peaks)' spécial créé à cet effet. Celui-ci trouve tout pixel isolé entouré uniquement de pixels de couleur plus sombre. D'autres noyaux '[Peaks](morphology.html#peaks)' peuvent servir à trouver des correspondances « plus lâches ».

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

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

Et ici, vous pouvez facilement trouver l'emplacement où la meilleure correspondance de la forme a été trouvée, bien que le degré de correspondance ait été perdu. Vous pourriez consulter la section « recherche de pics » de Compare et recherche de sous-image. Mais regardez aussi le script "[maxima](http://www.fmwconcepts.com/imagemagick/maxima/)" de Fred Weinhaus. À VENIR : corrélation croisée normalisée avec la transformée de Fourier rapide, pour générer des corrélations d'images très rapides avec de très grandes images (image source comme sous-image).

Corrélation vs morphologie HitAndMiss

Si vous comparez l'image de noyau telle que je l'ai représentée aux noyaux utilisés par la méthode de morphologie Hit-And-Miss, vous constaterez qu'ils représentent en réalité la même chose. '[HitAndMiss](morphology.html#hitmiss)' '[Correlate](#correlate)'
Premier plan Une valeur de '1.0' Une valeur de '1.0' (avant normalisation)
Indifférent Une valeur de 'Nan' ou '0.5' Une valeur de 'Nan' ou '0.0'
Arrière-plan Une valeur de '0.0' Une valeur de '-1.0' (avant normalisation)
Résultats Soustrait le minimum du premier plan au maximum de l'arrière-plan. Seules les correspondances exactes produiront donc des résultats positifs, et un seuillage produira une image de correspondance binaire. Génère une échelle indiquant à quel point l'image correspond à une forme. Il est possible que certains pixels d'arrière-plan aient une valeur supérieure aux pixels de premier plan, tant que le motif d'ensemble est présent. Il peut être difficile de localiser des pics de « correspondance » précis. Vous pouvez aussi trouver des correspondances négatives.
Comme vous pouvez le voir, elles se correspondent. Ainsi, un noyau pour l'une pourrait être transformé en un noyau pour l'autre. Cependant, '[Hit-And-Miss](morphology.html#hitmiss)' ne trouvera que des correspondances parfaitement exactes, avec une différence nette entre premier plan et arrière-plan. Il est donc bien moins tolérant au bruit et aux quasi-manqués que '[Correlate](#correlate)'. '[Correlate](#correlate)', en revanche, peut s'effectuer par traitement d'image linéaire et plus précisément à l'aide d'une transformée de Fourier rapide. Cela peut rendre la mise en correspondance de motifs bien plus rapide avec de grands motifs et noyaux, en particulier lorsque plusieurs motifs sont en jeu, en vous économisant le coût de transformation des images et des motifs dans le domaine fréquentiel. Elle fonctionne aussi avec des images réelles, quoiqu'un certain prétraitement et l'usage de HDRI puissent aussi être nécessaires. Le choix vous revient vraiment, selon les résultats recherchés : uniquement des correspondances parfaites, ou des correspondances approchées avec beaucoup plus d'erreurs, et le recours possible à un algorithme plus rapide. Notez que, pour trouver des correspondances exactes de petites images couleur au sein d'images plus grandes, la fonction de localisation de sous-image du programme "magick compare" offrira une bien meilleure méthode que les méthodes '[Hit-And-Miss](morphology.html#hmt)' ou '[Correlate](#correlate)'. C'est parce qu'elle utilise un « moindre carré des différences de vecteurs de couleur » pour effectuer la correspondance de sous-image, ce qui peut produire une meilleure métrique pour les résultats de correspondance. Elle est cependant tout aussi lente, en particulier pour de grandes images.

Comptage des voisins

L'une des utilisations les plus inhabituelles de la convolution est connue sous le nom de comptage des voisins. Autrement dit, déterminer combien de pixels existent dans une zone particulière entourant chaque point pixel d'une image.

Compter les voisins

Fondamentalement, à l'aide d'un noyau de convolution très simple, vous pouvez créer une image qui contient un décompte du nombre de voisins entourant un point particulier dans une image binaire. En convoluant avec un noyau Ring de taille '1.5', vous obtenez un décompte des voisins. Voici un décompte des voisins de chaque pixel dans une petite zone, avec l'agrandissement des pixels individuels avant et après (généré à l'aide du script Enlarge Image)…

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

[IM Output] [IM Output]

Comme vous pouvez le voir, le niveau de gris de tous les pixels indique combien de voisins ils ont, y compris d'éventuels voisins Virtual Pixel le long des bords. Si vous voulez inclure le pixel courant dans le décompte, vous pouvez plutôt utiliser un noyau Square. Avec des conversions appropriées (y compris des ajustements de niveaux) et en utilisant le format de fichier PbmPlus, vous pouvez transformer les niveaux de gris ci-dessus en nombres réels, si c'est ce que vous voulez.

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

[IM Text]

Si vous voulez exclure les pixels situés à l'intérieur de la forme elle-même, vous pouvez utiliser un noyau avec un fort pixel central négatif, puis borner tout résultat négatif (si vous utilisez une version HDRI d'IM). Une méthode simple pour générer justement un tel noyau de 1 positifs entourant un grand centre négatif consiste à mettre à l'échelle négativement un noyau laplacien discret standard.

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

[IM Output] [IM Output]

Nous aurions bien sûr pu aussi utiliser l'image d'origine comme masque pour supprimer les pixels sans intérêt.

Le Jeu de la vie

En 1970, un mathématicien britannique, John Horton Conway, publia dans Scientific American une simulation particulière qui devint très populaire. Elle est aujourd'hui connue sous le nom de Jeu de la vie de Conway. Elle reposait sur une grille de points où chaque point était soit « vivant », soit « mort ». Les « cellules » classées comme « vivantes » ou « mortes » à la « génération » suivante dépendaient alors d'un ensemble de règles très simples, fondées uniquement sur le nombre de cellules voisines vivantes autour d'elles.

  • Le voisinage est constitué des 8 pixels entourant chaque « cellule ».
  • Une cellule « vivante » continue de vivre si elle a 2 ou 3 voisins.
  • Une cellule « morte » devient « vivante » (naît) si elle a exactement 3 voisins.
  • Sinon, la cellule devient ou reste « morte ».

Les résultats de ces règles sur des motifs binaires furent remarquables : on obtient des amas de « cellules » qui semblent s'étendre, se rétracter, osciller, voire se déplacer lentement à travers la grille. Cela devint un point majeur de recherche théorique, pour voir si l'on pouvait même générer une réplication de type « ADN » de plus grands « motifs de vie ». À NOTER : il semble que ce fût possible, mais si fragile que cela en était impraticable, ce qui rend la vie ADN actuelle d'autant plus remarquable. Cela suscita aussi un vif intérêt pour l'étude et l'implémentation d'autres formes d'automate cellulaire, comme méthode de génération et d'étude de grands effets à l'aide de règles très très simples à de très petites échelles. Un peu comme ce qui se passe en chimie aux niveaux atomique et moléculaire, mais avec une plus grande complexité. Implémentons donc le « Jeu de la vie » à l'aide d'ImageMagick. D'abord, pour simplifier, nous rendrons les cellules « vivantes » blanches et les cellules « mortes » noires. Ainsi, nous ne comptons que les pixels « blancs » entourant chaque cellule, dans un voisinage de 8 pixels. Nous aurions cependant aussi pu l'implémenter en inversant le noir et le blanc, mais il serait plus difficile de suivre comment cela se fait. Les règles dépendent toutefois fortement du fait que la cellule centrale soit vivante ou morte. Nous devons donc séparer les décomptes de voisinage d'une cellule « morte » de ceux d'une cellule « vivante ». Cela peut se faire simplement en donnant à la cellule centrale une valeur plus grande que la somme de tous ses voisins. Une valeur de « 10 » convient bien pour cela. C'est un joli nombre rond, supérieur au décompte maximal de voisinage, qui est de 8. Cela rend le noyau de convolution du « Jeu de la vie » équivalent à…

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

Le résultat sera un décompte des 8 voisins autour de chaque pixel (qui est « blanc »), plus une valeur de 10 si le pixel central est « vivant » ou « blanc ». Ainsi, la valeur de ce noyau ira de '0' à '8' pour les pixels morts, ou de '10' à '18' pour les pixels vivants. Si nous mettons ce noyau à l'échelle d'une valeur de 20 (en fait une mise à l'échelle de '0.05' pour générer un dégradé, voir ci-dessous), vous générerez une image comportant 21 niveaux de gris possibles. Autrement dit, vous obtiendrez un « noir » pour le niveau de gris '0' et une valeur blanche pour le niveau de gris '21', même si le noyau ne peut pas réellement générer une telle valeur. Nous pouvons maintenant encoder les règles du 'Jeu de la vie ' dans une image de table de correspondance de couleurs, afin de transformer le « niveau de gris » de décompte des voisins obtenu, généré par le noyau ci-dessus, en le résultat « vie et mort » approprié selon les « règles de la vie ».

  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]

L'image est très petite, j'ai donc utilisé un script Enlarge Image pour générer une version plus grande à afficher ci-dessus, avec chaque pixel clairement séparé. En gros, les 10 premiers pixels indiquent quoi faire pour une « cellule morte », les 10 pixels suivants quoi faire pour une « cellule vivante ». Le premier pixel blanc à gauche (décompte de voisins = 3 autour d'une cellule morte) est une « naissance », tandis que les deux pixels blancs à droite (décomptes de voisins 2 et 3 à côté d'une cellule vivante) permettent à une « cellule vivante » existante de continuer à vivre. Tout autre résultat laisse le résultat en noir (mort). La table de correspondance de couleurs fait 21 pixels de long parce que je vais diviser par un facteur d'échelle de 20, ce qui signifie que nous pourrions générer une valeur dans la plage de 0 à 20, soit 21 niveaux de gris distincts. Nous pourrions en fait utiliser une valeur autre que 10 pour le centre (état précédent des cellules) et 20 pour la mise à l'échelle, mais ces valeurs sont des nombres faciles à manipuler. En résumé, nous divisons le noyau de convolution par 20 et utilisons une CLUT de 21 pixels de long (avec interpolation entière) pour faire correspondre les résultats de convolution (niveaux de gris) à la bonne valeur de couleur de sortie. À NOTER : cette CLUT de « règles de la vie » peut être vue comme une table de règles générale d'automate cellulaire. Le motif de voisinage utilisé pour le comptage des voisins fait aussi partie de l'automate cellulaire. Cette technique est également décrite dans Cellular Automata Rules Lexicon, dans la section Rules Tables, comme moyen de définir des formes générales « sans limite » des automates cellulaires qu'il répertorie. En gros, presque n'importe quel automate peut être défini à l'aide d'une telle combinaison voisinage/table, bien que la plupart soient définis sous des formes plus simplifiées. Appliquons donc ceci à une image contenant un motif de « vie », à plusieurs reprises, pour voir comment le motif évolue d'une génération à la suivante, et pour vérifier qu'il fonctionne comme prévu.

  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]

Rappelez-vous que les images ci-dessus ont été agrandies ; pour voir l'image « minuscule » d'origine générée, cliquez sur l'image agrandie. Comme vous pouvez le voir, les motifs du « Jeu de la vie » se comportent comme ils le devraient (si vous connaissez les motifs). Le « clignotant » dans le coin supérieur gauche bascule d'avant en arrière, tandis que le « planeur » en bas s'est déplacé d'un pas diagonal vers lui, au cours des 4 « générations » sur lesquelles nous avons itéré les règles de la vie. [IM Output] Et voici un exemple plus grand, connu sous le nom de canon à planeurs de Gosper, où je génère une animation de 60 images à partir d'un motif de vie particulier. La taille réelle de l'image utilisée est montrée à droite, mais je mets l'animation obtenue à l'échelle pour un meilleur visionnage.

  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]

Notez que si le planeur « explose » sur le bord inférieur, c'est à cause de la gestion 'Virtual Pixel' par défaut qu'utilise la convolution, et de la perte de l'information de vie lorsqu'elle dépasse les limites de l'image. D'autres images de motifs de vie se trouvent dans le catalogue de motifs de vie, mais vous devrez recolorer (inverser) les images pour les utiliser dans le processeur de vie ci-dessus. Je laisse en exercice à quiconque le soin de mettre ce qui précède dans un script capable de générer une séquence de vie pour une image d'entrée particulière.
Ce n'est là qu'un exemple de toute la gamme d''automates cellulaires ' qu'IM pourrait traiter. Il existe bien sûr de nombreux programmes dédiés bien plus rapides pour le « Jeu de la vie » et les « automates cellulaires », qui font en général exactement la même chose, mais je voulais montrer qu'IM est suffisamment souple pour le faire aussi. Comme les résultats sont de simples images binaires, vous pouvez aussi utiliser les méthodes de morphologie d'IM, telles que la recherche de motifs Hit and Miss ou la corrélation croisée, pour rechercher des motifs de vie particuliers, ce qui rend l'usage d'IM pour la recherche sur la vie plus pratique, bien que lent.