SOMMAIRE


C++
Introduction
Scripts(54)
Exercices(3)
Liens
Livres
Forums


OpenGL
Introduction
Scripts(8)
Liens
Livres
Forums


IA
Script(6)
Forums


Jeux vidéo
Articles(1)
Forums


SDL
Introduction
Scripts(1)
Forums


Articles
Informatiques
TPE JPEG
Forums
Moteur de jeux 3D


PHP
Leçons
Scripts(11)
Exercices
Liens
Livres
Forums


JavaScript
Leçons
Scripts(2)
Exercices
Liens
Livres
Forums


HTML
Leçons
Scripts(2)
Exercices
Liens
Livres
Forums


Référencement
Leçons
Exercices
Liens
Livres
Forums


Quick Basic
Introduction
Scripts(14)
Exercices
Liens
Forums


Partenaires
Moteurprog.com
Mandragor.org
laltruiste.com
script-masters.com
Prografix
Zone DMC
Studios Tastalian
01php.com
Coder-studio.com
Melancolik.net
freddec.free.fr
InzeProg
Progmatique.fr
SMS
Covoiturage
en Europe

Cours de Yoga
en ligne



Autres liens
magazine - référencement






La compression d'images numériques par le JPEG




TPE 2003-2004



LA COMPRESSION D'IMAGES NUMERIQUES PAR LE JPEG



Classe :

Terminal 5 du Lycée Brizeux 29000 Quimper


Élèves :

Fabien Menou

Loïc Gueguen

Benjamin Trempont


Thème :

Images


Problématique :

«Comment deux images qui semblent identiques peuvent-elles prendre un espace mémoire différent?»


Professeurs :

mathématiques : Mr Bozec

physique/chimie : Mme Richard


Téléchargement du format PDF et du programme :

.PDF
Programmes


Contact :

webmaster@startjeux.com













Sommaire :


Introduction :


I/Le Système de couleurs YUV

1)Pourquoi changer le système de couleur ?

2)Détermination mathématique des coefficients de "passage"

3)Quels sont les effets visibles et les limites de cette compression?

Conclusion


II/La transformée en cosinus discrète (DCT) et la quantification

1)Le principe théorique de la DCT

2)L'application de la DCT dans la norme JPEG

3)La quantification


III/Compression non destructrice

1)La Compression RLE ou RLC

2)La Compression Huffman


Conclusion


Glossaire


Bibliographie



























Introduction :


La compression est une méthode très fréquemment utilisée qui touche le domaine de l'informatique, mais pour comprendre ce concept il faut avant tout faire une petite introduction sur la mémoire de l'ordinateur, en effet quand on parle de compression des données c'est cette espace mémoire qui sera réduit via la compression. La mémoire d'un ordinateur est constituée d'une suite de bits qui se suivent les uns à la suite des autres, un bit est le plus petit élément de la mémoire d'un ordinateur qui peut prendre deux valeurs possible, soit 1 ou soit 0, ce qui correspond à un état stable ou instable.


Exemple d'une suite de bits :

010011011011110011111110


Mais dans l'ordinateur, les bits sont regroupés par groupe de huit bits, que l'on appelle octet, ainsi les données de la mémoire sont mieux hiérarchisées. De plus, l'ordinateur associe à chaque octet de la mémoire un numéro d'octet, c'est-à-dire que l'on peut demander à l'ordinateur la valeur d'un octet en donnant le numéro physique associé dans la mémoire à un octet, ces numéros varient bien évidement de 0 à la taille de l'espace mémoire de l'ordinateur et croît de un en un à chaque octet qui se suivent dans la mémoire. Si on reprend l'exemple d'au-dessus, on aura par exemple :


bits dans la mémoire : 01001101 10111100 11111110

numéro associée à chaque octet : 56002 56003 56004


Mais que représente ces 1 et ces 0 dans la mémoire? Et bien ils représentent des nombres comme nous avons l'habitude de travailler dessus mais au lieu d'être en base 10, ils sont en base 2 d'où l'appellation binaire car l'ordinateur ne peut «comprendre» que cette base. Voici un exemple de nombre en base 10, décomposé :


108 = 102 x 1 + 101 x 0 + 100 x 8


Pour passer d'une base 10 en base 2, on effectue des divisions euclidiennes successives par 2 sur le nombre en premier puis sur les quotients de la division précédente. Les restes que l'on obtient au fur et à mesure sont les chiffres du nombre en base 2. Voici un exemple avec 108 :





En mettant bout à bout, le quotient de la dernière division puis les restes des divisions jusqu'au premier reste de la première division, on obtient 108 en binaire qui vaut 1101100. Pour revenir en base 10 à partir de ce nombre binaire, il suffit de traiter chaque chiffre binaire en le multipliant par 2 avec l'exposant du rang où ce chiffre appartient en commençant par 0 et enfin on fait la somme de l'ensemble des résultats obtenus. Voici un exemple illustrant le changement du nombre 1101100 en base 2, en base décimale :


108 en base 2 : 0 1 1 0 1 1 0 0

Valeur en base 10 de 108 : 108 = 27x0 + 26x1 + 25x1 + 24x1 + 23x1 + 22x1 + 21x1 + 20x1


On pourra bien entendu étendre la valeur d'une variable à plusieurs octets si on a besoin de travailler avec des plus grands nombres mais ici on se limitera souvent à 1 octet pour une valeur. Qui pourra ainsi avoir une valeur variant de 0 à 255 ou alors de -127 à 128 (par norme) si le bit du rang 7 représente le signe du nombre.

Maintenant que nous savons comment sont représentées les données dans l'ordinateur il faut savoir comment une image est représentée. Pour mieux cerner le problème nous allons prendre l'exemple de la numérisation d'une photo via un appareil photo numérique. Il est en fait constitué de lignes et de colonnes de capteurs de lumière (capteurs photosensibles). Plus il y a de capteurs, plus l'image sera de qualité. Chaque capteur décompose la lumière qu'il reçoit en un signal électrique qui sera lui-même ensuite transformé en données numérique. Pour chaque capteur il y aura trois octets de données pour décomposer l'image en trois composantes qui sont le rouge, le vert et le bleue : ce sont les couleurs primaires d'un faisceau lumineux. On appelle ce morceau de l'image, un pixel : c'est le plus petit élément composant une image. Un capteur sur ce type d'appareil photographique est à l'échelle microscopique, ils sont donc très nombreux.





