La compression JPEG
Transcription
La compression JPEG
6, bd maréchal Juin F-14050 Caen cedex 4 Spécialité Informatique Option Image 2e année Rapport de projet La compression JPEG Bourjas Rémi Nel François Suivi : Fourey Sébastien Année 2005-2006 Table des matières Introduction.................................................................................................................................3 1 La compression JPEG ..........................................................................................................4 1.1 Passage de RGB à YCrCb ......................................................................................................................................4 1.2 Sous-échantillonnage...............................................................................................................................................5 1.3 Découpage de l'image en blocs..............................................................................................................................6 1.4 Discrete Cosinus Transform...................................................................................................................................6 1.5 Quantification ...........................................................................................................................................................8 1.6 RLE et DCMP...........................................................................................................................................................9 1.6.1 RLE (Run Length Encoding) ........................................................................................................................9 1.6.2 DPCM (Differential Pulse Code Modulation) ...........................................................................................9 1.7 Huffman ...................................................................................................................................................................10 1.8 Ecriture du fichier JPEG .......................................................................................................................................10 1.9 Schéma récapitulatif ..............................................................................................................................................11 2 Cahier des charges..............................................................................................................12 2.1 2.2 3 Les propositions de départ....................................................................................................................................12 Cahier des charges final........................................................................................................................................12 Conception et implémentation ...........................................................................................13 3.1 Implémentation des algorithmes de compression.............................................................................................13 3.1.1 Choix du langage...........................................................................................................................................13 3.1.2 Représentation des données, détails des classes ......................................................................................13 3.1.3 Implémentation des algorithmes de compression....................................................................................13 3.2 Diagramme de classes ...........................................................................................................................................14 3.3 Description de l’interface utilisateur...................................................................................................................15 3.3.1 Utilisation de la bibliothèque Qt3 ..............................................................................................................15 3.3.2 Détails des classes et de leurs fonctionnalités..........................................................................................15 Conclusion ................................................................................................................................19 Références bibliographiques.....................................................................................................20 Annexe 1 ...................................................................................................................................21 Annexe 2 ...................................................................................................................................22 Introduction Durant la dernière décennie les avancées technologiques ont apporté une multitude d’applications utilisant des images numériques. La grande quantité de données nécessaires pour représenter une image numérique est un obstacle à de nombreuses applications (stockage de données sur appareil photo, caméra, Internet…) Un effort de standardisation à été fait dans le début des années 90 pour répondre au besoin de quasiment toutes les applications utilisant des images fixes en tons continus. Le standard JPEG a alors été créé. 3 1 La compression JPEG JPEG (Joint Photographic Expert Group) : standard international en 1992 1.1 Passage de RGB à YCrCb Y : luminance Cr : chrominance rouge Cb : chrominance bleue La rétine de l’œil humain contient environ 130 millions de cellules photo-réceptrices : 125 millions sont des bâtonnets et 5 millions sont des cônes. Les bâtonnets sont sensibles aux différences de luminances et ne distinguent pas les chrominances, alors que les cônes ne distinguent que les lumières rouge, verte et bleue. Comme l’œil comporte beaucoup moins de cônes que de bâtonnets une baisse de la résolution des chrominances n’est pas visible dans la plupart des cas. La première compression du JPEG utilise ce principe : on passe du domaine RGB dans le domaine YCrCb, puis on effectue une compression sur les Cr et Cb. NB : Confusion entre YCrCb, YUV, et YIQ : Il y a toutes sortes de confusion sur Internet par rapport à ces 3 espaces : Ils sont tout 3 différents : YCrCb : télévision numérique, JPEG YUV : PAL (standard allemand) 4 YIQ : NTSC (standard américain) A cause de ces confusions, nous avons d’abord fait notre programme en passant dans le domaine YUV, ce qui marchait tout aussi bien qu’avec YCrCb (La différence est difficilement perceptible). Le passage de RGB à YCrCb se fait sans perte (sauf due s aux arrondis) 1.2 Sous-échantillonnage La compression des chrominances est de 4 : 1 dans la plupart des logiciels ce qui correspond à un gain de 50% de place : 3/4 de place gagnée pour Cr et Cb (donc 2/3 de l’image) = 1/2 de gagné. Exemples : - Paint compresse toujours les chrominances en 4 : 1. - Photoshop prend un facteur de qualité en paramètre (de 0 à 12), il compresse les chrominances de la qualité 0 à 6 et ne les compresse plus de 7 à 12. Le problème avec la compression des chrominances est que dans certain cas, le résultat est médiocre. Exemple avec des traits de 1 pixel de large : Image d’origine convertie en JPEG par Paint Convertie par Photoshop en qualité 7 en qualité 6 5 Ce phénomène n’arrive presque jamais pour la compression des photos car elles n’ont que très rarement des variations importantes de chrominance. Dans la plupart des cas, cette compression est totalement imperceptible : Image d’origine : Convertie en JPEG 100% avec sous échantillonnage : 124 Ko 68,7 Ko 1.3 Découpage de l'image en blocs L’image est ensuite découpée en bloc de taille N×N en vue d’appliquer les calculs suivants. Plus N est grand, plus le rapport poids/qualité est grand, mais aussi plus le temps de calcul pour compresser et décompresser l’image est grand. Il a alors été décidé que N=8. (Le fait que le rapport poids/qualité augmente quand N augmente s’explique par l’utilisation de la compression RLE) 1.4 Discrete Cosinus Transform L’application de la FFT ou de la DCT permet de passer en domaine fréquentiel. La DCT a été choisie par les membres du groupe JPEG pour sa capacité à restituer une image de meilleure qualité que la FFT avec un nombre réduit de coefficients. Formules : Y(x,y) est la valeur du pixel aux coordonnées x et y F(u,v) la valeur de la composante du bloc dans le domaine fréquentiel aux fréquences u et v DCT : F ( u, v) = N −1 N −1 2 1 1 π π c(u ).c( v) ∑∑ cos u.( x + ) . cos v.( y + ) × Y ( x, y ) N 2 2 N N x =0 y = 0 1 si α = 0 c (α ) = 2 1 sinon 6 IDCT (Inverse Discrete Cosinus Transform) : Y ( x, y ) = 2 N N −1 N −1 π 1 π 1 ∑ ∑ c(u).c(v). cos N u.( x + 2 ) . cos N v.( y + 2 ) × F (u , v ) x = 0 y =0 1 si α = 0 c (α ) = 2 1 sinon En appliquant la DCT sur un bloc de N×N pixel, on passe dans le domaine fréquentiel : Un bloc de N² pixels (en ton de gris allant de 0 à 255) va être décomposé en N² motifs (en tons de gris correspondant à l’importance de ce motif dans le bloc) Le motif situé en haut à gauche correspond à la composante continue du bloc (DC), et plus on se rapproche du bas et de la droite, plus les fréquences augmentent et les motifs deviennent précis. L’avantage de la DCT est donc de pouvoir stocker beaucoup d’information avec peu de coefficients, ce qui permet de gagner beaucoup de place avec l’algorithme de compression RLE. Le passage dans le domaine fréquentiel se fait sans perte (sauf due aux arrondis) 7 1.5 Quantification Comme les images ont en général très peu de variation brutale de luminosité et de chrominance, il est possible de représenter toute l’information de l’image sur seulement quelques coefficients et/ou d’arrondir ces coefficients sans perdre trop de qualité. La quantification consiste à diviser chaque bloc de pixels par une matrice de même taille (la table de quantification). Les valeurs du bloc qui sont inférieures aux valeurs correspondantes dans la table de quantification sont donc mises à zéro. La limite de la quantification est l’apparition de blocs à trop forte compression. Récapitulatif des étapes précédentes sur un bloc de 8×8 pixels : DCT Bloc d’origine Quantification Table de quantification (Ici la table standard de luminance) Quantification inverse IDCT Bloc après décompression 8 1.6 RLE et DCMP 1.6.1 RLE (Run Length Encoding) La RLE est appliquée sur les composantes AC (les 63 coefficients de fréquence non nulle pour un bloc 8×8) : Le principe du RLE est de coder les répétitions d'un même pixel : un premier octet indique le nombre de pixels identiques et le second indique la valeur de ces pixels. Si un même pixel n'est pas répété au moins 3 fois, alors la suite d'octets n'est pas codée. Exemple : 157-157-157-157-157-157-007-007-007-000-255-255-255-255-089-089-089-089-089-089 => 006/157-004/007-001/000-004/255-006/089 Le parcourt en zigzag d’un bloc 8×8: En appliquant cet algorithme après un parcourt en zigzag, on peux coder tous les “0” se trouvant dans la partie inférieure droite d’un bloc sur très peu d’octets. 1.6.2 DPCM (Differential Pulse Code Modulation) Utilisé sur les composantes DC (le coefficient de fréquence nulle : la case [0,0] d’un bloc) : Les composantes DC ont généralement de grandes valeurs mais en revanche varient lentement d’un bloc à l’autre. On va donc coder non pas la composante DC elle- même mais sa différence avec celle du bloc précédent, ce qui donnera de plus petits nombres prenant moins de place et ayant moins de diversité. 9 1.7 Huffman Cet algorithme inventé par David Huffman en 1952, permet de coder les octets les plus fréquents sur peu de bits. Il est particulièrement bien adapté au codage octet par octet, ce qui est exactement ce qui sort de la RLE et de la DCMP. Le principe de ce codage est la création d’un arbre dont les feuilles sont les valeurs à coder. Un poids est associé à chacune de ces feuilles, et il correspond à la fréquence d’apparition de leurs valeurs. Ensuite, on associe les 2 nœuds de poids le plus faible pour donner un nœud de poids égal à la somme des poids de ces nœuds. Et on recommence jusqu'à ce que tous les nœuds soient reliés jusqu’à la racine de l’arbre binaire obtenu. Enfin pour chaque nœud on associe la valeur “0” à la branche amenant au nœud de poids le plus faible et “1” à l’autre. A l’association de ces valeurs est créée la table des correspondances (table de Huffman), qui sera stockée dans le header du fichier JPEG avec les tables de quantification. 1.8 Ecriture du fichier JPEG Le Header : Le header commence par les marqueurs JPEG SOI (Start of Image) et JFIF (JPEG File Interchange Format) (2 octets chacun) Puis la taille du fichier est indiquée sur 2 octets. Les 5 octets suivants sont toujours 4a 46 49 46 00, se qui signifie JFIF. Ensuite deux octets sont réservés à la version du JPEG. Les 5 octets suivants sont utilisés pour donner la densité de pixels par unité (cm, pouce). Enfin viennent les 2 tables de quantifications (luminances et chrominance) annoncées par des marqueurs spécifiques suivi de la taille de la table et de sa précision. Même chose pour les 4 tables de Huffman. Après le header, l’ image JPEG peut être écrite et doit être finie par le marqueur EOF (End of File) Une liste assez complète des marqueurs JPEG est disponible à l’annexe 2. 10 1.9 Schéma récapitulatif 11 2 Cahier des charges 2.1 Les propositions de départ A l’origine ce projet pouvait se décomposer en 3 étapes distinctes : 1 - Programmer un décodeur de fichier JPEG (qui permettra par exemple de convertir une image JPEG en un fichier BMP). 2 - Programmer un outil de démonstration (avec interface graphique) permettant d'illustrer l'affichage progressif d'une image JPEG. L'outil devra aussi offrir une fonction permettant d'afficher en temps réel l'image décompressée pour un choix d'une fraction des coefficients de la DCT à ignorer. 3 - Programmer un outil de démonstration pour illustrer l'effet d'une compression / décompression à l'aide de la DWT (Discrete Wavelet Transform) suivie d'une quantification uniforme. Après nous être documentés sur le principe de fonctionnement de la compression JPEG ainsi que sur les particularités de ce format (header) nous avons essayé dans un premier temps d’afficher à l’écran une image JPEG. La classe Qimage de la bibliothèque Qt3 nous a permis rapidement d’obtenir ce résultat. Voyant que la partie décompression d’un fichier JPEG était entièrement gérée par Qt nous nous sommes donc concentrés sur l’aspect compression. Le cahier des charges du projet s’est donc finalement limité au 2, la génération d’images BMP ou JPEG ainsi que l’utilisation de la DWT sont devenues des fonctionnalités facultatives à implémenter dans le futur. 2.2 Cahier des charges final Le projet consistait à développer un outil de démonstration permettant d’illustrer les effets de la compression JPEG sur une image. Le but était de pouvoir intervenir sur le plus de paramètres possibles de la compression et d’en afficher les résultats. Les étapes de la compression sur lesquelles nous devions avoir un contrôle total sont donc les étapes générant des pertes d’information : le sous-échantillonage et la quantification. Concrètement il fallait pouvoir appliquer un sous-échantillonnage, en voir l’effet sur l’image, puis appliquer une quantification avec un paramètre (nombre de coefficient de la DCT à ignorer) et afficher l’image obtenue. Au cours de la réalisation nous avons essayé de donner à notre programme le plus de souplesse possible. Nous avons donc pensé notre programme afin que l’utilisateur puisse choisir le plus de paramètres possibles tout en satisfaisant au standard JPEG durant ces 2 étapes de compression. 12 3 Conception et implémentation 3.1 Implémentation des algorithmes de compression 3.1.1 Choix du langage Pour réaliser un tel projet, un langage objet nous a paru bien adapté pour séparer les différentes étapes de compression du JPEG et les images dans des classes distinctes. De plus, Il nous a fallu choisir entre le Java et le C++. Comme nous devions faire une interface graphique et que nous allions avoir des cours et TP de QT, nous avons choisi le C++. 3.1.2 Représentation des données, détails des classes Les images de départ et d’arrivée se présentent sous la forme d’une QImage (RGB) pour des raisons de facilité d’affichage à l’écran. Les algorithmes de compressions ne s’appliquent pas sur ce type de données, d’où la création des classes suivantes : - Classe YCrCb : contient l’image sous la forme de 3 matrices Y, Cr et Cb - Classe DCT : contient l’image découpée en Blocks - Classe Block : contient 3 blocs de taille 8x8 un pour chaque composante. De plus afin de répondre au cahier des charges, il nous a fallu écrire une classe contenant les différentes matrices de quantification : - Classe QuantMat : contient la matrice de quantification de taille 8x8 3.1.3 Implémentation des algorithmes de compression La création de différentes structures de données est motivée par les caractéristiques des algorithmes de compression : Le sous-échantillonnage est implémenté dans la classe YCrCb par les méthodes : YUV& YUV& YUV& YUV& YUV& YUV& YUV& subsamplingH(); subsamplingV(); subsamplingHV(); decompressionH(); decompressionV(); decompressionHV(); decompression(); La quantification est appliquée sur un bloc après avoir appliqué la DCT. Dans la classe Block , on trouve donc les méthodes : DCT& applyDCT(); DCT& applyInvDCT(); DCT& applyQuantTab(QuantTab&,QuantTab&); DCT& applyInvQuantTab(QuantTab&,QuantTab&); 13 3.2 Diagramme de classes 14 3.3 Description de l’interface utilisateur 3.3.1 Utilisation de la bibliothèque Qt3 Par un soucis de portabilité et pour répondre au cahier des charges, nous avons utilisé la bibliothèque Qt pour réaliser l’interface graphique du programme. Cette partie n’était en aucun cas facultative car le programme se devait d’être utilisé en tant qu’un support à une présentation. 3.3.2 Détails des classes et de leurs fonctionnalités - Classe ImageWidget : Composée d’un scrollview contenant une image et d’un label pour la légende. L’image reste centrée dans le scrollview et peut être affichée en taille réelle ou redimensionnée (à l’aide du double clic). Cette classe permet aussi de récupérer le clic simple pour permettre l’affichage du zoom. ImageWidget sans redimensionnement ImageWidget avec redimensionnement Une image de petite taille reste centrée. 15 - Classe ZoomWidget : Elle sert à afficher les deux images du zoom. Le zoom transforme 21x21 pixels de l’image en une image 100x100. Il permet de mieux percevoir les différences entre l’image de départ et l’image d’arrivée et surtout l’aspect des artefacts dus à la compression. - Classe QuantTabView : Gère l’affichage d’une matrice 8x8 ici elle est utilisée pour afficher les matrices de quantification. De plus elle donne à l’utilisateur le choix de la matrice à utiliser (Combobox), le choix d’un nombre de coefficients de la DCT à ignorer (Slider) et la possibilité de modifier les valeurs case par case. Effet du Slider sur la matrice de quantification Choix de la matrice à charger 16 - Classe YCrCbView Cette classe est une QWidget qui s’ouvre dans une fenêtre à part. Elle est composée de 3 ImageWidget représentant respectivement Y Cr Cb après le sous-échantillonage. Elle permet d’apprécier directement l’effet du sous-échantillonnage sur la taille des composantes de l’image. A ceci vient s’ajouter dans MainWidget des affichages qui n’ont pas nécessités un isolement en classe : - Le choix des paramètres YCrCb : Propose à l’utilisateur 4 possibilités de sous-échantillonage. Le bouton DISPLAY gère l’affichage de la fenêtre YCrCbView. 17 - La fonctionnalité de calcul en temps réel : Lorsque le bouton radio est coché, la moindre modification de paramètre sur la matrice de quantification ou sur le sous-échantillonnage provoque le traitement complet de la compression et l’affichage de l’image compressée. Dans le cas contraire, la quantification n’est prise en compte qu’en appuyant sur REFRESH. La modification du paramètre du sous-échantillonnage provoque l’affichage de l’image compressée UNIQUEMENT par le souséchantillonage. - L’affichage du résultat du calcul d’erreur : Affiche la moyenne par pixel de la différence entre l’image d’origine et l’image compressée. Un screenshot de l’application est à l’annexe 1. 18 Conclusion Ce programme est un très bon outil pour illustrer le fonctionnement de la compression JPEG. Néanmoins, il peut être intéressant de développer l’exportation de l’image compressée au format JPEG. Cependant, quelques légères modifications pourraient être souhaitables : - Résoudre le “problème de bords”. (Il a partiellement été résolu en appliquant un ton moyen de gris sur la luminance et en mettant les chrominances à 0) - Optimiser la gestion de la mémoire. (La façon dont c’est actuellement implémenté est excessivement gourmande en ressources mémoire) Ce projet nous a permis de découvrir quelques méthodes de compressions fréquemment utilisées, et d’améliorer notre ma îtrise du C++ et de QT. 19 Références bibliographiques Cours sur la compression par transformée d’image fixes Conception d’interfaces graphiques - Sébastien Fourey The JPEG Still Picture Compression Standard - G.K. Wallace Liens : Doc de Trolltech : http://doc.trolltech.com/3.3/index.ht ml Les différents espaces de représentation des couleurs : http://www710.univ- lyon1.fr/~fdenis/club_EEA/cours/couleur3.html Le JPEG : http://en.wikipedia.org/wiki/Data_compression/JPEG http://www.chez.com/algorithmejpeg/reli.htm http://www.cs.sfu.ca/CourseCentral/365/li/material/notes/Chap4/Chap4.2/Chap4.2.html Un bon exemple de gestion de la quantification en Java : http://www.ta- formation.com/applets/JPEG-perroquets/perroquets.htm Structure du JPEG (marqueurs, header) : http://www.obrador.com/essentialjpeg/HeaderInfo.htm http://www.blackice.com/Help/Tools/Document%20Imaging%20SDK%20webhelp/WebHelp /What_is_JPEG_.htm Remerciement à Ludovic Angot pour son aide (débuggage de la fuite de mémoire), aussi minime soit elle. 20 Annexe 1 Screenshot de l’application : 21 Annexe 2 Les marqueurs JPEG : Marker Value Size (bytes) Description SOI 0xFF,0xD8 2 Start Of Image APP0 0xFF,0xE0 18 JFIF (JPEG File Interchange Format) COM 0xFF,0xFE 17 Product Information Comment COM 0xFF,0xFE 17 Time Stamp Comment COM 0xFF,0xFE 6…262 Trigger Data Comment DQT 0xFF,0xDB 69 DQT 0xFF,0xDB 69 SOF 0xFF,0xC0 19/13 DHT 0xFF,0xC4 33 DHT 0xFF,0xC4 183 DHT 0xFF,0xC4 33 DHT 0xFF,0xC4 183 SOS 0xFF,0xDA 14/10 ... ... ... EOF 0xFF,0xD9 2 Quantization Table - Luminance (Y) Quantization Table - Chrominance (Cb/Cr) Start Of Frame (19 color/13 black&white) Huffman Table - Luminance (Y) - DC Diff Huffman Table - Luminance (Y) - AC Coeff Huffman Table - Chrominance (Cb/Cr) - DC Diff Huffman Table - Chrominance (Cb/Cr) - AC Coeff Start Of Scan (14 color/13 black&white) Huffman coded image data End Of Image 22