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

Exemples ImageMagick -- Traitement de la vidéo

Préface et index des exemples ImageMagick
De la vidéo au GIF, récapitulatif de l'optimisation
Désentrelacer une image de vidéo

ImageMagick n'est pas particulièrement adapté au traitement de la vidéo numérique, mais il est couramment employé à cet usage, surtout sous Linux. J'explore ici des techniques et des exemples propres au traitement de séquences vidéo réelles (et de synthèse).


De la vidéo au GIF, récapitulatif de l'optimisation

Un développeur qui se sert d'IM pour créer des GIF animés à partir de films, Benoit Rouleau, m'a donné au cours de nos échanges une vidéo AVI d'un avion qui passe au-dessus, afin de nous aider à explorer ensemble les techniques de conversion vidéo d'IM. Toutefois, si l'AVI lui-même est assez petit, la vidéo décompressée atteint la taille colossale de [IM Text] octets et met en jeu [IM Text] couleurs réparties sur [IM Text] images. IM n'a cependant aucun mal à convertir cette vidéo en animation GIF. Sachez tout de même que vous obtiendrez probablement quelques erreurs « AVI chunk » non prises en charge, que l'on peut ignorer à l'aide du paramètre de contrôle "[-quiet](https://imagemagick.org/command-line-options/#quiet)". |

  magick -quiet -delay 1 plane.avi plane.gif

[IM Output]
On a utilisé ici les méthodes par défaut de quantification des couleurs et de tramage d'ImageMagick, pour produire une conversion tout à fait correcte de la vidéo. Il y a très peu de problèmes de couleur, car la vidéo n'emploie au départ que très peu de couleurs. Ce n'est pas toujours le cas, d'autant que le format GIF est limité à 256 couleurs par image. Le fichier d'animation pèse cependant [IM Text] octets ; bien que ce ne soit que le cinquième de la taille d'origine, grâce à la réduction des couleurs et à la compression des données de pixels du GIF, cela reste assez volumineux. De plus, si vous examinez l'animation obtenue de plus près, vous constaterez que sur les [IM Text] images du fichier, [IM Text] images se sont vu ajouter leur propre table de couleurs locale distincte. Autrement dit, chacune des images de l'animation GIF a réclamé sa propre table d'index de couleurs. C'est-à-dire que, même si chaque image compte moins de 256 couleurs (en raison des limites du format GIF), l'animation entière fait appel à un total de [IM Text] couleurs. Malheureusement, le format GIF ne compresse pas les tables de couleurs, si bien que toutes ces tables supplémentaires peuvent occuper jusqu'à : 256 couleurs * 3 octets par couleur * 106 images, soit 81 408 octets d'espace de fichier. Ce n'est pas énorme pour une vidéo d'1 Go, mais cela reste une quantité d'espace non négligeable, surtout à mesure que nous optimisons davantage la vidéo. À cela s'ajoute le fait que l'animation se prêtera mal à l'optimisation d'images GIF. Non seulement parce que l'arrière-plan est en mouvement (la caméra effectuant un panoramique vers le haut), mais aussi parce qu'IM a utilisé un tramage par correction d'erreur (tramage par courbe de Hilbert), qui produit un motif de couleurs pseudo-aléatoire différent d'une image à l'autre. Un exemple ultérieur rendra ce « bruit de tramage » beaucoup plus visible.

Table de couleurs globale commune

Je génère ici une table de couleurs globale unique pour toutes les images de la vidéo. |

  magick -quiet -delay 1 plane.avi  +remap   plane_cgc.gif

On obtient alors naturellement [IM Text] tables de couleurs locales, pour une taille de fichier de [IM Text] octets. [IM Output]
Comme vous pouvez le voir, l'animation obtenue ne comporte aucune table de couleurs locale supplémentaire. À la place, IM a généré une table de couleurs globale unique de [IM Text] des « meilleures » couleurs déterminées d'après l'ensemble des images de l'animation. Malheureusement, cela a aussi eu pour effet que les données de pixels se compressent moins bien qu'auparavant, car un tramage plus marqué était nécessaire. Le résultat est une animation d'aspect légèrement moins bon, d'une taille à peu près identique à la précédente. Pour cette vidéo particulière, aux couleurs limitées, je pourrais même réduire encore davantage le nombre de couleurs employées, jusqu'à 64 couleurs seulement, sans trop de problèmes, ce qui donnerait un fichier d'animation encore plus petit. Cela dépend toutefois fortement de la séquence vidéo utilisée et peut ne pas être très réussi. Votre propre vidéo pourra donner un meilleur ou un moins bon résultat, surtout face à une vidéo qui emploie beaucoup plus de couleurs et comporte éventuellement plusieurs scènes.