En fin de compte, pour chaque composante lumineuse on aura un tableau de valeurs qui aura n*m valeurs. La variable m représente le nombre de lignes de capteurs et n le nombre de colonnes de capteurs. En général, un appareil photo numérique possède 800*600 pixels, cette résolution peut être moins grande ou beaucoup plus grande également. Donc pour une composante on aura 800*600 octets c'est-à-dire 480 000 octets. Mais comme, on a trois composantes pour cette images, la taille de cette image sera donc de 800*600*3 = 1440000 octets ≈ 1,37 Mo. Or, la mémoire des appareils photos numériques est limitée et vaut 10 Mo environ mais cette valeur peut être beaucoup moins élevée ou au contraire beaucoup plus grande, ainsi l'appareil photo numérique ne pourrait pas prendre plus de 7 photos! Imaginez si nous avions à enregistrer une vidéo numérique à 24 images par secondes, un film de 1h30, prendrait 173,81 Go soit environ 249 CD-Rom et encore sans le son! On se rend vite compte que c'est strictement impossible et des techniques de compression d'image ont été mises en place pour contrer ce problème.

A travers cet exposé, nous allons analyser, une norme de compression qui est le JPEG (pour Joint Photographic Experts Group). Pourquoi cette norme en particulier? C'est actuellement la norme la plus utilisée pour la compression d'images numériques que ce soit pour internet, ou pour les appareils photos numériques par exemple. De plus, il permet à l'utilisateur de choisir un facteur de qualité, c'est-à-dire qu'il peut choisir une image qui sera de très bonne qualité mais qui prendra beaucoup d'espace mémoire ou alors une image de moins bonne qualité mais qui prendra également moins de mémoire mais pourtant avec certains facteurs qualités, on a deux images de qualité identique à première vue mais qui prennent des espaces mémoires différents. Ainsi on s'est posé la problématique suivante : «comment deux images qui semblent identiques peuvent-elles prendre un espace mémoire différent? ». Cet exposé va répondre à cette problématique en analysant l'ensemble des traitements que la compression JPEG fait à une image non compressée.



























































I) Le Système de couleurs YUV


Tout d'abord, il faut définir le terme qui semble ambigu. Une image numérique est découpée en pixels, carrés de couleurs (ou de teintes de gris allant du blanc au noir) comme nous l'avons précédemment vu dans l'introduction. Au départ, lorsque l'on ne compresse pas l'image, chaque pixel est caractérisé par 3 composantes de base (format BMP ou BITMAP), la composante R, qui défini les domaines de nuances rouges, le V qui défini les domaines de nuance vertes et en dernier lieu le B, qui s'occupe de la couleur bleue. Ce qui nous donne au final un pixel codé en RVB (ou aussi appelé RGB). Le principe de la compression YUV est tout simplement d'optimiser ce codage couleur. En effet, au lieu de décomposer le pixel en 3 couleurs, on le décompose en 3 "caractéristiques" qui sont la luminance ou luminescence (Y ou Brigthness en anglais), la chrominance bleue (Cb ou U, tons de bleu), ainsi pour finir que la chrominance rouge (Cr ou V, tons de rouge). Tout cela dans le but de compresser l'image grâce aux caractéristiques de l'oeil qui est, pour nous humain, plus sensible au variations d'intensité lumineuse qu'au variations dans l'échelle des teintes (chrominance), mais nous allons développer tout cela plus en détails dans la suite de la partie.


1) Pourquoi changer le système de couleur ?


Comme toute étape d'un format de compression, ce passage en YUV (ou YCbCr) a pour but une exploitation optimisée du format d'image et donc aussi une compression par étapes. Ici ce changement possède les deux avantages, il compresse et rend l'image exploitable pour la DCT (Discrete Cosine Transform), deuxième étape de compression qui sera développée ultérieurement dans notre TPE. Pour mieux expliquer comment fonctionne ce passage et quels en sont les gains, nous allons prendre un exemple d'image formée par un bloc de 64 pixels (8x8 pixels) au format bitmap donc codée en RGB.

Nous allons tout d'abord devoir appliquer une donnée de luminance a chaque pixel, étant donné que cette dernière est très importante dans une image, le passage en YUV va donc la garder pour chaque pixel. Ensuite, au lieu de définir une donnée pour chaque couleur (R V et B), nous allons prendre des blocs de 2x2 pixels et leur appliquer une composante Cb et une composante Cr, il ne nous reste plus que, dans ce même bloc de 4 pixels, 4 informations de luminance et 2 pour la chrominance (une Cb et une Cr), ce qui nous fait au total 6 octets pour le codage couleur sur un bloc de 4 pixels au lieu de 12 octets (4 pixels multiplié par 3 composantes). Nous avions pris une image de 64 pixels, qui pour des couleurs codées en RGB , pèse 3x64= 192 octets alors que notre image au format YUV ne pèse que (4+2)x16= 96 octets. Nous gagnons donc la moitié d'espace mémoire. Bien sur ces espaces mémoires ne sont que la partie couleur de l'image, ces 2 images auront des "poids" différents sur l'ordinateur, car après cette compression interviennent d'autres compressions.

Voici un schéma qui illustre ce que nous avons décrit ci-dessus:





( Cb = V et Cr = U)



2) Détermination mathématique des coefficients de "passage"


Bien entendu, nous sommes parvenus a fixer les composantes Y, U et V grave a différentes méthodes physiques et mathématiques. La luminance Y étant la donnée fondamentale de l'image, nous la déterminons en premier lieu en faisant une moyenne pondérée des composantes RGB, ensuite nous procédons a l’établissement des formules de passage des autres composantes, a savoir la chrominance rouge et la chrominance bleue.

