Vous êtes sur la page 1sur 12

Travail personnel

codage et compression

Senouci
Houda
G :03
Travail préparatoire:

a) Processus de codage/décodage JPEG

1
2 3 4 5
Coefficients Coefficients

Mot
d'Huffm ann

Coeff. DC Coeff. AC
BF

HF
Un seul bloc de
8x8 pixels ou
Suivant une table de Ordonnem ent des coefficients
coefficients
quantification: suivant un ordre prédéfini:

b)

1ère étape:
On divise l'image en blocs de 8x8 pixels.

2ème étape:
On applique une Transformée en Cosinus Discrète à chacun des blocs. On obtient alors des
coefficients représentant les différentes fréquences de l'image pour un canal donné. En haut à
gauche se trouve les basses fréquences, en bas à droite les hautes fréquences.

3ème étape:
On quantifie différement les coefficients suivant la fréquence. Dans la norme JPEG il existes 4
tables de quantification différentes suivant la compression voulue. Cette technique a pour but de
supprimer les hautes fréquences, qui sont moins visibles par l'oeil humain ( voir courbe Nill).

4ème étape:
On classe les coefficients suivant un ordre en zig-zag.

5ème étape:
On procède au codage entropique, c'est à dire que l'on passe d'une suite de coefficients à une suite
de zéros et de uns:
On code le coefficient DC du bloc traité en le soustrayant au coefficient DC du bloc précédent. On
appelle ça un codage différentiel.
Ensuite on code les coefficients AC, pour éliminer les coefficients à zéro on regarde dans la table
d'Huffman ci-dessous le nombre de zéros avant un coefficient non nul ainsi que la catégorie du
coefficient non nul, on obtient alors un premier code, auquel on ajoute le code donnant la position
du nombre dans la catégorie.

Après zig-zag

On obtient désormais le mot d'Huffman différentiel. Pour le décodage on effectue les mêmes étapes
dans le sens inverse.

c) Les pertes sont dûes à la quantification où l'on est obligé d'arrondire à l'entier le plus proche,
lorsque l'on fait le décodage, les valeurs de l'image d'origine ne sont donc pas retrouvées. On
exploite les redondances fréquentielles de l'images ainsi que les redondances entre chaque bloc des
coefficients DC.

Transformée en Cosinus Discret d’une image

Introduction

La transformée en Cosinus Discret aussi connue sous l’abréviation de DCT et une


opération très connue dans le domaine du traitement d’image qui permet de
passer de la représentation spatial d’un signal à une représentation spectrale de
celui-ci.

La DCT est proche de la transformée de Fourier, mais possède des propriétés


intéressantes qui la rendent parfois plus adaptée à certaines opérations de
traitement du signal et notamment de l’image. Ces trois propriétés de base sont :
 Transformée à coefficient réels (simple à calculer).
 Transformation sans pertes (le signal orignal peut être retrouvé à l’identique par
transformée inverse).
 Concentration de l’information dans les coefficients de basse fréquence.
Du fait de son aptitude à concentrer l’information d’un signal réel dans les
coefficients de basse fréquence, la DCT peut être utilisée dans des opérations de
compression de l’information. A ce propos la DCT est une des étapes clef de la
compression d’images au format JPEG.

Nous présentons dans cet article comment calculer la DCT et la DCT inverse sur
un signal en deux dimensions . La programmation à été réalisée en langage C avec
les bibliothèques standard du langage C.

Théorie et précisions

Tout d’abord voici les formules de la DCT et de l’IDCT pour un signal en 2


dimensions (typiquement une image) :

DCT 2D

IDCT 2D

Avec :

 n et m, la largeur et la hauteur de l’image en pixel (ex n=512 m=512).


 C(u) et C(v) les facteur d’orthogonalité de la transformée :

 I(x,y) la valeur du pixel de l’image a transformer à la position x et y.


 F(u,v) correspond au coefficient de la transformée.
On constate que ces formules amènent une quantité non négligeable de calculs, par
exemple dans le cas d’une image de 512*512 pixels il faut au minimum calculer 512²
multiplications. C’est pourquoi dans les application de base il est plus commode de
découper l’image en petit morceaux pour ensuite appliquer la DCT sur chacun de ces
morceaux séparément. Le format JPEG se base sur des blocs de 8*8 pour effectuer le
traitement.