Table de couleurs globale universelle

La meilleure façon de générer une animation GIF « plus petite » consiste à fournir simplement une gamme générale et universelle de couleurs, plutôt que de générer la « meilleure » table de couleurs globale pour une animation. Utilisez-en une qui devrait bien fonctionner quelles que soient les couleurs présentes dans la vidéo d'origine. Une autre raison de procéder ainsi est que vous pouvez allonger votre vidéo sans effet néfaste sérieux sur la sélection des couleurs ni recourir à des tables de couleurs locales pour chaque image. Chaque image est tramée vers la même palette de couleurs, en toute indépendance des autres images de l'animation. J'utilise ici une palette de couleurs « 332 », généralement considérée comme une très bonne palette standard lorsqu'aucune transparence n'est nécessaire. J'ai souvent vu cette palette (ou une palette « web-safe » de 219 couleurs, « web-safe ») employée dans divers formats vidéo. |

  magick -quiet -delay 1 plane.avi -remap colormap_332.png plane_ugc.gif

[IM Output]
Cette animation possède [IM Text] tables de couleurs locales et, de ce fait, l'animation est plus petite, soit [IM Text] octets. Le problème, cependant, c'est que vous verrez souvent un « bruit » manifeste et gênant dans les zones de couleur uniforme. Ce bruit était également présent dans TOUTES les animations vidéo précédentes. Il n'est devenu visible que maintenant, du fait de l'emploi d'un mappage de couleurs plus universel, et donc plus largement réparti. Ce bruit est en réalité causé par le tramage du jeu de couleurs réduit lors de la régénération de l'image. Or cela produit un motif de couleurs pseudo-aléatoire qui change d'une image à l'autre, d'où l'apparence d'un bruit de fond dans l'image. Voir Problèmes liés aux tramages par diffusion d'erreur pour plus de détails sur les raisons de ce phénomène. On pourrait tout simplement désactiver le tramage des couleurs pour supprimer ce « bruit de tramage »… |

  magick -quiet -delay 1 plane.avi \
          +dither -remap colormap_332.png plane_ugc_nd.gif

Ce qui donne [IM Text] tables de couleurs locales, pour une taille de [IM Text] octets. [IM Output]
L'animation obtenue est très petite, le soixantième de la taille de l'animation d'origine, principalement parce que les grandes étendues de couleur unie produisent une compression des pixels extrêmement bonne. Mais si cela corrige le bruit de tramage et donne un fichier très petit, on obtient en revanche des bandes de couleur (banding), ce qui est généralement considéré comme un très mauvais compromis.

Vidéo en tramage ordonné

La vraie solution consiste à employer une autre technique de tramage des couleurs, qui ne produise pas un motif différent d'une image à la suivante. Par exemple, j'ai utilisé ici un tramage ordonné à niveaux de couleur postérisés pour tramer la même palette universelle « 332 ». |

  magick -quiet -delay 1 plane.avi \
          -ordered-dither o8x8,8,8,4 +remap plane_od.gif

Ce qui donne [IM Text] tables de couleurs locales, pour une taille de [IM Text] octets. [IM Output]
Ce qui précède a également utilisé l'opérateur "[+remap](https://imagemagick.org/command-line-options/#remap)", afin de garantir que toutes les images emploient exactement la même palette de couleurs globale (que le tramage ordonné a déjà réduite à un maximum de 256 couleurs). Le nombre de couleurs étant déjà optimal, l'opérateur "[+remap](https://imagemagick.org/command-line-options/#remap)" n'effectue ni tramage ni réduction des couleurs. Le motif de tramage obtenu n'est pas aléatoire et ne varie pas beaucoup d'une image à la suivante. Ainsi, le « bruit de tramage » a été supprimé de l'animation, donnant un motif de couleurs fixe d'une image à l'autre. Ce motif est en outre très répétitif, ce qui autorise une bien meilleure compression. Enfin, la palette de couleurs étant fixe, elle devrait fonctionner raisonnablement bien quelle que soit la vidéo utilisée.

Vidéo en tramage ordonné de meilleure qualité

Cette vidéo particulière n'emploie toutefois qu'une faible gamme de couleurs, surtout diverses nuances de bleu, si bien qu'elle n'utilise pas réellement une grande partie des couleurs fournies par une palette uniforme générale. De fait, seules [IM Text] couleurs ont été employées dans la dernière animation vidéo ! C'est extrêmement faible, et donc plutôt visible. Mais cela signifie aussi que cette animation particulière peut tirer parti d'un grand nombre de « niveaux de couleur » dans l'opération de tramage ordonné, afin d'améliorer la qualité d'ensemble. Il faut cependant d'abord déterminer combien de niveaux de couleur l'animation peut supporter avant d'atteindre la limite de 256 couleurs imposée à la fois par le format GIF et par le remappage vers la palette globale. Le plus délicat est qu'il faut le déterminer AVANT d'enregistrer l'animation dans le format GIF limité. Et voici la commande que j'utilise…

    magick -quiet plane.avi -ordered-dither o8x8,23 -append -format %k info:

[IM Text]

J'ai pour l'essentiel augmenté puis diminué le nombre de niveaux de couleur à utiliser, jusqu'à obtenir un chiffre tout juste compris dans la limite requise de 256 couleurs. Je peux ensuite appliquer le choix de « niveau de couleur » ainsi trouvé à l'animation plane. |

  magick -quiet -delay 1 plane.avi \
          -ordered-dither o8x8,23 +remap plane_od2.gif

Ce qui donne [IM Text] tables de couleurs locales, une taille de [IM Text] octets et [IM Text] couleurs. [IM Output]
Comme vous pouvez le constater, une vidéo en tramage ordonné de très haute qualité a été générée, comparable à la version en palette globale « meilleure palette » générée plus haut, mais aussi un tiers plus petite, tandis que le « bruit de tramage » est désormais beaucoup plus difficile à percevoir. Bien sûr, la qualité étant nettement supérieure, le fichier est plus volumineux, car il ne se compresse pas aussi bien que la version de moindre qualité. En revanche, vous disposez maintenant d'un véritable contrôle sur le compromis qualité / taille de fichier, sous la forme du nombre de « niveaux de couleur » employés. Souvenez-vous simplement que cette technique est un cas particulier, valable pour une animation qui n'emploie pas trop de couleurs. Et allonger la vidéo en ajoutant des images ajoutera aussi des couleurs, et imposera donc une réduction du réglage de qualité « niveau de couleur ». C'est à peu près la meilleure méthode d'optimisation des couleurs que j'aie vue à ce jour pour les animations GIF en général. Elle supprime le « bruit de tramage », offre un certain contrôle de la qualité et conserve la possibilité d'utiliser d'autres méthodes d'optimisation des animations GIF, comme l'optimisation des images.

Optimisation de la compression (transparence)

Comme cette vidéo utilise un panoramique de caméra, l'arrière-plan change d'une image à l'autre. L'animation GIF se prêtera donc mal à l'optimisation des images. On peut néanmoins recourir à une simple optimisation par transparence pour réduire encore la taille finale de l'animation GIF. |

  magick plane_od2.gif  -layers OptimizeTransparency +remap plane_opt.gif

Le résultat fait [IM Text] octets et compte [IM Text] couleurs. [IM Output]
Autrement dit, une couleur supplémentaire, un index de couleur transparente, a été ajoutée à l'image, et tout pixel qui ne modifie pas la couleur actuellement affichée a été rendu transparent. Cela engendre à son tour de larges plages transparentes dans l'animation d'origine, ainsi que des répétitions de séquences de pixels semblables, ce qui améliore la compression LZW dans l'image GIF finale. Pas mal : l'animation pèse désormais la moitié de la conversion directe vers GIF, tout en conservant une qualité raisonnablement élevée. Si vous souhaitez compléter ce qui précède, ou discuter de techniques pour l'améliorer encore, n'hésitez pas à me contacter ou à écrire sur le forum IM. Je serai ravi d'entendre vos avis, techniques et discussions, ou d'examiner un problème de vidéo/animation particulier que vous pourriez avoir. L'une de ces discussions est Finding the "right levels" for quantization with anim GIF.

Optimisation LZW par compression Giflossy

Un nouvel outil, GifLossy, qui est un fork du programme original Gifsicle, modifie les couleurs de chaque image afin que LZW puisse compresser l'image bien davantage. Par exemple, je l'ai appliqué ici à l'animation GIF d'origine, en lui demandant de réduire les couleurs à une unique table de 256 couleurs. |

  gifsicle -O3 --lossy=80 --colors 256 plane.gif -o plane_giflossy.gif

On obtient une taille absolument stupéfiante de [IM Text] octets. Ce n'est pas d'aussi bonne qualité que ce que nous avons obtenu avec le tramage ordonné, mais c'est moins de la moitié de la taille. [IM Output]
Enhardi par ce résultat, j'ai décidé d'appliquer GifLossy au meilleur résultat de tramage ordonné que nous ayons obtenu, pour voir s'il pouvait le rendre encore plus petit. |

  gifsicle -O3 --lossy=80 plane_od2.gif -o plane_od2_giflossy.gif