Ce qui nous donnera :



Y = 0.3R + 0.59V + 0.11B.

U = - 0.1687R – 0.3313V + 0.5B + 128

V = 0.5R – 0.41874G – 0.0813B + 128



A partir de ces équations, nous pouvons également revenir de ces composantes YUV aux composantes RVB :



R = Y + 1.402 (Cr – 128)

G = Y - 0.34414 (Cb – 128) - 0.71414 (Cr – 128)

B = Y + 1.772 (Cb – 128)



La luminance est une quantité physique objective, c’est l’intensité des radiations lumineuses par unité de surface considérées (en lumen, ou lux par mètre carré).


Cette dernière va de 0 (luminance du noir) à 255 (luminance du blanc), car on admet qu’il y a 256 échelles de gris allant du noir au blanc. On mesure la luminance par des récepteurs photoélectriques : on fait les mesures pour chaque composante RVB, on divise ensuite par la somme des trois résultats. Ainsi on obtient les coefficients donnés sur la page précédente. Puis grâce a cela, on détermine les coefficients Cb (V) et Cr (U). Mais avant cela nous devons représenter nos 3 composantes dans un repère orthonormé (unités équivalentes sur les 3 axes, ainsi que des axes perpendiculaires entre eux). Voici le repère en détails que nous expliquerons plus bas.





U et V doivent être respectivement dans le plan (R,Y) et (B,Y), car elles dépendent évidemment de ces deux données qui sont leurs chrominances respectives et la luminance. Pour que ces composantes soient bien distinctes, on doit toutes les mettre dans un plan orthogonal aux deux autres, ainsi, pour se faire, on doit poser U et V de telle forme que : U = a x (R-Y) et V = b x (B-Y). On obtient donc bien une « base orthogonale » comme RVB. Dans ces 2 formules, on choisit a et b arbitrairement et on ajoute 128 pour que U et V restent bien comprises entre 0 et 255. Dans les formules, on a posé a = 0.713 et b = 0.565, ce qui permet bien, après vérification, aux 2 composantes de rester dans des valeurs comprises entre 0 et 255. En effet pour Cb et Cr, si on regarde bien pour Cb par exemple (ceci est aussi et bien sur valable pour Cr), 0.1687 + 0.3313 = 0.5, or dans la formule nous avons +0.5B, si R, V et B sont comprises entre 0 et 255 et que nous n’ajoutons pas 128, nous aurons des valeurs comprises entre -128 et +128, or des valeurs négatives n’existent pas ici en terme de « données ».



3) Quels sont les effets visibles et les limites de cette compression ?



Théoriquement et mathématiquement, cette transformation est bijective, c'est-à-dire qu’on peut l’effectuer dans un sens, comme dans l’autre en re-écrivant l’équation de façon à isoler les inconnues qui nous intéressent. Mais en pratique, une fois la compression faite, on ne peut pas revenir en arrière, car cette compression effectue une moyenne de chrominance par 4 pixels et pour 4 pixels. On ne peut donc plus retrouver les valeurs initiales de chaque pixel puisque les 3 autres pixels le bordant ont la même donnée de chrominance. Visuellement, on ne décèle la compression qu’en regardant les endroits bien précis de l’image ou en prenant une image très petite (en général, des phots numériques sont très « grandes », ou hautement définies, c'est-à-dire comportant un nombre énorme de pixels, il est donc impossible pour nos yeux de trouver un défaut sur une photo complexe). Voici quelques exemples ou la compression se « voit » :





On voit très nettement la différence… regardez la couleur de fond de l’image et les coins de plus près. Ce ci montre bien que la compression YUV, et même plus généralement JPEG n’est pas recommandée dans le cas de petites images ou de formes géométriques parfaites possédant des angles tels les carrés ci-dessus.



Conclusion :


La conversion YUV, couramment utilisée dans les algorithmes de compression d’images tel le JPEG dans ce TPE, s’avère très avantageuse des lors qu’elle est utilisée à des fins précises comme la retouche photographique ou le stockage numérique, mais garde des limites et des défauts comme toute compression.

































II/La transformée en cosinus discrète (DCT) et la quantification :


1)Le principe théorique de la DCT :


La transformée en cosinus discrète est une transformation mathématique complexe qui a pour but dans la compression JPEG de transformer le domaine de représentation de nos données, c'est-à-dire de passer d'un domaine spatiale à un domaine fréquentiel, ce que fait également sa grande soeur la transformée de Fourier, en effet après les transformations de visualisations nos données restent toujours dans un domaine spatiale à trois dimensions où x et y représentent un point de l'image (ou un point sur l'écran), ou plus précisément un élément de la matrice de pixel, avec une valeur pour chaque élément de cette matrice représentant l'intensité de couleur pour une des composante Y, Cb ou Cr, c'est-à-dire l'axe z dans un repère à trois dimension(l'image en dessous montre un signal en 3 dimensions), mais comme nous l'avons vu notre oeil est moins sensible à certaines données de l'image et le but de la transformée en cosinus discrète est de passer dans un domaine fréquentiel, ce qui nous permettra de trier efficacement l'ensemble des données de l'image et ainsi supprimer certaines données de l'image où l'oeil humain ne verra que très peu de différences : les hautes fréquences de l'image tout en gardant les données majeures de l'image qui sont les représentées par les bases fréquences.




L'image dans un domaine spatial, a ses données non ordonnées et on voit bien qu'en supprimant même très peu de valeurs de l'image et bien cette perte se voit tout de suite, ainsi la DCT permettra de séparer les données majeures des données moins utiles pour mieux les manipuler par la suite. L'image en dessous montre la suppression de certaines données en remplaçant un carré de couleurs proches par une couleur uniforme, cette «perte» se voit immédiatement.





Les hautes fréquences représentent les zones à forts contrastes dans l'image, ce qui signifie lorsqu'il y a un changement brutal de couleurs dans l'image, comme par exemple, une image qui a d'un côté une couleur noire et de l'autre côté une couleur blanche. Voici cette image qui montre un très fort contraste :