La DCT permet de passer de la représentation spatiale d’un signal à sa représentation


spectrale.

La IDCT quand à elle permet de repasser du domaine spectral au domaine spatial.

Calcule de DCT et IDCT sur une matrice 8*8

Dans cette partie nous allons simplement réaliser la DCT et la IDCT sur un signal
quelconque de 8*8 afin de constater les propriétés de bases de ces opérations.
Aucunes subtilités ou optimisations n’ont été ajoutés afin de ne pas rendre la
compréhension plus difficile.

Pour commencer, on développe les deux fonctions de base :DCT et IDCT, grâce aux
formules théoriques, elles sont assez similaires et utilisent chacune deux tableaux. La
DCT utilise un tableau représentant un signal et renvoie un tableau contenant les
coefficients de la DCT.

La IDCT quand à elle prend en paramètre un tableau contenant les coefficients d’une
DCT et renvoie un tableau représentant le signal reconstruit dans le domaine spatial.

DCT :

/* transformée DCT : on passe à cette fonction un bloc de


8*8 pixel de l'image et elle renvoie la matrice des coeffs
de la DCT coresspondante*/
void DCT_8(int pixel[8][8], float Coeff_DCT[8][8])
{
int u=0, v=0;
int x=0, y=0;
float au=0, av=0;
for(v=0;v<=7;v++)
{
for(u=0;u<=7;u++)
{
//Calcule des doubles sommes
for(y=0;y<=7;y++)
{
for(x=0;x<=7;x++)
{
Coeff_DCT[v][u]+=pixel[y][x]*(cos((PI*(2*x+1)*u)/16)*cos((PI*(2*y+1)*v)/16));
}
}
//Calcule des facteurs d'ortogonalité
if(u==0){au=(1/sqrt(2));}
else {au=1;}
if(v==0){av=(1/sqrt(2));}
else{ av=1;}
//Calcule du coefficient complet
Coeff_DCT[v][u]=Coeff_DCT[v][u]*0.25*au*av;
}
}
}
Calcule de la DCT
IDCT :

/* transformée inverse de la DCT, on passe en parametres


une matrice de coefficients et elle renvoi une matrice
de nombre entier representant la martice de départ */
void IDCT_8(float Coeff_DCT[8][8], int matrice_reconstruite[8][8])
{
int u=0, v=0;
int x=0, y=0;
float au=0, av=0;
//Matrice intermédiaire pour travailler en nombre réel
float f[8][8]={0};
for(y=0;y<=7;y++)
{
for(x=0;x<=7;x++)
{
for(v=0;v<=7;v++)
{
for(u=0;u<=7;u++)
{
if(u==0){au=1/sqrt(2);}
else {au=1;}
if(v==0){av=1/sqrt(2);}
else{ av=1;}
f[y][x]+=Coeff_DCT[v][u]*au*av*cos(((2*x+1)*PI*u)/16)*cos(((2*y+1)*PI*v)/16);
}
}
f[y][x]*=0.25;
//Conversion réel entier avec arrondi
matrice_reconstruite[y][x]=floor(f[y][x]+0.5);
}
}
}
Calcule de la IDCT
On utilise maintenant ces deux fonctions pour calculer la DCT d’une matrice
représentant un signal et ensuite la IDCT pour voir si il est possible de retrouver notre
matrice de départ :

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define N 8
#define PI 3.141592653589793
void DCT_8(int pixel[8][8], float Coeff_DCT[8][8]);
void IDCT_8(float C[8][8], int matrice_reconstruite[8][8]);
int main(int argc, char const *argv[])
{
int i=0,j=0,k=0;
float coeff_DCT[8][8]={0};//Matrice pour placer les coeff de la DCT
int matrice_reconstruite[8][8]={0}; //Matrice pour placer le signal
reconstruit
//Matrice representant le signal de base
int matrice[8][8]={{244,243,118,154,126,246,137,184},
{178,127,196,155,184,184,147,245},
{114,116,134,231,145,166,214,112},
{178,127,196,155,184,184,247,245},
{200,224,133,145,105,167,237,118},
{137,263,118,154,126,246,137,89},
{178,127,196,255,184,184,147,245},
{114,116,134,231,145,166,247,198}};
//Calcule de la DCT sur la matrice d'origine
//On place les coeff dans coeff_DCT
DCT_8(matrice, coeff_DCT);
//Calcule de la IDCT grace à la martice des coeff
//On place le signal regénérer dans martrice_reconstruite
IDCT_8(coeff_DCT, matrice_reconstruite);

//Affichage des differentes etapes


for(k=0;k<4;k++)
{
if(k==0)puts("\nMatrice d'origine :");
if(k==1)puts("\nMatrice des coefficients :");
if(k==2)puts("\nMatrice reconstruite :");
if(k==3)puts("\nDifférence Origine/Reconstruite:");
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
{
if(k==0)printf("%d ",matrice[i][j]);
if(k==1)printf("%5.1f ",coeff_DCT[i][j]);
if(k==2)printf("%d ",matrice_reconstruite[i][j]);
if(k==3)printf("%d ",matrice[i][j]-matrice_reconstruite[i][j]);
}
printf("\n");
}
}
return 0;
}
On obtient le résultat suivant :