Et nous avons effectivement obtenu une taille encore plus petite, de [IM Text] octets. Malheureusement, nous avons pour l'essentiel perdu le résultat de tramage ordonné de haute qualité que nous avions eu tant de mal à obtenir auparavant. Ce qui est décevant. [IM Output]


Désentrelacer une image de vidéo

Toutes les images ne proviennent pas d'appareils photo numériques. Il est très courant d'extraire des images d'un flux vidéo numérique issu d'une caméra non CCD. Ces images sont entrelacées pour un affichage direct sur un téléviseur, ce qui fait qu'une ligne sur deux appartient à une image différente (entrelacement). Pour deux trames où rien ne bouge, l'entrelacement n'est en général pas très perceptible. Il produit tout au plus un léger flou des contours de l'image. Mais lorsqu'un objet en mouvement rapide est en jeu, l'image entrelacée obtenue est très déconcertante, car deux trames ont été fusionnées. Wolfgang Hugemann Auto@Hugemann.de (Allemagne) avait ce problème et m'a envoyé un cliché d'un crash test qu'il avait réalisé lui-même. Mais pour la démonstration, j'utiliserai une image plus petite découpée dans celle-ci. Les techniques fonctionneront néanmoins sur l'image en taille réelle. |

    magick video_frame.png  -crop 100x100+200+470 +repage  interlaced.png

[IM Output]
| Wolfgang Hugemann a utilisé le format TIFF pour la trame vidéo d'origine ; je l'ai convertie en PNG pour les exemples IM. Ne soyez pas tenté d'utiliser du JPEG pour ces images avant d'avoir terminé le traitement, car cela détruirait la qualité de bas niveau nécessaire à ce procédé.
---|---
Comme vous pouvez le voir, l'entrelacement laisse apparaître deux trames distinctes, puisqu'il provient d'une séquence vidéo numérique PAL entrelacée (environ 50 demi-trames par seconde). Oui, la voiture roulait très vite et la caméra utilise un obturateur à grande vitesse, produisant une image vidéo de très haute qualité. L'image obtenue est formée de deux demi-trames entrelacées, le rétroviseur latéral de la voiture s'étant déplacé d'une distance assez grande pendant l'intervalle d'1/50 de seconde séparant les deux demi-trames. Ici, nous remplaçons simplement l'une des demi-trames entrelacées (une ligne sur deux) par du blanc. C'est la méthode de désentrelacement standard, connue sous le nom de filtre « BoB ». Elle a été contribuée par Wolfgang pour les exemples IM. |

  magick interlaced.png  -fx "floor(j/2)==j/2 ? u : 1"  deinterlace_1.png

[IM Output]
Or l'opérateur FX est lent ; une autre solution consiste donc à créer une « image rayée ». Une telle image peut être générée à partir de l'image intégrée spéciale "pattern:Horizontal2". Cette image peut ensuite être superposée à l'originale, à l'aide d'une méthode de composition '[Screen](compose.html#screen)' pour superposer des lignes blanches, ou bien d'un '[Multiply](compose.html#multiply)' pour superposer des lignes noires. Par exemple… |

  magick -size 100x100 pattern:Horizontal2 \
          interlaced.png -compose Multiply -composite  deinterlace_2.png

[IM Output]
Inverser le motif permet de sélectionner l'autre moitié de l'image entrelacée. Ou bien, si vous changez le 'Multiply' en 'Screen', vous pouvez extraire les trames sur fond blanc. Comme alternative, j'ai essayé de combler les lignes manquantes de la trame en dupliquant simplement la ligne précédente. |

    magick interlaced.png  -fx "u.p{i,j-j%2}"  deinterlace_3.png

[IM Output]
Vous pouvez aussi recourir à une technique de pixellisation pour réduire puis agrandir une image, de façon à dédoubler une ligne sur deux. |

    magick interlaced.png -sample 100%x50% \
                           -sample 100%x200%  deinterlace_4.png

[IM Output]
Et avec une légère variante, vous pouvez combiner les lignes des deux côtés pour lisser verticalement l'image de demi-trame dans le cadre de l'agrandissement au redimensionnement. |

    magick interlaced.png -sample 100%x50% \
                           -resize 100%x200%  deinterlace_5.png

[IM Output]
Le résultat est une extraction particulièrement réussie d'une trame de l'image vidéo entrelacée. Si vous voulez extraire l'autre demi-trame de l'image, vous pouvez ajuster 'sampling:offset' (à partir d'IM v6.8.4-7). |

    magick interlaced.png -define sample:offset=75 \
            -sample 100%x50%  -resize 100%x200%    deinterlace_6.png

[IM Output]
Avant cette version d'IM, il fallait "[-roll](https://imagemagick.org/command-line-options/#roll)" (décaler) l'image d'un pixel pour obtenir le même résultat.