En reprenant l'image d'au-dessus et en changeant le contraste de l'image en l'abaissant comme le fait n'importe quel logiciel de traitement d'image, on obtient une nouvelle image et on voit bien que les bases fréquences représentent les zones qui n'ont pas de changement brutaux de couleurs dans l'image, représentant ainsi une plage de couleurs uniformes:





Affichons un exemple d'image qui nous démontre l'importance du contraste sur les images compressées via la norme JPEG, voici une image à fort contraste non compressée :




Les discontinuités entre le disque bleu et son fond blanc, peuvent être considérées comme des zones à forts contrastes et en compressant cette image via la norme JPEG, on obtient très rapidement, même avec des facteurs de qualités petits, des dégradés qui se forment entre la couleur du disque et le fond blanc. Ce qui signifie qu'en supprimant les hautes fréquences de l'image on supprime les parties de l'image qui ont de forts contrastes, donc cette image a tendance à linéariser ses couleurs pour avoir des dégradés de couleurs comme on le voit sur l'image en-dessous, mais cette linéarisation n'est pas forcement un beau dégradé comme on aimerait avoir, cela donne souvent un rendu pas très agréable pour l'oeil et donc un résultat non cohérent par rapport à ce que représente l'image :




Cette transformation est une transformation avec le qualificatif «discrète», car on a affaire à un signal non continue, en effet, comme on l'a vu avec l'appareil photo numérique, et bien celui-ci va prendre grâce à ses capteurs une valeur pour chacun des récepteurs photosensibles, et ainsi avec ce prélèvement de valeurs, on aura affaire à un signal à trois dimensions discret car il y aura comme un «saut» entre une valeur et celles qui sont autour d'elle comme le montre l'image en dessous d'une dimension de 4*4 pixels :




Afin de mieux comprendre le fonctionnement de cette transformation on va d'abord étudier comment une variante de la DCT agit sur un signal à deux dimensions, en effet ce type de signal est plus courant et surtout beaucoup plus intuitif et donc mieux compréhensible. Ce type de signal se retrouve très fréquemment comme par exemple lorsque l'on a un repère orthonormé où l'axe des abscisses est le temps et l'axe des ordonnées représente les amplitudes comme on a souvent affaire en physique. L'enregistrement d'un signal sonore est un exemple de ce type de signal qui utilise également une compression du même genre que celle de la transformée en cosinus discrète dans le célèbre format MP3.

Dans notre exemple ici, on va considérer juste une image qui a pour dimension 8 colonnes sur une seule ligne, de plus on ne considère qu'une seule composante de l'image car la transformée en cosinus discrète s'applique séparément pour chacune des composantes de luminance et des deux chrominance. Pourquoi ne considère-t-on qu'une seule ligne? Tout simplement parce qu'on pourra considérer qu'à chaque unité d'abscisse on a un pixel avec une valeur comprise entre 0 et 255 représentant l'intensité lumineuse en ordonnée. Voici le tableau des huit valeurs que l'on considère :


Valeurs :

0

195

205

240

250

100

10

50


Juste en dessous, on a la représentation visuelle de ces valeurs en considérant la valeur 255 comme étant le blanc, 0 le noir et toutes les autres valeurs comprises entre 0 et 255, des couleurs intermédiaires :




Enfin, on a un repère orthonormé affichant la représentation de l'ensemble des pixels avec des flèches bleues pour les amplitudes des pixels sur l'axe des ordonnées et en allant d'unité en unité d'abscisse on a les pixels de gauche à droite de l'abscisse 0 à l'abscisse 7. De plus, j'affiche une fonction (une parmi d'autres) qui passe par les points représentant les pixels :





Le but de la DCT ou de l'une des transformation de la même famille est de transformer les données que l'on a dans un domaine fréquentiel, après cette transformation on obtient un spectre de fréquences qui décrit notre signal en une comme de fonctions sinus pour cet exemple. Voici le spectre que l'on obtient après transformation :





A partir, ce ce spectre, il nous est facile de retrouver le signal que l'on avait au départ, il suffit de faire la somme des fonctions sinus en fonction de leur fréquence et de leur amplitude. Pour cette exemple, notre signal de départ a alors pour équation :


f(x) = 200*sin(2*pi*x*0.0625) + 100*sin(2*pi*x*0.125) + 50*sin(2*pi*x*0.3125)

(pour le premier terme, 200 représente l'amplitude, et de 0.0625 la fréquence, même principe pour les termes qui suivent)


En-dessous, nous avons la représentation de cette fonction qui passe bien par les points représentant nos pixels. Ainsi, on se rend compte qu'il est facile de supprimer certaines données de l'image de façon cohérente, en supprimant certaines fréquences du signal.





On va juste conserver dans le signal, les deux fréquences les plus bases qui le décrivent pour montrer un exemple de perte de données. Voici à présent, l'image que l'on obtient, avec l'image originale juste en dessous, certes il y a une différences mais qui n'est pas si énorme et ce principe est celui utilisé par la transformée en cosinus discrète :






2)L'application de la DCT dans la norme JPEG :


Après avoir vu, le principe théorique général de la DCT et donc l'objectif qu'elle devait atteindre avec pour principal exemple un signal en deux dimensions, il est temps d'expliquer son application à un signal en trois dimensions et donc à une image. En effet, ici on ne considère plus un signal en deux dimensions comme on travaille souvent dessus mais sur trois signaux en trois dimensions, un pour chacune des composante donc l'application de la transformée en cosinus discrète s'applique sur chacune des composante séparément. De plus, il faut savoir qu'on ne peut appliquer la DCT que sur une matrice carré donc l'image que l'on a doit être découpée en bloc de N*N pixels, si les dimensions de l'image ne sont pas des multiples de N, alors l'image est agrandie sur la droite et/ou sur le bas de façon a avoir des dimensions qui soient des multiples de N, avec ces nouveaux pixels qui prennent pour valeurs, les mêmes que les pixels les plus à droite ou les plus en bas de l'image. On définit DCT(i, j) comme étant l'élément à la colonne i et à la ligne j de la matrice après la DCT, avec i et j variant de 0 à 7. Img(x,y) représente l'élément de la matrice carré de pixels N*N à la colonne x et à la ligne y avec x et y variant de 0 à 7. L'application de la DCT se fait donc sur chacune des matrices N*N prisent séparément. En gardant les mêmes notations, voici la formule de la DCT, avec Img la matrice de pixel avant transformation et DCT, les données après la DCT :