Matrice d'origine :
244 243 118 154 126 246 137 184
178 127 196 155 184 184 147 245
114 116 134 231 145 166 214 112
178 127 196 155 184 184 247 245
200 224 133 145 105 167 237 118
137 263 118 154 126 246 137 89
178 127 196 255 184 184 147 245
114 116 134 231 145 166 247 198

Matrice des coefficients :


1385.2 -62.7 22.3 19.7 -20.8 50.7 -7.6 -82.0
5.5 29.0 47.8 38.4 4.2 -36.1 42.0 15.2
22.2 -15.4 -7.4 -21.1 69.1 -21.6 44.7 -43.9
6.5 129.7 61.6 83.7 -65.1 -101.9 9.4 -83.9
26.7 -14.0 86.5 27.1 -28.2 26.5 -36.9 15.5
53.4 -11.7 -12.6 -14.6 48.8 -2.8 39.7 -6.5
-73.1 33.9 -42.3 67.1 -86.5 7.2 -79.1 -79.2
-24.7 36.1 -11.0 3.8 6.7 61.6 -45.1 -24.4

Matrice reconstruite :
244 243 118 154 126 246 137 184
178 127 196 155 184 184 147 245
114 116 134 231 145 166 214 112
178 127 196 155 184 184 247 245
200 224 133 145 105 167 237 118
137 263 118 154 126 246 137 89
178 127 196 255 184 184 147 245
114 116 134 231 145 166 247 198

Différence Origine/Reconstruite:
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
Affichage de la console
La DCT calcule une matrice de 64 coefficients représentant l’image dans le domaine
spectral. Ensuite on utilise cette matrice de coefficients pour calculer la DCT Inverse
(IDCT) et vérifier que le signal reconstruit est bien identique au signal de départ. Au
final on constate que la matrice reconstruite à partir de la transformée est
rigoureusement identique à la matrice de base. Cet exemple montre la propriété sans
pertes de la DCT : avec un nombre fini de coefficients et en n’oubliant pas les arrondis
dans le code, il est possible de reconstruire exactement le signal de départ.

Réduction de l’information

Maintenant que nous pouvons réaliser la DCT et la DCT inverse nous allons montrer
pour quelle raison la transformée en cosinus discret peut être utilisée pour réaliser de la
compression de données.

Pour observer ses propriétés nous allons modifier les coefficients de la DCT et
constater l’impact sur le signal reconstruit par la IDCT.

Pour cela nous allons utiliser une matrice dite « de quantification » qui permet de
diviser la matrice des coefficients de la DCT par un facteur quelconque. Ensuite pour
retrouver une matrice de coefficients proche de l’original il faut re-multiplier par la
matrice de quantification et enfin appliquer une IDCT. Ces deux opérations semblent
inutile à première vue, mais elles ont pour but de mettre à zéro les coefficients proches
de zéro ou les coefficients inutiles.

Voici les deux fonctions de quantification et de dé-quantification :


