Exemples ImageMagick -- Transformations d'image
- Transformer les images en boutons en relief ou en creux
- Ajouter une bordure intérieure
- Dispersion aléatoire des pixels
- Transformation photo en vignette
- Transformation Polaroid complexe
- Peinture à l'huile, taches de couleur
- Fusain, croquis d'artiste d'une scène
- Transformation en croquis au crayon
- Emboss, créer une empreinte métallique
- Stegano, cacher un secret dans une image
- Chiffrer les données d'image
- Pixeliser les images
- Grilles de pixels
- Détecteur de contours Canny
- Contours à partir de formes anti-crénelées
- Contours à partir de formes bitmap
- Contours à l'aide d'un convertisseur matriciel vers vectoriel
- Détecteur de lignes de Hough
- Formes ombrées masquées
- Images de formes ombrées
- Arrondir les bords ombrés
- Créer des reflets en superposition
- Les expressions FX comme échappements de pourcentage
- Méthodes intégrées façon FX
-
Evaluate, opérations mathématiques simples
Set, Add, Subtract, Multiply, Divide * Fonctions mathématiques Evaluate
Pow, Log, Sin, Cos * Function, Evaluate à plusieurs arguments
- Multiplier des dégradés biaisés
- Additionner des dégradés biaisés
- Modulation de fréquence
Ces opérations produisent des changements majeurs dans l'apparence globale de l'image, que ce soit à des fins visuelles ou pour des effets façon art. Toutefois, bien que l'aspect général de l'image ait changé, souvent de manière spectaculaire, l'image d'origine elle-même reste généralement visible dans le résultat.
Transformations façon art
Bordures en relief ou en creux
L'opérateur « [-raise](https://imagemagick.org/command-line-options/#raise) » est une transformation d'image si simple qu'elle en est presque anodine. Tout ce qu'il fait, c'est ajouter un reflet en biseau rectangulaire à une image existante. |
magick rose: -raise 5 rose_raise.gif
![[IM Output]](../static/img/transform/rose_raise.gif)
Un effet inversé en creux peut être généré en utilisant la forme « plus » de l'opérateur… |
magick rose: +raise 5 rose_sunken.gif
![[IM Output]](../static/img/transform/rose_sunken.gif)
Cet opérateur ressemble un peu à l'encadrement d'une image, mais au lieu d'ajouter des pixels supplémentaires en guise de bordure, l'opérateur « [-raise](https://imagemagick.org/command-line-options/#raise) » recolorie les pixels du bord de l'image. C'est ce qui en fait une transformation d'image. | En réalité, l'encadrement d'image s'obtient en ajoutant une bordure, puis en la mettant en relief !
---|---
| L'opérateur ne fonctionne que sur les images rectangulaires et échouera pour les images à fond transparent, car les modifications de couleur seront elles aussi transparentes. Au fond, c'est un opérateur plutôt bête !
---|---
Ajouter une bordure intérieure
Au lieu de placer une bordure autour de l'extérieur de l'image, l'utilisateur voulait superposer une bordure directement sur les bords de l'image elle-même. Pour obtenir cet effet, la solution consistait à dessiner un rectangle qui s'aligne précisément avec les dimensions de l'image. Comme l'image intégrée « rose » mesure 70×46 pixels, la superposition obtenue correspond exactement à ces dimensions. |
magick rose: -fill none -stroke navy -strokewidth 11 \
-draw 'rectangle 0,0 69,45' inside_border.jpg
![[IM Output]](../static/img/transform/inside_border.jpg)
La largeur de la bordure ajoutée est contrôlée par le « [-strokewidth](https://imagemagick.org/command-line-options/#strokewidth) » du rectangle. C'est-à-dire
{stroke width} = {border width} * 2 - 1
Ainsi, la bordure de 6 pixels ci-dessus nécessitait un « [-strokewidth](https://imagemagick.org/command-line-options/#strokewidth) » de 11. Si vous ne connaissez pas la taille de l'image, vous pouvez raboter l'image puis ajouter la bordure normalement. C'est probablement plus simple, mais peut-être pas aussi polyvalent. |
magick rose: -bordercolor green -shave 6x6 -border 6x6 inside_border2.jpg
Dispersion aléatoire des pixels
L'opérateur « [-spread](https://imagemagick.org/command-line-options/#spread) » remplace chaque pixel par la couleur d'un pixel voisin choisi au hasard dans l'image source. Cette sélection aléatoire se fait selon l'interpolation de pixels et le réglage des pixels virtuels. Par exemple… |
magick -size 80x40 xc:red xc:blue -append -spread 5 spread_interpolated.png
![[IM Output]](../static/img/transform/spread_interpolated.png)
Si vous examiniez les pixels de l'image, vous verriez que certains pixels peuvent présenter un mélange de rouge et de bleu. Autrement dit, ils sont interpolés, et non simplement dispersés ou permutés. Cet effet est plus marqué avec de petites valeurs de distance. Notez également que « [-spread](https://imagemagick.org/command-line-options/#spread) » utilise lui aussi le réglage des pixels virtuels. |
magick -size 80x80 xc: -virtual-pixel black -spread 10 spread_virtual.png
![[IM Output]](../static/img/transform/spread_virtual.png)
Comme vous pouvez le voir, vous obtenez une bordure aléatoire, faite principalement de pixels virtuels d'un noir pur. Il y a cependant quelques pixels gris interpolés à partir de la frontière entre les pixels réels de l'image et les pixels virtuels. Pour obtenir un effet de dispersion de pixels plus classique, vous pouvez empêcher ce mélange de couleurs en forçant la recherche de couleur de pixels précis à l'aide de « [-interpolate](https://imagemagick.org/command-line-options/#interpolate) [Nearest](misc.html#nearest) ». Pour éviter les problèmes liés aux pixels virtuels et l'éventuel « biais de couleur de bord », je vous recommande d'utiliser « [-virtual-pixel](https://imagemagick.org/command-line-options/#virtual-pixel) [Mirror](misc.html#mirror) ». On obtient ainsi une « dispersion » aléatoire de pixels plus classique… |
magick rose: -interpolate nearest -virtual-pixel mirror \
-spread 5 spread_rose.png
En construction
Le principal problème de ce qui précède est que vous pouvez perdre certaines données de pixels de l'image. En effet, les pixels ne sont pas « permutés » mais copiés au hasard, ce qui signifie qu'un pixel précis de l'image peut être dupliqué ou perdu. Depuis IM v6.9.2-2, vous pouvez utiliser « [+spread](https://imagemagick.org/command-line-options/#spread) » pour réellement permuter les pixels dans l'image, de sorte qu'aucun pixel de l'image ne soit dupliqué ni perdu. Chaque pixel de l'image d'origine est toujours présent, simplement déplacé vers un nouvel emplacement. Toutefois, en raison de la manière dont les pixels sont traités, certains pixels peuvent être « doublement permutés ». Autrement dit, un pixel donné peut être permuté, puis sélectionné pour être permuté à nouveau avec un pixel ultérieur. Cela signifie qu'un pixel précis pourrait dériver plus loin que ne le demandait l'argument de dispersion. Cette double permutation implique aussi que les pixels avaient tendance à se disperser davantage vers le coin inférieur droit. Ce mouvement est bien sûr compensé par une dérive plus faible d'un grand nombre de pixels vers le coin supérieur gauche. Par exemple, je disperse ici les pixels en préfixant l'original comme référence. |
magick -size 40x40 xc:red xc:blue -append \
\( +clone +spread 5 \) +append spread_bias.png
![[IM Output]](../static/img/transform/spread_bias.png)
Remarquez comment certains pixels rouges se dispersent davantage vers le bas, mais vous obtenez aussi quelques pixels bleus qui se dispersent vers le haut plus que prévu ( bien que vers le côté gauche de l'image). Ce problème est plus marqué lorsque vous utilisez un argument de distance plus petit pour la dispersion. La solution à ce problème de double permutation n'est pas facile, et nous recherchons un algorithme de « brassage à zone limitée » pour le résoudre. Mais en attendant, vous pouvez au moins atténuer le biais directionnel en effectuant la dispersion deux fois, avec une distorsion Transverse (miroir diagonal du coin supérieur gauche au coin inférieur droit). |
magick -size 40x40 xc:red xc:blue -append \
\( +clone +spread 5 -transverse -spread 5 -transverse \) \
+append spread_no_bias.png
![[IM Output]](../static/img/transform/spread_no_bias.png)
Bien sûr, cela rend la dispersion plus marquée et moins linéaire, mais au moins elle est sans biais directionnel ni duplication/perte de pixels. L'ajout ci-dessus a été développé à partir d'une discussion de forum : t=28043 IM Forum Discussion rearrange vertical pixel row .
Transformation photo en vignette
Un opérateur spécial pour rendre une image circulaire avec un contour doux et flou. |
magick rose: -background black -vignette 0x5 rose_vignette.gif
![[IM Output]](../static/img/transform/rose_vignette.gif)
En utilisant un sigma nul (ou très petit), vous pouvez supprimer le flou et générer des cadres elliptiques ou ovales. Notez toutefois qu'il n'utilise pas réellement la plus grande ellipse possible, vous voudrez donc peut-être le faire vous-même. |
magick rose: -background black -vignette 0x0 rose_vignette_0.gif
![[IM Output]](../static/img/transform/rose_vignette_0.gif)
Vous pouvez l'utiliser avec la transparence (et le format PNG)… |
magick rose: -alpha Set -background none -vignette 0x3 rose_vignette.png
![[IM Output]](../static/img/transform/rose_vignette.png)
Une autre méthode de spécification des arguments consiste à utiliser un très grand nombre pour la seconde composante sigma, puis à utiliser le premier radius pour définir l'étalement du flou. Cela produit une distribution « linéaire » plutôt qu'une distribution gaussienne, plus courante, pour le flou de la vignette. |
magick rose: -background black -vignette 5x65000 rose_vignette_linear.gif
![[IM Output]](../static/img/transform/rose_vignette.gif)
Une autre technique pour une vignette plus rectangulaire, produisant des bords doux sur l'image, est présentée dans Vignettes à bords doux.
Transformation Polaroid complexe
Grâce au travail réalisé par Timothy Hunter (célèbre pour RMagick), un opérateur de transformation « [-polaroid](https://imagemagick.org/command-line-options/#polaroid) » a été ajouté à IM v6.3.2.
Polaroid® est une marque déposée de la Polaroid Corporation.
Par exemple, je donne ici un aspect polaroid à une vignette de photo. L'image regarde vers le haut dans l'escalier en colimaçon (vers le bas), à l'intérieur de l'Arc de Triomphe, Paris. C'est un escalier très long ! |
magick spiral_stairs_sm.jpg -thumbnail 120x120 \
-bordercolor white -background black +polaroid poloroid.png
![[IM Output]](../static/img/transform/poloroid.png)
| Notez que l'image obtenue comporte une ombre semi-transparente, vous devez donc soit utiliser une image au format PNG, soit « [-flatten](https://imagemagick.org/command-line-options/#flatten) » le résultat sur une couleur de fond fixe pour les formats GIF ou JPG.
---|---
Cet opérateur est très complexe, car il ajoute une bordure (selon le réglage « [-bordercolor](https://imagemagick.org/command-line-options/#bordercolor) »), « enroule » le papier et ajoute un enroulement inverse à l'ombre. La couleur de l'ombre peut être contrôlée par le réglage de couleur « [-background](https://imagemagick.org/command-line-options/#background) ». Comme vous l'avez vu plus haut, la forme plus de l'opérateur fait pivoter le résultat d'une quantité aléatoire. Cet opérateur rend un index de photos bien plus intéressant et moins statique que ce que l'on obtiendrait autrement. La forme moins de l'opérateur vous permet de contrôler l'angle de rotation de l'image. |
magick spiral_stairs_sm.jpg -thumbnail 120x120 \
-bordercolor AliceBlue -background SteelBlue4 -polaroid 5 \
poloroid_5.png
![[IM Output]](../static/img/transform/poloroid_5.png)
Si l'image possède des métadonnées « [-caption](https://imagemagick.org/command-line-options/#caption) », ce texte sera également ajouté dans la bordure inférieure du cadre polaroid, via l'opérateur de création d'image « [caption:](text.html#caption) ». Autrement dit, il sera renvoyé à la ligne mot par mot selon la largeur de la photo. |
magick -caption '%c %f\n%wx%h' spiral_stairs_sm.jpg -thumbnail 120x120 \
-bordercolor Lavender -background gray40 +polaroid \
poloroid_captioned.png
![[IM Output]](../static/img/transform/poloroid_captioned.png)
Les autres réglages de texte standard (selon « [caption:](text.html#caption) ») vous permettent de contrôler l'aspect de la légende ajoutée. |
magick spiral_stairs_sm.jpg -thumbnail 120x120 -font Candice -pointsize 18 \
-bordercolor Snow -background black -fill dodgerblue -stroke navy \
-gravity center -set caption "Spiral Stairs\!" -polaroid 10 \
poloroid_controls.png
![[IM Output]](../static/img/transform/poloroid_controls.png)
| _L'attribut de métadonnées d'image « [-caption](https://imagemagick.org/command-line-options/#caption) » a été utilisé en raison de l'usage interne du générateur de texte en image « [caption:](text.html#caption) ».
En revanche, la commande IM « [montage](montage.html#montage) » utilise « [-label](https://imagemagick.org/command-line-options/#label) », car elle emploie le générateur de texte en image « [label:](text.html#label) » qui ne renvoie pas les mots à la ligne._
---|---
L'usage par cette transformation des distorsions de cisaillement Rotate et Wave pour ajouter un léger « enroulement » à la photo a tendance à produire des lignes horizontales de flou dans le texte de l'image générée. C'est un problème bien connu de distorsion d'image (voir Rotation d'une ligne fine), qui peut être résolu à l'aide d'une technique de suréchantillonnage. En gros, nous générons le polaroid deux fois plus grand que ce que nous voulons réellement, puis nous redimensionnons simplement l'image à sa taille normale finale. La réduction de la taille de l'image affine efficacement l'image obtenue et, plus important encore, le texte de la légende. Cependant, pour que cela fonctionne, il nous faut non seulement une image au moins deux fois plus grande que la taille finale, mais nous pouvons aussi avoir besoin d'ajouter une bordure plus grande à l'image et de dessiner le texte au double de sa « [-density](https://imagemagick.org/command-line-options/#density) » normale. N'augmentez pas la « [-pointsize](https://imagemagick.org/command-line-options/#pointsize) » de la police, car cela n'agrandit pas le texte tout à fait de la même manière. |
magick -caption 'Spiral Staircase, Arc de Triumph, Paris, April 2006' \
spiral_stairs_sm.jpg -thumbnail 240x240 \
-bordercolor Lavender -border 5x5 -density 144 \
-gravity center -pointsize 8 -background black \
-polaroid -15 -resize 50% poloroid_modified.png
![[IM Output]](../static/img/transform/poloroid_modified.png)
Comme vous pouvez le voir, même si nous avons utilisé une police de bien plus petite taille, le texte de la légende est très net, clair et lisible. Il en va de même pour tout autre détail fin qui aurait pu être présent dans l'image d'origine. Le seul inconvénient est que l'ombre de l'image obtenue sera plus petite et moins floue. Pour un contrôle total de la transformation polaroid, vous pouvez effectuer vous-même toutes les étapes impliquées. La technique originale est documentée sur la page de Tim Hunter, RMagick Polaroid Effect. Les étapes sont : créer et ajouter la légende, ajouter les bordures, enrouler la photo avec wave, ajouter une ombre à enroulement inversé et, enfin, faire pivoter l'image. Pour plus d'exemples et d'autres méthodes maison, voir Exemples de vignettes polaroid et Un montage de photos polaroid. Certains exemples polaroid de RubbleWeb IM Examples, Other pourraient également vous intéresser.
Peinture à l'huile, taches de couleur
L'opérateur « [-paint](https://imagemagick.org/command-line-options/#paint) » est conçu pour transformer les images en peintures réalisées en appliquant d'épaisses « taches » de peinture sur une toile. Le résultat est une fusion des couleurs voisines en des zones de couleur unique plus grandes.
magick rose: -paint 1 rose_paint_1.gif
magick rose: -paint 3 rose_paint_3.gif
magick rose: -paint 5 rose_paint_5.gif
magick rose: -paint 10 rose_paint_10.gif
magick rose: -blur 0x3 -paint 10 rose_blur_paint_10.gif
Notez qu'à grand rayon des taches de peinture, celles-ci commencent à prendre un aspect carré. Cet effet peut être quelque peu adouci en floutant légèrement l'image au préalable, comme le montre la dernière image ci-dessus. C'est un effet intéressant qui pourrait servir à créer des images de fond étranges et merveilleuses. Voir par exemple son utilisation dans Exemples d'arrière-plans. Un dernier avertissement. Bien que « [-paint](https://imagemagick.org/command-line-options/#paint) » soit censé produire des zones d'une seule couleur unie, à de grandes valeurs de rayon, il a tendance à produire un dégradé vertical dans certaines zones. C'est très agaçant et il s'agit peut-être d'un bug. Quelqu'un le sait-il ? Il existe des alternatives à l'usage de « [-paint](https://imagemagick.org/command-line-options/#paint) ». L'une consiste à utiliser « -statistic Mode » à la place, qui attribue à chaque pixel la « couleur prédominante » dans le voisinage rectangulaire donné, et peut produire un plus beau résultat. |
magick rose: -statistic Mode 10 rose_paint_mode.gif
![[IM Output]](../static/img/transform/rose_paint_mode.gif)
Une autre consiste à utiliser certaines des méthodes de morphologie, et plus précisément la variante Intensity pour les images en couleur. Voici par exemple une morphologie « OpenIntensity » sur la rose. |
magick rose: -morphology OpenI Disk rose_paint_open.gif
![[IM Output]](../static/img/transform/rose_paint_open.gif)
Et ici, j'utilise « CloseIntensity » avec un « Disk » légèrement plus petit. |
magick rose: -morphology CloseI Disk:2.5 rose_paint_close.gif
![[IM Output]](../static/img/transform/rose_paint_close.gif)
Vous n'êtes pas obligé d'utiliser des « disks » ; vous pouvez concevoir votre propre noyau en forme de « pinceau » pour les taches qu'il crée. Par exemple, que diriez-vous d'utiliser un pinceau en ligne diagonale.
Fusain, croquis d'artiste d'une scène
L'effet fusain vise à simuler un croquis au fusain de l'image donnée par un artiste. L'opérateur « [-charcoal](https://imagemagick.org/command-line-options/#charcoal) » ressemble à certains égards aux transformations de détection de contours utilisées par la vision par ordinateur. En gros, il tente de transformer les principales frontières et arêtes des objets de l'image en nuances de crayon et de fusain. L'unique argument est censé représenter l'épaisseur des lignes de contour.
magick rose: -charcoal 1 rose_charcoal_1.gif
magick rose: -charcoal 3 rose_charcoal_3.gif
magick rose: -charcoal 5 rose_charcoal_5.gif
| Pour un meilleur exemple d'utilisation d'une transformation fusain sur une image réelle, voir Croquis au fusain d'une photo. | Techniquement, l'opérateur « [-charcoal](https://imagemagick.org/command-line-options/#charcoal) » est un opérateur « [-edge](https://imagemagick.org/command-line-options/#edge) » avec un certain seuillage appliqué à une conversion en niveaux de gris de l'image d'origine. |
|---|---|
Transformation en croquis au crayon
L'opérateur « [-sketch](https://imagemagick.org/command-line-options/#sketch) » applique essentiellement un motif de traits de ligne à une image pour générer quelque chose qui ressemble à un croquis au crayon artistique. Les arguments contrôlent la longueur et l'angle des traits. Toutefois, il s'applique au mieux à une image plus grande présentant des contrastes et des ombrages distincts. Voir Croquis au crayon pour un exemple complet de cet opérateur et de son fonctionnement interne.
Emboss, créer une empreinte métallique
L'opérateur « [-emboss](https://imagemagick.org/command-line-options/#emboss) » tente de générer l'effet d'une empreinte à l'acide d'une image en niveaux de gris sur une feuille de métal. Il ressemble à bien des égards à l'opérateur « [-shade](https://imagemagick.org/command-line-options/#shade) » que nous examinerons plus bas, mais sans les bords à l'aspect 3D. Son argument est un radius/sigma, seul le sigma étant important. Je n'ai pas trouvé cet argument très utile, et il est peut-être en fait bogué. L'argument a aussi changé dans une version récente d'IM. Je ne sais tout simplement pas ce qui se passe. Aidez-moi à comprendre si vous le pouvez.
magick rose: -emboss 0x.5 rose_emboss_0x05.gif
magick rose: -emboss 0x.9 rose_emboss_0x09.gif
magick rose: -emboss 0x1 rose_emboss_0x10.gif
magick rose: -emboss 0x1.1 rose_emboss_0x11.gif
magick rose: -emboss 0x1.2 rose_emboss_0x12.gif
magick rose: -emboss 0x2 rose_emboss_0x20.gif
L'opérateur est un opérateur en niveaux de gris, ce qui signifie qu'il sera appliqué séparément aux trois canaux de couleur. Il ne devrait donc être appliqué qu'à des images en niveaux de gris. Comme vous l'avez vu plus haut, les images en couleur peuvent produire des effets étranges.
magick rose: -colorspace Gray -emboss 0x.5 rose_g_emboss_0x05.gif
magick rose: -colorspace Gray -emboss 0x.9 rose_g_emboss_0x09.gif
magick rose: -colorspace Gray -emboss 0x1 rose_g_emboss_0x10.gif
magick rose: -colorspace Gray -emboss 0x1.1 rose_g_emboss_0x11.gif
magick rose: -colorspace Gray -emboss 0x1.2 rose_g_emboss_0x12.gif
magick rose: -colorspace Gray -emboss 0x2 rose_g_emboss_0x20.gif
Si quelqu'un sait exactement ce que l'algorithme emboss est censé faire,
merci de me le faire savoir.
Stegano, cacher une image secrète dans une image
L'opérateur « [-stegano](https://imagemagick.org/command-line-options/#stegano) » est vraiment plutôt un opérateur « pour s'amuser ». Par exemple, un espion pourrait l'utiliser pour cacher des informations dans le « chaos » d'une image aléatoire. D'abord un avertissement…
N'utilisez pas JPEG, GIF ni aucun autre encodage d'image « avec perte » avec Stegano
Par exemple, générons un message cryptique (image) que vous voulez envoyer à votre collègue espion… | |
magick -gravity center -size 50x40 label:"Watch\nthe\nPidgeon" message.gif
magick identify message.gif
Notez que nous aurons aussi besoin de la taille de l'image du message (36x43 pixels), d'où le identify ci-dessus. Ensuite, on la place dans une image quelconque avec un certain décalage. Le décalage (et la taille du message) utilisé constitue la « clé » cryptographique du message caché. |
magick composite message.gif rose: -stegano +15+2 rose_message.png
![[IM Output]](../static/img/transform/rose_message.png)
Vous pouvez maintenant envoyer cette image à votre compère, qui connaît vraisemblablement déjà la taille et le décalage du message. Nous pouvons alors récupérer le message caché dans l'image… |
magick -size 50x40+15+2 stegano:rose_message.png message_recovered.gif
![[IM Output]](../static/img/transform/message_recovered.gif)
Plus l'image contenante est grande, meilleure sera l'image récupérée ; cacher de petites images dans de plus grandes vaut donc mieux que l'exemple montré ci-dessus. Juste pour vous montrer comment le message caché a été réparti dans toute l'image conteneur, faisons une comparaison de l'image combinée avec l'original. | |
magick compare -metric PAE rose: rose_message.png rose_difference.png
Ce qui montre comment l'image du message a été chiffrée et répartie sur toute l'image conteneur pour la cacher. De plus, la métrique « PAE » renvoyée ci-dessus montre que la plus grande différence n'était que d'une seule valeur de couleur sur les valeurs de couleur 8 bits utilisées pour cette image. Autrement dit, minuscule. Si minuscule qu'un petit changement ou une modification de l'image détruira le message caché à l'intérieur. La différence est si petite que vous ne pouvez même pas utiliser JPEG avec sa compression avec perte comme format d'image, ni aucun autre format d'image avec perte (y compris GIF) pour l'image conteneur. De plus, si vous aviez la mauvaise « clé de décalage », vous n'obtiendrez pas le message… |
magick -size 50x40+14+2 stegano:rose_message.png message_bad.gif
![[IM Output]](../static/img/transform/message_bad.gif)
Vous pouvez aussi limiter la zone de l'image où le message doit être caché en utilisant un réglage Region. Le même réglage sera également nécessaire lorsque vous tenterez de récupérer le message. Cela rendrait probablement la recherche et le décodage du message caché dans une grande image, surtout s'il est restreint à une zone « chargée », d'un ordre de grandeur plus difficile à déterminer. Sachez cependant que ce n'est pas une technique très sûre sur le plan cryptographique. Surtout si l'image source d'origine est également disponible. L'analyse fréquentielle de l'image permettra généralement à un attaquant de savoir qu'il y a un message caché. Comme méthode de protection du droit d'auteur des images, l'opérateur Stegano est également inutile, car le plus petit changement apporté à l'image détruira le message, et donc son efficacité. Comme outil d'espionnage, il n'est pas très bon non plus, avec un nombre aussi réduit de « combinaisons » pour une image de taille raisonnable. Quiconque sait à peu près ce que vous faites pourrait probablement le casser rapidement. Mieux vaut s'en tenir à des méthodes cryptographiques bien connues et éprouvées par le temps. Son seul véritable usage pratique est comme outil amusant, ou comme moyen d'ajouter de très petites quantités de bruit à une image existante.
Chiffrement des données d'image
Les opérateurs « [-encipher](https://imagemagick.org/command-line-options/#encipher) » et « [-decipher](https://imagemagick.org/command-line-options/#decipher) » vont fondamentalement chiffrer les données d'image en un fouillis brouillé. Autrement dit, le contenu de l'image lui-même n'est plus du tout reconnaissable jusqu'à ce que l'image soit déchiffrée ultérieurement. Cela peut servir par exemple à protéger des images sensibles sur des services publics, de sorte que seules les personnes disposant de la phrase secrète puissent la visualiser plus tard. Mais d'abord un avertissement…
N'utilisez pas JPEG, GIF, ou tout autre encodage d'image « avec perte » avec le chiffrement
Par exemple, chiffrons cette image de message secret que nous avons créée plus haut, en utilisant une phrase secrète que j'ai enregistrée dans un fichier pas tout à fait si « secret », « pass_phrase.txt ».
magick message.gif -encipher pass_phrase.txt \
-depth 8 png24:message_hidden.png
| _L'image chiffrée suppose qu'elle est enregistrée dans un format de fichier image 8 bits. Il est donc recommandé d'imposer cette limitation en réglant « [-depth](https://imagemagick.org/command-line-options/#depth) 8 » avant l'enregistrement final dans le fichier de sortie.
Le « png24 » était également nécessaire ci-dessus pour garantir que la sortie ne soit pas une image « png8: » à palette ou à table de couleurs, ce qui ne fonctionne pas correctement non plus._
---|---
Comme vous pouvez le voir, l'image résultante ressemble à un fouillis complet, sans aucune indication du contenu réel de l'image. Vous pouvez maintenant publier cette image sur le web, et seule une personne connaissant la phrase secrète d'origine exacte peut restaurer les données de l'image… |
magick message_hidden.png -decipher pass_phrase.txt message_restored.gif
![[IM Output]](../static/img/transform/message_restored.gif)
Sachez cependant que si les données de l'image sont corrompues d'une manière ou d'une autre, vous ne pourrez pas la restaurer. Cela inclut le cas où le PNG a été enregistré dans un format d'image en niveaux de gris. Ainsi, seul un format d'image sans perte peut être utilisé, tel que PNG, MIFF, TIFF, ou même le texte d'énumération de pixels. En revanche, utiliser un format d'image avec perte, tel que JPEG, PNG8 et GIF, corrompra les données de l'image, détruisant ainsi le chiffrement résultant. Notez que toute méta-donnée susceptible de décrire l'image restera en clair. Cela signifie que vous pourriez chiffrer des images en utilisant la propre chaîne « comment » de l'image comme phrase secrète, ou utiliser ce commentaire chiffré à l'aide d'un mot de passe plus court. C'est une idée simple qui pourrait rendre la phrase secrète plus variable. Chiffrer une image peut n'être qu'une étape. Aller un tout petit peu plus loin avec le résultat peut produire une image qui ne se déchiffrera pas simplement, sans un traitement supplémentaire. Par exemple, ici j'utilise quelques distorsions simples et non destructives pour tromper quiconque tenterait de déchiffrer l'image de la manière habituelle.
echo "password" | magick message.gif -encipher - \
-transpose -depth 8 png24:message_obfuscate.png
echo "password" | magick message_obfuscate.png -transpose \
-decipher - message_restored_2.png
Si vous n'aviez pas inclus le « [-transpose](https://imagemagick.org/command-line-options/#transpose) » dans la commande de déchiffrement ci-dessus, l'image n'aurait pas été déchiffrée correctement. Notez aussi qu'en raison du chiffrement par flux utilisé (voir la note d'expert ci-dessous), utiliser juste un « [-roll](https://imagemagick.org/command-line-options/#roll) » quelconque n'empêchera pas l'image d'être déchiffrée, au moins partiellement. Notez que dans ce qui précède, je n'ai pas utilisé de fichier pour contenir la « phrase secrète » mais j'ai fourni la phrase à la commande « magick » via l'entrée standard, ce qui vous permet d'utiliser un autre programme ou une autre commande pour obtenir la phrase de l'utilisateur, la générer, ou toute autre méthode, au lieu d'utiliser un fichier texte contenant la phrase secrète en clair. La phrase secrète pourrait aussi être générée à partir d'autres fichiers et images librement téléchargeables. Par exemple, vous pourriez déchiffrer votre image en utilisant la signature, ou la chaîne de commentaire d'une image de référence bien connue et librement téléchargeable. Par exemple, ici j'utilise la signature de l'image « rose.gif » pour chiffrer puis déchiffrer l'image « message.gif ».
magick identify -format %# rose.gif |\
magick message.gif -encipher - -depth 8 png24:message_signed.png
magick identify -format %# rose.gif |\
magick message_signed.png -decipher - message_restored_3.png
Depuis IM v6.4.8-0, le fichier utilisé par « [-encipher](https://imagemagick.org/command-line-options/#encipher) » et « [-decipher](https://imagemagick.org/command-line-options/#decipher) » peut être un fichier binaire. Vous pourriez donc même utiliser directement une image elle-même comme phrase secrète.
magick message.gif -encipher rose.gif -depth 8 png24:message_binary.png
magick message_binary.png -decipher rose.gif message_restored_4.png
| Avant IM v6.4.8-0, un fichier binaire s'arrêtait au premier caractère « NULL » rencontré. Ce qui se produirait assez tôt si une image PNG était utilisée.
---|---
Cette technique est exacte (à moins qu'une partie des données n'ait été détruite lors de la transmission). Vous pouvez donc l'utiliser pour chiffrer une image contenant d'autres informations cachées telles qu'une image Stegano. Cela signifie que même si les autorités déchiffrent l'image, ou vous forcent à révéler le mot de passe, elles verront une image réelle, mais cette image peut ne pas être l'image finale cachée. | Les opérateurs « [-encipher](https://imagemagick.org/command-line-options/#encipher) » et « [-decipher](https://imagemagick.org/command-line-options/#decipher) » ont été ajoutés à IM v6.3.8-6, mais nécessitaient d'inclure une option « --enable-cipher » dans la configuration de compilation. Cependant, dès IM v6.4.6 (quand cela a-t-il changé ?), cet élément de configuration n'était plus nécessaire et est devenu un réglage de configuration standard. Vous pouvez donc probablement l'utiliser immédiatement.
---|---
| _Le chiffrement a été implémenté à l'aide d'un chiffrement par flux auto-synchronisant implémenté à partir d'un chiffrement par blocs.
Cela signifie que vous pouvez toujours déchiffrer même un téléchargement partiel de l'image, qui a été détruit par une erreur de transmission, même si une partie de l'image a pu être détruite. Vous n'avez pas non plus besoin de télécharger l'image entière pour déchiffrer et examiner les parties qui ont été téléchargées avec succès.
Mais vous avez besoin de la phrase secrète pour avoir la moindre chance de déchiffrer l'image avec succès, car il s'agit d'un chiffrement très très fort.
Pixelliser une image
Pixelliser une image sert essentiellement à transformer une image en un ensemble de gros « pixels » colorés qui ne montrent qu'un vague contour de l'image d'origine. Les deux techniques impliquent de réduire l'image (pour générer moins de pixels), puis de l'agrandir de manière à créer des « blocs de pixels » en utilisant soit un opérateur de mise à l'échelle soit un opérateur d'échantillonnage pour générer le bloc de couleur. C'est simplement la manière dont l'image est réduite qui détermine exactement quelle couleur sera utilisée. Un échantillon d'un seul pixel, ou une couleur moyenne fusionnée.
magick rose: -sample 25% -scale 70x46\! rose_pixelate_sampled.gif
magick rose: -scale 25% -scale 70x46\! rose_pixelate_scaled.gif
magick rose: -resize 25% -scale 70x46\! rose_pixelate_resized.gif
Comme vous pouvez le voir, les zones « échantillonnées » auront des « pixels » beaucoup plus distincts (crénelés), tandis que les deux autres utilisent une couleur fusionnée ou moyennée, ce qui tend à produire une représentation de couleur plus atténuée, mais plus fidèle, pour chaque « pixel ». Voir aussi Protéger l'anonymat de quelqu'un pour un exemple d'utilisation de ceci sur une petite zone masquée seulement de l'image, telle que le visage d'une personne.
Grilles de pixels
Quadriller une image est très similaire à pixelliser une image. Dans ce cas, nous voulons seulement agrandir l'image, afin de générer une vue distincte des détails de l'image au niveau du pixel. Typiquement une très petite image. La façon la plus simple est comme dans l'exemple précédent : simplement mettre à l'échelle une petite image, pour agrandir les pixels.
magick rose: -crop 10x10+12+20 +resize grid_input.png
magick grid_input.png -scale 1000% grid_scale.png
Le problème d'une simple mise à l'échelle est que, dans les zones où les pixels sont de couleur similaire, vous pouvez avoir du mal à voir les « blocs de pixels » individuels. Ce qu'il faut, c'est ajouter une bordure autour des pixels, pour les séparer. Pour cela, nous devons superposer un masque de tuile généré. Voir Tuilage avec une image déjà en mémoire pour diverses méthodes d'utilisation d'une image de tuilage générée, en une seule commande. Ici nous générons une « grille » blanche sur noir qui est superposée à l'aide de la composition Screen (superpose le blanc, tout en laissant les zones noires telles quelles). |
magick -size 10x10 xc: -draw 'rectangle 1,1 9,9' -write mpr:block +delete \
grid_input.png -scale 1000% -size 101x101 tile:mpr:block \
+swap -compose screen -composite grid_blocks.png
![[IM Output]](../static/img/transform/grid_blocks.png)
Notez que la taille utilisée pour générer la tuile est _scale_ *_image_size_ +_gap_size_ (dans ce cas 10*10+1 => 101). J'ai aussi échangé les deux images de sorte que la taille de l'image finale provienne de l'image de tuile, plutôt que de l'image mise à l'échelle qui est d'un pixel plus petite. Cependant, cela peut faire perdre toute méta-donnée d'image qui se trouvait dans l'image d'origine, car j'ai utilisé l'image tuilée comme destination. Ici je génère des « points » de couleur circulaires, mais cette fois j'ai utilisé une composition Multiply (superpose le noir, tout en laissant les zones blanches telles quelles). |
magick -size 10x10 xc: -draw 'circle 5,5 1,3' -negate \
-write mpr:spot +delete \
grid_input.png -scale 1000% -size 101x101 tile:mpr:spot \
+swap -compose multiply -composite grid_spots.png
![[IM Output]](../static/img/transform/grid_spots.png)
Vous pouvez rendre la bordure de la grille transparente en négativant aussi la superposition tuilée (les zones noires deviennent transparentes) et en utilisant une composition CopyOpacity au lieu de Multiply. D'autres couleurs peuvent aussi être ajoutées, mais pour que cela fonctionne vous devez utiliser une image de tuile qui contient réellement une véritable transparence. Pour cela vous devez convertir l'image de tuile en noir et blanc en un masque de forme. Par exemple, ici j'utilise l'opérateur de morphologie de base pour générer des « trous » en forme de losange dans une superposition colorée. Pour cela, un seul pixel « germe » est dessiné et étendu à l'aide d'un noyau de morphologie Diamond. |
magick -size 10x10 xc: -draw 'point 5,5' -morphology Erode:4 Diamond \
-background Navy -alpha shape -write mpr:diamond +delete \
grid_input.png -scale 1000% -splice 1x1+0+0 \
-size 101x101 -background none tile:mpr:diamond \
-alpha set -compose Over -composite grid_diamonds.png
![[IM Output]](../static/img/transform/grid_diamonds.png)
| Notez que le codeur « tile: » remplacera toute transparence dans l'image par la couleur d'arrière-plan actuelle. Si vous voulez préserver la transparence de l'image de tuilage, réglez soit « -background none » soit « -compose Src ». La première option est plus simple.
---|---
Notez que, techniquement, la mise en forme alpha peut se faire soit avant d'enregistrer l'image de tuile, soit après avoir tuilé l'image de tuile, avant de la superposer. Le choix vous appartient. Une dernière technique consiste à utiliser un mauvais filtre de rééchantillonnage pour produire un échec de rééchantillonnage afin de générer des cercles crénelés de chaque pixel. Ce n'est pas une bonne technique (détourner un échec de traitement d'image), mais elle forme bien une grille de pixels.
Espacer les tuiles
Un problème similaire consiste à espacer une grille de tuiles dans une image. Il ne s'agit pas simplement de mettre à l'échelle des pixels individuels en « blocs de pixels » mais d'insérer de l'espace entre des zones rectangulaires d'une image. C'est-à-dire, insérer des pixels supplémentaires dans une image à intervalles réguliers. Actuellement, la meilleure solution consiste à découper l'image en lignes et colonnes et à insérer l'espacement supplémentaire sur chaque tuile avant de rassembler les tuiles. Par exemple…
magick rose: -background SkyBlue \
-crop 10x0 +repage -splice 3x0 +append \
-crop 0x10 +repage -splice 0x3 -append \
grid_tile.png
Voici une autre méthode qui sépare également l'image d'origine en tuiles, mais qui utilise ensuite quelques expressions FX maison pour calculer la nouvelle position d'une tuile à partir de son ancienne position. |
magick rose: -crop 10x10 \
-set page '+%[fx:page.x+3*page.x/10]+%[fx:page.y+3*page.y/10]' \
-background skyblue -layers merge +repage grid_tile_fx.png
![[IM Output]](../static/img/transform/grid_tile_fx.png)
Le nombre « 3 » ci-dessus est la largeur de l'espace à ajouter, et « 10 » est la taille de la tuile. Il ne vous reste plus qu'à ajouter une bordure ou un autre bord au résultat. Avec un peu plus de travail, vous pouvez même ajouter un « tremblement » aléatoire au placement de chaque tuile dans la grille ci-dessus, pour un effet moins régulier. Le problème de ces deux méthodes est que générer de nombreuses petites images, uniquement pour les réunir à nouveau, engendre beaucoup de travail. Surtout pour de très petites tailles de tuiles. Une meilleure méthode qui a été proposée est une extension spéciale de l'opérateur Splice, dans la discussion du forum IM Splice (adding tile gridding gaps).
Transformations de vision par ordinateur
Détection de contours
L'opérateur « [-edge](https://imagemagick.org/command-line-options/#edge) » met en évidence les zones de dégradés de couleur au sein d'une image. C'est un opérateur en niveaux de gris, il est donc appliqué séparément à chacun des trois canaux de couleur.
magick mask.gif -edge 1 mask_edge_1.gif
magick mask.gif -edge 2 mask_edge_2.gif
magick mask.gif -edge 3 mask_edge_3.gif
magick mask.gif -edge 10 mask_edge_10.gif
Comme vous pouvez le voir, le contour n'est ajouté qu'aux zones ayant un dégradé de couleur qui est à plus de 50 % blanc ! Je ne sais pas si c'est un bogue ou intentionnel, mais cela signifie que le contour ci-dessus est situé presque entièrement dans les parties blanches de l'image mask d'origine. Ce fait peut être extrêmement important lors de l'exploitation des résultats de l'opérateur « [-edge](https://imagemagick.org/command-line-options/#edge) ». Par exemple, si vous effectuez une détection de contours sur une image qui contient un contour noir, l'opérateur « [-edge](https://imagemagick.org/command-line-options/#edge) » va « dédoubler » les lignes noires, produisant un résultat étrange.
magick piglet.gif -colorspace Gray -edge 1 -negate piglet_edge.gif
Cependant, en négativant l'image avant de faire la détection de contours, les lignes dédoublées vont vers l'intérieur et se rejoignent, supprimant l'effet de « ligne double ». |
magick piglet.gif -colorspace Gray \
-negate -edge 1 -negate piglet_edge_neg.gif
![[IM Output]](../static/img/transform/piglet_edge_neg.gif)
J'ai constaté que les contours ont tendance à être trop nets, générant un contour non lisse dans les images résultantes. C'est pourquoi je trouve qu'un très très léger flou appliqué au résultat en améliore assez nettement l'apparence. |
magick piglet_edge_neg.gif -blur 0x.5 piglet_edge_blur.gif
![[IM Output]](../static/img/transform/piglet_edge_blur.gif)
Ici j'ai appliqué la détection de contours à une image en couleur, et à une version en niveaux de gris, pour vous montrer ses effets sur des images de type photo.
magick rose: -edge 1 rose_edge.gif
magick rose: -colorspace Gray -edge 1 rose_edge_grey.gif
Comme vous pouvez le voir, sans convertir l'image en niveaux de gris, les contours des différents canaux de couleur sont générés de manière complètement indépendante les uns des autres.
Détecteur de contours de Canny
Depuis IM v6.8.9-0, IM prend désormais en charge le détecteur de contours de Canny. (Voir les exemples de l'annonce sur le forum IM). C'est un algorithme de détection de contours très avancé, qui produit des lignes très fortes (binaires) d'un seul pixel de large sur tous les bords nets, avec très peu d'interférence de bruit. Par exemple, ici nous l'appliquons aux images de test que nous avons utilisées plus haut…
magick mask.gif -canny 0x1+10%+30% mask_canny.gif
magick piglet.gif -canny 0x1+10%+30% piglet_canny.gif
magick piglet.gif -negate -canny 0x1+10%+30% piglet_canny_neg.gif
magick rose: -canny 0x1+10%+30% rose_canny.gif
Comme vous pouvez le voir, il produit un résultat bien plus net que l'opérateur Edge ci-dessus. Le bord flou anti-crénelé a peu ou pas d'effet sur le résultat, produisant de fines lignes bitmap. De plus, comme le montre l'image piglet, il n'est pas placé d'un côté spécifique comme le faisait l'opérateur de contour précédent. En conséquence, négativer l'image d'entrée n'a aucun effet. Mais comme tous les détecteurs de contours, il peut avoir des problèmes avec les images du monde réel présentant des arrière-plans « chargés », telle que l'image rose intégrée. Ce résultat net est très important plus loin dans la détection de lignes de Hough.
Contours de bords à partir de formes anti-crénelées
Le plus gros problème des méthodes normales de détection de contours est que le résultat est fortement crénelé. Autrement dit, il génère un effet de pixels très en escalier, que la forme soit lisse (anti-crénelée) ou crénelée. Par exemple, voici une bulle de dialogue lisse et anti-crénelée (caractère « ( » de la police « WebDings »). |
magick -size 80x80 -gravity center -font WebDings label:')' voice.gif
![[IM Output]](../static/img/transform/voice.gif)
Et voici son image après détection de contours… |
magick voice.gif -edge 1 -negate voice_edge.gif
![[IM Output]](../static/img/transform/voice_edge.gif)
Comme vous pouvez le voir, cela a un aspect horrible, avec un léger anti-crénelage à l'extérieur du contour, et un aspect totalement crénelé (en escalier) à l'intérieur de la ligne. Le fait de négativer l'image a généré un contour similaire autour de l'extérieur de l'image, mais présente aussi un fort crénelage à l'extérieur de la ligne. |
magick voice.gif -negate -edge 1 -negate voice_edge_negate.gif
![[IM Output]](../static/img/transform/voice_edge_negate.gif)
Une alternative, lorsque vous avez déjà une image avec un bord anti-crénelé, consiste à générer l'image de différence d'un clone « tremblé » de la forme d'origine. Par exemple, ici nous trouvons l'image de différence entre l'image d'origine et une image qui a été décalée (ou tremblée) vers la droite de 1 pixel. |
magick voice.gif \( +clone -roll +1+0 \) -compose difference -composite \
-negate voice_jitter_horiz.gif
![[IM Output]](../static/img/transform/voice_jitter_horiz.gif)
Notez que cela ne produit pas un bon bord pour les bords inclinés horizontalement. Cependant, en combinant à la fois une image de différence tremblée horizontalement et une verticalement, nous pouvons obtenir un très bon contour anti-crénelé de la forme. |
magick voice.gif \
\( -clone 0 -roll +1+0 -clone 0 -compose difference -composite \) \
\( -clone 0 -roll +0+1 -clone 0 -compose difference -composite \) \
-delete 0 -compose screen -composite -negate voice_jitter_edge.gif
![[IM Output]](../static/img/transform/voice_jitter_edge.gif)
Cette technique a aussi l'avantage de fonctionner que le masque soit négativé ou non. Notez cependant que le résultat présente un décalage de 1/2 pixel par rapport à l'image d'origine, il peut donc nécessiter un traitement de « distorsion » supplémentaire pour réaligner soit la forme d'origine, soit le contour, si les deux doivent être combinés pour obtenir le résultat souhaité.
Contours de bords à partir de formes bitmap
Les images bitmap sont bien plus difficiles, car elles n'ont aucun pixel anti-crénelé pouvant servir à produire un contour lisse. Par exemple, voici une jolie forme de « cœur » qui a été extraite de la police « WebDings » (caractère « Y »). Cependant, je l'ai délibérément générée comme un bitmap crénelé, pour simuler une horrible image bitmap téléchargée depuis le réseau. Comme le contour d'une image GIF contenant de la transparence. |
magick +antialias -size 80x80 -gravity center \
-font WebDings label:Y heart.gif
![[IM Output]](../static/img/transform/heart.gif)
Nous avons donc cette horrible image, mais nous voulons trouver le contour de l'image plutôt que sa forme. L'usage direct de la détection de contours ne générera qu'un pur bord bitmap autour de l'extérieur de la forme bitmap. |
magick heart.gif -edge 1 -negate heart_edge.gif
![[IM Output]](../static/img/transform/heart_edge.gif)
Un contour négativé génère une image de contour mais pour l'intérieur de la zone noire. |
magick heart.gif -negate -edge 1 -negate heart_edge_negate.gif
![[IM Output]](../static/img/transform/heart_edge_negate.gif)
En additionnant les deux ci-dessus, vous obtenez un bord de 2 pixels centré sur le bord de la forme bitmap. |
magick heart.gif \( +clone -negate \) -edge 1 \
-compose add -composite -negate heart_edge_double.gif
![[IM Output]](../static/img/transform/heart_edge_double.gif)
Comme vous pouvez le voir, l'image résultante est fortement crénelée avec des effets en « escalier » dans le contour, même si l'image d'origine n'est elle-même pas trop mauvaise à cet égard. Ce n'est pas une bonne solution. Un bord légèrement meilleur peut être créé en utilisant une méthode de morphologie « [EdgeIn](morphology.html#edge-in) », ou d'autres similaires. |
magick heart.gif -negate -morphology EdgeIn Diamond -negate heart_edgein.gif
![[IM Output]](../static/img/transform/heart_edgein.gif)
Et un effet similaire peut être obtenu en utilisant simplement des redimensionnements pour flouter le bord de la bonne manière, avant d'utiliser un Solarize pour extraire les pixels gris moyens qui forment le bord. Un bord plus épais peut être généré en ajoutant un réglage « -filter Cubic », ou d'autres filtres de rééchantillonnage. |
magick heart.gif -resize 400% -resize 25% \
-solarize 50% -evaluate multiply 2 -negate heart_resize.gif
![[IM Output]](../static/img/transform/heart_resize.gif)
Ou pour un effet flou plus contrôlé, vous pouvez simplement flouter la forme et extraire le bord de manière similaire. Je trouve qu'un flou de « 0.7 » est à peu près le meilleur, avec une limite de 3 pixels pour accélérer les choses. |
magick heart.gif -blur 3x.7 -solarize 50% -level 50%,0 heart_blur.gif
![[IM Output]](../static/img/transform/heart_blur.gif)
Notez l'utilisation de l'opérateur Level, qui est l'équivalent du « -evaluate multiply 2 -negate » utilisé dans l'exemple précédent. Avec une bordure anti-crénelée, vous pouvez maintenant réajouter la forme d'origine si vous voulez simplement lisser la forme d'origine plutôt que d'obtenir son contour. N'oubliez pas simplement que le contour est positionné exactement le long du bord de l'image d'origine, il sera donc d'un demi-pixel plus grand en taille que dans les exemples précédents. Connaissez-vous d'autres façons de générer un contour anti-crénelé à partir d'une forme (anti-crénelée ou bitmap) ? Si oui, veuillez me l'envoyer par courriel, à moi ou au forum IM. Vous serez crédité.
Détourage à l'aide d'un convertisseur matriciel vers vectoriel
Une des solutions les plus idéales consiste à utiliser un programme de conversion « matriciel vers vectoriel » externe à IM pour transformer cette forme bitmap en un contour vectoriel. Les programmes capables de le faire incluent : « ScanFont », « CorelTrace », « Streamline » d'Adobe, et « [Vector Magic](http://vectormagic.com/home) ». La plupart d'entre eux vous coûtent cependant au moins un peu d'argent. « VectorMagick » et un autre programme de détourage, « AutoTracer », disposent de convertisseurs d'images en ligne gratuits. D'autres solutions gratuites sont « [AutoTrace](http://autotrace.sourceforge.net/) », ou « [PoTrace](http://potrace.sourceforge.net/) ». D'autres suggestions sont les bienvenues. Ces programmes de détourage sont simples à utiliser, mais nécessitent généralement une forme de configuration d'image en amont et en aval. Ils ont un nombre limité de formats d'entrée, et produisent une image vectorielle qui créera une forme « lissée » de l'image d'entrée. Je préfère « AutoTrace » car il ne met pas à l'échelle les données SVG résultantes, produisant ainsi une épaisseur de trait standard ; cependant vous ne pouvez pas l'utiliser dans un « pipeline ». Pour de meilleurs résultats, il est judicieux de s'assurer de ne lui fournir qu'une image bitmap basique, ce que nous pouvons garantir en appliquant un seuil à l'image d'entrée, tout en la convertissant dans un format d'image qu'autotrace comprend. Je peux ensuite transformer cette image en une image vectorielle SVG.
magick heart.gif -colorspace gray -threshold 50% heart_tmp.pbm
autotrace -output-format svg -output-file heart.svg heart_tmp.pbm
magick heart.svg heart_svg.gif
rm -f heart_tmp.pbm
| | | ![[IM Text]](../static/img/transform/heart.svg.gif)
Depuis IM v6.4.2-6, vous pouvez effectuer la séquence ci-dessus directement à l'aide du délégué d'entrée d'image « autotrace: ». Cela nécessite uniquement que la commande « autotrace » soit installée. Par exemple |
magick autotrace:heart.gif heart_traced.gif
![[IM Output]](../static/img/transform/heart_traced.gif)
Si votre IM a été compilé avec la bibliothèque déléguée « [AutoTrace](http://autotrace.sourceforge.net/) », vous pouvez aussi faire générer directement par IM l'image SVG à partir d'une image en mémoire. Pour les détails de ceci, voir Gestion de la sortie SVG. Par exemple…
magick heart.gif heart_2.svg
Maintenant, la sortie SVG représentera bien sûr une version lissée de l'image d'origine, ce qui n'est pas ce que nous voulons réellement dans cet exemple. Mais comme nous avons désormais la forme du bitmap sous forme vectorielle, il nous suffit d'ajuster les attributs « style » du SVG pour « stroke » (tracer) le contour, plutôt que « fill » (remplir) la forme. Le SVG modifié peut ensuite être réinjecté dans ImageMagick pour recréer l'image matricielle au contour net. Par exemple… |
cat heart.svg |
sed 's/"fill:#000000[^"]*"/"fill:none; stroke:black;"/' |
magick svg:- heart_outline.gif
![[IM Output]](../static/img/transform/heart_outline.gif)
Oui, c'est un peu laborieux, mais le résultat lisse et anti-crénelé vaut bien l'effort. Il serait agréable de pouvoir spécifier le détourage ou d'autres modifications comme options de la commande « autotrace » elle-même, mais ce n'est actuellement pas une fonctionnalité. Vous pouvez aussi modifier davantage la sortie SVG pour épaissir le bord, ou spécifier un autre trait ou une couleur d'arrière-plan, changer la couleur de remplissage de la forme de bord vectorielle. Par exemple, ici nous générons un contour plus épais de la forme avec un remplissage rouge, le tout joliment anti-crénelé. |
cat heart.svg |
sed 's/"fill:#000000;[^"]*"/"fill:red; stroke:black; stroke-width:5;"/' |
magick svg:- heart_outline_thick.gif
![[IM Output]](../static/img/transform/heart_outline_thick.gif)
Un cœur d'apparence aussi parfaite n'aurait pu être généré à partir d'une forme bitmap d'aucune autre manière. Nous pourrions aussi simplement extraire l'élément de chemin « d="..." » pour l'utiliser directement comme chaîne de chemin SVG dans la commande Draw. Cela vous permettrait alors d'utiliser n'importe lequel des autres réglages de dessin d'IM avec ce contour vectoriel, vous donnant un contrôle complet du résultat final. Pour un autre exemple d'utilisation du programme « [AutoTrace](http://autotrace.sourceforge.net/) », voir Squelette à l'aide d'Autotrace.
Détecteur de lignes de Hough
Le détecteur de lignes de Hough (« [-hough-lines](https://imagemagick.org/command-line-options/#hough-lines) », ajouté à IM v6.8.9-1) est une transformation très complexe comportant de nombreuses étapes (pour les détails, voir Wikipedia, Hough Transform). Fondamentalement, il est conçu pour examiner une image, y rechercher des lignes blanches sur un fond noir, et essayer de renvoyer la localisation exacte de tout segment de ligne (séquences linéaires de pixels) présent dans l'image. Cela peut être très important pour des choses comme la suppression des rotations d'image, ou la détermination de la transformation de perspective dans une image, afin de pouvoir la répéter ou la supprimer. Voici l'ensemble complet des options de l'opérateur
-background {_background_} -stroke {_line_color_} -hough-lines {_W_}x{_H_}+{_threshold_}
Les couleurs (background et line_color) servent à définir les couleurs des lignes dans l'image résultante (si vous les dessinez réellement). L'argument de l'opérateur Hough (W}x{H}+{threshold) sert à définir la taille et le seuil du filtre utilisé pour trouver les « pics » dans l'« image de recherche » intermédiaire. C'est-à-dire qu'il contrôle à quel point il « trouve » réellement les lignes que nous essayons de détecter (voir ci-dessous). Vous ajusteriez ces valeurs pour aider à la détection des lignes. Par exemple, essayons de trouver les lignes dans une image de forme rectangulaire. D'abord, nous devons réduire l'image à des lignes, et pour un résultat net, le détecteur de contours de Canny est recommandé.
magick shape_rectangle.gif -canny 0x1+10%+30% rectangle.gif
Maintenant, appliquons le détecteur de lignes de Hough à cette image. |
magick rectangle.gif -background black -stroke red \
-hough-lines 5x5+20 rectangle_lines.gif
![[IM Output]](../static/img/transform/rectangle_lines.gif)
Comme vous pouvez le voir, 5 lignes ont été trouvées, dont 2 sont très proches l'une de l'autre. La raison de la ligne supplémentaire est que le rectangle de l'image n'est pas parfait. Or, bien que j'affiche un résultat sous forme d'image matricielle (GIF), l'opérateur Hough génère en réalité une image vectorielle au format Magick Vector Graphics. Cela signifie que vous pouvez lister les informations des lignes pour un traitement ultérieur.
magick rectangle.gif -background black -stroke red \
-hough-lines 5x5+20 rectangle_lines.mvg
Notez que les lignes sont tracées d'un bord (avec des valeurs à virgule flottante) à un autre bord de l'image. Et de là, vous pouvez voir que les deuxième et troisième lignes sont les deux qui sont proches. Le commentaire dans la sortie MVG vous donne le nombre cumulé de pixels que la ligne « touche » dans l'image, et constitue donc un bon indicateur de la force de la ligne dans l'image. Cette valeur sera toujours plus grande que la valeur de seuil que vous donnez à l'opérateur « [-hough-line](https://imagemagick.org/command-line-options/#hough-line) ». De là, vous pouvez voir que la première et la dernière lignes (qui sont des correspondances proches) sont toutes deux de force à peu près égale, il serait donc difficile de choisir l'une plutôt que l'autre. Si cela vous arrive, je vous suggère d'essayer d'améliorer votre étape de détection de contours. Notez que l'image MVG n'a aucune couleur définie. Les réglages de couleur de cet exemple n'ont pas réellement été utilisés. Les couleurs ne servent que si vous « dessinez » réellement les vecteurs en convertissant le résultat ci-dessus en une image « matricielle », comme nous l'avons fait précédemment. Vous pouvez aussi voir l'« image de recherche » intermédiaire, ou « accumulateur », qui recherche des pixels blancs dans toutes les orientations, en utilisant un define spécial. |
magick rectangle.gif \
-define hough-lines:accumulator=true -hough-lines 5x5+20 \
-delete 0 -contrast-stretch 0.1% rectangle_accumulator.gif
![[IM Output]](../static/img/transform/rectangle_accumulator.gif)
Le define va simplement ajouter l'« image de recherche » au résultat de l'image, que dans ce cas nous supprimons. Nous avons également appliqué un peu de contraste aux « valeurs accumulées » afin de les rendre plus visibles. C'est l'image que les arguments du détecteur de Hough recherchent. L'image fait toujours 180 pixels de large (1 pixel par degré d'angle de ligne), tandis que la hauteur vaut deux fois la longueur de la diagonale de l'image. Ainsi, l'emplacement du pic définit directement l'angle de la ligne, et la distance perpendiculaire de la ligne par rapport au point central de l'image d'entrée. Autrement dit, la coordonnée X est l'angle en degrés, et la coordonnée Y la distance depuis le centre, de -distance diagonale à +distance diagonale. Si vous regardez de près le pic en bas à droite, vous verrez pourquoi nous avons obtenu deux lignes au lieu d'une. Le pic ici est « dédoublé » avec un léger écart entre les deux. L'algorithme est basé sur le script « [houghlines](http://www.fmwconcepts.com/imagemagick/houghlines/) » de Fred Wienhaus, quoique avec une gestion différente de l'accumulation de la « distance perpendiculaire ».
Seuillage adaptatif local
En construction
L'opérateur « [-lat](https://imagemagick.org/command-line-options/#lat) » tente de seuiller chaque pixel de manière adaptative en fonction de la valeur des pixels d'une fenêtre environnante. Cela sert couramment à seuiller des images ayant un arrière-plan irrégulier (c.-à-d. un éclairage irrégulier). Cela repose sur l'hypothèse que les pixels d'une petite fenêtre auront à peu près la même couleur d'arrière-plan et à peu près la même couleur de premier plan.
Par exemple.
magick input.png -lat 17 output.png
Ci-dessus, une « fenêtre » carrée de 17 pixels sert à déterminer la couleur moyenne de l'image en chaque point ; si le pixel est plus sombre que cette moyenne il est rendu noir, s'il est plus clair que cette moyenne il est rendu blanc. Une petite taille de fenêtre rendra le seuil plus sensible aux petits changements d'éclairage, sera plus rapide à calculer mais sera affectée négativement par le bruit dans l'image.
Exemple
Une plus grande taille de fenêtre rendra le seuil moins sensible aux petits changements d'éclairage, sera plus lente à calculer et moins affectée par le bruit dans l'image. Cela a pour effet de rendre la sélection de la valeur de seuil plus ou moins sensible aux petits changements des valeurs de pixels.
Exemple
La fenêtre n'a pas besoin d'être carrée. par exemple...
magick input.png -lat 15x25 output.png
Vous pouvez aussi fournir un décalage qui sera ajouté à la couleur moyenne calculée, rendant la valeur de seuil locale de chaque pixel plus claire ou plus sombre. Cela peut servir par exemple à réduire l'effet du bruit ou l'effet des petits changements des valeurs de pixels.
magick input.png -lat 15x25+2%
Ces petits changements se produisent normalement lorsqu'un scanner ou un appareil photo numérique sert à acquérir l'image. Utilisez une valeur de décalage positive pour rendre le seuillage adaptatif moins sensible aux petites variations des valeurs de pixels. Utilisez un seuil négatif pour rendre le seuil adaptatif plus sensible aux petites variations des valeurs de pixels. Alternativement, on pourrait réduire le bruit dans l'image avant de la traiter avec « -lat ».
En résumé, chaque pixel est seuillé selon la logique suivante :
AVG = valeur moyenne de chaque pixel dans la fenêtre
IF (pixel d'entrée > AVG + OFFSET)
Le pixel de sortie est NOIR
else
Le pixel de sortie est BLANC
---
Une alternative consiste à soustraire une copie floutée de l'image d'origine
à l'aide d'une soustraction (Modulo), puis à seuiller.
magick rose: -colorspace gray -lat 10x10+0% x:
est à peu près équivalent à...
magick rose: -colorspace gray \( +clone -blur 10x65535 \) \
-compose subtract -composite -threshold 50% x:
Le « -blur 10x65535 » spécial est un flou de moyennage linéaire se limitant lui-même à une
fenêtre 10x10.
La composition « Subtract », étant une opération de type modulo mathématique, va
ramener les valeurs qui deviennent négatives à une valeur supérieure à 50%.
Si vous voulez inclure un décalage, vous pouvez le faire en soustrayant également une image
d'arrière-plan de couleur unie à l'aide d'un -flatten... par exemple
magick rose: -colorspace gray -lat 10x10+10% x:
est à peu près équivalent à...
magick rose: -colorspace gray \( +clone -blur 10x65535 \) \
-compose subtract -background gray10 -flatten -threshold 50% x:
Ce qui précède a été modifié à partir de notes initiales fournies par D Hobson dhobson@yahoo.com
-adaptive-sharpen
Ne rend nettes que les zones autour des bords des images
-segment cluster-threshold x smoothing-threshold
Segmentation de l'espace colorimétrique (pas des objets de l'image)
Cela peut produire une sortie très verbeuse.
Cela applique l'« algorithme fuzzy c-means » si vous voulez en savoir plus.
En rapport également : -despeckle. pour supprimer les pixels isolés de couleur aberrante.
Génère un stéréogramme 3D à partir de deux images (une pour chaque œil)
Cela est aussi connu sous le nom d'anaglyphe
magick composite left.jpg right.jpg -stereo anaglyph.jpg
Mise en relief 3D avec Shade
Utilisation de Shade
L'opérateur « [-shade](https://imagemagick.org/command-line-options/#shade) » a toujours été à mes yeux l'un des opérateurs les plus intéressants fournis par ImageMagick. La documentation de cet opérateur ne donnait qu'un aperçu sommaire de ses capacités. Il m'a fallu beaucoup de recherches personnelles pour comprendre cet opérateur, et même déterminer comment utiliser au mieux la puissance qu'il peut offrir aux utilisateurs d'IM. En gros, ce que fait cet opérateur, c'est supposer que l'image fournie est ce que l'on appelle un « champ de hauteur ». C'est-à-dire une image en niveaux de gris représentant la surface d'un objet ou d'un terrain. La couleur « white » représente le point le plus haut d'une image, tandis que « black » le point le plus bas. Cette représentation est issue des recherches en vision par ordinateur de 1980, où une photo avec une forte « lumière d'appareil photo » était utilisée, rendant les points proches lumineux et les points éloignés sombres. |
Comme une image en niveaux de gris est nécessaire pour « [-shade](https://imagemagick.org/command-line-options/#shade) », l'opérateur supprime automatiquement toute couleur de l'image d'entrée. De même, toute transparence éventuellement présente dans l'image est totalement inutile et ignorée par l'opérateur. |
|---|---|
Maintenant « [-shade](https://imagemagick.org/command-line-options/#shade) » prend ce champ de hauteur en niveaux de gris et fait briller une lumière dessus. Le résultat est une représentation des nuances de lumière qui seraient ainsi produites. Rappelez-vous que vous devez penser à l'image d'entrée comme à une « surface » pour que la sortie ait un sens. Pour nos démonstrations, il nous faudra une image de « champ de hauteur », alors dessinons-en une. |
magick -font Candice -pointsize 64 -background black -fill white \
label:A -trim +repage -bordercolor black -border 10x5 \
shade_a_mask.gif
![[IM Output]](../static/img/transform/shade_a_mask.gif)
Cette image est aussi l'équivalent d'un « masque » d'une forme, et sert souvent non seulement d'entrée à « [-shade](https://imagemagick.org/command-line-options/#shade) », mais aussi au masquage d'images pour découper la même forme dans les résultats du shade. Voir Masquer une image shade ci-dessous. Pour l'opérateur « [-shade](https://imagemagick.org/command-line-options/#shade) », cette image ressemblera à une plaine noire plate, avec un plateau blanc plat s'élevant verticalement vers le haut. Seuls les bords de cette image produiront donc des effets intéressants. À cet effet, les deux arguments définissent la direction depuis laquelle la lumière brille. Le premier argument est la direction depuis laquelle la lumière vient. Ainsi un angle de « 0 » degré sera depuis l'est (ou la gauche), « 90 » depuis le nord (ou le haut) dans le sens antihoraire, et ainsi de suite. Par exemple...
magick shade_a_mask.gif -shade 0x45 shade_direction_0.gif
magick shade_a_mask.gif -shade 45x45 shade_direction_45.gif
magick shade_a_mask.gif -shade 90x45 shade_direction_90.gif
magick shade_a_mask.gif -shade 135x45 shade_direction_135.gif
magick shade_a_mask.gif -shade 180x45 shade_direction_180.gif
Vous avez compris l'idée. La lumière peut venir de n'importe quelle direction. L'autre argument est l'elevation (élévation), et représente l'angle que la source de lumière forme avec le sol. Vous pouvez y penser comme à la hauteur du soleil pendant la journée, de sorte que « 0 » est l'aube, et « 90 » est directement au-dessus.
![[diagram]](../static/img/img_diagrams/shade_elevation.gif)
magick shade_a_mask.gif -shade 90x0 shade_elevation_0.gif
magick shade_a_mask.gif -shade 90x15 shade_elevation_15.gif
magick shade_a_mask.gif -shade 90x30 shade_elevation_30.gif
magick shade_a_mask.gif -shade 90x45 shade_elevation_45.gif
magick shade_a_mask.gif -shade 90x60 shade_elevation_60.gif
magick shade_a_mask.gif -shade 90x75 shade_elevation_75.gif
magick shade_a_mask.gif -shade 90x90 shade_elevation_90.gif
Comme vous pouvez le voir, avec une elevation de « 0 », la forme n'est mise en relief que du côté d'où vient la lumière. Tout le reste est noir, car aucune lumière ne brille sur aucune autre surface. J'appelle cela une « mise en relief à l'aube » (Dawn Highlight) et elle a ses propres usages spéciaux. Cela nous amène au premier point à noter. Une image « [-shade](https://imagemagick.org/command-line-options/#shade) » aura souvent plus de zones sombres, ou ombrées, que de zones mises en relief. L'ombrage n'est pas égal. À mesure que la lumière monte au-dessus de l'image de « champ de hauteur », la luminosité globale de l'image deviendra plus blanche, jusqu'à ce qu'au « plein midi » ou à une elevation de « 90 », toutes les zones plates soient d'un blanc éclatant, et que seuls les pentes et les bords soient ombrés en une couleur grise, avec un gris moyen comme maximum, soit un changement de pente de type « falaise ». Cette image de « midi » est un autre cas particulier qui ressemble un peu à un système de détection de bords, bien qu'il fasse entre 2 et 4 pixels de large pour les bords nets. J'ai déjà utilisé cette image par le passé pour générer un masque du bord biseauté des images « [-shade](https://imagemagick.org/command-line-options/#shade) », afin de rendre les zones plates transparentes. Si l'angle d'elevation dépasse « 90 » degrés, vous obtiendrez le même résultat que si la lumière venait de la direction opposée. Ainsi l'argument « 0x135 » produira exactement le même résultat que « 180x45 ». Un angle d'elevation négatif produira aussi le même résultat, comme si la lumière venait d'en dessous, sur une surface de type « translucide ». Ainsi « 0x-45 » sera identique à « 0x45 ». Autrement dit, pour un shade donné, il y a généralement 4 autres arguments qui produiront aussi le même résultat. D'après ce qui précède, je considérerais qu'un argument de « 120x45 » est à peu près le meilleur pour un usage direct de la sortie du shade. Par exemple, ici il crée du texte biseauté...
magick -size 320x100 xc:black \
-font Candice -pointsize 72 -fill white \
-draw "text 25,65 'Anthony'" \
-shade 120x45 shade_anthony.jpg
L'un des principaux problèmes de « [-shade](https://imagemagick.org/command-line-options/#shade) » est l'épaisseur du biseau qui est réellement produit. Un bord net comme celui que j'ai utilisé ci-dessus produira toujours un biseau d'environ 4 pixels de large, à la fois vers l'intérieur et vers l'extérieur de la zone masquée. Il n'y a aucun moyen d'ajuster cette épaisseur, sinon en redimensionnant les images avant et après l'utilisation de l'opérateur « [-shade](https://imagemagick.org/command-line-options/#shade) ». Si vous voulez savoir à quel point les « zones plates » seront lumineuses pour un angle d'éclairage d'elevation donné, vous pouvez utiliser la commande suivante, pour shader une surface plate de couleur unie.
magick -size 50x50 xc:white -draw 'circle 25,25 20,10' \
-blur 0x2 -shade 0x45 -gravity center -crop 1x1+0+0 txt:-
Comme vous pouvez le voir, une elevation de « 45 » degrés produit une couleur plate assez lumineuse d'environ 70% de gris, ce qui est un niveau de gris raisonnable pour un affichage général. Cependant, si vous prévoyez d'utiliser shade pour générer des mises en relief 3D de formes variées, alors le niveau de gris réel devient très important. Nous y reviendrons plus tard dans Créer des mises en relief en superposition. C'est-à-dire que, en gros, c'est tout pour l'opérateur « [-shade](https://imagemagick.org/command-line-options/#shade) ». Cependant, l'utiliser efficacement présente toute une gamme de techniques et de possibilités, que nous allons examiner ensuite.
Masquer des formes shade
Comme mentionné ci-dessus, une simple forme de « masque » sert souvent avec « [-shade](https://imagemagick.org/command-line-options/#shade) » pour générer des effets 3D complexes à partir d'une forme simple. Par exemple, faisons cela à une image de masque directement shade.
magick shade_direction_135.gif shade_a_mask.gif \
-alpha Off -compose CopyOpacity -composite shade_beveled.png
Remarquez qu'environ la moitié du biseau généré par l'opérateur « [-shade](https://imagemagick.org/command-line-options/#shade) » tombe en réalité en dehors de la zone masquée. Autrement dit, un biseau droit est réduit de moitié une fois masqué. En revanche, l'image shade verticale ou de « milieu de journée » (utilisant un angle d'elevation de « 90 » degrés) peut servir à extraire uniquement le bord biseauté, laissant le centre de l'image creux.
magick shade_direction_135.gif \
\( shade_elevation_90.gif -normalize -negate \) \
-alpha Off -compose CopyOpacity -composite shade_beveled_edge.png
Notez toutefois que l'image shade de « milieu de journée », tout en offrant un moyen de masquer l'emplacement (et l'intensité) des effets de l'opérateur « [-shade](https://imagemagick.org/command-line-options/#shade) », ne couvre pas réellement ces effets complètement. En combinant l'image shade de « milieu de journée » avec le masque d'origine, vous pouvez augmenter légèrement la taille de ce masque pour produire une image biseautée mieux masquée.
![[IM Output]](../static/img/transform/shade_direction_180.gif)
magick shade_direction_135.gif \
\( shade_elevation_90.gif -normalize -negate \
shade_a_mask.gif -compose screen -composite \) \
-alpha Off -compose CopyOpacity -composite shade_beveled_plus.png
![[IM Output]](../static/img/transform/shade_beveled_plus.png)
Rappelez-vous qu'avec IM v6 vous pouvez générer l'image « shade » que j'ai générée précédemment, le tout dans la même commande. Ainsi, ce qui précède aurait pu être entièrement généré à partir de zéro. Par exemple. |
magick -font Candice -pointsize 72 -background black -fill white \
label:X -trim +repage -bordercolor black -border 10x5 \
\( -clone 0 -shade 135x45 \) \
\( -clone 0 -shade 0x90 -normalize -negate \
-clone 0 -compose screen -composite \) \
-delete 0 -alpha Off -compose CopyOpacity -composite \
shade_beveled_X.png
Images de formes shade
L'opérateur d'extraction alpha ne se contente pas d'extraire le canal alpha d'une image ayant une forme sous forme de masque en niveaux de gris, mais a aussi pour effet secondaire de préserver la forme dans le canal alpha « désactivé ». Comme il est « désactivé », il ne sera pas touché par de nombreux opérateurs de traitement d'image, y compris « [-shade](https://imagemagick.org/command-line-options/#shade) », préservant ses détails. Cela signifie que pour des images ayant une forme, vous pouvez extraire la forme, effectuer le travail, puis simplement récupérer la transparence APRÈS avoir terminé tout le traitement d'image, simplement en réactivant l'alpha ! Par exemple, ici je dessine un « cœur » sur un arrière-plan transparent, effectue un peu de flou et de shade sur l'image, puis restaure le contour de la forme d'origine de l'image. |
magick -size 100x100 -gravity center -background None \
-font WebDings label:Y \
-alpha Extract -blur 0x6 -shade 120x21 -alpha On \
-normalize +level 15% -fill Red -tint 100% shade_heart.png
![[IM Output]](../static/img/transform/shade_heart.png)
Tout ce que je peux dire, c'est WOW, quel gain de temps ! Bien plus simple que la commande précédente avec tout son traitement supplémentaire et son clonage d'images.
Arrondir les bords du shade
Comme vous l'avez vu dans le dernier exemple, en floutant le masque de forme de l'image, la « pente » des « falaises » de bord sera lissée, comme usée par le temps. Cela produit un bel effet arrondi sur l'image shade.
magick -size 50x50 xc:black -fill white -draw 'circle 25,25 20,10' \
shade_circle_mask.gif
magick shade_circle_mask.gif -shade 120x45 shade_blur_0.gif
magick shade_circle_mask.gif -blur 0x1 -shade 120x45 shade_blur_1.gif
magick shade_circle_mask.gif -blur 0x2 -shade 120x45 shade_blur_2.gif
magick shade_circle_mask.gif -blur 0x3 -shade 120x45 shade_blur_3.gif
magick shade_circle_mask.gif -blur 0x4 -shade 120x45 shade_blur_4.gif
magick shade_circle_mask.gif -blur 0x5 -shade 120x45 shade_blur_5.gif
Comme vous pouvez le voir, le flou n'arrondit pas seulement les bords, mais rend aussi les effets d'éclairage plus faibles. Vous pouvez maximiser le contraste du résultat en le normalisant, afin de ramener les points les plus clairs et les plus sombres respectivement vers des couleurs blanc et noir purs.
magick shade_blur_3.gif -normalize shade_blur_3n.gif
Le seul inconvénient est que cela assombrit aussi généralement l'image shade. C'est quelque chose que nous devrons prendre en compte dans Créer des mises en relief en superposition. Terminons cette image shade en la masquant aussi directement.
magick shade_blur_3n.gif shade_circle_mask.gif \
-alpha Off -compose CopyOpacity -composite shade_blur_3n_mask.png
Comme vous pouvez le voir, flouter l'image de masque arrondit très joliment les bords de la forme résultante.
Créer une mise en relief en superposition
La sortie de l'opérateur « [-shade](https://imagemagick.org/command-line-options/#shade) » est très belle, mais il est rare que vous vouliez réellement une simple image en niveaux de gris de votre forme. Ce qu'il faut, c'est un peu de couleur. Cela n'est cependant pas si facile, car les deux principales façons d'ajouter de la couleur, le teintage colorimétrique des demi-tons pour recolorer un simple niveau de gris, ou la composition alpha « Overlay » pour remplacer les zones grises par une image, reposent toutes deux sur une forme particulière d'image en niveaux de gris. C'est-à-dire qu'un gris demi-ton parfait (« grey50 ») est remplacé par la couleur ou l'image, tandis que les gris plus clairs ou plus sombres blanchissent et assombrissent la couleur ou l'image de manière appropriée. Ces images spéciales en niveaux de gris de « mise en relief en superposition » avec des gris demi-ton parfaits pour les zones non modifiées ne sont pas si simples à créer avec « [-shade](https://imagemagick.org/command-line-options/#shade) ». Cependant, voici quelques-unes des méthodes les plus simples que j'ai découvertes. Utiliser un angle d'éclairage à 30 degrés d'élévation avec « [-shade](https://imagemagick.org/command-line-options/#shade) » est un moyen de produire un gris demi-ton parfait pour les zones plates de la forme shade. Par exemple, ici je shade une image, puis j'extrais le pixel en haut à gauche pour vérifier la couleur résultante d'une partie « plate » de l'image.
![[IM Output]](../static/img/transform/shade_blur_5.gif)
| |
magick -size 50x50 xc:black -fill white -draw 'circle 25,25 20,10' \
-blur 0x2 -shade 120x30 shade_30.png
magick shade_30.png -gravity center -crop 1x1+0+0 txt:-
Malheureusement, modifier l'effet d'arrondi du « [-blur](https://imagemagick.org/command-line-options/#blur) » dans la commande ci-dessus a aussi tendance à faire varier l'intensité de la mise en relief résultante de l'image shade. C'est-à-dire qu'utiliser un grand flou produit non seulement un bord d'aspect bien arrondi, mais rend aussi la mise en relief si faible qu'elle en devient presque invisible. Cela signifie que vous devez ajouter beaucoup plus de contraste à la sortie de l'image « [-shade](https://imagemagick.org/command-line-options/#shade) » produite, pour rendre la mise en relief efficace en tant qu'image de superposition. Pour corriger cela, il nous faut un moyen de supprimer cet effet de contraste dû à l'ajustement d'arrondi. La façon typique de le faire est simplement de « [-normalize](https://imagemagick.org/command-line-options/#normalize) » l'image, mais faire cela sur une image shade à 30 degrés fait que les zones « plates » ne seront plus d'un gris parfait. Par exemple... | |
magick -size 50x50 xc:black -fill white -draw 'circle 25,25 20,10' \
-blur 0x2 -shade 120x30 -normalize shade_30_norm.png
magick shade_30_norm.png -gravity center -crop 1x1+0+0 txt:-
Après quelques expérimentations supplémentaires cependant, j'ai découvert qu'utiliser un angle d'élévation de shade de 21,78 degrés produit, après normalisation, le niveau de gris demi-ton parfait souhaité ainsi qu'un bon effet de mise en relief fort. | |
magick -size 50x50 xc:black -fill white -draw 'circle 25,25 20,10' \
-blur 0x2 -shade 120x21.78 -normalize shade_21_norm.png
magick shade_21_norm.png -gravity center -crop 1x1+0+0 txt:-
Comme l'image shade passe désormais par l'opérateur « [-normalize](https://imagemagick.org/command-line-options/#normalize) », la valeur de « [-blur](https://imagemagick.org/command-line-options/#blur) » utilisée pour « arrondir les bords » n'affectera plus l'intensité finale du résultat. Une bien meilleure méthode. En résumé, normaliser une image shade décalera les demi-tons hors d'une couleur gris parfaite. Nous pouvons maintenant ajuster l'intensité de sortie des mises en relief produites de manière totalement indépendante des autres ajustements. Typiquement, comme le résultat normalisé est extrême, il nous faudra une dé-normalisation contrôlée, ou un contrôle d'anti-contraste, pour réduire la mise en relief au niveau souhaité. La méthode la plus simple pour ajuster la mise en relief résultante est de teinter en couleur l'image avec un gris parfait. Cela décalera tous les niveaux de couleur de l'image vers la couleur gris demi-ton pure centrale. Par exemple...
magick -size 50x50 xc:black -fill white -draw 'circle 25,25 20,10' \
\( +clone -blur 0x2 -shade 120x21.78 -normalize \) \
+swap -alpha Off -compose CopyOpacity -composite shade_tint_0.png
magick shade_tint_0.png -fill grey50 -colorize 10% shade_tint_10.png
magick shade_tint_0.png -fill grey50 -colorize 30% shade_tint_30.png
magick shade_tint_0.png -fill grey50 -colorize 50% shade_tint_50.png
magick shade_tint_0.png -fill grey50 -colorize 80% shade_tint_80.png
Une alternative au simple teintage linéaire de la mise en relief est de réduire son effet général tout en préservant les points extrêmes clairs/sombres de la mise en relief en utilisant plutôt le contraste non linéaire sigmoïdal. Cela devrait donner un aspect plus « naturel » à l'effet de mise en relief, et peut rendre la mise en relief plus lumineuse, comme si la surface était plus réfléchissante. Cependant, pour rendre cette technique plus efficace, nous devons nous assurer de ne pas avoir de couleurs blanc et noir purs dans le résultat du shade. Cela peut se faire en utilisant d'abord un « [-contrast-stretch](https://imagemagick.org/command-line-options/#contrast-stretch) » de « 0% » plutôt qu'un « [-normalize](https://imagemagick.org/command-line-options/#normalize) », et aussi en dé-normalisant ce résultat d'une petite quantité, comme nous l'avons fait ci-dessus. Cela peut sembler n'ajouter que de la complexité à la génération de l'image de superposition de mise en relief, mais accentuer les points lumineux de la mise en relief rend le traitement supplémentaire digne de l'effort. Par exemple...
magick -size 50x50 xc:black -fill white -draw 'circle 25,25 20,10' \
\( +clone -blur 0x2 -shade 120x21.78 -contrast-stretch 0% \) \
+swap -alpha Off -compose CopyOpacity -composite shade_sig_0.png
magick shade_sig_0.png -sigmoidal-contrast 10x50% shade_sig-10.png
magick shade_sig_0.png -sigmoidal-contrast 5x50% shade_sig-5.png
magick shade_sig_0.png -sigmoidal-contrast 2x50% shade_sig-2.png
magick shade_sig_0.png +sigmoidal-contrast 2x50% shade_sig+2.png
magick shade_sig_0.png +sigmoidal-contrast 5x50% shade_sig+5.png
magick shade_sig_0.png +sigmoidal-contrast 10x50% shade_sig+10.png
Comme vous pouvez le voir, la mise en relief globale est réduite en intensité, mais le point lumineux issu de la lumière réfléchie reste aussi brillant que jamais, seulement réduit en taille. Le résultat donne un aspect « brillant » bien plus naturel à la forme. Le seul inconvénient de cette technique est qu'un « point » d'ombre est aussi généré, bien qu'il ne soit souvent pas aussi visible. Enfin, nous pouvons combiner un « point de mise en relief » avec une réduction générale de la mise en relief pour produire un ensemble hautement configurable de contrôles de générateur de superposition de mise en relief...
![[IM Output]](../static/img/transform/shade_tint_80.png)
magick -size 50x50 xc:black -fill white -draw 'circle 25,25 20,10' \
\( +clone -blur 0x4 -shade 120x21.78 -contrast-stretch 0% \
+sigmoidal-contrast 7x50% -fill grey50 -colorize 10% \) \
+swap -alpha Off -compose CopyOpacity -composite shade_overlay.png
- En résumé, l'exemple ci-dessus comporte quatre contrôles distincts...
- "
[blur](https://imagemagick.org/command-line-options/#blur)" : Arrondir les bords de la forme (0.001=biseauté 2=lissé 10=arrondi) - "
[shade](https://imagemagick.org/command-line-options/#shade)" : La direction d'où vient la lumière (120=haut-gauche 60=haut-droite) - "
[sigmoidal](https://imagemagick.org/command-line-options/#sigmoidal-contrast)" : contrôle de réflexion de surface des points de mise en relief (1=plat 5=bon 10=réfléchissant ) - "
[colorize](https://imagemagick.org/command-line-options/#colorize)" : Contraste global de la mise en relief ( 0%=lumineux 10%=bon 50%=faible )
Notez que si les exemples ci-dessus ont été mis à la forme originale du « cercle », la transparence ne devrait être restaurée qu'APRÈS que la composition « Overlay » ait été appliquée, pas avant. De plus, si vous prévoyez d'utiliser une mise en relief de manière répétée sur la même forme (après toute rotation effectuée), vous pouvez pré-générer la superposition de mise en relief une seule fois pour chaque forme que vous prévoyez d'utiliser, en enregistrant le résultat pour de multiples réutilisations. Un exemple de cette réutilisation de superposition de shade se trouve dans la génération de jaquettes de DVD 3D à partir d'images sources plates dans les forums de discussion IM. Je vous recommande également vivement d'expérimenter les techniques ci-dessus, car elles sont la clé pour rendre vos images de formes plates bien plus réalistes. Si vous trouvez d'autres idées de mise en relief, veuillez me le faire savoir.
FUTURE :
Teinter en couleur l'image de superposition
Composition alpha Overlay avec une image
Utiliser une mise en relief shade à l'aube
Dans Masquer des images shade ci-dessus, nous avons montré combien une image shade de « milieu de journée » ou de « plein midi » (utilisant une elevation de « 90 ») peut être utile pour masquer l'emplacement et l'étendue des effets produits par « [-shade](https://imagemagick.org/command-line-options/#shade) ». Cependant, les images shade horizontales ou d'« aube » (utilisant une elevation de « 0 ») d'une forme peuvent aussi être tout à fait utiles. Elles peuvent par exemple servir de masque pour des images blanches ou noires afin de générer des effets de mise en relief et d'ombrage distincts sur des formes. Cela peut aussi servir à garantir qu'une forme reçoive des quantités à peu près égales de zones claires et sombres (ou même des quantités inégales), puisque je les produis séparément mais d'une manière totalement contrôlée.
FUTURE : plus de détails ici
Voir le premier logo 3D avancé pour un exemple d'utilisation de cette technique.
Utiliser FX, l'opérateur d'image du bricoleur L'opérateur de liste d'images « [-fx](https://imagemagick.org/command-line-options/#fx) » est un opérateur du bricoleur généraliste qui n'entre dans aucune catégorie spécifique d'opérateurs IM, car il peut servir à créer à peu près n'importe quelle opération d'image. Des exemples de son utilisation parsèment ces pages, mais ici nous examinerons spécifiquement ses capacités et comment vous pouvez les utiliser. La commande est si générique dans ses aptitudes qu'elle peut,
- créer des canevas, des dégradés, des cartes de couleurs mathématiques.
- déplacer des valeurs de couleur entre images et canaux.
- ajuster les couleurs d'une image de à peu près toutes les manières imaginables
- translater, retourner, mettre en miroir, pivoter, mettre à l'échelle, cisailler et déformer les images de façon générale.
- fusionner ou composer plusieurs images ensemble.
- carreler une ou plusieurs images de façons étranges et merveilleuses.
- convoluer ou fusionner des pixels voisins.
- générer des métriques d'image ou des « empreintes ».
- comparer des images de manières inhabituelles.
Bien sûr, beaucoup de ces techniques font déjà partie d'IM, produisant un résultat plus rapide et plus flexible. Mais si ce n'est pas intégré, « [-fx](https://imagemagick.org/command-line-options/#fx) » vous permet de générer votre propre version de l'opération souhaitée. En fait, moi-même et d'autres l'avons souvent utilisé pour prototyper de nouvelles opérations qui ont été ensuite intégrées à la bibliothèque centrale d'IM. À titre d'exemple, voir Remplacement DIY du nouveau tramage ordonné où j'ai utilisé « [-fx](https://imagemagick.org/command-line-options/#fx) » pour développer une version révisée de l'opérateur [-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither) ». L'opérateur vous permet essentiellement d'effectuer des opérations mathématiques libres sur une ou plusieurs images. Pour le résumé officiel de la commande, voir FX, l'opérateur d'image à effets spéciaux sur le site web d'ImageMagick.
Utilisation de base de FX
La commande prend une séquence d'images comportant autant d'images d'entrée que vous voulez. Typiquement une ou deux images, et remplace TOUTES les images d'entrée par une copie de la première image, qui a été modifiée par les résultats de la fonction « [-fx](https://imagemagick.org/command-line-options/#fx) ». Autrement dit, toute métadonnée présente dans la première image sera préservée dans le résultat de l'opérateur « [-fx](https://imagemagick.org/command-line-options/#fx) ». Pour une facilité d'usage mathématique, toutes les valeurs de couleur fournies sont normalisées dans une plage de valeurs de 0.0 à 1.0. Les résultats sont aussi censés être dans cette plage. Cela inclut le canal de transparence ou alpha, qui va de 0.0 (signifiant totalement transparent) à 1.0 (signifiant totalement opaque). Les valeurs représentent la « transparence alpha » et sont en réalité l'inverse de la façon dont IM stocke normalement la transparence en interne (sous forme de valeurs matte). C'est toutefois mathématiquement plus correct et plus facile à utiliser sous cette forme. Le paramètre « [-channel](https://imagemagick.org/command-line-options/#channel) » définit quel(s) canal(aux) de la première image (aussi appelée la « zéroième » ou « u ») est remplacé par le résultat de l'opérateur « [-fx](https://imagemagick.org/command-line-options/#fx) ». Cela est limité, par défaut, aux seuls canaux de couleur (« RGB ») de l'image d'origine. Toute transparence existante dans cette image ne sera pas modifiée, à moins que le paramètre « [-channel](https://imagemagick.org/command-line-options/#channel) » ne soit changé, pour inclure le canal alpha (« A »). L'expression est exécutée une fois pour chaque pixel, ainsi qu'une fois pour chaque canal de couleur du pixel en cours de traitement. De plus, comme l'expression est ré-analysée à chaque exécution, une expression complexe pourrait prendre du temps à traiter sur une grande image. Par exemple, ici nous définissons une image noire, mais réglons ensuite le canal bleu à mi-luminosité pour former à la place une couleur « bleu marine ». |
magick -size 64x64 xc:black -channel blue -fx '1/2' fx_navy.gif
![[IM Output]](../static/img/transform/fx_navy.gif)
Et ici, nous prenons un dégradé noir-blanc, puis réglons les canaux bleu et vert à zéro, de sorte qu'il devienne un dégradé noir-rouge. |
magick -size 64x64 gradient:black-white \
-channel blue,green -fx '0' fx_red.gif
![[IM Output]](../static/img/transform/fx_red.gif)
| _Pour rendre le paramètre « -channel » plus semblable à l'opérateur « -fx », il acceptera toute combinaison des lettres « RGBA » pour spécifier les canaux auxquels les opérateurs doivent limiter leurs actions.
Cela signifie que pour limiter la sortie de « -fx » aux seuls canaux bleu et vert, vous pouvez désormais dire « -channel BG » au lieu du plus long « -channel blue,green »._
---|---
Nous aurions pu générer les exemples ci-dessus sans utiliser « [-fx](https://imagemagick.org/command-line-options/#fx) », mais pouvoir faire cela sur une image existante est ce qui en fait un puissant opérateur d'image. La fonction peut en fait lire et utiliser N'IMPORTE QUEL pixel, ou une couleur spécifique, de N'IMPORTE LAQUELLE des images déjà présentes dans la séquence d'images courante en mémoire. La première image « zéro » reçoit le nom spécial de « u ». La deuxième image « v ». Les autres images en mémoire peuvent être référencées par un index. Ainsi « u[3] » est la quatrième image de la séquence d'images courante, tandis que « u[-1] » est la dernière image de la séquence. C'est le même schéma d'indexation utilisé par les opérateurs de liste d'images, vous devriez donc vous sentir tout à fait à l'aise. Si aucun autre qualificatif n'est donné, la valeur de couleur utilisée est la même couleur que celle utilisée dans l'image spécifiée. C'est-à-dire que, à moins de dire explicitement que vous voulez utiliser la couleur rouge, il utilisera la valeur de couleur du canal de couleur que la commande traite à ce moment-là. C'est-à-dire qu'il appliquera l'expression pour la valeur de couleur bleue lorsqu'il traitera le canal bleu. Sauf indication contraire, il traitera chacune des valeurs de couleur RGB (telles que définies par le paramètre « [-channel](https://imagemagick.org/command-line-options/#channel) » par défaut), pour chaque pixel de l'image. C'est-à-dire, 3wh calculs qui modifient toutes les valeurs de l'image par l'expression donnée. Par exemple, ici nous prenons l'image intégrée « rose: » d'IM et multiplions toutes les valeurs de pixels par 50%. |
magick rose: -fx 'u*1.5' fx_rose_brighten.gif
![[IM Output]](../static/img/transform/fx_rose_brighten.gif)
Dans l'exemple ci-dessus, chacune des valeurs individuelles rouge, verte et bleue a été multipliée par 1.5. Si la valeur résultante est hors de la plage 0 à 1, elle sera limitée à la borne appropriée (1.0 dans ce cas), à moins que vous n'utilisiez la version HDRI d'ImageMagick par défaut. De nombreuses autres formules « [-fx](https://imagemagick.org/command-line-options/#fx) » pour recolorer les images sont explorées dans Ajustements mathématiques des couleurs et Courbes d'histogramme. Comme nous pouvons aussi référencer n'importe quelle image de la séquence d'images courante, dans le cadre de l'expression pour modifier la première image, nous pouvons fusionner deux images, ou même davantage, de à peu près n'importe quelle manière voulue. Ici, nous générons une image de charte de couleurs noir-rouge-bleu, en copiant le canal bleu depuis un dégradé noir-bleu (pivoté), dans le dégradé noir-rouge précédent que nous avons généré ci-dessus.
magick -size 64x64 gradient:black-blue -rotate -90 fx_blue.gif
magick fx_red.gif fx_blue.gif \
-channel B -fx 'v' fx_combine.gif
| _Bien sûr, nous aurions pu utiliser à la place une méthode de composition par copie de canal, ce qui serait bien plus rapide. Mais là n'est pas la question.
Quoique l'inverse soit également vrai. À peu près toute opération d'image IM pourrait être remplacée par une fonction FX équivalente.
_
---|---
Or, la deuxième image ci-dessus n'est utilisée que comme image source. Ce qui se passe réellement, c'est que « [-fx](https://imagemagick.org/command-line-options/#fx) » crée d'abord une copie de la seule première image. Il modifie ensuite cette image selon la formule, en utilisant toutes les autres images fournies. Et enfin, il jette toutes les images d'entrée en les remplaçant par la copie modifiée de la première image. Vous pouvez aussi calculer des valeurs en fonction de l'emplacement de chaque pixel dans l'image. Les valeurs « i,j » sont la position courante du pixel en cours de traitement, tandis que « w,h » donne la taille de l'image (la première image sauf si un qualificatif d'image spécifique est donné). Par exemple, ici nous générons une image de dégradé DIY. |
magick rose: -channel G -fx 'sin(pi*i/w)' -separate fx_sine_gradient.gif
![[IM Output]](../static/img/transform/fx_sine_gradient.gif)
Ou quelque chose de plus complexe utilisant les deux valeurs de position « i,j ». |
magick -size 80x80 xc: -channel G -fx 'sin((i-w/2)*(j-h/2)/w)/2+.5'\
-separate fx_2d_gradient.gif
![[IM Output]](../static/img/transform/fx_2d_gradient.gif)
Lors de la génération de dégradés en niveaux de gris, il est possible de faire fonctionner l'opérateur -fx environ 3 fois plus vite, simplement en lui demandant de ne traiter 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 générer l'image finale en niveaux de gris. Cela peut représenter un gain de vitesse très important, en particulier lors de l'utilisation d'une formule « [-fx](https://imagemagick.org/command-line-options/#fx) » très complexe. Pour davantage de dégradés générés par FX, voir les exemples Créez vos propres dégradés. Il est possible d'utiliser l'information de position pour rechercher des pixels spécifiques de l'image source à l'aide de la syntaxe « p{x,y} ». Par exemple, on peut aisément créer sa propre fonction de type « image miroir » (comme l'opérateur d'image « [-flop](https://imagemagick.org/command-line-options/#flop) »), qui remplace chaque pixel par les valeurs de couleur de la position « miroir » de la source originale. |
magick rose: -fx 'p{w-i-1,j}' fx_rose_mirror.gif
![[IM Output]](../static/img/transform/fx_rose_mirror.gif)
Ce type de « distorsion d'image » a été rendu plus puissant par la création de Mappage d'image de distorsion, ou d'autres types de tables de correspondance de valeurs, sous forme d'images. Des exemples de cette technique sont fournis dans Motifs de tramage DIY et cartes de seuil, où FX est utilisé pour remplacer des couleurs spécifiques par des motifs issus d'autres images. Or, la taille de l'image finale générée par une expression FX est la même que celle de la première image donnée ; ainsi, pour générer une image plus grande, il faut définir la première image à la taille souhaitée. Dans ce type de situation, une deuxième image (voire une troisième) peut servir de source de couleur (d'où le Swap dans l'exemple suivant). Par exemple, ici, on redimensionne l'image rose (en utilisant le redimensionnement ou la mise à l'échelle par interpolation) pour générer une image plus grande. |
magick rose: -size 120x80 xc: +swap \
-fx 'v.p{ (i+.5)*v.w/w-.5, (j+.5)*v.h/h-.5 }' \
fx_scaled.png
![[IM Output]](../static/img/transform/fx_scaled.png)
Notez comment la recherche de pixel est effectuée ; cela peut sembler complexe, mais c'est la bonne manière de mettre à l'échelle (déformer) une image. En gros, toutes les valeurs « 0.5 » supplémentaires ajoutées à l'expression sont nécessaires pour convertir correctement entre les Coordonnées de pixel utilisées pour les coordonnées d'entrée « i,j » et la recherche de position « v.p{...} », tandis que les Coordonnées d'image plus mathématiquement correctes sont nécessaires pour les calculs mathématiques réels (la mise à l'échelle). Ce qui précède est en fait la méthodologie exacte employée par toute forme de Distorsion d'image. On peut voir cet équivalent FX pour la plupart des distorsions en activant le Résumé détaillé de la distorsion. Celui-ci rapporte un équivalent FX pour la plupart des distorsions d'image, comme moyen de vérifier que la distorsion fait bien ce qui est attendu. L'utilisation de l'opérateur FX DIY pour réaliser des distorsions d'image montre à quel point cet opérateur est réellement puissant. Sans cet opérateur, je doute que bon nombre des nouvelles opérations, telles que les distorsions, sparse-color ou les tramages ordonnés, auraient été ajoutées à la bibliothèque ImageMagick Core. Voici quelque chose d'un peu plus simple : l'échange des canaux rouge et bleu de l'image rose. Voyez si vous parvenez à comprendre comment cela fonctionne. |
magick rose: \( +clone -channel R -fx B \) \
+swap -channel B -fx v.R fx_rb_swap.gif
![[IM Output]](../static/img/transform/fx_rb_swap.gif)
| _Une manière plus rapide et meilleure de faire la même chose est d'utiliser « [-separate](https://imagemagick.org/command-line-options/#separate) » et « [-combine](https://imagemagick.org/command-line-options/#combine) »). Voir Combinaison des images de canaux RVB. Vous pouvez aussi utiliser une « [-color-matrix](https://imagemagick.org/command-line-options/#color-matrix) » pour faire la même chose plus vite encore.
Voyez-vous une tendance ici ?_
---|---
Comme réglage « [-channel](https://imagemagick.org/command-line-options/#channel) » par défaut, cela limite la sortie de l'opérateur « [-fx](https://imagemagick.org/command-line-options/#fx) » aux seuls trois canaux de couleur. Cela signifie que si vous voulez agir sur le canal alpha ou de transparence, vous devez le spécifier explicitement, en changeant le réglage du canal. Par exemple, créons une image « rose: » semi-transparente, en réglant toutes les valeurs du canal alpha à la moitié. |
magick rose: -alpha set -channel A -fx '0.5' fx_rose_trans.png
![[IM Output]](../static/img/transform/fx_rose_trans.png)
Notez que pour que ce qui précède fonctionne correctement, j'ai dû m'assurer que « rose: » possédait effectivement un canal alpha avec lequel « [-fx](https://imagemagick.org/command-line-options/#fx) » puisse travailler. Je l'ai fait grâce à l'Opérateur de contrôle du canal alpha. Cette capacité de l'opérateur « [-fx](https://imagemagick.org/command-line-options/#fx) » à manipuler les canaux RGBA d'une image rend cet opérateur parfait pour la manipulation des canaux et des masques.
Depuis IM 6.2.10, vous pouvez ajouter des affectations de variables aux expressions « [-fx](https://imagemagick.org/command-line-options/#fx) », ce qui permet de réduire la complexité de certaines expressions qui seraient autrement pour ainsi dire impossibles à écrire. Par exemple, ici je crée un dégradé basé sur la distance depuis un point particulier (affecté aux variables « xx » et « yy »). Sans l'usage des variables, cette formule aurait pu devenir très difficile à lire. |
magick -size 100x100 xc: -channel G \
-fx 'xx=i-w/2; yy=j-h/2; rr=hypot(xx,yy); (.5-rr/70)*1.2+.5' \
-separate fx_radial_gradient.png
![[IM Output]](../static/img/transform/fx_radial_gradient.png)
| En raison de la tokenisation simple utilisée par « [-fx](https://imagemagick.org/command-line-options/#fx) », les noms de variables ne peuvent être composés que de lettres et ne doivent pas contenir de chiffres. De plus, comme beaucoup de lettres seules sont utilisées pour des variables internes accédant à l'information de l'image, il est recommandé que les noms de variables comportent au moins deux lettres. C'est pourquoi j'utilise « xx » et « yy » plutôt que simplement « x » ou « y ».
---|---
| _La fonction « [-fx](https://imagemagick.org/command-line-options/#fx) » « rr=hypot(xx,yy) » a été ajoutée à IM v6.3.6 pour accélérer l'expression très couramment utilisée « rr=sqrt(xx*xx+yy*yy) ».
Bien entendu, si vous avez besoin du carré de la distance, vous devriez éviter la fonction « hypot() » et la fonction sqrt() qu'elle implique._
---|---
Pour d'autres exemples d'expressions vraiment complexes, voir Dégradés DIY plus complexes, qui seraient impossibles sans affectations à énoncés multiples. Il en va de même pour la forme FX de la distorsion en perspective. Depuis la version IM 6.3.0-1, la complexité des expressions « [-fx](https://imagemagick.org/command-line-options/#fx) » a commencé à nécessiter des fichiers externes, si bien que le standard « @_filename_ » peut désormais être utilisé pour lire l'expression depuis un fichier. |
echo "u*2" | magick rose: -fx "@-" fx_file.png
![[IM Output]](../static/img/transform/fx_file.png)
Cela signifie aussi que vous pouvez utiliser des scripts plus complexes pour générer les expressions FX spécifiques à une tâche particulière. En interne, le fichier est simplement lu dans une chaîne et interprété comme d'habitude. D'autres réglages importants pour « [-fx](https://imagemagick.org/command-line-options/#fx) » sont « [-virtual-pixel](https://imagemagick.org/command-line-options/#virtual-pixel) » et « [-interpolate](https://imagemagick.org/command-line-options/#interpolate) ». Le Réglage de pixel virtuel permet de définir quelles couleurs ou quels résultats d'image doivent être retournés lorsque les coordonnées de recherche sortent de la zone couverte par l'image d'entrée. Cela permet de définir des effets de bord pour des opérations comme les flous, ainsi que de mettre l'image en mosaïque sur une zone plus grande. Le Réglage d'interpolation permet de spécifier comment IM doit mélanger les couleurs des pixels voisins lorsque les coordonnées de recherche (valeurs à virgule flottante) tombent entre les coordonnées entières des pixels de l'image d'entrée. Pour plus d'informations, voir Recherche de pixel par interpolation. | Quelques fonctions supplémentaires ont été ajoutées à divers moments
IM v6.3.6 : hypot()
IM v6.7.3-4 : while(), not(), guass(), squish()
---|---
Débogage FX
« debug(_expr_) » est essentiellement un moyen d'afficher une valeur à virgule flottante, chaque fois que l'expression FX est calculée. Cela fournit à son tour une méthode pour déboguer vos expressions. Vous pouvez toutefois limiter la sortie de « debug() » en utilisant une expression conditionnelle ternaire if-else. Par exemple, ceci affichera les valeurs de couleur à virgule flottante du pixel 10,10 de l'image « rose: » intégrée. Le résultat d'image réel est ignoré grâce au gestionnaire d'image « [NULL:](files.html#null) ». |
magick rose: -fx 'i==10&&j==10?debug(u):1; u' null:
![[IM Output]](../static/img/transform/fx_debug.txt.gif)
Rappelez-vous que la sortie va sur la sortie d'erreur standard, et non sur la sortie standard normale, de sorte que vous pouvez l'utiliser dans un pipeline de commandes sans problème. Notez que l'expression FX a été exécutée trois fois, une fois pour chaque canal, pour ce seul pixel. Multipliez cela par le nombre de pixels, et vous pouvez imaginer la longueur de la sortie si « debug() » n'était pas limité à un seul pixel, même pour cette petite image.
Opérations intégrées de type FX
L'opérateur [-fx](https://imagemagick.org/command-line-options/#fx) représente un moyen de développer de nouvelles fonctions de traitement d'image qui n'existaient pas auparavant dans ImageMagick. Le résultat de tels développements par les utilisateurs a permis à ImageMagick de s'étendre, avec de nouvelles fonctions et méthodes, telles que la Table de correspondance de couleurs (« [-clut](https://imagemagick.org/command-line-options/#clut) »). Généralement toutefois, une fois qu'une nouvelle méthode s'est stabilisée à l'aide de « [-fx](https://imagemagick.org/command-line-options/#fx) », l'expression est convertie en une opération intégrée plus rapide, habituellement ajoutée dans le cadre d'un groupe d'opérateurs similaires. Ceux-ci comprennent les opérateurs d'image généraux suivants et leurs méthodes… -evaluate | Fonctions de modification directe des pixels, valeurs de couleur, canaux.
(Voir Evaluate ci-dessous).
---|---
-function | Fonctions plus complexes de modification des pixels, valeurs de couleur, canaux.
(Voir Function ci-dessous).
-evaluate-sequence | Fusionner mathématiquement une séquence de plusieurs images
(Voir Evaluate-Sequence ci-dessous).
-sparse-color | Opérateur général de recoloration d'image.
(Voir Dégradés Sparse Color )
-compose | Méthode générale de combinaison et de superposition de plusieurs images.
(Voir Composition alpha).
-distort | Opérateur général de distorsion d'image, utilisant un mappage de pixels inversé.
(Voir l'Opérateur Distort )
-morphology | Fonction générale de convolution/morphologie à effet de zone.
(Voir l'Opérateur Morphology et l'Opérateur Convolve )
Lorsque des personnes développaient de nouveaux types d'opérations d'image, elles en réalisaient généralement d'abord un prototype à l'aide d'un opérateur « [-fx](https://imagemagick.org/command-line-options/#fx) ». Une fois la mise au point terminée, cette « méthode » est alors convertie en un nouvel opérateur intégré ultra-rapide dans la bibliothèque ImageMagick Core. Les utilisateurs sont invités à proposer leurs propres expressions « [-fx](https://imagemagick.org/command-line-options/#fx) » (ou d'autres fonctions définies) qui, selon eux, constitueraient un ajout utile à IM, mais qui ne sont pas encore couvertes par d'autres opérateurs d'image ; si elles peuvent être prises en charge par l'un des opérateurs généralisés ci-dessus, il devrait être raisonnablement facile de les ajouter. Par exemple, j'avais moi-même besoin d'une opération de type « masquer si couleur similaire » pour comparer deux images. Elle a été ajoutée sous la forme d'une nouvelle méthode « [-compose](https://imagemagick.org/command-line-options/#compose) » « [ChangeMask](compose.html#changemask) ». Cela m'a ensuite permis d'ajouter une Optimisation de la transparence plus complexe pour les animations GIF. Si la vitesse et la complexité de « [-fx](https://imagemagick.org/command-line-options/#fx) » commencent à poser problème, il est probablement préférable de passer à un langage de script d'API tel que PerlMagick. Un exemple de cela utilisant PerlMagick, « [pixel_fx.pl](https://github.com/ImageMagick/ImageMagick/blob/main/PerlMagick/demo/pixel-fx.pl) », fait partie de la distribution de cette API.
Expressions FX comme échappements de format et d'annotation
Depuis la version IM 6.2.10, vous pouvez désormais utiliser des Expressions FX au sein de chaînes d'échappement de propriétés d'image telles que celles utilisées par les arguments « [-format](https://imagemagick.org/command-line-options/#format) » et « [-annotate](https://imagemagick.org/command-line-options/#annotate) ». La séquence d'échappement « %[fx:...] » est remplacée par un nombre sous forme de valeur à virgule flottante, calculée une fois pour chaque image de la séquence d'images courante. L'Expression FX est cependant légèrement modifiée durant le traitement. Précisément…
- Les coordonnées du pixel courant «
i», «j» sont fixées à la valeur 0, de sorte qu'à elle seule une variable d'image ne retourne que la valeur du pixel 0,0, à moins qu'un index «p{}» ne soit utilisé. - Sauf si un canal de couleur est sélectionné, seule la valeur du canal rouge est retournée.
- La référence d'image par défaut «
s» est réglée sur l'image courante, en cours d'annotation ou d'identification. - L'index «
t» retourne l'index de l'image référencée par «s».
| Avant IM v6.6.8-6, les deux valeurs d'expression FX « t » (index d'image) et « n » (nombre total d'images) étaient défectueuses, et ne retournaient respectivement que les valeurs 0 et 1 pour TOUTES les images. Il en va de même pour les échappements pour cent équivalents « %p » et « %n ».
---|---
Par exemple, ici j'« [-annotate](https://imagemagick.org/command-line-options/#annotate) » chaque image avec la couleur de son coin supérieur gauche. |
magick -size 150x25 xc:DarkRed xc:Green xc:Blue \
-fill white -gravity center \
-annotate 0 '%[fx:t] / %[fx:n] : %[fx:r],%[fx:g],%[fx:b]' \
annotate_fx_%d.gif
![[IM Output]](../static/img/transform/annotate_fx_2.gif)
Remarquez comment le texte écrit diffère pour chaque image, car « r » est en fait équivalent à « s.p{0,0}.r ». Il en va de même pour les valeurs des canaux de couleur « g » et « b ». Bien entendu, chacune retourne une valeur normalisée dans la plage de 0.0 à 1.0. Pour faciliter la sortie des valeurs de couleur de pixels spécifiques, un échappement « %[pixel:...] » a également été ajouté dans IM v6.3.0. Cet opérateur appelle l'expression FX donnée une fois pour chaque canal de chaque image, et met en forme la valeur retournée en une couleur qu'IM peut traiter comme argument de couleur.
magick -size 300x100 gradient:yellow-limegreen \
-gravity NorthWest -annotate 0 '%[pixel:s.p{0,0}]' \
-gravity Center -annotate 0 '%[pixel:s.p{0,50}]' \
-gravity SouthEast -annotate 0 '%[pixel:s.p{0,99}]' \
annotate_pixel.gif
Vous pouvez simplement afficher le résultat directement à l'aide d'un « [-format](https://imagemagick.org/command-line-options/#format) » avec la commande « [identify](basics.html#identify) ». |
magick identify -format '%[fx:atan(1)*4]' null:
![[IM Output]](../static/img/transform/fx_math.txt.gif)
Cela calcule et retourne mathématiquement la valeur de PI , bien que cette valeur soit disponible via la variable intégrée « pi ». Vous pouvez générer des nombres aléatoires. Par exemple, pour générer un entier compris entre -5 et 10 inclus. Ici, j'utilise l'équivalent « [info:](https://usage.imagemagick.org/files/#info:) » de la commande « magick identify ». |
magick xc: -format '%[fx:int(rand()*16)-5]' info:
![[IM Output]](../static/img/transform/fx_rand.txt.gif)
Pour d'autres méthodes, voir Alternatives à Identify : options de sortie texte. Voir aussi Bordure à coins arrondis qui a utilisé des Expressions FX pour générer une chaîne de dessin basée sur l'information de largeur et de hauteur de l'image. Vous pouvez Calculer la position des images à l'aide de formules FX ou même les positionner à l'aide de la taille et de l'emplacement d'autres images (voir Positions calculées de manière incrémentale). Vous pouvez également utiliser des Échappements FX dans les Échappements pour cent de nom de fichier pour générer de nouveaux fichiers basés sur des valeurs calculées. Pour un exemple, voir le dernier exemple dans Découpe en tuiles.
Tout ce qui précède exécutera pour l'essentiel le « [-format](https://imagemagick.org/command-line-options/#format) », et donc toute Expression FX qu'il contient, une fois pour chaque image de la séquence d'images courante. L'opérateur « [-print](https://imagemagick.org/command-line-options/#print) » fonctionne à peu près comme « [-identify](https://imagemagick.org/command-line-options/#identify) », sauf qu'il n'est exécuté qu'une seule fois, avec accès à TOUTES les images de la séquence d'images courante. Avec cet opérateur, vous pouvez utiliser « u[{i}] » pour accéder aux valeurs de n'importe quelle image, contrairement à ce qui précède.
Les expressions Fx peuvent être appliquées à des images dans d'autres espaces colorimétriques ; ainsi je peux par exemple connaître la valeur de « Teinte » (dans le canal « rouge ») pour trois couleurs différentes. |
magick xc:red xc:green xc:blue -colorspace HSL \
-format '%[fx: s.r ]\n' info:
![[IM Output]](../static/img/transform/fx_hues.txt.gif)
Vous pouvez également utiliser IM pour certains calculs de couleur directs, comme trouver la couleur moyenne de « gold », « yellow » et « khaki ». |
magick xc: -format '%[pixel:(gold+yellow+khaki)/3]' info:
![]()
Tandis que ceci montre à quoi ressemble la couleur comparée aux trois couleurs sources… |
magick xc:gold xc:yellow xc:khaki +append \
\( xc: -fx '(gold+yellow+khaki)/3' \) \
-scale 90x30\! -append fx_hues.png
![[IM Output]](../static/img/transform/fx_hues.png)
Vous pouvez aussi utiliser « [-print](https://imagemagick.org/command-line-options/#print) » pour afficher des informations. Cela n'est appliqué qu'une seule fois sur l'ensemble de la séquence d'images. Cela signifie que vous pouvez utiliser cet opérateur pour calculer des expressions « %[fx:...] » bien plus complexes impliquant plusieurs images.
Accéder aux données d'autres images
L'utilisation d'expressions échappées FX pose toutefois un problème sérieux. IM n'a pas d'accès direct aux autres images de la séquence d'images courante lorsque vous créez des images. Cela n'est tout simplement généralement pas nécessaire, dans la création d'images typique, car les nouvelles images ne dépendent généralement pas des images précédentes en mémoire. En gros, si vous voulez récupérer la couleur d'un pixel précis dans une image différente de celle sur laquelle vous dessinez (comme ci-dessus), ou si vous créez une nouvelle image, alors les fonctions IM Core n'ont aucun lien direct vers l'information désirée. Par exemple, si vous essayez de créer une étiquette avec la couleur du pixel 12,26 de l'image « rose: » intégrée (un pixel bleuâtre), l'approche directe échouera ! |
magick rose: label:'%[pixel:p{12,26}]' -delete 0 label_fx_direct.gif
![[IM Output]](../static/img/transform/label_fx_direct.gif)
Or, l'image rose ne contient en réalité aucun pixel noir, si bien que le résultat ci-dessus était erroné. La manière de corriger cela consiste à extraire l'information voulue et à l'enregistrer dans les métadonnées globales d'IM. Celles-ci sont transmises à tous les sous-programmes du cœur de la bibliothèque, y compris ceux dédiés à la création d'images. |
magick rose: -set option:mylabel '%[pixel:u.p{12,26}]' -delete 0 \
label:'%[mylabel]' label_fx_indirect.gif
![[IM Output]](../static/img/transform/label_fx_indirect.gif)
Ce n'est pas intuitif, mais nous obtenons maintenant le résultat correct. La balise spéciale « option: » indique à l'option « [-set](https://imagemagick.org/command-line-options/#set) » que vous voulez que le réglage donné soit enregistré en tant qu'Artefact global, plutôt que comme chaîne d'« Attribut » ou de « Propriétés » de l'image, tout comme « [-define](https://imagemagick.org/command-line-options/#define) » peut le faire. Toutefois, la forme « [-set](https://imagemagick.org/command-line-options/#set) » vous permet de développer les Échappements pour cent lors de la définition de l'Artefact, ce que « [-define](https://imagemagick.org/command-line-options/#define) » ne fait pas. Lorsque l'opérateur « label: » développe ses échappements pour cent, la « clé » donnée est d'abord recherchée en tant qu'« attribut » ou « propriétés » par image, mais s'il ne trouve rien, il cherche alors la « clé » dans les réglages d'Artefact globaux. Ainsi, l'« artefact » global que nous avons créé à partir de l'image précédente est utilisé, même si cette image n'est plus présente au moment où l'Artefact a été créé. En gros, les réglages d'« Artefact » sont globaux pendant toute la durée de vie de la commande « magick », et peuvent donc servir à transmettre de l'information d'une image à une autre. Pour les API programmées, cette situation peut être évitée, car vous pouvez lire les données requises directement depuis l'image et générer vous-même la chaîne d'étiquette, sans avoir besoin qu'IM stocke cette information d'une manière aussi alambiquée.
Evaluate et Function, modificateurs de canal libres
Comme l'Opérateur FX est un gestionnaire d'expressions interprétées, l'opérateur « [-evaluate](https://imagemagick.org/command-line-options/#evaluate) » a été ajouté pour permettre d'effectuer plus rapidement de simples modifications d'image. Plus tard, un opérateur « [-function](https://imagemagick.org/command-line-options/#function) » plus complexe a été ajouté dans IM v6.4.8-8, pour offrir une plus grande souplesse dans les ajustements d'image complexes. Ces deux opérateurs, ainsi que d'autres Opérateurs d'ajustement de niveau d'image tels que « [-negate](https://imagemagick.org/command-line-options/#negate) », « [-level](https://imagemagick.org/command-line-options/#level) », seront probablement les plus utiles pour des retouches mineures sur des images en niveaux de gris, avant que vous n'appliquiez ces images. En particulier pour les images en niveaux de gris telles que celles utilisées pour la Suppression de l'arrière-plan, les Superpositions de rehauts et d'ombres, ainsi que la génération et le réglage fin des Cartes d'image.
Evaluate, opérations mathématiques simples
L'opérateur « [-evaluate](https://imagemagick.org/command-line-options/#evaluate) » est essentiellement une version rapide, mais très simple, de l'opérateur « [-fx](https://imagemagick.org/command-line-options/#fx) » (en réalité, il précède son ajout à IM de quelques mois seulement). Il est cependant limité à une seule opération simple, utilisant un unique nombre constant fourni par l'utilisateur. Vous pouvez découvrir quelles fonctions ont été intégrées à evaluate en utilisant
magick -list evaluate
Cela inclut les fonctions mathématiques typiques « add », « subtract », « multiply » et « divide », par rapport à des valeurs constantes. Contrairement à l'opérateur [-fx](https://imagemagick.org/command-line-options/#fx), les valeurs ne sont pas normalisées dans une plage de 0 à 1, mais restent les valeurs de couleur réelles de l'image. Ainsi, soustraire une valeur de 50 dans un IM Q8 (voir Qualité et profondeur) entraînera une soustraction importante, mais pour une version Q16 d'IM, ce ne sera qu'un changement minime, à peine perceptible. Cependant, si vous ajoutez un « % » à l'argument, cet argument représentera un pourcentage de la valeur de couleur maximale (connue sous le nom de « QuantumRange », qui est égale à (« 2 _quality_ -1 »). Cela signifie que vous pouvez rendre vos arguments « [-evaluate](https://imagemagick.org/command-line-options/#evaluate) » indépendants du niveau de qualité d'IM, par un usage approprié des pourcentages pour les méthodes evaluate appropriées. Par exemple, remplacer simplement toutes les valeurs de couleur d'une image par un niveau de gris à 50 % est très simple et très rapide, en utilisant « Set » |
magick rose: -evaluate set 50% rose_set_gray.gif
![[IM Output]](../static/img/transform/rose_set_gray.gif)
L'opérateur « [-evaluate](https://imagemagick.org/command-line-options/#evaluate) » inclut également les fonctions mathématiques typiques « add », « subtract », « multiply » et « divide ». Par exemple, pour réduire de moitié le contraste de l'image, vous pouvez la « divide » par « 2 » puis « add » « 25% » pour la recentrer autour d'un gris parfait. |
magick rose: -evaluate divide 2 -evaluate add 25% rose_de-constrast.gif
![[IM Output]](../static/img/transform/rose_de-constrast.gif)
C'est plusieurs ordres de grandeur plus rapide que d'utiliser directement l'opérateur « [-fx](https://imagemagick.org/command-line-options/#fx) » avec « u/2+.25 ». Vous devriez donc utiliser cet opérateur de préférence à « [-fx](https://imagemagick.org/command-line-options/#fx) » chaque fois que possible. Le principal problème de « [-evaluate](https://imagemagick.org/command-line-options/#evaluate) » est que tous les résultats sont écrêtés aux limites 0 à « QuantumRange » (à moins que vous n'utilisiez une version HDRI d'ImageMagick), car chaque valeur modifiée est réenregistrée dans les données de l'image. Cela signifie qu'après toute opération « [-evaluate](https://imagemagick.org/command-line-options/#evaluate) » individuelle, les valeurs pourraient être écrêtées par le « QuantumRange ». Ainsi, si vous essayez d'appliquer une fonction de rehaussement de contraste (équivalente à « [-fx](https://imagemagick.org/command-line-options/#fx) '2*u-.25' ») directement telle quelle, vous n'obtiendrez pas les résultats corrects, car la valeur doublée sera écrêtée avant que la soustraction ne soit effectuée. |
magick rose: -evaluate multiply 2 -evaluate subtract 25% \
rose_contrast.gif
![[IM Output]](../static/img/transform/rose_contrast.gif)
D'abord le « multiply » écrête toutes les grandes valeurs de couleur à la valeur maximale, puis le « subtract » écrête les valeurs de la borne inférieure. Le résultat est un écrêtage incorrect des bornes supérieures, produisant un résultat sombre et aux couleurs déformées. La solution directe consiste à « subtract » d'abord la constante appropriée (en effectuant l'écrêtage final mais correct des bornes inférieures), avant de multiplier, en utilisant en fait la formule équivalente « (u-.125)*2 » |
magick rose: -evaluate subtract 12.5% -evaluate multiply 2 \
rose_contrast2.gif
![[IM Output]](../static/img/transform/rose_contrast2.gif)
Il existe cependant de nombreuses alternatives à ce problème d'« écrêtage ». La première logique étant la plus récente Méthode de fonction polynomiale (voir ci-dessous). D'autres alternatives incluent aussi l'utilisation d'Opérateurs d'ajustement de niveau ou même d'un Ajustement de niveau par couleur, pour spécifier simplement les valeurs de couleur originales que vous voulez étirer, afin de remplir toute la plage de couleurs. En gros, faites attention à l'écrêtage des valeurs de couleur lorsque vous utilisez plusieurs méthodes « [-evaluate](https://imagemagick.org/command-line-options/#evaluate) ».
L'opérateur « [-evaluate](https://imagemagick.org/command-line-options/#evaluate) », comme « [-fx](https://imagemagick.org/command-line-options/#fx) » (et la plupart des autres opérateurs IM de bas niveau), est affecté par « [-channel](https://imagemagick.org/command-line-options/#channel) ». Cela vous permet de contrôler la transparence alpha d'une image séparément des canaux de couleur. Et oui, comme « [-fx](https://imagemagick.org/command-line-options/#fx) », la transparence est traitée comme des « valeurs alpha » et non comme une valeur « matte ». Par exemple, pour rendre une image transparente à 50 %, dans le cadre d'une opération de type Dissolve. |
magick rose: -alpha set -channel A -evaluate divide 2 rose_transparent.png
![[IM Output]](../static/img/transform/rose_transparent.png)
Le résultat est une image semi-transparente, ce qui signifie qu'à l'affichage, la moitié de la couleur que vous voyez est la couleur d'arrière-plan de la page web. L'image affichée est donc atténuée vers la couleur d'arrière-plan. J'ai aussi souvent constaté qu'il est fréquemment plus simple d'utiliser « [-evaluate](https://imagemagick.org/command-line-options/#evaluate) » sur les canaux de couleur individuels avant de séparer les différents canaux en images distinctes à des fins précises (voir Séparation des canaux). Par exemple, ici je l'utilise pour réaliser une forme rapide, mais inhabituelle, de conversion en niveaux de gris. En gros, je multiplie chaque canal par la quantité appropriée, puis je sépare et additionne les canaux pour produire une image ayant été mise en niveaux de gris à l'aide d'un ensemble spécifique de ratios de couleur. |
magick test.png -channel R -evaluate multiply .2 \
-channel G -evaluate multiply .5 \
-channel B -evaluate multiply .3 \
-channel RGB -separate -background black -compose plus -flatten gray_253.png
Fonctions mathématiques d'Evaluate
Evaluate inclut également un ensemble de fonctions mathématiques à usage spécial. Ces fonctions sont généralement implémentées de manière à utiliser une valeur de couleur normalisée (plage de 0 à 1) avec une sortie de nouveau normalisée afin de s'ajuster à toute la plage de couleurs de l'image. La fonction Contraste sigmoïdal est aussi un exemple de cet ajustement de fonction mathématique.
Puissance
La fonction « Pow » (ajoutée dans IM v6.4.1-9) fonctionne par exemple avec des valeurs de couleur normalisées, et permet aux utilisateurs d'effectuer des modifications de luminosité de l'image. Elle est exactement équivalente à la fonction C pow(), (en utilisant des valeurs de couleur normalisées dans une plage de 0 à 1)
value = pow(value, constant)
Ainsi, pour créer un dégradé « parabolique », vous pouvez utiliser un argument de « 2 ». Ou utiliser une valeur de « 0.5 » pour créer un dégradé « racine carrée ». Par exemple…
magick -size 20x600 gradient: -rotate 90 gradient.png
magick gradient.png -evaluate Pow 2 eval_pow_parabola.png
magick gradient.png -evaluate Pow 0.5 eval_pow_sq_root.png
| Les trois images du bas montrent le profil du dégradé produit, à la fois sous forme de graphe et de l'image originale elle-même. Cela facilite la compréhension de la façon dont une image de dégradé a été modifiée pour en devenir une autre. Elles ont été générées à l'aide du programme de tracé de graphesGnuplot, via le script « [im_profile](../static/img/scripts/im_profile) » du répertoire Scripts d'IM Examples.
---|---
Ceci est en fait équivalent à l'opérateur Ajustement gamma mais avec l'argument inversé. Par exemple, une opération « -gamma 2 » serait équivalente à une fonction d'opération « -evaluate pow 0.5 » ou « racine carrée ». De même, « -gamma 0.5 » est équivalent à une mise au carré à l'aide de « -evaluate pow 2 ». En effectuant certaines manipulations spéciales de dégradés, vous pouvez utiliser cette méthode pour transformer un dégradé linéaire en un arc circulaire complexe. |
magick -size 20x300 gradient: -rotate 90 \
-evaluate Pow 2 -negate -evaluate Pow 0.5 \
-flop \( +clone -flop \) +append eval_circle_arc.png
![[IM Output]](../static/img/transform/eval_circle_arc_pf.gif)
Pour ceux qui veulent comprendre cela, la deuxième ligne ci-dessus est équivalente à l'expression FX « sqrt(1-u^2) ». Cela génère un seul arc de quart de cercle, qui est ensuite Retourné horizontalement, et Concaténé, pour produire un arc de demi-cercle. C'est aussi bien plus rapide que d'utiliser une expression FX, même si cela nécessite beaucoup plus d'étapes individuelles (plus petites). Voir aussi la Fonction polynomiale plus avancée.
Logarithmique
La fonction « Log » (ajoutée dans IM v6.4.2-1) fonctionne aussi avec des valeurs normalisées (avec un 1.0 ajouté pour éviter les infinis), la constante donnée servant de base logarithmique. La formule réelle (avec des valeurs normalisées) est donc…
value = log(value*constant+1.0)/log(constant+1.0)
Par exemple… |
magick gradient.png -evaluate Log 10 eval_log.png
![[IM Output]](../static/img/transform/eval_log_pf.gif)
Cela peut sembler très similaire à la précédente Méthode Pow d'Evaluate, mais ce n'est pas tout à fait pareil. « Log » produira une pente appréciable à l'approche de « 0 », là où « Pow » produira une pente verticale. La valeur contrôle la pente. Une fonction logarithmique est aussi étroitement liée à une fonction exponentielle, qui n'est actuellement implémentée que comme opérateur d'Ajustement de contraste sigmoïdal. Celui-ci contient les mêmes caractéristiques de pente que vous pouvez voir dans les courbes logarithmiques ci-dessus. Cela explique pourquoi « [-sigmoidal-contrast](https://imagemagick.org/command-line-options/#sigmoidal-contrast) » est une meilleure technique pour rehausser les images comportant des conditions de faible luminosité, qu'un Ajustement gamma ou une courbe de type « puissance ».
Sinus et cosinus
Depuis IM v6.4.8-8, les méthodes « sin » et « cos » ont été ajoutées. Ces méthodes prennent la valeur donnée dans l'image et la normalisent en un angle de sorte que la plage complète couvre un cercle complet d'angles. Le résultat reçoit un biais de 50 % et est mis à l'échelle pour s'ajuster de nouveau dans la plage normale de valeurs. La constante est utilisée comme multiplicateur de la valeur (et donc de l'angle), si bien que « N » signifie que la fonction fera « N » fois le tour du cercle sur toute la plage de valeurs. Précisément, elle définit ces fonctions (en utilisant des valeurs normalisées) ainsi…
value = 0.5 * sin( constant*value*2*PI ) + 0.5
value = 0.5 * cos( constant*value*2*PI ) + 0.5
Essentiellement, ce que ces fonctions font, c'est remapper les valeurs de l'image (généralement des valeurs en niveaux de gris) sur une courbe sinus/cosinus. Par exemple, ici je prends une image de dégradé et je la modifie à l'aide de ces méthodes evaluate.
magick gradient.png -evaluate sin 1 eval_sin_1.png
magick gradient.png -evaluate cos 1 eval_cos_1.png
Or, comme le paramètre constant est un multiplicateur d'angle, la valeur donnée à la méthode evaluate créera ce nombre de pics sur l'ensemble du dégradé au sein d'une image. |
magick gradient.png -evaluate cos 5 -negate eval_cos_5.png
![[IM Output]](../static/img/transform/eval_cos_5_pf.gif)
C'est parfait pour de nombreuses tâches, de la génération d'effets d'ondulation ou de dispersion à la génération de courbes de déplacement d'aspect ondulé. En utilisant une constante multiplicatrice de « 0.5 », vous pouvez simplement transformer un dégradé linéaire en un dégradé en courbe sinusoïdale, qui conserve la même pente que l'original. En inversant (negate) le résultat, vous pouvez faire en sorte que le dégradé s'incline aussi correctement. |
magick gradient.png -evaluate cos 0.5 -negate eval_cos.5.png
![[IM Output]](../static/img/transform/eval_cos.5_pf.gif)
Ce qui est excellent pour générer des dégradés lisses à utiliser dans des photos qui se chevauchent. Toutefois, ces deux dernières méthodes « [-evaluate](https://imagemagick.org/command-line-options/#evaluate) » sont rarement utilisées, car elles ont été remplacées par une Fonction Sinusoid plus générale (voir ci-dessous) qui offre davantage d'options de contrôle, au-delà d'une simple option de fréquence.
Function, Evaluate à plusieurs arguments
Les générateurs d'ondes ci-dessus se sont révélés extrêmement utiles, en particulier avec le Mappage d'image de distorsion. Mais on a constaté qu'un contrôle bien plus fin des fonctions était nécessaire, exigeant plus d'un paramètre. C'est pourquoi l'opérateur « [-function](https://imagemagick.org/command-line-options/#function) » a été ajouté dans IM v6.4.8-9. En gros, « [-function](https://imagemagick.org/command-line-options/#function) » est une forme à plusieurs arguments de « [-evaluate](https://imagemagick.org/command-line-options/#evaluate) ». Cependant, contrairement à l'Opérateur Evaluate, ces opérateurs, comme les opérateurs mathématiques, ne fonctionnent tous que sur des valeurs de canal normalisées (plage de 0.0 à 1.0) de l'image, ce qui, dans la plupart des cas, les rend plus faciles à utiliser.
Fonction polynomiale
La méthode « polynomial » prendra n'importe quel nombre de valeurs, et modifiera les valeurs de couleur d'une image selon l'expression exacte donnée, bien plus rapidement que ne le peut l'Opérateur FX.
-function Polynomial a,b,c,...
Chaque valeur sera utilisée comme coefficient, du plus haut degré au plus bas, pour produire un polynôme comportant le nombre de termes donné. Par exemple, un argument de « 4,-4,1 » générera l'expression polynomiale équivalente à l'expression « [-fx](https://imagemagick.org/command-line-options/#fx) » « 4*u^2 - 4*u + 1 ». Si vous connaissez vos mathématiques du lycée, vous devriez alors savoir que cette fonction polynomiale produit une courbe parabolique allant de 1.0 à 0.0 puis revenant à 1.0, sur la plage de couleurs d'entrée (« u ») de 0.0 à 1.0. Autrement dit, elle rendra les couleurs noires et blanches « blanches », et les gris parfaits « noirs ». |
magick gradient.png -function Polynomial 4,-4,1 func_parabola.png
![[IM Output]](../static/img/transform/func_parabola_pf.gif)
Vous pouvez même créer un dégradé bien plus complexe, par exemple un polynôme quartique, qui était le résultat de la génération d'un Ajustement de niveau par courbe, à l'aide d'un ensemble de « points de contrôle de niveau ». Cela sert typiquement à ajuster les couleurs d'une image pour lui donner divers effets d'ombrage. |
magick gradient.png -function Polynomial '-25, 53, -36, 8.3, 0.2' \
func_quartic.png
![[IM Output]](../static/img/transform/func_quartic_pf.gif)
Bien entendu, une simple modification linéaire est également possible, exactement comme vous l'obtiendriez en utilisant un Opérateur Level… |
magick gradient.png -function Polynomial '4, -1.5' func_linear.png
![[IM Output]](../static/img/transform/func_linear_pf.gif)
Notez toutefois que vous ne pouvez pas utiliser « Polynomial » pour effectuer une opération complète de Seuil, en raison du besoin de coefficients infinis pour y parvenir, bien que vous puissiez vous en approcher assez près. Une valeur unique n'est naturellement qu'une constante, et se traduit par une affectation directe de cette valeur. En d'autres termes, c'est exactement comme la méthode « [-evaluate](https://imagemagick.org/command-line-options/#evaluate) Set », dans ce cas à une valeur de gris à 33 %. |
magick gradient.png -function Polynomial 0.33 func_constant.png
![[IM Output]](../static/img/transform/func_constant_pf.gif)
En combinant un « Polynomial » avec d'autres fonctions mathématiques, vous pouvez créer des modifications de dégradé encore plus complexes. Par exemple, en prenant la racine carrée d'un polynôme, je peux créer un véritable arc circulaire sur un dégradé linéaire. L'expression « [-fx](https://imagemagick.org/command-line-options/#fx) » équivalente « sqrt( -4*u^2 + 4*u + 0 ) »… |
magick gradient.png -function Polynomial -4,4,0 -evaluate Pow 0.5 \
func_circle_arc.png
![[IM Output]](../static/img/transform/func_circle_arc_pf.gif)
Voir aussi la Méthode Pow d'Evaluate pour une alternative à ce qui précède.
Fonction Sinusoid
La méthode de fonction « Sinusoid » est une version bien plus avancée des méthodes « sin » et « cos » de « [-evaluate](https://imagemagick.org/command-line-options/#evaluate) », et peut en fait reproduire ces fonctions, mais vous disposez d'un bien meilleur contrôle sur la façon dont elle modifie les valeurs de couleur d'une image.
-function Sinusoid frequency,phase,amplitude,bias
Et elle est implémentée à l'aide de la formule…
value = ampl * sin(2*PI( freq*value + phase/360 ) ) + bias
Cela peut sembler complexe, mais garantit que la fonction est facile à utiliser. Seule la première valeur, « frequency », qui fonctionne exactement comme ci-dessus, est requise, tous les autres paramètres étant optionnels. Par défaut, elle génère une courbe sinusoïdale. |
magick gradient.png -function Sinusoid 1 func_sine.png
![[IM Output]](../static/img/transform/func_sine_pf.gif)
En ajoutant un argument « phase » en degrés, vous pouvez spécifier l'angle de départ de la courbe. Ce qui vous permet de transformer la courbe sinusoïdale par défaut en cosinusoïde. |
magick gradient.png -function Sinusoid 1,90 func_cosine.png
![[IM Output]](../static/img/transform/func_cosine_pf.gif)
En ajustant la « frequency » et la « phase », il est possible de transformer directement avec magick un dégradé linéaire en un dégradé sinusoïdal lisse allant du noir au blanc (du minimum au maximum le long d'une courbe sinusoïdale). Voir la méthode Evaluate Cosine pour une approche moins directe. |
magick gradient.png -function Sinusoid 0.5,-90 func_sine_grad.png
![[IM Output]](../static/img/transform/func_sine_grad_pf.gif)
Les deux valeurs optionnelles suivantes, « amplitude » et « bias », contrôlent l'échelle et la ligne centrale de la courbe sinusoïdale. Par exemple, on crée ici une onde (courbe cosinus inversée) qui oscille entre le blanc et le gris (valeurs allant de 0.75 ±0.25, soit 0.5 to 1.0), commençant et finissant sur le blanc. |
magick gradient.png -function Sinusoid 5,90,.25,.75 func_sine_bias.png
![[IM Output]](../static/img/transform/func_sine_bias_pf.gif)
Attention à ces derniers paramètres, car ils peuvent facilement faire dépasser à la forme d'onde les limites de la plage des valeurs de couleur, et donc être écrêtée (sauf si vous utilisez une version HDRI d'ImageMagick).
Fonction Arcsin
La fonction sinusoïdale inverse « Arcsin » a été ajoutée dans IM v6.5.3-0. Il s'agit d'une courbe spéciale nécessaire pour générer une carte de déplacement cylindrique. Ses paramètres sont…
-function Arcsin width,center,range,bias
Et elle est implémentée à l'aide de la formule...
value = range/PI * asin(2/width*( value - center ) ) + bias
Par défaut, les valeurs (si non définies) « 1, 0.5, 1, 0.5 » garantissent que la fonction est centrée de manière à couvrir toute la plage de couleurs de 0,0 à 1,1. |
magick gradient.png -function Arcsin 1 func_arcsin.png
![[IM Output]](../static/img/transform/func_arcsin_pf.gif)
En divisant par deux la « width » de la courbe résultante, on obtient… |
magick gradient.png -function Arcsin 0.5 func_arcsin_width.png
![[IM Output]](../static/img/transform/func_arcsin_width_pf.gif)
Le « center » permet de repositionner la courbe selon les valeurs de gris en entrée. |
magick gradient.png -function Arcsin 0.4,0.7 func_arcsin_center.png
![[IM Output]](../static/img/transform/func_arcsin_center_pf.gif)
L'argument « range » permet de réduire la plage de sortie des valeurs de couleur, et le « bias » ajuste le centre de cette plage. |
magick gradient.png -function Arcsin 0.5,0.5,0.5,0.5 func_arcsin_range.png
![[IM Output]](../static/img/transform/func_arcsin_range_pf.gif)
Remarquez comment sont traitées les valeurs devenues invalides du fait de la fonction. Cela permet un meilleur contrôle lorsque la fonction est utilisée dans des déplacements, et offre des moyens de les nettoyer. Les valeurs réellement utilisées sont « _bias_ ± _range_ /2 », comme on peut s'y attendre. Notez que si la « width » ou le « range » est rendu négatif, la pente de la fonction sera inversée du fait de cette valeur négative. |
magick gradient.png -function Arcsin -1 func_arcsin_neg.png
Fonction Arctan
La méthode « Arctan » a été ajoutée dans IM v6.5.3-1. Ses paramètres sont…
-function Arctan slope,center,range,bias
Et elle est implémentée à l'aide de la formule...
value = range/PI * atan(slope*PI*( value - center ) ) + bias
Comme vous pouvez le voir, elle est presque exactement identique à la fonction « Arcsin », avec seulement une petite modification qui la rend plus utile. Elle possède même le même jeu de valeurs par défaut (si non définies) « 1, 0.5, 1.0, 0.5 ». Cela signifie que si vous spécifiez une valeur de pente de « 1.0 », la pente du changement de l'histogramme produira une variation 1:1 autour du gris pur (sans mise à l'échelle), tout en rendant le blanc et le noir plus gris. Par exemple |
magick gradient.png -function Arctan 1 func_arctan.png
![[IM Output]](../static/img/transform/func_arctan_pf.gif)
Autrement dit, la partie centrale du dégradé reste en réalité inchangée, seules les extrémités noire et blanche voyant leur contraste réduit. À mesure que la « slope » de la courbe augmente, le dégradé au centre devient d'autant plus marqué (plus comprimé au milieu). |
magick gradient.png -function Arctan 10 func_arctan_10.png
![[IM Output]](../static/img/transform/func_arctan_10_pf.gif)
À bien des égards, cela ressemble beaucoup à l'opérateur de modification de couleur Contraste sigmoïdal. Cependant, une fonction « Arctan » n'atteindra JAMAIS réellement les limites de la plage de sortie que sont le noir et le blanc purs. Elle s'approchera de ces limites sans jamais les franchir. Comme pour les fonctions précédentes (et le Contraste sigmoïdal), le second argument ajuste la position de la courbe par rapport aux valeurs du dégradé en entrée. |
magick gradient.png -function Arctan 10,.7 func_arctan_center.png
![[IM Output]](../static/img/transform/func_arctan_center_pf.gif)
Et les deux derniers arguments : « range » permet d'ajuster la plage de sortie des valeurs qui seront générées. Par exemple, en élargissant légèrement cette valeur, vous pouvez garantir qu'elle couvrira entièrement toute la plage des valeurs possibles. |
magick gradient.png -function Arctan 5,0.7,1.2 func_arctan_range.png
![[IM Output]](../static/img/transform/func_arctan_range_pf.gif)
Cependant, si vous voulez vraiment générer une courbe pour modifier ainsi tout le contraste d'une image, il est plus courant d'utiliser l'opérateur de contraste sigmoïdal, conçu à cette fin. L'usage plus typique d'une fonction de dégradé « Arctan » consiste à créer une courbe qui s'approchera très rapidement d'une valeur précise sans la dépasser. Ce sont ces valeurs limites que contrôlent les arguments « range » et « bias ». Par exemple, cette courbe modifiera le dégradé d'une image pour produire un seuil très net autour du niveau de gris d'entrée de 0.7, mais avec des valeurs variant entre les limites de plage de 0.5 et 1.0 |
magick gradient.png -function Arctan 15,0.7,0.5,0.75 func_arctan_typ.png
![[IM Output]](../static/img/transform/func_arctan_typ_pf.gif)
C'est quelque chose que le Contraste sigmoïdal ne peut pas générer.
Mathématiques sur les images de dégradé
Les fonctions ci-dessus fournissent des transformations très basiques pour les images de dégradé. Mais que faire si vous voulez effectuer des calculs mathématiques avec deux images de dégradé ou plus ? C'est-à-dire modifier un dégradé à l'aide du dégradé d'une autre image. Pour cela, vous devez utiliser les méthodes de composition mathématiques spéciales (comme « [Plus](compose.html#plus) » et « [Divide](#divide) »). Avant de commencer toutefois, je voudrais vous donner un avertissement. Si vos images de dégradé sont purement en niveaux de gris, sans canaux alpha, vous pouvez utiliser directement les méthodes de composition mathématiques. En revanche, si vous voulez limiter ces méthodes à un canal spécifique, ou les appliquer au canal alpha (transparence), vous devez veiller à définir le réglage « [-channel](https://imagemagick.org/command-line-options/#channel) » approprié, sans le drapeau de canal « Sync » spécial. Voir Mathématiques d'images par composition d'images pour plus de détails. Normalement, l'utilisation des méthodes de composition mathématiques n'est pas vraiment difficile. Les complications surviennent lorsque vous avez des dégradés qui contiennent aussi un « bias ». C'est-à-dire que le dégradé devrait représenter une valeur de « zéro » à 50 % de gris, et couvrir une plage allant de -1 (noir) à +1 (blanc). De telles images sont souvent utilisées pour le mappage d'image de distorsion. Ainsi, effectuer des mathématiques sur des « dégradés biaisés » est le vrai problème, et c'est ce qui sera examiné plus précisément ici.
Atténuer un dégradé biaisé
Par exemple, je veux ici créer une onde sinusoïdale, mais qui commence petite puis dont l'amplitude augmente. C'est ce qu'on appelle « atténuer » un dégradé biaisé. Ou, dit autrement, multiplier un dégradé biaisé par un autre dégradé absolu. C'est aussi ainsi que fonctionne la « modulation d'amplitude », comme dans la radio AM ! Il nous faut donc d'abord une onde sinusoïdale, que l'on peut simplement générer à partir d'un dégradé linéaire…
magick -size 5x300 gradient: -rotate 90 math_linear.png
magick math_linear.png -evaluate sine 12 math_sine.png
Maintenant, pour l'atténuer, on multiplie l'onde sinusoïdale par un dégradé linéaire, à l'aide d'une composition alpha Multiply…
magick math_sine.png math_linear.png \
-compose Multiply -composite math_sine_2.png
Mais pour l'utiliser dans, disons, une carte de déplacement d'ondulations d'eau, l'onde doit rester centrée autour d'un gris parfait. Pour cela, il faut ajouter un bias à l'image d'origine. Il se trouve que c'est la même fonction que celle utilisée pour multiplier l'image d'origine, inversée et divisée par deux…
magick math_linear.png -negate -evaluate divide 2 math_bias.png
magick math_sine_2.png math_bias.png \
-compose Plus -composite math_attenuated.png
Et nous avons ainsi un dégradé d'onde sinusoïdale atténué linéairement, adapté à un usage dans une carte de déplacement.
Bien sûr, vous pouvez réaliser tout le processus en une seule commande, et il n'est pas non plus nécessaire que ce soit une simple atténuation linéaire. Par exemple, j'atténue ici l'onde sinusoïdale à haute fréquence à l'aide d'une onde cosinus inversée, au lieu d'un dégradé linéaire.
magick math_linear.png -evaluate cos 1 -negate math_cosine_peak.png
magick math_sine.png math_cosine_peak.png \
\( -clone 0,1 -compose multiply -composite \) \
\( -clone 1 +level 50%,0 \
-clone 2 -compose plus -composite \) \
-delete 0--2 math_cosine_atten.png
Depuis IM v6.5.4-3, il est désormais possible d'effectuer toutes les étapes ci-dessus en une seule méthode de composition, à l'aide de la méthode de composition Mathematics spéciale. Il suffit essentiellement de reconnaître qu'une opération d'atténuation correspond à la formule Sc*Dc-.5*Sc+.5, soit les arguments « 1,-.5,0,.5 ». |
magick math_sine.png math_cosine_peak.png \
-compose Mathematics -set option:compose:args 1,-.5,0,.5 \
-composite math_attenuate.png
![[IM Output]](../static/img/transform/math_attenuate_pf.gif)
Le même résultat peut aussi être obtenu en ajustant d'abord le dégradé d'atténuation à l'aide d'une fonction polynomiale, puis en utilisant un opérateur de composition Exclusion pour fusionner les images. |
magick math_sine.png \( math_cosine_peak.png -function polynomial -.5,.5 \) \
-compose Exclusion -composite math_poly_excl.png
Multiplier des dégradés biaisés
Mais que se passe-t-il si les DEUX fonctions sont biaisées, de sorte qu'un gris parfait signifie zéro, et que le noir et le blanc représentent la plage de -1 à +1 ? Eh bien, c'est un peu plus complexe, car on ne peut pas simplement les multiplier en espérant que le résultat soit correct, la multiplication pouvant comporter des valeurs négatives. Cela demande une certaine prudence pour éviter d'écrêter les valeurs et pour obtenir la bonne négation de la courbe dans l'image résultante. L'astuce consiste à décomposer la multiplication en plusieurs étapes. Ainsi, A × B peut aussi s'écrire A × abs(B) × sign(B). En procédant ainsi, on évite de multiplier par une valeur négative, qui ne peut pas être stockée dans une image de dégradé normale. Il suffit donc de prendre l'un des dégradés biaisés et de le séparer en deux parties, afin de pouvoir les appliquer correctement à l'autre dégradé. Le « sign() » d'un dégradé biaisé, autrement dit l'obtention d'un masque des parties négatives, peut être extrait en appliquant un seuil sur le dégradé au niveau du bias. Vous pourrez ensuite négationner sélectivement l'autre dégradé à l'aide d'une composition Difference avec cette image de seuil. Le « abs() » d'un dégradé biaisé peut être extrait facilement à l'aide de Solarize, puis en l'inversant et en le doublant (à l'aide de Level) pour obtenir la valeur absolue du dégradé allant de 0.0 à 1.0. Comme nous aurons aussi besoin du décalage de bias dans le cadre de la multiplication (comme pour l'atténuation ci-dessus), vous pouvez directement utiliser la sortie de solarize inversée et réduite de moitié, avant qu'elle ne soit convertie en valeur absolue du dégradé. Transformons donc avec magick un dégradé en ces trois composants.
magick math_cosine_peak.png -threshold 50% -negate math_m_sign.png
magick math_cosine_peak.png -solarize 50% math_m_bias.png
magick math_m_bias.png -level 50%,0 math_m_abs.png
|
| Signe du dégradé
blanc = négatif
---|---|---
|
| Décalage de bias
|
| Valeur absolue
Maintenant que nous avons ces trois parties de l'une des images de dégradé, nous pouvons les fusionner avec l'autre dégradé. Pour cela, on multiplie par la valeur absolue, on rajoute le bias, puis on inverse les parties qui doivent être rendues négatives.
magick math_sine.png math_m_abs.png \
-compose Multiply -composite math_m_1.png
magick math_m_1.png math_m_bias.png \
-compose Plus -composite math_m_2.png
magick math_m_2.png math_m_sign.png \
-compose Difference -composite math_multiply.png
Et voilà une multiplication parfaite de deux images de dégradé biaisé ! La revoici, mais entièrement en une seule commande…
magick math_sine.png math_cosine_peak.png \
\( -clone 1 -threshold 50% -negate \) \
\( -clone 1 -solarize 50% \) \
\( -clone 3 -level 50%,0 \) \
\( -clone 0,4 -compose multiply -composite \
-clone 3 -compose plus -composite \
-clone 2 -compose difference -composite \) \
-delete 0--2 math_multiply_2.png
Une dernière remarque : contrairement à l'atténuation, cette multiplication de dégradés biaisés est commutative. Autrement dit, échanger les images d'entrée n'affecte pas le résultat final. Comme ce qui précède équivaut à la formule 2*Sc*Dc-Sc-Dc+1, depuis IM v6.5.4-3, vous pouvez implémenter les étapes complexes ci-dessus en une seule méthode de composition « [Mathematics](compose.html#mathematics) » à l'aide de l'argument « 2,-1,-1,1 ». |
magick math_sine.png math_cosine_peak.png \
-compose Mathematics -set option:compose:args 2,-1,-1,1 \
-composite math_bias_multiply.png
![[IM Output]](../static/img/transform/math_bias_multiply_pf.gif)
C'est une méthode bien plus simple et rapide que la douzaine d'étapes ou plus nécessaires sans cette méthode de composition avec arguments. Il se trouve qu'une fois cette formule vue, j'ai réalisé qu'elle correspond simplement à la négation de la méthode de composition « [Exclusion](compose.html#exclusion) ». Étrange, mais vrai. Ainsi, ce qui suit génère également la même multiplication à bias nul. |
magick math_sine.png math_cosine_peak.png \
-compose exclusion -composite -negate math_excl_neg.png
Additionner des dégradés biaisés
Avec l'arrivée de la méthode de composition « [Mathematics](compose.html#mathematics) », additionner des dégradés biaisés est aussi relativement facile. La formule FX équivalente est « u+v-0.5 », soit un argument de composition « 0,1,1,-.5 ». Par exemple, ce qui suit était un exemple de transformée de Fourier que j'avais généré à la main, nécessitant l'addition de 3 sinusoïdes biaisées et d'une valeur continue DC constante.
magick math_linear.png -function sinusoid 3.5,0,.25 wave_1.png
magick math_linear.png -function sinusoid 1.5,-90,.13 wave_2.png
magick math_linear.png -function sinusoid 0.6,-90,.07 wave_3.png
magick wave_1.png wave_2.png wave_3.png -background gray40 \
-compose Mathematics -set option:compose:args 0,1,1,-.5 \
-flatten added_waves.png
Remarquez ci-dessus comment j'ai utilisé l'opérateur « [-flatten](https://imagemagick.org/command-line-options/#flatten) » avec un réglage « [-background](https://imagemagick.org/command-line-options/#background) » pour réaliser une composition de plusieurs images. Ou, dans ce cas, une « somme biaisée » de toutes les images données plus la constante de fond.
Modulation de fréquence
En appliquant une fonction directement à la sortie d'une autre fonction, on NE produit PAS un résultat simple. La raison est que toutes ces fonctions mathématiques s'appliquent à la « valeur » de dégradé de chaque pixel, et non à la valeur x du pixel dans le dégradé. Par exemple… |
magick gradient.png -evaluate sin 0.5 -normalize \
-evaluate cos 8 math_cos_var.png
![[IM Output]](../static/img/transform/math_cos_var_pf.gif)
Cela génère une fonction très complexe, essentiellement équivalente à
cos( 8 * sin( _{value}_ /2 ) )
Autrement dit, une fréquence variable, où la fréquence varie avec le dégradé de la première courbe sinusoïdale. En gros, plus le dégradé change rapidement dans l'image d'origine, plus la distance entre les pics est petite. Cependant, la hauteur (amplitude) des pics ne varie pas. C'est en réalité ainsi que fonctionne la « modulation de fréquence », où une fonction apparemment simple produit un résultat très complexe.
En construction
Techniques diverses de transformation d'image.
Celles-ci n'ont pas encore été illustrées, mais ce sont quelques transformations basiques développées pour IM
qui pourraient être utiles. Si vous avez un effet intéressant, veuillez contribuer.
pixéliser une image
redimensionner une image par un facteur 10 vers le bas puis la mettre à l'échelle par 10 pour produire des blocs
de couleur approximativement moyennée.
Par exemple…
magick input.jpg -resize 10% -sample 1000% output.jpg
Corriger l'inclinaison d'images légèrement pivotées
-deskew {threshold}
redresser une image. Un seuil de 40 % fonctionne pour la plupart des images.
Utilisez -set option:deskew:auto-crop {width} pour rogner automatiquement l'image. L'argument
set est la largeur en pixels du fond de l'image (par ex. 40).
De façon programmatique, on rogne automatiquement en appliquant un filtre médian sur l'image
pour éliminer le bruit poivre et sel. Ensuite, on obtient les limites de l'image du
résultat du filtre médian avec un facteur de flou (par ex. -fuzz 5%). Enfin, on
rogne l'image d'origine selon ces limites. Le code ressemble à ceci :
median_image=MedianFilterImage(image,0.0,exception);
geometry=GetImageBoundingBox(median_image,exception);
median_image-DestoryImage(median_image);
print(" Auto-crop geometry: %lux%lu%+ld%+ld",
geometry.width,geometry.height, geometry.x,geometry.y);
crop_image=CropImage(rotate_image,&geometry,exception);
Voir [Rognage des images « bruitées »](crop.html#trim_blur)
Segmentation
regardez les scripts
[divide_vert](../static/img/scripts/divide_vert)
[segment_image](../static/img/scripts/segment_image)
pour quelques scripts simples que j'ai écrits pour segmenter des images bien définies en
parties plus petites. J'espère intégrer des fonctions de segmentation simples comme celle-ci
dans la bibliothèque principale, pour permettre par exemple la sous-division automatique des
animations GIF, et la séparation des images et diagrammes des documents scannés.
![[IM Output]](../static/img/transform/inside_border2.jpg)
![[IM Output]](../static/img/transform/spread_rose.png)
![[IM Output]](../static/img/images/rose.gif)
![[IM Output]](../static/img/transform/rose_paint_1.gif)
![[IM Output]](../static/img/transform/rose_paint_3.gif)
![[IM Output]](../static/img/transform/rose_paint_5.gif)
![[IM Output]](../static/img/transform/rose_paint_10.gif)
![[IM Output]](../static/img/transform/rose_blur_paint_10.gif)
![[IM Output]](../static/img/transform/rose_charcoal_1.gif)
![[IM Output]](../static/img/transform/rose_charcoal_3.gif)
![[IM Output]](../static/img/transform/rose_charcoal_5.gif)
![[IM Output]](../static/img/transform/rose_emboss_0x05.gif)
![[IM Output]](../static/img/transform/rose_emboss_0x09.gif)
![[IM Output]](../static/img/transform/rose_emboss_0x10.gif)
![[IM Output]](../static/img/transform/rose_emboss_0x11.gif)
![[IM Output]](../static/img/transform/rose_emboss_0x12.gif)
![[IM Output]](../static/img/transform/rose_emboss_0x20.gif)
![[IM Output]](../static/img/images/rose_grey.gif)
![[IM Output]](../static/img/transform/rose_g_emboss_0x05.gif)
![[IM Output]](../static/img/transform/rose_g_emboss_0x09.gif)
![[IM Output]](../static/img/transform/rose_g_emboss_0x10.gif)
![[IM Output]](../static/img/transform/rose_g_emboss_0x11.gif)
![[IM Output]](../static/img/transform/rose_g_emboss_0x12.gif)
![[IM Output]](../static/img/transform/rose_g_emboss_0x20.gif)
![[IM Output]](../static/img/transform/message.gif)
![[IM Text]](../static/img/transform/message_size.txt.gif)
![[IM Output]](../static/img/transform/rose_difference.png)
![[IM Text]](../static/img/transform/rose_diff_pae.txt.gif)
![[IM Output]](../static/img/transform/message_hidden.png)
![[IM Output]](../static/img/transform/message_obfuscate.png)
![[IM Output]](../static/img/transform/message_restored_2.png)
![[IM Output]](../static/img/transform/message_signed.png)
![[IM Output]](../static/img/transform/message_restored_3.png)
![[IM Output]](../static/img/transform/message_binary.png)
![[IM Output]](../static/img/transform/message_restored_4.png)
![[IM Output]](../static/img/transform/grid_input.png)
![[IM Output]](../static/img/transform/grid_scale.png)
![[IM Output]](../static/img/transform/grid_tile.png)
![[IM Output]](../static/img/transform/mask.gif)
![[IM Output]](../static/img/transform/mask_edge_1.gif)
![[IM Output]](../static/img/transform/mask_edge_2.gif)
![[IM Output]](../static/img/transform/mask_edge_3.gif)
![[IM Output]](../static/img/transform/mask_edge_10.gif)
![[IM Output]](../static/img/images/piglet.gif)
![[IM Output]](../static/img/transform/piglet_edge.gif)
![[IM Output]](../static/img/transform/rose_edge.gif)
![[IM Output]](../static/img/transform/rose_edge_grey.gif)
![[IM Output]](../static/img/transform/mask_canny.gif)
![[IM Output]](../static/img/transform/piglet_canny.gif)
![[IM Output]](../static/img/transform/piglet_canny_neg.gif)
![[IM Output]](../static/img/transform/rose_canny.gif)
![[IM Output]](../static/img/transform/heart_svg.gif)
![[IM Text]](../static/img/transform/heart_2.svg.gif)
![[IM Output]](../static/img/images/shape_rectangle.gif)
![[IM Output]](../static/img/transform/rectangle.gif)
![[IM Text]](../static/img/transform/rectangle_lines.mvg.gif)
![[IM Output]](../static/img/transform/shade_anthony.jpg)
![[IM Text]](../static/img/transform/shade_elevation_45.txt.gif)
![[IM Output]](../static/img/transform/shade_beveled.png)
![[IM Output]](../static/img/transform/shade_elevation_90.gif)
![[IM Output]](../static/img/transform/shade_beveled_edge.png)
![[IM Output]](../static/img/transform/shade_elevation_0.gif)
![[IM Output]](../static/img/transform/shade_elevation_15.gif)
![[IM Output]](../static/img/transform/shade_elevation_30.gif)
![[IM Output]](../static/img/transform/shade_elevation_45.gif)
![[IM Output]](../static/img/transform/shade_elevation_60.gif)
![[IM Output]](../static/img/transform/shade_elevation_75.gif)
![[IM Output]](../static/img/transform/shade_beveled_X.png)
![[IM Output]](../static/img/transform/shade_blur_3n.gif)
![[IM Output]](../static/img/transform/shade_blur_3n_mask.png)
![[IM Image]](../static/img/transform/shade_30.png)
![[IM Text]](../static/img/transform/shade_30.txt.gif)
![[IM Image]](../static/img/transform/shade_30_norm.png)
![[IM Text]](../static/img/transform/shade_30_norm.txt.gif)
![[IM Image]](../static/img/transform/shade_21_norm.png)
![[IM Text]](../static/img/transform/shade_21_norm.txt.gif)
![[IM Output]](../static/img/transform/shade_sig-10.png)
![[IM Output]](../static/img/transform/shade_sig-5.png)
![[IM Output]](../static/img/transform/shade_sig-2.png)
![[IM Output]](../static/img/transform/shade_sig_0.png)
![[IM Output]](../static/img/transform/shade_sig+2.png)
![[IM Output]](../static/img/transform/shade_sig+5.png)
![[IM Output]](../static/img/transform/shade_sig+10.png)
![[IM Output]](../static/img/transform/shade_overlay.png)
![[IM Output]](../static/img/transform/fx_blue.gif)
![[IM Output]](../static/img/transform/fx_combine.gif)
![[IM Output]](../static/img/transform/grey_253.png)
![[IM Output]](../static/img/transform/gradient.png)
![[IM Output]](../static/img/transform/eval_pow_parabola.png)
![[IM Output]](../static/img/transform/eval_pow_sq_root.png)
![[IM Output]](../static/img/transform/gradient_pf.gif)
![[IM Output]](../static/img/transform/eval_pow_parabola_pf.gif)
![[IM Output]](../static/img/transform/eval_pow_sq_root_pf.gif)
![[IM Output]](../static/img/transform/eval_sin_1.png)
![[IM Output]](../static/img/transform/eval_cos_1.png)
![[IM Output]](../static/img/transform/eval_sin_1_pf.gif)
![[IM Output]](../static/img/transform/eval_cos_1_pf.gif)
![[IM Output]](../static/img/transform/func_arcsin_neg.png)
![[IM Output]](../static/img/transform/func_arcsin_neg_pf.gif)
![[IM Output]](../static/img/transform/math_linear_pf.gif)
![[IM Output]](../static/img/transform/math_sine_pf.gif)
![[IM Output]](../static/img/transform/math_sine_2_pf.gif)
![[IM Output]](../static/img/transform/math_bias_pf.gif)
![[IM Output]](../static/img/transform/math_attenuated_pf.gif)
![[IM Output]](../static/img/transform/math_cosine_atten_pf.gif)
![[IM Output]](../static/img/transform/math_poly_excl_pf.gif)
![[IM Output]](../static/img/transform/math_m_1_pf.gif)
![[IM Output]](../static/img/transform/math_m_2_pf.gif)
![[IM Output]](../static/img/transform/math_multiply_pf.gif)
![[IM Output]](../static/img/transform/math_multiply_2_pf.gif)
![[IM Output]](../static/img/transform/math_excl_neg_pf.gif)
![[IM Output]](../static/img/transform/wave_1_pf.gif)
![[IM Output]](../static/img/transform/wave_2_pf.gif)
![[IM Output]](../static/img/transform/wave_3_pf.gif)
![[IM Output]](../static/img/transform/added_waves_pf.gif)