N représente la taille de la matrice carré, mais elle est en général égale à 8 mais cette valeur pourrait être plus grande mais au détriment des calculs car pour chacun des N*N coefficients on a N*N additions et 2*N*N multiplications environ. Si N vaut 8, on a 64*64=4096 additions à calculer pour une matrice 8*8 et 8192 multiplications environ, ce qui est déjà énorme pour un bloc de seulement 8*8 pixels! La valeur 8 a donc été choisie car c'est un bon compromis entre la qualité de l'application de la DCT et la rapidité des calculs, de plus, au delà d'un bloc de 8*8 pixels, il n'y a en général plus beaucoup de rapport entre les pixels au niveau de leurs variations de couleurs.

On va maintenant expliquer comment marche cette transformée, mais pour mieux la comprendre on va commencer par se limiter à une image d'une ligne de huit pixels, on étendra après le principe sur huit lignes. On garde donc la valeur 8 pour la variable N. On va donc commencer par construire 8 fonctions de base nécessaire pour décrire nos pixels, qui ont des fréquences de plus en plus élevées. Voici les huit fonctions de base qui sont après l'équation de leur courbe avec i variant de 0 à 7 de la fonction :





















Le but de la DCT est de calculer un coefficient pour chacune de nos fonctions en fonction des données de nos huit pixels, c'est-à-dire huit coefficients en tout. On numérote les huit pixels en leur donnant un indice de 0 à 7 de gauche à droite dans la représentation spatiale. Donc après cette transformation nous aurons toujours huit valeurs d'où aucun gain d'espaces mémoire. Pour le calcul d'un coefficient d'une fonction, on décrit la fonction considérée seulement avec huit valeurs (les ordonnées des abscisses de 0 à 7 par la fonction fi) et pour chacune des valeurs que l'on a, on l'a multiplie par la valeur du pixel avec le même indice, puis on fait la somme de ces huit multiplications pour avoir le coefficient d'une des fonction. On réitère cette opération pour nos huit fonctions. Voici un schéma illustrant cette opération pour une des fonctions de base :




Le calcul d'un coefficient d'une des fonction de base, est calculer par rapport à la forme décrite par les valeurs de nos pixels. Plus la valeur absolue du coefficient de la fonction est élevé, plus il y a d'informations sur l'image stockées par le coefficient, à l'inverse plus elle est petite moins il y a d'informations sur l'image décrient par le coefficient de l'une des fonction de base. Par exemple, si on prend la fonction f3 et 8 pixels représentés par les colonnes bleues sur l'image en-dessous. Plus ces colonnes sont élevées, plus la valeur du pixel est grande. Après avoir multiplié cette valeur par l'ordonnée de la fonction au-dessus, on a le signe de ce produit, et en observant, la hauteur des colonnes bleues, on voit bien que la somme de ces huit multiplications c'est-à-dire la valeur de ce coefficient est élevé et que cette fonction décrit la forme de nos pixels.





En gardant la même fonction de base mais en changeant la valeur de nos pixels tels qu'ils aient la même couleur pour une des composante, alors on s'aperçoit qu'en faisant la somme des huit multiplications on obtient une valeur nul, donc ici le coefficient de cette fonction de base ne décrit pas la forme de nos pixels, ce qui confirme ce qu'on voit en comparant la courbe du dessus et la droite d'équation y=a avec a qui vaut la valeur des pixels car tous les pixels ont la même valeur.


Ainsi, en calculant les huit coefficients de nos fonctions de base, on a la forme de notre image qui est décrite par ces valeurs qui représentent un spectre de fréquences. Ainsi pour retrouver nos données de départ, il suffit de faire comme on a fait pour le spectre que l'on avait dans le chapitre 1, c'est-à-dire que la fonction passant par la représentation de nos pixels, a pour équation la somme des multiplications de la fonction de base fi(x) (fréquence) par le coefficient de la fonction de base i(amplitude de cette fréquence). On a ainsi la valeur du pixel i qui vaut IDCT(i). La transformée inverse est donc assez simple à retrouver et vaut :




On a ainsi vu l'explication de la transformée en cosinus discrète et sa transformée inverse sur une seule ligne de huit pixels. Pour étendre cette relation, à un bloc de 8*8 pixels, il suffit d'étendre nos formules en prenant en compte les fonctions de base horizontales et les fonctions de bases verticales. C'est ce qui a été effectué dans la première formule qui a déjà été donnée plus haut mais pour la transformée inverse non. Il faut donc ajouter, une seconde variable à DCT pour pouvoir localiser un élément de la matrice après la DCT. En ajoutant cette variable, il faut également ajouter un symbole sigma d'addition comme le premier en début de formule sauf qu'il concerne la nouvelle variable que l'on a ajouté et enfin il faut multiplier le terme de la fonction cosinus par un terme de la même forme sauf qu'il concerne y au lieu de x, c'est-à-dire le domaine spatiale vertical. Au final, on obtient la transformée inverse en cosinus discrète, qui transforme la matrice N*N représentant le spectre de fréquences en la matrice IDCT de pixels que l'on avait au départ par la formule suivante :




Ainsi, après la transformée en cosinus discrète on obtient un nouveau domaine de représentation de notre image qui est un domaine fréquentiel via un spectre de fréquences. D'après les fonctions de bases que l'on a crée, plus on va vers les éléments de droites et/ou du bas de la matrice 8*8 que l'on a maintenant, alors plus on se dirige vers les hautes fréquences de l'image, c'est-à-dire les zones de l'image à forts contrastes. C'est à l'étape qui suit que l'on considéra cette propriété et que l'on exploitera pour justement enlever ces parties de l'image car l'oeil humain, ne verra que très peu de baisse de qualité.


