Exemples ImageMagick -- Effets de mappage d'image
- Préface et index des exemples ImageMagick
- Introduction au mappage d'image
- Déformer des images par mappage d'image
- Cartes de recherche à distorsion absolue
- Cartes de distorsion absolue
- Composition à distorsion absolue
- La carte de distorsion neutre revisitée
- Problèmes des cartes de distorsion
- Définir les pixels indéfinis à l'aide d'un masque
- Image de distorsion unifiée
- Carte de distorsion en sablier
- Carte de distorsion sphérique
- Carte de distorsion en arc de cercle
- Opérateur de composition Displace
- Exemples de déplacement simples
- Tracé de graphe par déplacement
- Déplacement de zone
- Reflets sur une eau ondulée
- Cartes de déplacement bidimensionnelles
- Déplacement cylindrique
- Flou à rapport d'aspect variable
- Flou à angle variable
Déformer ou modifier une image à l'aide d'une image « de mappage » secondaire qui contrôle le traitement. Qu'il s'agisse de remplacer des couleurs, de flouter l'image de façon variable, ou de déformer des images en spécifiant les coordonnées source de manière absolue ou relative.
Introduction
Comme vous l'avez vu dans les sections précédentes sur la Composition, le Gauchissement simple et la Distorsion, vous pouvez modifier les images de bien des manières. Toutefois, elles se limitent toutes aux méthodes spécifiques intégrées à ImageMagick. Vous pouvez même « fabriquer votre propre » distorsion d'image à l'aide de l'Opérateur DIY 'FX', ou modifier directement les valeurs d'une image avec des opérateurs comme Evaluate ou Function, voire les divers opérateurs Level. Cependant, les distorsions demandent beaucoup de calculs (et de temps) pour accomplir leur tâche, et si vous prévoyez d'appliquer le même traitement à plusieurs images, laisser IM répéter tous ces calculs peut représenter une réelle perte de temps. L'autre aspect est qu'il est très difficile de limiter les effets de la distorsion de façon libre. Vous ne pouvez pas simplement éditer ou modifier la distorsion que vous voulez appliquer. Vous n'avez qu'un contrôle limité. Le mappage d'image est différent. Vous utilisez une image « de mappage » supplémentaire pour contrôler quelles parties d'une image doivent être modifiées, dans quelle mesure et de quelle manière. Il n'est pas nécessaire de modifier l'image entière, ni de la modifier d'une façon prédéfinie ou préprogrammée. Vous pouvez créer une « carte » capable de modifier une image de N'IMPORTE QUELLE manière possible, sans limitation. Vous pouvez aussi éditer ou modifier davantage le mappage, pour ajuster ou limiter son effet, le rendre plus complexe en fusionnant différentes cartes, ou simplement adoucir ou flouter l'effet. Et enfin, vous pouvez enregistrer le mappage afin de le réutiliser plus tard. C'est l'image « carte » qui contrôle les résultats. Comme la modification est pilotée par la « carte », ImageMagick n'a généralement que très peu de calculs à effectuer, si bien que le « mappage d'image » est en général très rapide. Il est aussi reproductible, car vous pouvez appliquer la même carte très complexe à un nombre quelconque d'images pour obtenir exactement la même modification. Autrement dit, vous pouvez l'appliquer très rapidement à tout un répertoire d'images. En substance, ce que fait le mappage d'image, c'est déplacer les mathématiques lentes et complexes d'un effet particulier, d'une image spécifique vers une image « carte » plus générale. Une fois cette « carte » générée, elle peut ensuite être appliquée très rapidement à un grand nombre d'images réelles.
Que sont les cartes d'image
Les images de mappage sont essentiellement des « tables de recherche » ou LUT qui définissent la manière dont un effet particulier doit être appliqué à une image, pixel par pixel. Autrement dit, le fait qu'un effet soit appliqué et dans quelle mesure est entièrement contrôlé par la carte d'image. Fondamentalement, une image est un tableau de valeurs, et ce que ces valeurs signifient dépend du traitement de mappage appliqué. Elles peuvent indiquer...
- une valeur de remplacement directe (recherche de couleur),
- de quelle image une couleur doit provenir (masquage d'image),
- dans quelle mesure un pixel doit être éclairci ou assombri (mise en évidence),
- la spécification d'une coordonnée source (distorsion),
- ou un emplacement relatif à la position actuelle (déplacement).
- dans quelle mesure flouter les pixels à cet emplacement
Nous avons déjà vu beaucoup d'entre elles dans la Composition d'image, et en un sens le mappage d'image n'est qu'une autre façon de fusionner plusieurs images. En fait, beaucoup de techniques de mappage d'image sont simplement implémentées sous forme de méthodes de composition spécialisées ! Rappelez-vous simplement que la véritable composition d'image consiste réellement à superposer deux véritables images couleur de différentes manières (en particulier les méthodes de composition alpha de Duff-Porter). Le mappage d'image consiste plus généralement à utiliser des images spécialisées qui modifient une image d'une manière particulière. La partie la plus difficile du mappage d'image est de générer une « carte » particulière pour un effet particulier. Et c'est là que réside une grande partie du travail, des efforts et des techniques présentés sur cette page. Une fois que vous avez une carte, cependant, vous pouvez l'utiliser de nombreuses fois avec de nombreuses images différentes, très rapidement.
Déformer des images par mappage d'image
Si les divers opérateurs de distorsion décrits dans les sections précédentes des exemples IM (comme le Gauchissement d'image simple et les Distorsions générales d'image) vous restreignent aux seuls types de distorsions programmés dans la bibliothèque graphique d'IM, en général au moyen d'équations et de formules mathématiques précises. Cependant, il arrive que vous vouliez concevoir votre propre distorsion d'une manière plus libre et moins mathématique. Par exemple, pour générer une distorsion plus complexe, comme mapper une image sur une forme particulière ou avec un effet de lentille complexe particulier, qu'il est plus facile de dessiner que de définir mathématiquement. Parfois, vous voulez simplement pouvoir répéter votre distorsion sur un grand nombre d'images et éviter d'avoir à la recalculer encore et encore. La solution consiste à précalculer votre distorsion et à l'enregistrer sous forme de table de recherche (LUT) spéciale, sous la forme d'une image en niveaux de gris. C'est-à-dire que, pour chaque pixel de sortie, nous consultons la LUT, puis utilisons cette valeur pour rechercher la couleur dans l'image source. Trois étapes sont donc nécessaires.
- Rechercher chaque pixel de destination dans la LUT
- Faire correspondre la valeur de la LUT à l'emplacement dans l'image source (deux méthodes)
- Rechercher la couleur dans l'image source
Comme une image sert de « table de recherche » pour la distorsion, vous pouvez créer ou modifier la carte de distorsion à l'aide d'un éditeur d'image comme 'Gimp' ou 'PhotoShop', ce qui vous donne la liberté de réaliser des distorsions vraiment sophistiquées et complexes. Vous devez toutefois vous rappeler que, comme toutes les autres méthodes de distorsion que nous avons vues, la recherche est appliquée sous forme de mappage inverse des pixels. C'est-à-dire que, pour chaque pixel de l'image de destination, nous recherchons la couleur du pixel dans l'image source, en utilisant la méthode de distorsion appliquée. Dans ce cas, la méthode consiste à rechercher la coordonnée source à partir de l'image table de recherche fournie.
Il existe désormais deux façons d'utiliser une carte d'image pour déterminer où, dans l'image source, une couleur doit être recherchée... absolue ou relative. Avec une recherche de coordonnées absolue, une carte de distorsion convertit directement la valeur de couleur de la LUT en une coordonnée dans l'image source à partir de laquelle rechercher la couleur à utiliser. Peu importe où se trouve la couleur dans la LUT, chaque couleur renvoie au point de recherche exact à utiliser. Les images LUT de distorsion présentent un dégradé de couleurs, mais tout gauchissement ou toute distorsion de ce dégradé produira le même effet lorsque la carte est appliquée. Avec une recherche de coordonnées relative, une carte de déplacement utilise la valeur de couleur pour décaler la coordonnée actuelle afin de déterminer l'emplacement, dans l'image source, où rechercher la couleur. Cela signifie qu'une image LUT en gris pur est utilisée, ses zones plus claires et plus sombres définissant la façon dont les pixels doivent être décalés ou déplacés par la carte, quel que soit leur emplacement dans celle-ci. Les deux méthodes ont des avantages et des inconvénients, comme vous le verrez.
Cartes de recherche à distorsion absolue
La création d'une carte LUT de distorsion absolue est la plus simple des deux méthodes, tant à comprendre qu'à créer et à appliquer. Cependant, comme vous le verrez, elle présente un inconvénient très sérieux qui la rend moins pratique qu'une carte de déplacement relatif. C'est la couleur en un point donné de la « carte de distorsion » qui renvoie directement à un emplacement dans l'image source. Autrement dit, le dégradé en niveaux de gris à travers la « carte » définit la « texture » à placer à cet emplacement. Imaginez maintenant que l'image carte soit en réalité l'image d'un objet complexe tel qu'un tee-shirt, avec des plis et des ondulations complexes. Si ce tee-shirt présente un dégradé, vous pouvez mapper n'importe quelle image plate sur ce tee-shirt. C'est là toute la puissance d'une carte de distorsion absolue. Tout pixel « noir » de l'image LUT (valeur de couleur 0) sera considéré comme le pixel le plus à gauche, soit la coordonnée X '0' de l'image source, tandis que tout ce qui est « blanc » dans la LUT (valeur 1) sera considéré comme le pixel le plus à droite (la largeur de l'image source). Notez que cette LUT ne recherchera que la position X ou horizontale de la couleur dans l'image source. Elle ne changera pas la hauteur ni la position Y des couleurs. Essayons donc cela avec un simple dégradé horizontal ordinaire en niveaux de gris comme LUT.
magick koala.gif \( -size 75x75 gradient: -rotate 90 \) \
-fx 'p{v*w,j}' distort_noop.gif
Notez que cela n'a produit aucun véritable changement dans le mappage de l'image source vers l'image de destination. En effet, la coordonnée X que nous avons recherchée dans la carte de distorsion était la même position pour laquelle nous recherchions la couleur. En retournant simplement le dégradé, la recherche des pixels est elle aussi retournée, créant une image en miroir. C'est-à-dire que le blanc est à gauche et le « noir » à droite, avec un dégradé horizontal à travers l'image.
magick koala.gif \( -size 75x75 gradient: -rotate -90 \) \
-fx 'p{v*w,j}' distort_mirror_x.gif
Si nous prenons le dégradé d'origine et le comprimons à l'aide d'un opérateur d'amélioration du contraste, nous obtenons une distorsion bien plus utile.
magick -size 75x75 gradient: -rotate 90 \
-sigmoidal-contrast 8,50% map_compress.gif
magick koala.gif map_compress.gif -fx 'p{v*w,j}' distort_compress.gif
Remarquez que les côtés de la distorsion sont étirés tandis que le centre est comprimé. Nous pouvons étendre cela à deux dimensions en utilisant 2 cartes de distorsion, l'une pour ajuster la coordonnée X, l'autre pour la coordonnée Y.
magick map_compress.gif -rotate 90 map_compress_y.gif
magick koala.gif map_compress.gif map_compress_y.gif \
-fx 'p{u[1]*w,u[2]*h}' distort_compress_2D.gif
Comme vous pouvez le voir, ce qui précède recrée une variante de la méthode d'implosion, mais uniquement en comprimant les images le long des axes X et Y (simultanément), plutôt que radialement comme le fait l'opérateur Implode. L'essentiel ici est que tout ce que vous faites à la carte de distorsion absolue, vous le ferez à l'image finale, quelle que soit l'image à laquelle vous l'appliquez. C'est là toute la puissance des cartes de distorsion.
Méthode de composition 'Distort'
Jusqu'à présent, nous avons utilisé l'opérateur DIY général FX pour appliquer les cartes de distorsion absolue. Cela offre un moyen d'ajuster et de peaufiner précisément ce que vous faites, mais c'est aussi très lent. L'opérateur de composition "Distort" encode une formule très semblable à celle que nous avons utilisée ci-dessus. Il a toutefois été implémenté d'une manière qui le rend aussi un peu plus compatible avec l'opérateur de composition "Displace" que nous examinerons plus loin dans les cartes de déplacement relatif.
Répétons donc le dernier exemple d'« implosion » à l'aide d'une composition "Distort".
magick koala.gif map_compress.gif map_compress_y.gif \
-compose Distort -define compose:args=37.5x37.5 -composite \
distort_compose.gif
Notez l'utilisation du "réglage Define" "compose:args" ci-dessus. Cette valeur est un multiplicateur appliqué au dégradé LUT utilisé (centré sur un gris parfait). La valeur '37.5' utilisée correspond à la moitié de la largeur et de la hauteur de l'image (75 pixels). Vous pouvez modifier ce multiplicateur pour agrandir ou réduire l'échelle globale de la distorsion. Si les valeurs de "compose:args" ne sont PAS définies, elles prendront par défaut les valeurs correctes. Si la valeur est fixée à zéro, aucune distorsion ne sera appliquée dans cette direction. Si vous vouliez définir automatiquement les arguments de composition, vous pouvez utiliser la méthode équivalente Set "option:" suivante pour la calculer... |
magick koala.gif map_compress.gif map_compress_y.gif \
-set option:compose:args '%[fx:w/2]x%[fx:h/2]' \
-compose Distort -composite \
distort_compose_set.gif
![[IM Output]](../static/img/mapping/distort_compose_set.gif)
Ou bien laissez-la indéfinie afin qu'IM calcule les valeurs correctes (pour une Distort 2D)... |
magick koala.gif map_compress.gif map_compress_y.gif \
-compose Distort -define compose:args='' -composite \
distort_compose_default.gif
Carte de distorsion neutre
Avant d'aller plus loin, j'aimerais prendre un instant pour revenir sur l'exemple « noop » ci-dessus. Celui-ci va en réalité flouter légèrement l'image, car la formule telle que je l'ai décrite n'est pas tout à fait exacte. Obtenir la copie « neutre » de l'original est un bon test pour vérifier que les mathématiques de votre distorsion sont correctes.
Autrement dit, à partir d'un dégradé parfait, vous pouvez mapper chaque pixel de l'image source vers l'image de destination. C'est-à-dire que la valeur « blanche » (ou 1.0) de la LUT correspondra exactement au pixel le plus à droite (ou le plus bas) de la destination.
Pour tester les distorsions neutres, nous utilisons une « image à damier de pixels » (par ex. "pattern:gray50") car elle fera apparaître toute distorsion, et donc tout problème dans les mathématiques appliquées. Essayons donc d'appliquer une distorsion neutre aux méthodes que nous avons utilisées jusqu'ici... |
magick -size 75x75 pattern:gray50 \
\( gradient: -rotate 90 \) \( gradient: -flip \) \
-fx 'p{u[1]*w,u[2]*h}' distort_fx_check.gif
magick -size 75x75 pattern:gray50 \
\( gradient: -rotate 90 \) \( gradient: -flip \) \
-set option:compose:args '%[fx:w/2] x %[fx:h/2]' \
-compose Distort -composite distort_compose_check.gif
![[IM Output]](../static/img/mapping/distort_compose_check.gif)
Comme vous pouvez le voir, les DEUX méthodes n'ont pas réussi à reproduire l'image « damier de pixels ». Elles ont toutefois échoué de manières légèrement différentes, en raison de la façon dont les coordonnées sont calculées. Ce qui s'est passé, c'est que le facteur d'échelle, de la recherche de couleur à la coordonnée de pixel, est décalé d'1 pixel. Pour savoir pourquoi cela se produit, voyez Distorsions, coordonnées d'image contre coordonnées de pixel. | _La distorsion FX est centrée sur le coin supérieur droit (position de pixel 0,0) et génère des pixels virtuels dupliqués le long des bords inférieur et droit. Cela vient du fait qu'elle ne tente pas de déplacer le centre de la mise à l'échelle, de la couleur recherchée vers les coordonnées d'image utilisées pour la recherche réelle. Ainsi, les pixels noirs restent centrés sur le pixel 0,0, même si la mise à l'échelle est erronée.
L'opérateur de composition "Distort" translate les coordonnées de sorte que zéro se trouve au centre de l'image, avant l'application de la mise à l'échelle. Il le fait dans le cadre de la mise à l'échelle des « cartes de déplacement » (voir plus loin). Ainsi, la mise à l'échelle imprécise tire les bords de l'image vers l'intérieur d'un demi-pixel le long de chaque bord, tout en laissant le centre de l'image correct._
---|---
Voici les versions « neutre parfaite » corrigées pour les cartes de distorsion absolue, qui utilisent essentiellement les coordonnées d'image (largeur et hauteur réduites de un) lors du calcul du facteur d'échelle entre couleur et coordonnées. |
magick -size 75x75 pattern:gray50 \
\( gradient: -rotate 90 \) \( gradient: -flip \) \
-fx 'p{u[1]*(w-1),u[2]*(h-1)}' distort_fx_check_correct.gif
magick -size 75x75 pattern:gray50 \
\( gradient: -rotate 90 \) \( gradient: -flip \) \
-set option:compose:args '%[fx:(w-1)/2] x %[fx:(h-1)/2]' \
-compose Distort -composite distort_compose_check_correct.gif
![[IM Output]](../static/img/mapping/distort_compose_check_correct.gif)
En réalité, les valeurs par défaut de "compose:args", si elles ne sont pas définies, utilisent les valeurs de mise à l'échelle correctes. |
magick -size 75x75 pattern:gray50 \
\( gradient: -rotate 90 \) \( gradient: -flip \) \
-compose Distort -define compose:args='' -composite \
distort_compose_default_check.gif
![[IM Output]](../static/img/mapping/distort_compose_default_check.gif)
Il faut cependant souligner que ces légères imprécisions n'ont normalement pas grande importance lors de l'utilisation des distorsions, si bien que toute petite différence est généralement ignorée. Gardez simplement cela à l'esprit pour le savoir lorsque cela compte vraiment.
Problèmes des cartes de distorsion
Poursuivons notre distorsion d'image en tentant une rotation. Générer la carte pivotée peut être un peu délicat, mais c'est faisable...
magick -size 75x75 gradient: -background black -rotate 45 \
-gravity center -crop 75x75+0+0 +repage map_rot45_x.png
magick map_rot45_x.png -rotate 90 map_rot45_y.png
magick koala.gif map_rot45_x.png map_rot45_y.png \
-compose Distort -composite distort_rot45.gif
Et nous disposons maintenant d'une autre façon de faire pivoter n'importe quelle image. Le plus gros problème de cette technique est qu'en créant nos cartes de distorsion à l'aide de rotations, nous avons introduit des pixels aux couleurs étranges le long des bords diagonaux. Dans le dernier exemple, cela a provoqué l'ajout de quelques pixels aléatoires en une ligne le long du coin inférieur droit de l'image. Ces couleurs « aléatoires » sont des valeurs d'anticrénelage que la rotation a introduites pour produire une « meilleure » image. Cependant, pour les cartes de distorsion, les pixels de bord anticrénelés peuvent poser un réel problème. Nous pouvons maintenant tenter de mieux définir les couleurs aux bords des images LUT pivotées. Dans ce cas, nous pouvons générer une image de dégradé plus grande, puis rogner la rotation à la bonne taille.
magick -size 100x20 xc:white xc:black -size 115x75 gradient: \
+swap -append -rotate 45 \
-gravity center -crop 75x75+0+0 +repage map_rot45b_x.png
magick map_rot45b_x.png -rotate 90 map_rot45b_y.png
magick koala.gif map_rot45b_x.png map_rot45b_y.png \
-compose Distort -composite distort_rot45_better.png
De cette façon, tous les pixels de la LUT sont désormais correctement définis, sans anticrénelage. Cela révèle maintenant un problème légèrement différent. Tous les pixels de l'image finale sont correctement définis, mais certains pixels ne devraient pas faire partie de l'image finale. Ils n'ont aucune signification réelle dans l'image résultante. C'est là le plus gros problème de l'utilisation d'une LUT pour spécifier les coordonnées absolues à récupérer dans l'image source. Vous n'avez aucun moyen de spécifier ce qu'IM doit faire dans ces zones indéfinies.
Définir les pixels indéfinis à l'aide d'un masque
Une façon plus générale de résoudre le problème des « pixels indéfinis » consiste à définir une carte indiquant quels pixels constituent réellement un résultat valide et défini dans la distorsion. Autrement dit, une image de masquage. Par exemple...
magick -size 75x75 xc:white -background black -rotate 45 \
-gravity center -crop 75x75+0+0 +repage map_rot45b_m.png
magick distort_rot45_better.png map_rot45b_m.png \
-alpha off -compose CopyOpacity -composite distort_rot45_masked.png
Nous avons désormais trois images impliquées dans la carte de distorsion, et le résultat devient vraiment complexe. Bien sûr, dans une situation typique, vous n'aurez probablement pas besoin d'aller aussi loin, mais dans le cas général, si.
Image de distorsion unifiée
Vous avez toutefois peut-être remarqué que les trois cartes sont toutes des images en niveaux de gris. Cela signifie qu'il est tout à fait raisonnable de fusionner toutes les cartes en une seule image de carte de distorsion. Par exemple, mappons la « carte de distorsion X » sur le canal 'red', la « carte Y » sur le 'green', et le masque sur le canal 'alpha' ou de transparence, ce qui facilite la manipulation.
magick map_rot45b_x.png map_rot45b_y.png \( map_rot45b_m.png -negate \) \
-alpha off -channel RGA -background black -combine map_rot45u.png
| Le canal 'blue' de l'image à canaux combinés n'est pas défini, il prend donc sa valeur de la couleur "-background" actuelle, que j'ai préréglée sur 'black' ou une valeur de zéro ci-dessus.
---|---
Appliquons maintenant cette carte de distorsion unifiée à notre image de koala. Cela nécessite malheureusement deux étapes de traitement d'image, l'une pour déformer l'image, l'autre pour masquer le résultat.
magick koala.gif -alpha set map_rot45u.png \
\( -clone 0,1 -fx 'p{v.r*w,v.g*h}' \
+clone -compose Dst_In -composite \) -delete 0,1 \
distort_rot45_unified.png
Vous pouvez aussi utiliser directement la méthode de composition "Distort" avec l'image de carte de distorsion unifiée... |
magick koala.gif -alpha set map_rot45u.png \
-compose Distort -define compose:args='' -composite \
distort_rot45_compose.gif
![[IM Output]](../static/img/mapping/distort_rot45_compose.gif)
Il reste un canal inutilisé (blue) dans l'image « carte de distorsion unifiée ». Une utilisation logique consiste à s'en servir pour ajouter des rehauts et des ombres à l'image déformée. (Voir Rehauts en incrustation). Vous verrez cette technique poussée un cran plus loin dans l'exemple de la carte de distorsion sphérique ci-dessous.
Carte de distorsion en sablier
Je voulais maintenant une carte de distorsion unidimensionnelle qui mette à l'échelle chaque ligne de l'image différemment selon la hauteur de cette ligne. Une sorte de véritable distorsion de miroir déformant de fête foraine qui fait paraître les gens corpulents très minces. Autrement dit, une sorte de distorsion en sablier. C'est une image LUT assez complexe, et après pas mal de tâtonnements, j'en suis arrivé à l'expression suivante pour générer une carte de dégradé variable en hauteur mais linéaire horizontalement. |
magick -size 100x100 xc: -channel G \
-fx 'sc=.15; (i/w-.5)/(1+sc*cos(j*pi*2/h)-sc)+.5' \
-separate map_hourglass.png
![[IM Output]](../static/img/mapping/map_hourglass.png)
| Lorsque vous générez des dégradés en niveaux de gris, vous pouvez rendre l'opérateur -fx 3 fois plus rapide, simplement en lui demandant de ne générer qu'un seul canal de couleur, comme le canal 'G' ou vert dans l'exemple ci-dessus. Ce canal peut ensuite être séparé pour former l'image en niveaux de gris requise. Cela peut représenter un très gros gain de vitesse, en particulier avec une formule "[-fx](https://imagemagick.org/command-line-options/#fx)" très complexe.
---|---
Le 'sc' est le facteur d'échelle du sablier (sa valeur varie de 0 à 0.5) et vous permet d'ajuster l'amplitude de la distorsion. Appliquons maintenant cette carte à l'image intégrée "rose:". Notez que la carte de 100x100 pixels ne correspond pas à l'image de 70x46 pixels. Cela complique les choses, car nous devrons mettre à l'échelle le pixel courant de l'image source de la quantité appropriée pour correspondre à la carte de distorsion fournie, afin de rechercher l'emplacement de la couleur de ce pixel. |
magick rose: map_hourglass.png \
-fx 'p{ v.p{i*v.w/w,j*v.h/h}*w, j}' distort_hourglass.png
![[IM Output]](../static/img/mapping/distort_hourglass.png)
Si vous regardez attentivement, la coordonnée X du pixel 'i' est multipliée par la largeur de l'image carte de distorsion 'v.w', et divisée par la largeur de l'image d'origine 'w', pour produire 'i*v.w/w. La même chose se produit pour la coordonnée Y du pixel, 'j*v.h/h'. Cela remet à l'échelle la coordonnée du pixel dans l'image de destination pour correspondre à l'image LUT de distorsion. La coordonnée recherchée est ensuite mise à l'échelle en multipliant la valeur de la LUT par la largeur de l'image source, pour devenir la coordonnée X de la recherche de couleur. Si vous disposez à la fois d'une carte de distorsion X et Y, vous devrez répéter la recherche mise à l'échelle pour la carte Y. Bien sûr, nous avons les mêmes distorsions de « bord » que précédemment, changeons donc le réglage du pixel virtuel pour la transparence. |
magick rose: -alpha set -virtual-pixel transparent -channel RGBA \
map_hourglass.png -fx 'p{ v.p{i*v.w/w,j*v.h/h}.g*w, j}' \
distort_hourglass2.png
![[IM Output]](../static/img/mapping/distort_hourglass2.png)
Notez l'utilisation du réglage "-channel" pour garantir que "[-fx](https://imagemagick.org/command-line-options/#fx)" fonctionnera avec le canal alpha (transparence) de l'image source et renverra ses valeurs. En particulier les pixels virtuels transparents. Notez aussi que, lors de la recherche dans la carte de distorsion, nous n'avons recherché que dans le canal vert (à l'aide de 'v.p{}.g'). Sans cela, le même canal que celui traité dans l'image source serait utilisé, or pour la carte le canal 'alpha' n'est pas défini. Cette carte de distorsion pourrait être encore améliorée en utilisant un dégradé non linéaire, afin que l'image reste rectangulaire, avec plus de distorsion sur les bords qu'au milieu, pour lui donner un aspect plus « arrondi » ou « cylindrique ». Quelqu'un voudrait-il s'y essayer ? Écrivez-moi
Carte de distorsion sphérique
Dans l'exemple précédent de carte de distorsion en sablier, j'ai généré un dégradé mis à l'échelle horizontalement par une courbe cosinus. Avec un peu plus de travail, vous pouvez générer une forme sphérique à la place... |
magick -size 100x100 xc: -channel R \
-fx 'yy=(j+.5)/h-.5; (i/w-.5)/(sqrt(1-4*yy^2))+.5' \
-separate +channel sphere_lut.png
![[IM Output]](../static/img/mapping/sphere_lut.png)
Notez toutefois que ce qui précède n'est pas strictement exact. Le dégradé comprimé reste un dégradé linéaire, simplement comprimé pour tenir dans un cercle. Une représentation plus exacte nécessiterait probablement la création d'un dégradé non linéaire. Ce qui, en termes de position absolue, correspondrait à une fonction 'arccos()'. Or ce mappage comporte aussi de grandes zones qui seraient classées comme invalides, il faudra donc un type de masquage pour définir quels pixels seront valides et invalides dans l'image finale. Un simple cercle fera l'affaire dans ce cas. |
magick -size 100x100 xc:black -fill white \
-draw 'circle 49.5,49.5 49.5,0' sphere_mask.png
![[IM Output]](../static/img/mapping/sphere_mask.png)
Et pour terminer, il nous faut aussi un rehaut d'ombrage, tel que celui développé dans Rehauts en incrustation, destiné à une composition Overlay ou Hardlight... |
magick sphere_mask.png \
\( +clone -blur 0x20 -shade 110x21.7 -contrast-stretch 0% \
+sigmoidal-contrast 6x50% -fill grey50 -colorize 10% \) \
-composite sphere_overlay.png
![[IM Output]](../static/img/mapping/sphere_overlay.png)
Rappelez-vous que l'ombrage ci-dessus ne comptera qu'à l'intérieur des limites de l'objet sphère, le fait que l'ombrage déborde de ces limites n'a donc pas d'importance. D'ailleurs, si vous voulez tenter de proposer un meilleur ombrage sphérique, qui produise une image encore plus proche d'une boule, j'aimerais le voir. Appliquons donc les trois images : LUT de coordonnée X, ombrage en incrustation et masque de transparence ; à une image réelle de la bonne taille (pour simplifier).
magick lena_orig.png -resize 100x100 sphere_lut.png -fx 'p{ v*w, j }' \
sphere_overlay.png -compose HardLight -composite \
sphere_mask.png -alpha off -compose CopyOpacity -composite \
sphere_lena.png
Cet exemple particulier illustre l'aspect le plus puissant d'une carte de distorsion absolue. Vous pouvez définir un dégradé sur n'importe quel objet de forme libre (pas nécessairement de façon mathématique), de sorte que n'importe quelle image puisse être mappée sur cet objet, qu'il s'agisse de courbes, de rides, de plis, etc. En clair, une fois le mappage de l'objet établi, vous pouvez mapper n'importe quelle image sur sa surface. Puis, pour lui donner un aspect plus réaliste, vous pouvez superposer un second mappage, afin d'ajouter des rehauts, des ombres, des bords et d'autres détails. Bien sûr, comme les trois images sont en niveaux de gris, vous pouvez les combiner en une seule image de carte de distorsion unifiée, pour un stockage aisé. Dans ce cas, je vais en faire une distorsion plus sphérique en réutilisant la LUT de distorsion de coordonnée X également pour la coordonnée Y. |
magick sphere_lut.png \( +clone -transpose \) \
sphere_overlay.png \( sphere_mask.png -negate \) \
-channel RGBA -combine spherical_unified.png
![[IM Output]](../static/img/mapping/spherical_unified.png)
C'est une carte plutôt jolie. Mais si vous cherchez à l'interpréter, souvenez-vous que : les canaux 'red' et 'green' sont les LUT de coordonnées X et Y, 'blue' est l'incrustation des effets de rehauts et d'ombres, et le canal de transparence contient le masque des pixels invalides de l'image finale. Appliquons-la donc à l'aide de la méthode de composition "Distort".
magick mandrill_grid_sm.jpg spherical_unified.png \
\( -clone 0,1 -alpha set -compose Distort -composite \) \
\( -clone 1 -channel B -separate +channel \) \
\( -clone 2,3 -compose HardLight -composite \) \
\( -clone 4,1 -compose DstIn -composite \) \
-delete 0--2 spherical_mandrill.png
Dans l'ordre...
- nous appliquons la carte de distorsion (qui inclut le masque)
- nous extrayons la carte d'ombrage de l'image carte unifiée
- nous appliquons la carte d'ombrage à l'image déformée
- nous restaurons le masque perdu lors de l'opération d'ombrage
- nous supprimons tout sauf l'image finale et l'enregistrons
La complexité de tout cela tient uniquement au besoin d'extraire le masque d'ombrage et de restaurer le masque alpha que l'ombrage a supprimé.
Carte de distorsion en arc de cercle
Juste pour montrer ce qui est réellement possible avec les cartes de distorsion positionnelles, voici une LUT de distorsion absolue, semblable à ce que fournit la méthode de distorsion 'Arc' ci-dessus. Au lieu de calculer les mappages de coordonnées pour chacun des pixels de chacune des images à déformer, nous enregistrons ces coordonnées calculées dans les deux cartes LUT de coordonnées X et Y en niveaux de gris. Autrement dit, nous précalculons toute la distorsion dans une simple image table de recherche, ce qui permet de l'appliquer encore et encore, sans avoir besoin d'autres racines carrées ni fonctions trigonométriques.
magick -pointsize 30 -font Candice label:Anthony -trim +repage \
-gravity center -resize 95x95 -crop 100x100+0+0\! \
-flatten text_image.jpg
magick -size 100x100 xc: -channel G -fx 'atan(j/(i+.5))*2/pi' \
-separate -flip -flop map_p_angle.png
magick -size 100x100 xc: -channel G -fx '1-hypot(i,j)/(w*1.6)' \
-separate -transverse map_p_radius.png
magick text_image.jpg map_p_angle.png map_p_radius.png \
-fx 'p{u[1]*w,u[2]*h}' distort_p_curved.jpg
Source de couleur |
|
Angle - carte X |
|
Rayon - carte Y |
|
Texte incurvé
---|---|---|---|---|---|---
Bien sûr, générer cette carte de distorsion a été difficile, mais une fois que c'est fait, par n'importe quel moyen (même de façon artistique avec un éditeur d'image comme "Gimp"), vous pouvez ensuite la réutiliser sur un très grand nombre d'images.
Carte de distorsion polaire
Il vous faudra parfois que l'image de destination soit définie par la carte de distorsion, plutôt que par l'image source, simplement pour que les choses fonctionnent correctement. Par exemple, si nous voulons mapper du texte dans un cercle (ce que l'on appelle aussi une transformation polaire), il faut vraiment pouvoir utiliser une image environ 3 à 4 fois plus longue que haute (rapport d'aspect élevé), sinon le résultat ne sera pas très lisible. Pour cela, nous plaçons les images de carte de distorsion avant l'image source de couleur, de sorte que la première image (la carte X) serve à fixer la taille du résultat final, plutôt que l'image source d'entrée.
magick -size 100x100 xc: -channel G \
-fx 'atan2(i-w/2,h/2-j)/pi/2 + .5' \
-separate map_p_angular.png
magick -size 100x100 xc: -channel G \
-fx 'rr=hypot(i-w/2,j-h/2); (.5-rr/70)*1.2+.5' \
-separate map_p_radial.png
magick -font Candice -gravity center -size 200x50 \
label:'Around the World' text.jpg
magick map_p_angular.png map_p_radial.png text.jpg \
-fx 'u[2].p{ u*u[2].w, v*u[2].h }' distort_p_circle.jpg
Angulaire - carte X |
|
Radial - carte Y |
|
Source de couleur |
|
Texte en cercle
---|---|---|---|---|---|---
Essentiellement, l'image source de couleur peut désormais avoir n'importe quelle taille ou rapport d'aspect, et tout sera traité correctement ; il se peut toutefois que vous deviez ajuster la génération de la carte de distorsion pour gérer correctement le rapport d'aspect des images source. Lors de la génération des cartes ci-dessus, la valeur '70' contrôle la taille finale du cercle, le long duquel est placée la ligne médiane. La valeur '1.2', quant à elle, contrôle la mise à l'échelle verticale de l'image dans le cercle, ce qui vous permet d'ajuster la hauteur du texte déformé. |
Rappelez-vous que cette expression "-fx" exige que les cartes de distorsion soient données en premier, et que la source de couleur soit donnée comme troisième image (indice 2). Cela signifie toutefois aussi que toute métadonnée stockée dans l'image source sera également perdue. |
|---|---|
| _Le problème de cette carte de distorsion, c'est qu'il existe une disjonction de couleurs très nette dans la 'carte X' (causée par une asymptote dans les mathématiques). Cette ligne doit rester nette lorsque vous effectuez une recherche de couleur, ou un redimensionnement de la carte, pour produire une image plus grande. Autrement dit, vous devrez veiller à ce qu'aucun redimensionnement ni recherche interpolée de cette carte ne produise une couleur de recherche grise le long de cette ligne asymptotique. |
Si vous générez bien des recherches grises le long de cette ligne, vous obtiendrez une ligne de pixels colorés (recherchés au milieu de l'image) dans votre résultat final.
C'est pourquoi il est recommandé de toujours générer cette carte de distorsion à la taille dont vous avez besoin pour l'image finale, et de ne jamais utiliser une technique de mise à l'échelle montrée précédemment._
---|---
Vous pouvez aussi utiliser cela pour d'autres effets, comme un damier circulaire... |
magick map_p_angular.png map_p_radial.png \
-size 150x90 pattern:checkerboard \
-fx 'u[2].p{ u*u[2].w, v*u[2].h }' distort_check_circle.gif
![[IM Output]](../static/img/mapping/distort_check_circle.gif)
Essayez certains des autres motifs intégrés qu'IM propose avec ce qui précède pour d'autres effets intéressants. | _Ce qui précède montre clairement les limites des distorsions d'image utilisant "-fx". Près du centre de l'image, les lignes radiales se crénèlent, car la fusion des pixels de grandes zones en un seul pixel n'a pas lieu. En revanche, les bords de l'image, en particulier les coins, présentent un flou approprié des lignes radiales.
La cause en est que "-fx" (et la plupart des anciennes méthodes de distorsion) ne fait que de simples recherches interpolées non mises à l'échelle des couleurs de l'image source. Cela signifie qu'à mesure que l'image est réduite, les pixels de l'image source ne sont pas fusionnés pour produire la couleur correcte du pixel de destination.
Ce n'est pas un problème pour les zones d'agrandissement (comme dans les coins), seulement de compression extrême (le centre). Une solution consiste donc à utiliser le suréchantillonnage, mais cela ne fait que repousser les problèmes à un niveau de compression plus élevé._
---|---
| _La même ligne asymptotique (changement brusque) dans la carte de distorsion (du centre au bas de l'image) produit aussi un changement de couleur net le long de cette ligne dans l'exemple ci-dessus. Comparez cette ligne avec les autres lignes radiales (comme celle du centre vers le haut de l'image) qui deviennent très floues à mesure qu'elles approchent du bord de l'image, du fait de la recherche interpolée notée précédemment.
Cela peut poser problème lors de la génération d'un motif circulaire avec une image mosaïquable (comme ci-dessus), et peut nécessiter un traitement particulier pour éviter des différences visibles dans cette partie de l'image.
Pour éviter cela, il peut être préférable de déformer la moitié supérieure de l'image séparément de la moitié inférieure, afin d'éviter la région asymptotique.
Mélanger les lignes
Dans cet exemple, nous faisons quelque chose d'un peu plus inhabituel... Mélanger les lignes d'une image au hasard. Nous créons d'abord une carte comportant un dégradé pour X (canal rouge) et une image de bruit aléatoire pour Y (canal vert).
magick rose: \
\( -size 46x70 gradient: -rotate -90 \) \
\( -size 1x46 gradient: -spread 23 -scale 70x46\! \) \
-compose Distort -define compose:args='' -composite \
rose_row_shuffle.png
Malheureusement, "-spread" semble inclure les pixels virtuels dans sa sélection de pixels à échanger, ce qui fait que certaines lignes deviennent des doublons tandis que d'autres sont totalement perdues. Autrement dit, la carte de mélange n'est pas tout à fait correcte. Avez-vous une meilleure solution pour mélanger les pixels ?
Cartes de recherche à déplacement relatif
Comme vous pouvez le voir, créer une carte de distorsion absolue est raisonnablement facile à faire et à utiliser. Elle a toutefois un sérieux problème lorsqu'une distorsion comporte des régions « indéfinies », ou des zones où la distorsion sort des limites normales de l'image source. Un problème plus grave encore est que vous manipulez toujours des dégradés, qui définissent les coordonnées absolues de la recherche de couleur. Aucune partie de l'image de mappage n'est simple, propre, ni facile à modifier ou à éditer à la main. Des techniques et des mathématiques particulières sont nécessaires à leur création et à leur usage. Ce qui signifie en général qu'il y a très peu de place pour un développement « artistique ». Il existe cependant une autre méthode d'utilisation d'une table de recherche pour spécifier les coordonnées où obtenir la couleur finale : la carte de déplacement relatif. Au lieu que la « carte » définisse la coordonnée exacte où rechercher la couleur de chaque pixel dans l'image source, elle définit un décalage ou déplacement relatif à la position actuelle. Or un décalage peut être une valeur positive ou négative, et une valeur négative demande une petite astuce pour être encodée dans une valeur de couleur. Ce qu'on fait donc, c'est définir le « gris pur » comme un déplacement 0 de la coordonnée (aucun changement). On fait ensuite du « noir » un déplacement négatif maximal, et du « blanc » un déplacement positif maximal. Cela peut être difficile à décrire, regardons donc un exemple. Nous créons d'abord une image de test à « déplacer ». |
magick -font Candice -gravity center -size 150x50 \
label:'Anthony' label.jpg
![[IM Output]](../static/img/mapping/label.jpg)
Je vais maintenant utiliser un peu de « magie » pour créer une image en « gris pur » comportant des zones en « blanc pur » et en « noir pur ». |
echo "P2 5 1 255\n 127 0 127 255 127" |\
magick - -scale 150x50\! -alpha off displace_map.jpg
![[IM Output]](../static/img/mapping/displace_map.jpg)
Pour utiliser maintenant cette image comme « carte de déplacement », nous récupérons la « valeur de gris » de la carte de déplacement et l'ajoutons à la coordonnée X et/ou Y. Autrement dit, nous déplaçons la recherche d'une quantité relative par rapport à la position actuelle, selon le « niveau de gris » de la carte de déplacement. La « valeur » est traitée d'une manière particulière : un « gris pur » signifiera un déplacement nul du point de recherche (juste la coordonnée Y dans ce cas), tandis qu'un « déplacement maximal » est utilisé pour une valeur « blanche » (positive) ou « noire » (négative). Par exemple, appliquons la carte de déplacement à notre image "label". |
magick label.jpg displace_map.jpg -virtual-pixel Gray \
-fx 'dy=10*(2*v-1); p{i,j+dy}' displaced.jpg
![[IM Output]](../static/img/mapping/displaced.jpg)
Comme vous pouvez le voir, les différentes sections de l'image semblent avoir « bougé » selon la couleur de la carte de déplacement. Une région « blanche » ajoute la « valeur de déplacement » donnée au point de recherche, de sorte que, dans cette zone, chaque pixel recherche l'image source '10' pixels plus « au sud » (direction Y positive). En conséquence, l'image source semble avoir bougé vers le haut. Rappelez-vous que c'est la recherche qui est déplacée, PAS l'image elle-même, ce qui explique pourquoi elle semble avoir bougé vers le haut, dans une direction négative, pour le blanc. Un effet similaire s'observe pour les zones à déplacement « noir ». L'image source semble avoir bougé vers le bas, parce que le déplacement de la recherche s'est fait dans une direction négative. Réfléchissez-y bien. Vous remarquerez aussi que la « recherche déplacée » peut en fait regarder au-delà des limites normales de l'image, ce qui vous permet d'utiliser un réglage de pixel virtuel pour contrôler ces pixels hors limites. Ci-dessus, j'ai simplement demandé qu'un pixel gris soit renvoyé. La valeur de « déplacement maximal » '10' dans l'exemple ci-dessus est très importante : c'est la distance relative maximale dont une partie de l'image source semble se déplacer, pour une valeur de déplacement « blanc pur » ou « noir pur » dans l'image de mappage. Vous ne pouvez pas déplacer la recherche, et donc l'image d'entrée, au-delà de cette valeur. Les autres nuances de gris entre les valeurs maximales de blanc ou de noir et la valeur centrale de non-déplacement, le gris à 50 %, déplaceront la recherche d'une quantité appropriée. Ainsi, un gris à 25 % déplacera la recherche de la moitié de la valeur de déplacement dans la direction négative, tandis qu'un gris à 75 % la déplacera de la moitié de cette valeur dans la direction positive. Cette valeur est une différence essentielle entre une carte de distorsion absolue et une carte de déplacement relatif. Vous pouvez augmenter ou diminuer les déplacements relatifs, rendant l'image plus ou moins déformée, simplement en changeant la valeur de déplacement, sans avoir à modifier la carte de déplacement du tout. De plus, comme une carte à « déplacement nul » n'est qu'un gris uni à 50 % ou gris pur, et non un dégradé complexe, vous pouvez partir d'une simple image grise et éclaircir ou assombrir artistiquement des zones pour générer les déplacements voulus. Vous pouvez le faire simplement en dessinant des formes ou des zones, plutôt qu'en ayant besoin d'une formule mathématique complexe et exacte. Et enfin, comme tous les déplacements sont relatifs, des valeurs extravagantes telles que celles produites par les effets de bord ne produisent pas de couleurs de pixels extravagantes ou aléatoires. En fait, comme vous le verrez, adoucir ou flouter les cartes de déplacement est en réalité une bonne chose, car cela supprime l'effet de « coupure » discontinue que vous pouvez voir dans l'exemple ci-dessus. En résumé, une carte de déplacement est beaucoup plus contrôlable et artistique, offrant des déplacements localisés sans avoir besoin de mathématiques complexes et exigeantes, et elle est très indulgente à l'égard des erreurs, des effets de bord, voire du floutage de la carte de déplacement. Elle est idéale pour les distorsions simples de type « déplacement », comme lorsqu'on génère des effets d'eau, de vagues, de miroirs déformants, de courbure de la lumière, des effets de lentille, ou des effets de verre dépoli ou à bulles. En revanche, les distorsions très mathématiques telles que les distorsions « polaires », rotationnelles et « perspectives », ou d'autres mappages 3D du monde réel, ne s'obtiennent pas facilement. Ce n'est pas pour autant impossible, car nous montrerons plus loin que vous pouvez en fait passer d'un style de carte à l'autre, c'est juste plus difficile.
Méthode de déplacement par composition
Nous avons utilisé l'opérateur DIY FX pour faire le mappage de déplacement, afin que vous puissiez voir ce qui se passe réellement. Mais c'est une technique lente. Il existe toutefois un opérateur de composition intégré équivalent, "Displace". Voici comment l'utiliser...
magick {_image_} {_displacement_map_} \
-compose Displace -define compose:args={_X_}x{_Y_} \
-composite {_result_ +}
magick {_image_} {_displacement_map_} \
-compose Displace -set option:compose:args {_X_}x{_Y_} \
-composite {_result_ +}
magick composite {_displacement_map_} {_image_} \
-displace {_X_}x{_Y_} {_result_ +}
Notez l'ordre, en particulier dans la commande "magick composite".
L'utilisation de "-set" au lieu de define vous permet aussi d'utiliser des échappements de pourcentage dans l'argument. Les valeurs 'X ' et 'Y ' définissent la direction et le « déplacement maximal » qui seront utilisés pour les couleurs « blanche » et « noire » de la carte de déplacement donnée. Vous pouvez définir l'une des deux valeurs, ou les deux, afin de pouvoir déplacer dans n'importe quelle direction particulière. Autrement dit, normalement les cartes de déplacement produisent un déplacement linéaire dans une direction quelconque, avec une intensité maximale contrôlée par les valeurs 'X ' et 'Y '. L'« image carte » définit alors quelle proportion de ce maximum est appliquée, d'un maximum négatif (noir) à un maximum positif (blanc), un gris parfait signifiant aucun déplacement de la recherche pour ce pixel. Par exemple, voici le même exemple de déplacement Y que ci-dessus... |
magick label.jpg displace_map.jpg -virtual-pixel Gray \
-compose Displace -define compose:args=0x10 -composite \
displaced_y.jpg
![[IM Output]](../static/img/mapping/displaced_y.jpg)
Vous pouvez aussi tirer parti d'autres réglages comme "[-geometry](https://imagemagick.org/command-line-options/#geometry)" et "[-gravity](https://imagemagick.org/command-line-options/#gravity)", pour ajuster la zone où la carte de déplacement est superposée à l'image. La recherche de pixels résultant de la carte de déplacement peut toujours référencer des zones situées en dehors de la partie superposée de l'image, en les dupliquant dans la zone superposée.
Exemples de déplacement simples
Une carte de déplacement faite de zones de couleurs brutes, sans transition douce, produira généralement des déplacements disjoints (discontinus) entre les différentes zones de l'image résultante, comme vous l'avez vu ci-dessus. Vous pouvez d'ailleurs produire une carte de déplacement qui se « fracture » comme si vous regardiez dans un miroir fissuré, à l'aide de cette technique. Voyez par exemple le miroir brisé ci-dessous. Vous pouvez obtenir des résultats plus jolis et plus doux si les couleurs passent en douceur d'une zone à l'autre. Par exemple, en floutant la carte de déplacement, vous générez une transition de type vague entre les zones déplacées... |
magick displace_map.jpg -blur 0x10 dismap_wave.jpg
magick label.jpg dismap_wave.jpg -virtual-pixel Gray \
-compose Displace -define compose:args=0x10 -composite \
displaced_wave_y.jpg
![[IM Output]](../static/img/mapping/dismap_wave.jpg)
![[IM Output]](../static/img/mapping/displaced_wave_y.jpg)
Plutôt que de déplacer l'image dans une direction Y, vous pouvez aussi utiliser une carte pour la déplacer dans une direction X, ce qui donne une sorte d'onde de compression. |
magick label.jpg dismap_wave.jpg -virtual-pixel Gray \
-compose Displace -define compose:args=10x0 -composite \
displaced_wave_x.jpg
![[IM Output]](../static/img/mapping/displaced_wave_x.jpg)
En utilisant la même carte de déplacement pour les directions X et Y, nous pouvons ajouter à la fois une onde de compression et une onde d'amplitude. |
magick label.jpg dismap_wave.jpg -virtual-pixel Gray \
-compose Displace -define compose:args=10x10 -composite \
displaced_wave_xy.jpg
![[IM Output]](../static/img/mapping/displaced_wave_xy.jpg)
Notez que l'image est toujours déplacée dans une seule direction linéaire, ce qui fait que l'image ci-dessus est étirée sur la pente descendante et resserrée sur la pente montante. Autrement dit, la distorsion se fait selon un angle ou « vecteur », avec des composantes à la fois horizontale et verticale. Vous pouvez constater que cet effet ressemble remarquablement à une vue sous l'eau, l'image étant déformée par de douces ondulations à la surface de l'eau. Une carte de distorsion peut toutefois contenir plusieurs copies de l'image d'origine, tout comme dans des images reflétées ou réfractées... |
echo "P2 3 1 255\n 255 127 0 " | magick - -scale 150x50\! dismap_copy.jpg
magick label.jpg dismap_copy.jpg \
-compose Displace -define compose:args=66x0 -composite \
displaced_copy.jpg
![[IM Output]](../static/img/mapping/dismap_copy.jpg)
![[IM Output]](../static/img/mapping/displaced_copy.jpg)
Vous pouvez aussi créer des retournements en miroir de parties de l'image, à l'aide de dégradés. Par exemple, vous pouvez ici utiliser une carte de déplacement linéaire pour copier des pixels d'un côté de l'image vers l'autre. |
magick -size 50x150 gradient: -rotate -90 -alpha off dismap_mirror.png
magick label.jpg dismap_mirror.png \
-compose Displace -define compose:args=150x0 -composite \
displaced_mirror.jpg
![[IM Output]](../static/img/mapping/dismap_mirror.png)
![[IM Output]](../static/img/mapping/displaced_mirror.jpg)
Pouvez-vous deviner comment fonctionne cette carte de déplacement ? Un indice : déterminez quel déplacement ont les bords le plus à gauche et le plus à droite, puis voyez comment le reste de l'image s'y insère. Cependant, comme vous utilisez de nouveau une image de dégradé, vous perdez la simplicité des cartes de déplacement. Ainsi, les miroirs sont soit mieux réalisés à l'aide d'une opération de retournement directe de l'image, soit à l'aide d'une carte de distorsion absolue. Notez qu'en retournant le dégradé, vous rétrécissez l'image. |
magick -size 50x150 gradient: -rotate 90 -alpha off dismap_shrink.png
magick label.jpg dismap_shrink.png \
-compose Displace -define compose:args=150x0 -composite \
displaced_shrink.jpg
![[IM Output]](../static/img/mapping/dismap_shrink.png)
![[IM Output]](../static/img/mapping/displaced_shrink.jpg)
Ce qui précède illustre aussi un problème particulier des cartes de déplacement. Lorsqu'une zone (ou la totalité) d'une image est comprimée de plus de 50 %, vous commencez à générer des artefacts de crénelage. C'est particulièrement visible dans les bords « crénelés » en escalier bien apparents. Comme évoqué précédemment, une solution consiste à suréchantillonner le nombre de pixels utilisés pour générer chaque pixel de sortie. Pour cela, nous agrandissons à la fois l'image et la carte de déplacement, puis redimensionnons l'image résultante à sa taille plus habituelle. Cela permet à davantage de pixels de participer au réglage d'un pixel donné du résultat, et produit donc une meilleure image. Par exemple... |
magick label.jpg dismap_shrink.png -resize 200% \
-compose Displace -define compose:args=400x0 -composite \
-resize 50% displaced_resize.jpg
![[IM Output]](../static/img/mapping/displaced_resized.jpg)
Un résultat bien meilleur et plus doux, quoique peut-être un peu flou lui aussi. Tracé d'un dégradé Découlant directement des exemples ci-dessus, l'idée est qu'en utilisant des déplacements Y d'une simple ligne, vous pouvez générer un graphe des couleurs d'une carte de déplacement. Par exemple, je génère ici une fonction mathématique sinc() (définie comme 'sin(x)/x'), et je trace ce dégradé en l'utilisant comme carte de déplacement...
magick -size 121x100 xc: -fx 'sin(i*24/w-12)/(i*24/w-12)/1.3+.2' \
gradient_sinc.gif
magick -size 121x100 xc: -draw 'line 0,50 120,50' graph_source.gif
magick graph_source.gif gradient_sinc.gif \
-compose Displace -define compose:args=0x49 -composite \
displace_graph.gif
Comme vous pouvez le voir, cela fonctionne, même si je ne voudrais pas l'utiliser pour des tracés mathématiques. Mieux vaut recourir à un vrai logiciel de tracé. Cette technique est toutefois utile comme méthode approximative pour tracer les intensités d'une ligne ou d'une colonne de pixels d'une image. Ce qu'elle montre, c'est comment de grandes différences de déplacement peuvent facilement produire une discontinuité ou un résultat non lisse. Fondamentalement, comme chaque pixel de la « source du graphe » n'est examiné qu'un à la fois, sans moyennage, une grande différence dans la recherche déplacée d'un pixel au suivant peut produire un grand changement de couleur dans le résultat. La morale, c'est que le déplacement fonctionne mieux non seulement avec des cartes de déplacement douces, mais aussi en déplaçant des images contenant de grandes zones ou nuances de couleur. Il ne fonctionne pas si bien pour des lignes fines et nettes. Bien sûr, vous pouvez améliorer les choses en suréchantillonnant de nouveau la carte de distorsion... |
magick graph_source.gif gradient_sinc.gif -resize 400% \
-compose Displace -define compose:args=0x196 -composite \
-resize 25% displace_graph_2.gif
![[IM Output]](../static/img/mapping/displace_graph_2.gif)
Le résultat est bien meilleur, quoique pas aussi bon que ce qu'on peut obtenir avec un logiciel de tracé. Pourtant, seul ImageMagick a servi à le créer. Voici une autre version du même graphe, mais cette fois en utilisant une couleur unie, ce qui fonctionne bien mieux que de déplacer une ligne fine. |
magick -size 121x50 xc:white xc:black -append \
gradient_sinc.gif -resize 400% \
-compose Displace -define compose:args=0x196 -composite \
-resize 25% displace_graph_3.gif
Déplacement de zone (linéaire)
Essayons un problème de déplacement plus logique. Déplacer une zone d'une image en ligne droite d'un emplacement à un autre. Comme nous l'avons vu, une image en « gris pur » ne provoque aucun déplacement, tandis qu'une couleur « blanche » provoque un déplacement de recherche positif depuis l'image source. Par exemple, créons une telle image.... |
magick -size 75x75 xc:gray50 -fill white \
-draw 'circle 37,37 37,20' dismap_spot.jpg
![[IM Output]](../static/img/mapping/dismap_spot.jpg)
Maintenant, lorsque nous appliquons cette image, le contenu de la zone marquée devrait comporter une copie de ce qui apparaît dans la direction de la valeur de déplacement donnée. Essayons donc une valeur de déplacement de X +10 et Y +10, soit '10x10'...
magick koala.gif dismap_spot.jpg \
-compose Displace -define compose:args=10x10 -composite \
displace_spot.png
Comme vous pouvez le voir, le contenu de la zone marquée contient désormais une copie de l'image qui se trouvait +10,+10 pixels au sud-est. En gros, une image de la « queue » du koala. Autrement dit, à l'intérieur du cercle, l'image a été déplacée vers le nord-est, soit -10,-10 pixels. Rappelez-vous que le déplacement porte sur la recherche, l'image source est donc décalée d'une quantité négative en raison du mappage inverse des pixels. L'image se déplace dans la direction inverse ! Notez aussi que c'est l'image à l'intérieur de la zone marquée qui est déplacée. Vous ne déplacez pas l'image marquée, mais vous déplacez l'image DANS la zone marquée. Et enfin, notez la discontinuité nette aux bords du cercle. Les zones à l'intérieur de la zone marquée sont déplacées, tandis que celles à l'extérieur restent exactement telles qu'elles étaient. Ce sont des faits, il vaut donc la peine de les répéter.
Le déplacement déplace les images dans la direction opposée à la valeur.
Seules les zones marquées non grises seront déplacées.
Les changements de couleur nets produisent des discontinuités d'image nettes.
Essayons donc quelque chose de plus concret. Déplaçons le centre situé entre le nez et les yeux du koala, à la position '32,22', vers le centre de notre cercle blanc (déplacement positif maximal) à '37,37'. Cela nécessite une valeur de déplacement de '-5,-15' (rappelez-vous que la direction est inversée)... |
magick koala.gif dismap_spot.jpg \
-compose Displace -define compose:args=-5x-15 -composite \
displace_head.png
![[IM Output]](../static/img/mapping/displace_head.png)
Et voilà une copie bien centrée de la partie centrale de la tête du koala. Mais l'image est encore « disjointe », et utiliser une valeur négative n'est pas très élégant. La solution consiste à utiliser plutôt une tache noire, mais aussi à flouter les bords de cette tache. Agrandissons-la également pour englober davantage la tête du koala. Voici donc notre image de « tache de mouvement positif »... |
magick -size 75x75 xc:gray50 -fill black \
-draw 'circle 37,37 37,17' -blur 0x5 dismap_area.jpg
![[IM Output]](../static/img/mapping/dismap_area.jpg)
Il ne faut pas trop flouter l'image, sinon le centre de la tache ne sera plus d'un noir uni. Autrement, vous pourriez simplement normaliser et ajuster les niveaux à l'envers l'image pour garantir que la zone dessinée soit noire et que les parties environnantes soient des gris parfaits. Vous verrez cela souvent dans les exemples suivants. Répétons maintenant ce dernier déplacement de « tête » à l'aide de notre carte de déplacement à « tache floue » noire. |
magick koala.gif dismap_area.jpg \
-compose Displace -define compose:args=5x15 -composite \
displace_area.png
![[IM Output]](../static/img/mapping/displace_area.png)
Comme vous pouvez le voir, nous déplaçons l'image de +5,+15 dans la zone « floue », mais cette fois la bordure de la zone est plus douce et reliée au reste de l'image. Bien sûr, les oreilles au bord du cercle ont été déformées par le bord flou, et le corps du koala comprimé lui aussi, mais c'est tout de même bien mieux qu'avant. Pour éviter la « déchirure » de l'image que vous voyez du côté arrière, ou le fait de laisser des copies de la partie déplacée, vous voudrez agrandir cette tache, ou créer une image de déplacement de type dégradé plus complexe. Par exemple, supposons que vous vouliez déplacer la tête du koala de sa position de départ '32,22' vers le centre de l'image '37,37', soit un mouvement de +5,+15 pixels, mais que vous vouliez adapter toute l'image à ce changement, pour un effet bien plus doux. Pour cela, vous voudrez le déplacement maximal du noir (un déplacement d'image positif) à '37,37', déplaçant d'une valeur de +5,+15. Mais vous voulez aussi vous assurer que le reste de l'image reste intact en « épinglant » les coins à un gris de 50 %. C'est parfait pour un dégradé épars interpolé de Shepard.
magick -size 75x75 xc: -sparse-color Shepards \
'37,37 black 0,0 gray50 74,74 gray50 0,74 gray50 74,0 gray50' \
dismap_move.jpg
magick koala.gif dismap_move.jpg \
-compose Displace -define compose:args=5x15 -composite \
displace_move.png
Comme vous pouvez le voir, vous obtenez une plus grande zone de déplacement répartie sur toute l'image. Le résultat est une image bien plus douce dans son évolution que la méthode de « tache » plus serrée utilisée auparavant. C'est en fait exactement équivalent à la distorsion de Shepard, mais pour un seul point de contrôle en mouvement. C'est aussi exactement la même méthode que celle utilisée dans le script '[shapemorph](http://www.fmwconcepts.com/imagemagick/shapemorph/)' de Fred Weinhaus, mais avec un peu d'animation. En résumé : pour de petits déplacements localisés, on peut utiliser des déplacements par « tache floue ». Mais pour des déplacements plus importants sur une plus grande distance, il faut utiliser une carte de déplacement à dégradé doux plus large, afin d'éviter de déchirer ou de dupliquer l'image source.
En construction
Morphing simple par déplacement
Modification de la taille des vecteurs de déplacement
Morphing entre deux images
Déplacements 1D aléatoires
Reflets sur une eau ondulée
Comme mentionné précédemment, les cartes de déplacement sont particulièrement utiles pour générer des distorsions de type eau et verre.
Pour cet exemple, j'ai généré une petite image en rognant une image de fleur. Je veux maintenant lui donner l'air d'être posée sur une eau ondulée. Pour générer des ondulations, il me faut un dégradé en onde sinusoïdale de la même taille, que je peux générer à l'aide de la fonction Evaluate Sin. Le nombre '8' représente le nombre d'« ondes » qui seront ajoutées au dégradé. |
magick -size 150x80 gradient: -evaluate sin 8 wave_gradient.png
![[IM Output]](../static/img/mapping/wave_gradient.png)
Déformons maintenant cette image à l'aide d'un vecteur de déplacement incliné, et non d'une simple distorsion verticale ou horizontale, afin de lui donner plus de relief. |
magick composite wave_gradient.png flower.jpg -displace 5x5 flower_waves.png
![[IM Output]](../static/img/mapping/flower_waves.png)
Cela ne semble pas très intéressant, mais que se passe-t-il si vous retournez cette image, la comprimez verticalement et l'accolez à l'originale... |
magick flower_waves.png -flip \
flower.jpg +swap -append flower_waves_2.png
![[IM Output]](../static/img/mapping/flower_waves_2.png)
Malheureusement, cela a encore l'air plutôt artificiel. La raison en est que le reflet est identique en haut et en bas de l'image. Il n'a aucune impression de « profondeur ». Le reflet a aussi la même luminosité que l'image d'origine, ce qui est rarement le cas. Pour le rendre plus réaliste, vous devez utiliser un motif d'ondulations dont l'intensité varie. Ce qui suit utilise quelques mathématiques de dégradé astucieuses pour « atténuer » le dégradé d'onde que nous utilisions ci-dessus. Autrement dit, nous avons rendu le motif d'onde linéairement plus petit du haut vers le bas. Cette astuce garantit que les ondes se terminent sur la couleur de gris pur ou « aucun déplacement » au bas de l'image (qui est ensuite retournée). |
magick -size 150x80 gradient: \
\( wave_gradient.png \
+clone -compose multiply -composite \) \
\( -clone 0 -negate -evaluate divide 2 \
-clone 1 -compose plus -composite \) \
-delete 0-1 waves_decreasing.png
![[IM Output]](../static/img/mapping/waves_decreasing.png)
Appliquons donc ce dégradé, pour former un nouveau reflet de la fleur. J'ai aussi légèrement assombri l'image reflétée pour représenter la lumière perdue dans l'eau elle-même, ce qui la fait ressembler davantage à un reflet aquatique. |
magick flower.jpg waves_decreasing.png \
-compose Displace -define compose:args=8x8 -composite \
-flip +level 0,80% \
flower.jpg +swap -append flower_in_water.png
![[IM Output]](../static/img/mapping/flower_in_water.png)
Notez que l'image déformée est retournée pour former un reflet. De plus, l'image aura moins d'« ondulations » en haut de l'« eau », au plus près de sa jonction avec l'image d'origine, qu'en bas. Cela donne à la distorsion une impression d'éloignement par rapport à l'observateur. Vous pouvez la rendre encore plus réaliste en déformant les cartes de déplacement d'onde avec une légère rotation, un arc, ou simplement des déplacements « aléatoires ». Cela donnera aux ondes un aspect plus naturel. Il vaut toutefois mieux le faire avant l'« atténuation », afin que la « profondeur » soit ajoutée ensuite. Essayez, expérimentez, et dites-moi ce que vous obtenez.
Futures ondulations animées -
Utiliser -function Sinusoid avec changement de phase
Mappage de déplacement bidimensionnel
Jusqu'à présent, toutes les cartes de déplacement relatif n'ont déplacé l'image que dans une seule direction. Cette direction peut certes être réglée sur n'importe quel angle souhaité en définissant la valeur ou le « vecteur » de déplacement '_X_ x _Y_' approprié. Vous pouvez toutefois produire un déplacement bien plus complexe, où l'image est déplacée dans n'importe quelle direction et de n'importe quelle quantité, en utilisant deux déplacements distincts. Pour cela, nous devons créer deux cartes de déplacement, une pour chacune des directions X et Y séparément. Voici les commandes que vous pouvez utiliser...
magick {_image_} {_X displacement_} {_Y displacement_} \
-compose Displace -define compose:args={_X_}x{_Y_} \
-composite {_result_ +}
magick {_image_} {_X displacement_} {_Y displacement_} \
-compose Displace -set option:compose:args {_X_}x{_Y_} \
-composite {_result_ +}
composite {_X displacement_} {_image_} {_Y displacement_} \
-displace {_X_}x{_Y_} {_result_ +}
Notez l'ordre des images d'entrée dans la commande "magick composite". Cet ordre étrange est dû à la nécessité de détourner la gestion des options de "magick composite", ainsi qu'à des raisons historiques. Il est vital de bien le respecter. C'est pourquoi je recommande d'utiliser la commande "magick" plutôt que "magick composite". |
Avant IM v6.4.4, l'utilisation de 2 cartes de déplacement distinctes pour des déplacements X et Y séparés était aléatoire. Cela fonctionnait parfois, et parfois non. Il est déconseillé de même tenter de l'utiliser sur des IM plus anciens que cette version. |
|---|---|
| De plus, comme avec les cartes de distorsion unifiées, vous pouvez utiliser une seule « carte de déplacement unifiée ». Si une seule image de déplacement est fournie, le déplacement X sera recherché dans le canal 'red', le déplacement Y dans le canal 'green', et tout masque alpha sera aussi transféré de la carte de déplacement vers l'image finale. Le canal 'blue' est ignoré. | _En interne, "magick" comme "magick composite' fusionnent en réalité les deux images (si elles sont fournies) afin de générer une « carte de déplacement unifiée », avant de la transmettre à l'API interne. |
Cela n'affecte pas les « déplacements linéaires » que nous avons examinés précédemment, car la carte de déplacement donnée était une image en niveaux de gris, si bien que les canaux 'red' et 'green' étaient identiques._
---|---
Déplacement cylindrique
Une demande revenue plusieurs fois sur les forums IM est un moyen de mapper une image sur un cylindre, par exemple pour l'appliquer sur un mug à café ou une canette de soda. Voici la solution... |
magick rose: -background black -gravity south -splice 0x8 \
\( +clone -sparse-color barycentric '0,0 black 69,0 white' \) \
\( -clone 1 -function arcsin 0.5 \) \
\( -clone 1 -level 25%,75% \
-function polynomial -4,4,0 -gamma 2 \
+level 50%,0 \) \
-delete 1 \
-virtual-pixel black -define compose:args=17x7 \
-compose Displace -composite rose_cylinder.png
![[IM Output]](../static/img/mapping/rose_cylinder.png)
Ce qui précède est très complexe, mais utilise en substance deux déplacements distincts simultanément. Une compression arcsin() dans la direction X, et un déplacement en arc de cercle dans la direction Y. Voici ce que fait la commande...
- Charger l'image « rose » et ajouter de l'espace pour le déplacement vertical
- Créer un dégradé mathématique horizontal pour les fonctions mathématiques ultérieures
- Créer une copie du dégradé pour générer une carte de déplacement compressive
- Créer une autre copie pour un déplacement en arc elliptique vertical
- Supprimer le dégradé linéaire
- Préparer et effectuer le déplacement
Résultat... Une rose correctement enroulée dans une vue isométrique de cylindre à 30 degrés. Décomposez la commande ci-dessus pour enregistrer et visualiser les cartes de déplacement individuelles. L'essentiel à retenir est que le déplacement à deux cartes effectue les recherches des valeurs X et Y, pour déterminer quel pixel doit se retrouver à l'emplacement de la recherche. Rappelez-vous que le déplacement n'est pas réellement un déplacement de l'image source, mais un déplacement de la recherche dans l'image source. Cette méthode de distorsion par déplacement a été intégrée au script "[cylinderize](http://www.fmwconcepts.com/imagemagick/cylinderize/)" de Fred Wienhaus.
Miroir brisé
Vous pouvez donner à une image un aspect de « miroir brisé » en générant des zones aléatoires de déplacements X et Y.
magick dragon_sm.gif -sparse-color voronoi ' \
%[fx:rand()*w],%[fx:rand()*h] red
%[fx:rand()*w],%[fx:rand()*h] lime
%[fx:rand()*w],%[fx:rand()*h] black
%[fx:rand()*w],%[fx:rand()*h] yellow
' -interpolate integer -implode 1 mirror_areas.gif
magick mirror_areas.gif -channel R -separate mirror_dismap_x.gif
magick mirror_areas.gif -channel G -separate mirror_dismap_y.gif
magick composite mirror_dismap_x.gif dragon_sm.gif mirror_dismap_y.gif -alpha off \
-background white -virtual-pixel background -displace 7 \
mirror_displaced.gif
magick mirror_areas.gif -edge 1 -threshold 20% \
-evaluate multiply .7 -negate mirror_cracks.gif
magick composite mirror_displaced.gif mirror_cracks.gif -compose multiply \
mirror_cracked.gif
| Quatre zones déplacées de façon aléatoire sont générées à l'aide d'une image couleur éparse de Voronoï aléatoire. On lui applique ensuite une distorsion par implosion pour gauchir ces zones vers le centre de l'image. Comme chacune des quatre zones colorées reste d'une couleur unie, chaque zone contiendra une copie non déformée, mais déplacée, de l'image d'origine. Chaque zone aura toutefois déplacé l'image d'une manière différente, tout comme le ferait chaque éclat d'un miroir brisé. Pour parachever le miroir, une détection de contours est utilisée pour souligner les bords des régions et donc la nature fracturée de l'image résultante. Autrement dit, les fissures sont elles aussi rendues visibles. | Techniquement, je n'avais pas à séparer les canaux 'red' et 'green' dans la carte de déplacement aléatoire colorée générée. J'aurais pu les utiliser directement, puisque le déplacement X est recherché dans le canal 'red' et le déplacement Y dans le canal 'green'. Autrement dit, j'aurais pu utiliser directement l'image "mirror_areas.gif" comme « carte de déplacement unifiée ». |
|---|---|
En construction
Déplacement de Shepard
Déplacements aléatoires
Effets de lentille
Effets de verre dépoli
Effets de dispersion (déplacements pivotés)
Effets de dispersion avec déplacement aléatoire
FUTUR : Autres exemples possibles de mappage par distorsion / déplacement
- Tracer par lancer de rayons un dégradé sur des objets 3D afin que, plus tard, N'IMPORTE QUELLE image puisse être mappée sur ces objets.
- Images de dégradé mappées en X et Y
- Image en gris pur pour la couleur, les rehauts et l'ombrage
Mappage de flou variable
Ajoutée à ImageMagick version 6.5.4-0, la méthode 'Blur' de "[-compose](https://imagemagick.org/command-line-options/#compose)" vous offre un moyen de remplacer chaque pixel par une moyenne gaussienne elliptique (un flou) des pixels voisins, selon une image de mappage.
magick composite -blur {_Xscale_}[x{_Yscale_}[+{_angle_}]] blur_map image result
magick image blur_map \
-define compose:args='{_Xscale_}[x{_Yscale_}[+{_angle_}]]' \
-compose blur -composite result
magick image blur_map \
-set option:compose:args '{_Xscale_}[x{_Yscale_}[+{_angle_}]]' \
-compose blur -composite result
Notez que cette composition d'image nécessite l'utilisation d'un argument opérationnel, qui peut être défini de plusieurs manières. Voir artefacts définis globalement pour plus de détails. En utilisant une carte variable pour contrôler le flou, vous pouvez flouter une partie de l'image tout en laissant une autre partie totalement intacte, ou produire des effets tels que l'effet tilt-shift, où une image du monde réel est rendue semblable à un petit modèle réduit artificiel.
Par exemple, je floute ici la moitié d'une image de koala tout en laissant l'autre moitié totalement nette...
magick -size 37x75 xc:black -size 38x75 xc:white +append blur_map_bool.gif
magick koala.gif blur_map_bool.gif \
-compose blur -define compose:args=3 -composite \
blur_koala_bool.gif
Comme vous pouvez le voir, tout pixel qui était « blanc » sur l'image 'blur_map' a été flouté avec la valeur maximale de 'sigma ' donnée, tandis que tout ce qui était « noir » n'a pas été flouté du tout. Autrement dit, vous obtenez un flou masqué très simple. Bien sûr, cela aurait pu être réalisé de bien d'autres façons, mais cela n'explique pas où réside la puissance du mappage de flou. Ce qui rend ce mappage de flou polyvalent, c'est qu'il est variable à travers l'image. Autrement dit, si la couleur du mappage de flou est grise, vous obtiendrez un résultat proportionnellement moins flou, avec un « voisinage » plus petit, pour ce pixel. Le noir n'est cependant pas flouté, tandis que le blanc est flouté au maximum, selon les valeurs données. Une chose à noter : seules les zones floutées demanderont le temps supplémentaire nécessaire. Les pixels qui ne sont pas floutés n'ont pas besoin de ce traitement supplémentaire. Cela rend ce qui précède bien plus rapide que d'utiliser un composite masqué, qui revient à flouter toute l'image et à fusionner les résultats. Ce gain de temps peut être encore plus important lorsqu'on traite de grands flous sur de très petites zones d'une image. Par exemple, rendons le koala progressivement plus flou vers ses pieds...
magick -size 75x75 gradient:black-white blur_map_gradient.gif
magick koala.gif blur_map_gradient.gif \
-compose blur -define compose:args=3 -composite \
blur_koala_gradient.gif
Et voici le même flou, mais montrant cette fois comment le flou varie avec la hauteur.
magick blur_map_bool.gif blur_map_gradient.gif \
-compose blur -define compose:args=15 -composite \
blur_edge_gradient.gif
Pour un exemple concret de flous mappés variables, jetez un œil à l'effet tilt-shift photo et à la police à ombre floutée selon la distance. Notez que c'est le voisinage autour de chaque pixel qui sert à générer la « couleur floutée » de ce pixel. Cela signifie que, même si vous spécifiez qu'une partie de l'image ne doit pas être floutée, des couleurs de cette zone non floutée peuvent être utilisées dans le flou des pixels environnants. Autrement dit, ce n'est pas parce qu'une zone n'est pas floutée que ses couleurs ne servent pas au résultat d'autres pixels floutés. Les couleurs de la zone non floutée peuvent donc « déborder » dans les zones floutées environnantes. Pour flouter un arrière-plan sans y inclure les pixels de premier plan, vous devez utiliser une technique de masque de lecture afin d'empêcher leur lecture dans le cadre de l'opération de flou.
Flou elliptique
Le réglage de composition 'Blur' utilise une technique différente des opérateurs de flou ou de flou gaussien habituels, car il est implémenté à l'aide d'un algorithme de rééchantillonnage de zone elliptique gaussien, développé pour le rééchantillonnage d'image à l'échelle dans le cadre de l'opérateur de distorsion généralisé. La zone elliptique utilisée pour le rééchantillonnage du voisinage rend aussi cette méthode de flou plus polyvalente qu'un flou « circulaire » uniforme normal fourni par les opérateurs "[-blur](https://imagemagick.org/command-line-options/#blur)" et "[-gaussian-blur](https://imagemagick.org/command-line-options/#gaussian-blur)". L'ellipse elle-même est définie par la 'largeur ' et la 'hauteur ' du sigma de la zone floutée. L'ellipse peut aussi être pivotée par rapport à un alignement orthogonal d'un 'angle ' donné (dans le sens horaire). Par exemple, dans le schéma suivant, nous montrons comment la couleur floutée d'un seul pixel obtient sa couleur à partir d'une zone elliptique pivotée, selon les valeurs de sigma données. Les pixels de cette zone sont ensuite moyennés de façon pondérée selon un filtre gaussien (à l'aide d'une formule de distance elliptique) pour produire la couleur floutée.
magick koala.gif -compose blur -define compose:args=5x1-30 -composite \) \
elliptical_blur.gif
# ... other commands to create diagram of blur effect ...
Comme mentionné, c'est exactement la même méthode de recherche de couleur que celle utilisée par l'opérateur de distorsion généralisé pour générer les couleurs de ses images déformées, car elle permet une fusion mise à l'échelle (et filtrée) d'une zone de l'image source en un seul pixel, en particulier dans les distorsions extrêmes comme celle illustrée dans Regarder des horizons lointains. Pour plus de détails sur ce processus, voir Rééchantillonnage de zone et Filtres de rééchantillonnage.
Comme exemple des contrôles elliptiques disponibles pour le mappage de flou variable, utilisons un point noir avec la même carte de flou en dégradé qu'auparavant. Mais cette fois, nous mettrons à l'échelle une ellipse horizontale longue et fine '30x0', plutôt qu'un cercle. Le 'x0' peut sembler étrange, mais signifie en gros qu'aucun flou vertical ne doit apparaître, juste une ellipse de la plus petite hauteur nécessaire pour produire un bon résultat.
magick -size 75x75 xc: -draw 'circle 36,36 36,8' black_circle.gif
magick black_circle.gif blur_map_gradient.gif \
-compose blur -define compose:args=15x0 -composite \
blur_horizontal.gif
Comme vous pouvez le voir, l'ampleur du flou varie toujours avec l'image carte fournie, produisant très peu de flou en haut de l'image et beaucoup de flou en bas. Mais remarquez aussi que le bord inférieur est flouté horizontalement de façon égale dans les deux directions, mais pas verticalement, produisant une coupure nette dans la direction verticale. En faisant pivoter l'ellipse longue et fine par un troisième argument angle, ou en définissant directement une ellipse verticale, vous pouvez flouter l'image uniquement verticalement... |
magick black_circle.gif blur_map_gradient.gif \
-compose blur -define compose:args=0x15 -composite \
blur_vertical.gif
![[IM Output]](../static/img/mapping/blur_vertical.gif)
Notez toutefois que le flou n'a pas été appliqué de façon égale ! La moitié supérieure paraît moins floutée que la moitié inférieure, car c'est ce que l'« image de mappage » lui a indiqué de faire. Cela déforme à son tour l'image, la faisant paraître un peu tronquée par l'effet de flou. Enfin, refaisons-le une dernière fois, mais avec une ellipse horizontale pivotée d'un angle fixe de 45 degrés. |
magick black_circle.gif blur_map_gradient.gif \
-compose blur -define compose:args=15x0+45 -composite \
blur_angle.gif
![[IM Output]](../static/img/mapping/blur_angle.gif)
L'image peut paraître très étrange, mais c'est parce que la carte de flou variable est verticale tandis que le flou lui-même est incliné, produisant cet effet à l'aspect bizarre, du fait de la non-concordance entre l'angle de l'ellipse et l'angle de la carte de flou. | Notez qu'utiliser des ellipses longues et fines comme celle-ci est en réalité bien plus rapide que d'utiliser un seul grand cercle. En fait, l'opérateur "[-blur](https://imagemagick.org/command-line-options/#blur)" tire sa vitesse de l'utilisation de deux flous distincts, horizontal et vertical, tandis que l'opérateur de flou "[-gaussian](https://imagemagick.org/command-line-options/#gaussian)" effectue une convolution complète en 2 dimensions, d'une manière plus simple que la méthode de composition 'Blur' que l'on vient de décrire.
---|---
Flou à rapport d'aspect variable
Jusqu'à présent, nous avons fait varier la taille de la zone elliptique utilisée pour le flou à l'aide de la 'carte de flou'. Cependant, si la taille de l'ellipse et même son angle peuvent être modifiés, sa forme et son angle restent fixes. Or la 'carte de flou' est une image composée de trois canaux de couleur : rouge, vert et bleu. Comme nous avons utilisé une image en niveaux de gris, les trois canaux de couleur avaient les mêmes valeurs. En interne, cependant, la largeur de l'ellipse est mise à l'échelle par la seule valeur du canal rouge, tandis que la hauteur est mise à l'échelle par la valeur du canal vert. L'effet de la valeur du canal bleu est généralement ignoré, sauf dans un cas particulier que nous examinerons plus loin. Cela signifie que la forme elliptique, ou son « rapport d'aspect », peut être modifiée en utilisant des cartes différentes pour les canaux rouge et vert individuels. Comme pour une carte de flou normale, une valeur nulle (ou « noir » dans ce seul canal) donnera une largeur ou une hauteur minimale, tandis qu'une valeur maximale (ou « blanc ») donnera l'ampleur de flou indiquée. Par exemple, je peux ici diviser l'image de sorte que deux quarts de l'image soient floutés horizontalement (canal rouge maximal) tandis que les autres zones sont floutées verticalement (canal vert maximal). Pour cet exemple, j'ai généré séparément des cartes de largeur et de hauteur, avant de les combiner en une seule 'carte de flou', désormais colorée. En pratique normale, vous pouvez créer la carte comme vous le souhaitez, ou même utiliser des cartes préparées à l'avance pour des effets de flou spécifiques.
magick -size 2x2 pattern:gray50 -sample 75x75! blur_map_r.gif
magick blur_map_r.gif -negate blur_map_g.gif
magick blur_map_r.gif blur_map_g.gif -background black \
-channel RG -combine blur_map_aspect.gif
magick black_circle.gif blur_map_aspect.gif \
-compose blur -define compose:args=10x10 -composite \
blur_aspect.gif
Vous pouvez bien sûr toujours fixer un angle constant à l'ellipse. |
magick black_circle.gif blur_map_aspect.gif \
-compose blur -define compose:args=15x15+45 -composite \
blur_aspect_angle.gif
![[IM Output]](../static/img/mapping/blur_aspect_angle.gif)
| Avant IM version 6.5.8-8, un bug avait été trouvé dans la gestion d'un flou elliptique vertical incliné.
---|---
Flou à angle variable
Jusqu'à présent, l'angle de l'ellipse utilisée pour flouter l'image a été constant sur toute l'image. Autrement dit, l'ellipse utilisée pour le flou a toujours été au même angle, même si le rapport d'aspect de l'ellipse peut être modifié en agissant sur les canaux rouge et vert de la carte de flou. Depuis IM v6.5.8-8, vous pouvez fournir un angle variable au flou, à l'aide du canal bleu de l'image de mappage de flou. Cela se fait en donnant deux angles aux arguments du flou. Le premier argument d'angle sert à définir l'angle pour une valeur nulle ('0' ou 'noir') dans le canal bleu, tandis que le second angle donné sert à définir la valeur maximale ('QuantumRange' ou 'blanc') du canal bleu. Si une seule valeur d'angle est donnée, cet angle sert à définir les angles pour les valeurs nulle et maximale du canal 'bleu', ce qui signifie en gros que l'angle devient fixe, quelle que soit la valeur présente dans le canal bleu de l'image 'carte de flou'. C'est pourquoi, dans les exemples précédents, l'angle était constant. Par exemple, j'utilise ici une ellipse floutant horizontalement, puis je fais varier l'angle de l'ellipse à l'aide du canal bleu, sur la plage d'angles de '+0' à '+360' autour du centre de l'image. La génération de la carte utilise un dégradé polaire, dont les détails se trouvent dans Dégradés déformés. Remarquez comment, en plaçant ce dégradé dans le canal bleu, j'utilise le réglage de couleur "[-background](https://imagemagick.org/command-line-options/#background)" avec l'opérateur Combine pour garantir que les canaux rouge et vert soient réglés sur une valeur maximale ('blanc'), afin de ne pas mettre à l'échelle l'ellipse inclinée. Bien sûr, cela signifie que, dans l'image de mappage finale, le blanc signifie utiliser l'angle maximal, tandis que le jaune (ou valeur nulle du canal bleu) signifie l'angle minimal.
magick -size 100x300 gradient: -rotate 90 \
+distort Polar '36.5,0,.5,.5' +repage -flop gradient_polar.jpg
magick gradient_polar.jpg -background white \
-channel B -combine blur_map_angle.jpg
magick koala.gif blur_map_angle.jpg \
-compose blur -define compose:args=5x0+0+360 -composite \
blur_rotated.jpg
Le résultat est, comme vous pouvez le voir, une image floutée en rotation. Comparez le résultat avec le mappage de flou utilisé. En haut de l'image, le dégradé était soit blanc soit noir, ce qui, avec les arguments utilisés, signifie que l'ellipse était inclinée à 0 ou 360, l'ellipse restant donc horizontale. En bas, le dégradé était en gris pur, un angle à mi-chemin de la plage donnée a donc été utilisé, soit 180 degrés. L'ellipse est de nouveau horizontale. Mais sur les côtés de l'image, le dégradé était soit à 25 % soit à 75 % de gris. L'angle était donc de 90 ou 270 degrés, faisant pivoter l'ellipse à la verticale. Tous les autres angles suivent, faisant pivoter l'ellipse en douceur autour de l'image. Le centre de l'image résultante a toutefois été flouté de façon vraiment étrange ! C'est parce que la taille de l'ellipse est restée constante et ne diminue pas comme il faut vers le milieu de l'image. La solution consiste à définir aussi la taille de l'ellipse à l'aide des canaux rouge et vert. Par exemple.
magick -size 106x106 radial-gradient: -negate \
-gravity center -crop 75x75+0+0 +repage gradient_radial.jpg
magick gradient_radial.jpg gradient_radial.jpg gradient_polar.jpg \
-channel RGB -combine blur_map_polar.jpg
magick koala.gif blur_map_polar.jpg \
-compose blur -define compose:args=10x0+0+360 -composite \
blur_polar.jpg
Un résultat bien meilleur. Notez toutefois que, si le résultat semble bon, l'ellipse de flou n'est pas correctement incurvée en arc comme elle devrait l'être pour une véritable image floutée en rotation. Ce qui précède n'est donc qu'une approximation d'un vrai flou rotationnel. Mais pour de petites distances de flou (équivalant à un angle de flou), c'est plutôt bon. La meilleure façon de faire des flous rotationnels est d'utiliser une technique de distorsion polaire-dépolaire spéciale, ou l'opérateur de flou radial actuellement mal nommé. En changeant la plage d'angles utilisée pour l'angle de l'ellipse (canal bleu), vous pouvez facilement transformer ce qui précède en un flou radial qui devient de plus en plus flou à mesure qu'on s'éloigne du centre. |
magick koala.gif blur_map_polar.jpg \
-compose blur -define compose:args=5x0+90+450 -composite \
blur_radial.jpg
![[IM Output]](../static/img/mapping/blur_radial.jpg)
Mais vous pouvez faire bien plus que ces flous radiaux/rotationnels, car vous pouvez faire pivoter et mettre à l'échelle le flou n'importe où et de n'importe quelle quantité sur toute l'image. Vous avez un contrôle total. Par exemple, vous pouvez créer un mélange très étrange des deux en utilisant une plage d'angles différente, de sorte que l'angle de l'ellipse de flou ne corresponde pas à l'angle autour du centre de l'image. |
magick koala.gif blur_map_polar.jpg \
-compose blur -define compose:args=10x0+0+180 -composite \
blur_weird.jpg
![[IM Output]](../static/img/mapping/blur_weird.jpg)
Vous disposez désormais en somme d'un contrôle complet sur la manière dont, et sur les parties de l'image qui seront floutées. Et grâce aux gabarits, vous pouvez créer toute une bibliothèque d'effets de flou.
![[IM Output]](../static/img/images/koala.gif)
![[IM Output]](../static/img/mapping/map_gradient_x.gif)
![[IM Output]](../static/img/mapping/distort_noop.gif)
![[IM Output]](../static/img/mapping/map_gradient-x.gif)
![[IM Output]](../static/img/mapping/distort_mirror_x.gif)
![[IM Output]](../static/img/mapping/map_compress.gif)
![[IM Output]](../static/img/mapping/distort_compress.gif)
![[IM Output]](../static/img/mapping/map_compress_y.gif)
![[IM Output]](../static/img/mapping/distort_compress_2D.gif)
![[IM Output]](../static/img/mapping/distort_compose.gif)
![[IM Output]](../static/img/mapping/distort_compose_default.gif)
![[IM Output]](../static/img/mapping/distort_fx_check.gif)
![[IM Output]](../static/img/mapping/distort_fx_check_correct.gif)
![[IM Output]](../static/img/mapping/map_rot45_x.png)
![[IM Output]](../static/img/mapping/map_rot45_y.png)
![[IM Output]](../static/img/mapping/distort_rot45.gif)
![[IM Output]](../static/img/mapping/map_rot45b_x.png)
![[IM Output]](../static/img/mapping/map_rot45b_y.png)
![[IM Output]](../static/img/mapping/distort_rot45_better.png)
![[IM Output]](../static/img/mapping/map_rot45b_m.png)
![[IM Output]](../static/img/mapping/distort_rot45_masked.png)
![[IM Output]](../static/img/mapping/map_rot45u.png)
![[IM Output]](../static/img/mapping/distort_rot45_unified.png)
![[IM Output]](../static/img/img_photos/lena_orig.png)
![[IM Output]](../static/img/mapping/sphere_lena.png)
![[IM Output]](../static/img/img_photos/mandrill_grid_sm.jpg)
![[IM Output]](../static/img/mapping/spherical_mandrill.png)
![[IM Output]](../static/img/images/rose.png)
![[IM Output]](../static/img/mapping/rose_row_shuffle.png)
![[IM Output]](../static/img/mapping/gradient_sinc.gif)
![[IM Output]](../static/img/mapping/graph_source.gif)
![[IM Output]](../static/img/mapping/displace_graph.gif)
![[IM Output]](../static/img/mapping/displace_graph_3.gif)
![[IM Output]](../static/img/mapping/displace_spot.png)
![[IM Output]](../static/img/mapping/dismap_move.jpg)
![[IM Output]](../static/img/mapping/displace_move.png)
![[IM Output]](../static/img/mapping/mirror_areas.gif)
![[IM Output]](../static/img/mapping/mirror_dismap_x.gif)
![[IM Output]](../static/img/images/dragon_sm.gif)
![[IM Output]](../static/img/mapping/mirror_dismap_y.gif)
![[IM Output]](../static/img/mapping/mirror_displaced.gif)
![[IM Output]](../static/img/mapping/mirror_cracks.gif)
![[IM Output]](../static/img/mapping/mirror_cracked.gif)
![[IM Output]](../static/img/mapping/blur_map_bool.gif)
![[IM Output]](../static/img/mapping/blur_koala_bool.gif)
![[IM Output]](../static/img/mapping/blur_map_gradient.gif)
![[IM Output]](../static/img/mapping/blur_koala_gradient.gif)
![[IM Output]](../static/img/mapping/blur_edge_gradient.gif)
![[IM Output]](../static/img/mapping/elliptical_average.gif)
![[IM Output]](../static/img/mapping/black_circle.gif)
![[IM Output]](../static/img/mapping/blur_horizontal.gif)
![[IM Output]](../static/img/mapping/blur_map_r.gif)
![[IM Output]](../static/img/mapping/blur_map_g.gif)
![[IM Output]](../static/img/mapping/blur_map_aspect.gif)
![[IM Output]](../static/img/mapping/blur_aspect.gif)
![[IM Output]](../static/img/mapping/gradient_polar.jpg)
![[IM Output]](../static/img/mapping/blur_map_angle.jpg)
![[IM Output]](../static/img/mapping/blur_rotated.jpg)
![[IM Output]](../static/img/mapping/gradient_radial.jpg)
![[IM Output]](../static/img/mapping/blur_map_polar.jpg)
![[IM Output]](../static/img/mapping/blur_polar.jpg)