/*Cette fonction réalise la quantification de la matrice des coefficients*/
/*L'indice permet de quantifier plus ou moins la matrice des coefficients*/
void Quantification(float Coeff_DCT[8][8],int Coeff_Quant[8][8],int
indice_quantifiaction)
{
int u=0, v=0;
//On parcour la matrice des coefficients
for(v=0;v<=7;v++)
{
for(u=0;u<=7;u++)
{
Coeff_Quant[v][u]=(int)trunc(Coeff_DCT[v][u]/(1+((1+u+v)*indice_quantifiaction)));
/*division par 1+((1+u+v)*indice_quantifiaction) et arrondi du
coefficient*/
}
}
}
Quantification de la matrice des coefficients
/*Cette fonction réalise la dé-quantification de la matrice des coefficients*/
/*Afin de retrouver une matrice des coefficients proche de l'originale*/
void Dequantification(float Coeff_DCT[8][8],int Coeff_Quant[8][8],int
indice_quantifiaction)
{
int u=0, v=0;
for(v=0;v<=7;v++)
{
for(u=0;u<=7;u++)
{
Coeff_DCT[v][u]=(int)trunc(Coeff_Quant[v][u]*(1+((1+u+v)*indice_quantifiaction)));
/*multiplication par 1+((1+u+v)*indice_quantifiaction) et arrondi du
coefficient*/
}
}
}
Dé-quantification des coefficients
DCT_8(matrice, coeff_DCT);
Quantification(coeff_DCT,coeff_Quant,1);
Dequantification(coeff_DCT,coeff_Quant,1);
//Calcule de la IDCT grace à la martice des coeff
//On place le signal regénérer dans martrice_reconstruite
IDCT_8(coeff_DCT, matrice_reconstruite);
On obtient le résultat suivant sur une matrice obtenue à partir d’une image réelle :

Matrice d'origine :
162 162 162 161 162 157 163 161
162 162 162 161 162 157 163 161
162 162 162 161 162 157 163 161
162 162 162 161 162 157 163 161
162 162 162 161 162 157 163 161
164 164 158 155 161 159 159 160
160 160 163 158 160 162 159 156
159 159 155 157 158 159 156 157

Coefficients quantifiée:
641 1 0 0 0 0 0 0
2 0 0 0 0 0 0 0
-1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

Matrice reconstruite :
161 161 161 161 161 160 160 160
161 161 161 161 161 161 160 160
162 162 161 161 161 161 161 161
162 162 161 161 161 161 161 161
161 161 161 161 161 160 160 160
160 160 160 160 160 160 159 159
160 160 159 159 159 159 159 159
159 159 159 159 158 158 158 158

Différence Origine/Reconstruite:
1 1 1 0 1 -3 3 1
1 1 1 0 1 -4 3 1
0 0 1 0 1 -4 2 0
0 0 1 0 1 -4 2 0
1 1 1 0 1 -3 3 1
4 4 -2 -5 1 -1 0 1
0 0 4 -1 1 3 0 -3
0 0 -4 -2 0 1 -2 -1
On remarque finalement que la matrice quantifiée ne contient plus que 4 coefficients
non nuls, et pourtant après dé-quantification et IDCT inverse, l’erreur entre le signal
d’origine et le signal reconstruit est plutôt faible. En résumé, nous sommes passés de
64 coefficients à seulement 4 pour décrire un signal proche de l’original, sur ce signal
en particulier nous avons réduit la taille d’information par 16. Autrement dit, si une
personne à l’autre bout du réseau, par exemple, connaît la méthode de dé-
quantification et de transformée inverse que j’ai utilisé, alors il est en mesure de
reconstruire quasiment le signal d’origine si je lui fournis seulement 4 coefficients, au
lieu de lui envoyer les 64 pixels de l’image de base.

Voilà finalement tout l’intérêt de la DCT, car on constate que si l’on réduit
intelligemment le nombre des coefficients il est quand même possible de retrouver une
variante exploitable de l’information d’origine. Ce qui serait tout bonnement
impossible avec une transformée de Fourier, du fait du phénomène de Gibbs entre
autres.

Dans un prochain article, nous aborderons la compression sans pertes des matrices de
coefficients afin de réduire encore plus le volume des données représentant une image.

Vous aimerez peut-être aussi