3)La quantification :


La transformée en cosinus discrète appliquée sur une matrice carré, dans notre cas une matrice 8*8 n'a fait que transformer nos données mais elles sont facilement retrouvable dans leur état avant transformation, donc il n'y a pas eut de pertes d'informations jusqu'à présent sauf aux erreurs de précisions et d'arrondis mais il n'y a également pas eut de gains de place mémoire car il y a toujours autant de nombres dans la matrice c'est-à-dire 64 coefficients, la quantification est justement cette étape qui va permettre de réduire le poids de nos données.

Cette étape divise chaque coefficient de la matrice 8*8 après la DCT par un coefficient d'une matrice carré de même taille que la précédente, donc ici dans notre cas, cette matrice sera de 8*8 éléments, il faut préciser que ce tableau de valeurs est spécifique pour chacune des composante de l'image, de même on a vu que la transformée en cosinus discrète s'applique sur des blocs de 8*8 pixels pour chacune des composantes prise séparément. Donc un élément de la matrice d'entrée qui est localisé par une colonne et une ligne et bien, le coefficient de la matrice de quantification qui est localisé par la même colonne et la même ligne divisera ce coefficient de la matrice d'entrée.

Si Quant(i, j) représente l'élément de la matrice de quantification située à la colonne i et à la ligne j, avec ces deux variables variant de 0 à 7, on a alors nos nouvelles valeurs dans une nouvelle matrice Nx par la formule suivante :


Nx(i, j)= DCT(i,j)/Quant(i,j)

(où Nx(i,j) représente l'élément de la matrice à la colonne i et à la ligne j de la matrice après quantification)


Mais comme arrive-t-on à réduire le poids d'un coefficient? En fait, cette étape est la seule étape destructrice de la norme JPEG, le tôt de compression d'une image va dépendre de la table de quantification que l'on aura. En effet plus un coefficient de cette matrice est grand, plus le coefficient de la matrice après la DCT, sera réduit, mais il sera également arrondi à l'entier le plus grand inférieur au nombre que l'on a après la division par le coefficient de quantification. Par exemple, si on a après la DCT un coefficient qui vaut 4 et que le coefficient de la matrice de quantification est 100, on a après quantification la valeur 0.04, mais comme cette valeur est arrondie à l'entier le plus grand inférieur à 0.04, on a la valeur 0. Comme on l'a vue précédemment le principe de la DCT est de trier nos données par fréquence, horizontales et verticales, plus on va vers les coefficients sur la droite, plus on sera dans les hautes fréquences horizontales qui sont moins importantes et plus on va vers les coefficients plus en bas, plus on ira vers les hautes fréquences verticales qui sont moins importantes. On a déduit que les données les plus importantes dans la matrice après la transformée en cosinus discrète se situent en haut à gauche de celle-ci, on peut donc attribuer dans la matrice de quantification des coefficients plus élevés plus on va vers la droite et vers le bas. Voici un schéma montrant deux flèches désignant deux sens des hautes fréquences :




La bonne manière de tirer partie des informations importantes du bloc 8*8 est de créer une équation qui prend en paramètre un facteur de qualité de 1 à 10 mais également le fait qu'il faut que les coefficients à droite et en bas aient des valeurs de plus en plus grandes lorsque l'on se dirige vers le coin en bas à droite. Voici l'exemple d'une équation qui prend en compte ces paramètres, où i et j représentent respectivement la colonne i et la ligne j avec Q(i,j) l'élément désigné dans la matrice de quantification:


Q(i,j)=1 + ( 1 + i + j )*Facteur


Ce n'est bien entendu qu'un exemple d'équation, on peut en créer une infinité et chaque logiciel utilise sa propre équation pour trouver le meilleur compromis entre qualité de l'image et sa taille. On peut également noter que chacune des diagonales doivent avoir des coefficients proches voir identiques, en effet sur cette droite, pour un coefficient donné, un autre coefficient de cette diagonale, sera plus dans les hautes fréquences horizontales mais plus dans les bases fréquences verticales, il y a donc comme un «équilibre» entre les coefficients d'une même diagonale. Sur l'image en-dessous, les lignes noires représentes ces diagonales et la flèche verte montre le sens où l'on monte de façon générale dans les hautes fréquences :




Cette caractéristique à propos des coefficients d'une même diagonale est importante car elle servira par la suite pour avoir un maximum de valeurs identiques les unes à la suite des autres mais surtout une suite de zéro plus ou moins longue.

En reprenant l'équation de la table de quantification, on a écrit un programme qui charge une matrice de pixel à partir d'un fichier de 8*8 valeurs et qui crée une matrice de quantification en fonction du facteur de qualité. Ce programme affiche les matrices de quantification et de pixels avant transformation et la matrice après les deux transformations mais également la matrice en utilisant les algorithmes inverses pour retrouver la matrice de pixel. On se rend bien compte qu'après les transformations, on obtient dans les deux cas, une matrice avec beaucoup de zéros à l'intérieur et que l'ensemble des valeurs ont tendance à être vers le haut à gauche, on se rend bien compte que les données pourront être beaucoup plus facilement réduite par rapport à la matrice de pixels du départ. De même, on se rend compte qu'en effectuant les algorithmes inverse on obtient une matrice de valeurs qui reste relativement proche de la matrice de départ, donc la perte de données est plus ou moins importante en fonction du facteur de qualité. Voici un aperçu des résultats que le logiciel donne pour les facteurs de qualité 5 et 17 :




Enfin si, on créer une table de quantification avec un facteur de qualité très élevé, par exemple 87, on obtient ce genre de résultats :





On voit ici qu'après la transformée en cosinus discrète, il ne reste plus d'un coefficient non nul dans la matrice, et la transformée inverse nous donne une matrice de pixels où chacun d'eux ont la même valeur donc la même couleur. Ce résultat signifie qu'à des taux de compression très élevés, nous aurons notre image qui commencera a avoir des blocs de N*N pixels qui auront la même couleur, on aura donc un effet de pixelisation c'est-à-dire où l'on verra de gros blocs de pixels qui auront la même couleur. Par exemple, si on a l'image originale juste en dessous, l'image compressée en JPEG un peu plus en dessous montre bien cette effet où l'on voit des blocs de couleurs uniformes ce qui donne un effet visuel pas très agréable pour l'oeil :




































III/Compression non destructrice :

Nous allons donc passer à la troisième étape de ce TPE, qui consiste à compresser, cette fois-ci sans perte d’information. Il reste après la DCT, deux compressions pour la norme JPEG : La compression RLE (Run Length Encoding) ou RLC (Run Length Coding) et la compression Huffman.

1)La Compression RLE ou RLC

Cette méthode de compression est l’une des plus simples. Le principe est de remplacer une séquence de l éléments u identiques par un couple (u, l) . C’est à dire remplacer une addition par une multiplication.

Exemple : JPPPPPPPPPPEEEEEEEEEEEEEEEEEEEEEEGGGGGGGGGGGGGGGGGGGGG

On choisi un caractère spécial comme $ , après la compression nous obtenons donc :

J$10O$23A$21L Gain : 42 caractères soit 24%

Cette méthode est très utile pour la compression JPEG, car comme vu dans la partie 2 suite à la compression du type DCT nous retrouvons une très grande suite de 0. Cette suite de 0 est beaucoup plus importante par une lecture en « zigzag » : 






Utilisons maintenant cette méthode au cas général : En premier temps on définit un caractère spécial (dans l’exemple $) pour repérer le nombre de répétition du caractère, puis un seuil de répétition ( car cette méthode peut augmenter la taille des données si celles-ci comportent peu de suites de symboles identiques, d’où la mise en place du seuil de répétition) Ensuite, on commence la lecture un par un de chaque caractère de la chaîne en suivant cet algorithme :






La compression RLE voit son utilité essentiellement pour la compression des images, une image étant composée de répétitions de pixels, de couleur identique, codés chacun par un caractère.

2)La Compression Huffman

La méthode de compression Huffman consiste à diminuer au maximum le nombre de bits utilisés pour coder un fragment d’information. Prenons l’exemple d’un fichier de texte : le fragment d’information sera un caractère ou un suite de caractères. Plus le fragment sera grand, plus les possibilités seront grandes et donc la mise en œuvre complexe à exécuter. L’algorithme de Huffman se base sur la fréquence d’apparition d’un fragment pour le coder : plus un fragment est fréquent, moins on utilisera de bits pour le coder. Par exemple dans un fichier texte, si on considère que notre fragment est la taille d’un caractère, on peut remarquer que les voyelles sont beaucoup plus fréquentes que les consonnes : par exemple la lettre ‘e’ est largement plus fréquente que la lettre ‘x’ par conséquent la lettre ‘e’ sera codée sur moins de bit que la lettre ‘x’ : la lettre ’e’ peut être sur 2 bits et ‘x’ sur 10 bits.

Pour utiliser cet algorithme, prenons exemple pour un codage des caractères dans un texte :

Il faut tout d’abord créer un tableau à deux entrées : d’une part les caractères de la chaîne , d’autre part leur nombre de répétition. Ensuite il faut trier la liste par ordre croissant de fréquences. Puis construire l’arbre à partir de la liste ordonnée de nœuds, il suffit de prendre les deux nœuds les moins fréquents et de les ajouter comme fils d’un nouveau nœud qui aura pour fréquence la somme des deux.

Si nous prenons par exemple un texte qui comporte :













5

F

9

E

12

C

13

B

16

D

45

A








On prend les deux nœuds les moins fréquents (f et e) , et on crée un nouveau nœud :




Et ainsi de suite jusqu’à ne plus avoir qu’un seul nœud.



Après cela, pour avoir le codage de chacune des lettres, on complète l’arbre : descendre vers la gauche équivaut à un 0 vers la droite à un 1 :











On en déduit donc le codage suivant :

LETTRES

Nombre de répétitions

Bits associés avec Huffman

Nombre de bits

f

5

1100

4

e

9

1101

4

c

12

100

3

b

13

101

3

d

16

111

3

a

45

0

1



Sur cet exemple nous voyons très bien que le a, apparaissant 45 fois est codé grâce à cette compression sur un seul bit, sans cet méthode il aurait très bien pu être codé sur 4 bits et la lettre f sur 1 bit ! Voilà donc pourquoi cette compression est importante.

Il existe 3 variantes de cet algorithme :

- Non adaptive : l’arbre est élaboré à partir d’une table des fréquences fixe ce qui fait qu’il est adapté à un seul type de donnée, et dans certain cas le fichier sera plus important après la compression.

- Semi adaptive : On lit une fois le fichier à compresser pour créer la table des fréquences, puis on s’en sert pour compresser le fichier. C’est la méthode la plus efficace mais elle présente l’inconvénient de nécessiter l’arbre que l’on devra introduire dans un en-tête.

  • Adaptive : La table des fréquences est élaborée au fur et à mesure de la lecture du fichier et l’arbre est reconstruit à chaque fois. On réalise l’arbre avec les premiers caractères (que l’on ne compresse pas) et on s’en sert pour compresser les caractères suivants que l’on utilise aussi pour actualiser l’arbre etc.. Elle est un peu moins efficace que la méthode semi adaptive mais le résultat final est souvent meilleur car elle ne nécessite pas le stockage de l’arbre, et de plus elle ne nécessite qu’une lecture du fichier.















































Conclusion :

Nous avons décidé de choisir comme sujet : «La compression d'images numériques par le JPEG» pour répondre à une question que nous nous posions, comment deux images paraissant pratiquement identiques à nos yeux puissent prendre un espace disque totalement différent, par exemple cette image :


L'image compressé qui prend 1150 Ko contre 35 Ko pour l'image compressé en JPEG, soit 3% de la taille original! Dans une première partie nous avons vu que chaque pixel, lorsque l'image n'est pas compressée (format BMP ou BITMAP) est caractérisée par 3 composantes de base, la composante R, qui definit les domaines de nuances rouges, le V qui definit les domaines de nuance vertes et en dernier lieu le B, qui s'occupe de la couleur bleue. Ce qui nous donne au final un pixel codé en RVB (ou aussi appellé RGB). Le principe de la compression YUV est tout simplement d'optimiser ce codage couleur. En effet, au lieu de décomposer le pixel en 3 couleurs, on le décompose en 3 "caractéristiques" qui sont la luminance ou luminescence (Y ou Brigthness en anglais), la chrominance bleue (Cb ou U, tons de bleu), ainsi pour finir que la chrominance rouge (Cr ou V, tons de rouge). Tout cela dans le but de compresser l'image avec les caractéristiques de l'oeil qui est, pour nous humain, plus sensible au variations d'intensité lumineuse qu'au variations dans l'echelle des teintes (chrominance). Ensuite dans une seconde partie la transformée en cosinus discrète, le but étant de transformer le domaine de représentation de nos données, c'est à dire de passer d'un domaine spatial à un domaine fréquentiel, ce qui permet de trier efficacement l'ensemble des données de l'image et ainsi supprimer certaines données de l'image où l'oeil humain ne verra que très peu de différences : les hautes fréquences de l'image représentant les zones à forts contrastes de l'image. Et enfin dans une troisième partie les deux dernières compressions du types RLE (Run Length Encoding) et Huffman, qui sont des encodages sans pertes d'informations, permettant de tirer partie du travail que la DCT a effectué.

A travers ce TPE, nous avons analyser comment la compression d'une image Bitmap se faisait, mais pour décompresser l'image, il faut appliquer les algorithmes inverses dans le sens inverse c'est-à-dire la décompression Huffman, puis RLE au niveau de la décompression sans perte puis on applique la transformée en cosinus discrète inverse et pour finir on applique la transformation inverse de couleur de YCbCr à RGB. On retrouve ainsi notre image de départ avec une perte de donnée cependant.

Ainsi en appliquant des procédés d'optimisations et de concentration de l'essentiel des données de l'images, on a pu réduire la taille de l'image sur l'ordinateur. Mais cette compression, a quand même un coup qui est une perte de donnée qui peut être faible mais également beaucoup plus grande et très désagréable pour l'oeil ce qui signifie également que la compression JPEG est surtout optimisé pour certains type d'images qui sont des images photographiques et surtout pas des images géométriques où les discontinuités de celles-ci entraînent de très mauvais rendus. Enfin, il faut compter du temps de calcul pour la décompression et la compression de l'image. Aujourd'hui les machines informatiques deviennent de plus en plus rapide donc ce n'est plus vraiment un inconvénient mais pour des machines plus vieilles, ce temps peut-être ressenti. On peut donc conclure en disant que le JPEG est une norme de compression d'image à utiliser pour des images de types photographiques, mais les dégradations que l'image subie peuvent être importante et c'est pour ça que de nouvelles normes de compression ont été mises en place pour avoir des images de meilleurs qualités en abaissant encore la taille de l'image comme par exemple la norme JPEG2000 qui pour une qualité équivalente a des images qui peuvent être de taille dix fois moins grande, ou encore la compression par ondelettes ou par fractale.





Glossaire :


Bit :

Le plus petit élément de la mémoire d'un ordinateur qui peut prendre deux valeurs possible, soit 1 ou soit 0.


Octet :

Un paquet de huit bits qui se suivent dans la mémoire et qui possède une adresse mémoire. La mémoire d'un ordinateur est caractérisée par le nombre d'octet qu'elle contient. Les autres unités sont le Kilo-octet (Ko) où 1 Ko = 1024 octets = 210 octets, le Méga-octet (Mo) où 1 Mo = 1024 Ko = 1048576 octet = 220 octets.


Pixel :

Cette le plus petit élément composant une image qui est décrit avec trois valeurs qui sont le rouge, le bleue et le vert avec une valeur variant de 0 à 255.


Pixelisation :

C'est un effet visuel où l'image originale perd en qualité. Elle transforme une belle image en un ensemble de gros blocs de pixels colorés avec la même couleur à l'intérieur de ce bloc.


Résolution :

C'est le nombre de colonnes et de lignes de pixels d'une image ou d'un écran d'ordinateur ou de télévision par exemple.


RBG (Red, Green, Blue pour rouge, vert et bleue):

C'est une abréviation pour désigner une couleur qui est définie par trois composantes : rouge, vert et bleue.









































Bibliographie :


Internet :


-Les algorithmes de compression et d'encodage du JPEG :


http://mp01.free.fr/comp/comp.htm

http://lab.erasme.org/compress/index.html

http://donut.99.free.fr/En-vrac/tipe/dct.htm

http://inepty.free.fr/

http://crteknologies.free.fr/projets/tpe_compression_graphique

http://xavier.chassagneux.free.fr/tipe/tipe.htm

http://www.artemis.jussieu.fr/wwwos2/html/dess/memoire/promo95/muller/COMPRESS.HTM

http://developpeur.journaldunet.com/tutoriel/gra/010820gra_compression.shtml

http://iphilgood.chez.tiscali.fr/Codage/Compressionjpeg.htm

http://www.kaddour.com/chap2/chap2.htm

http://www.chez.com/nico77


-L'appareil photo numérique :


http://artic.ac-besancon.fr/technologie/Formation/Production_01/gg1/fabric05.htm

http://www.ac-versailles.fr/etabliss/herblay/audiovis/techniq/FORMAT/Ccd.htm


-Les images :


http://donut.99.free.fr/En-vrac/tipe/synthese.htm

http://www.hebus.com








Tout le contenu de ce site web est protégé par les lois internationales de droits d'auteurs . Webmaster : Fabien Menou