Vous êtes sur la page 1sur 10

1- Processus général d’un codec JPEG d’images

Définition :
JPEG: Joint Photographic Experts Group.
C’est un algorithme standard de compression avec perte d’image fixe établit en 1991
basé sur le codage par la transformé en cosinus discrète DCT, et il existe plusieurs
modes opératoires de compression JPEG établies selon la rapidité du codec et le
besoin
-Codage
Codage basé sur la DCT séquentielle
-Codage
Codage basé sur la DCT progressive
-Codage sans perte
-Codage hiérarchique
JPEG basée sur la DCT séquentielle :
Celui quee nous allons aborder sur ce travail c’est celui basé sur la DCT séquentielle,
où l’image est traitée de gauche
gau à droite et de haut en bas ,la figure 1 montre le
processus d’un codec Source JPEG.

Découpage en sous blocs : L’image au début elle est découpée en sous sous-bloc de 8x8 (ou
16x16), chaque sous bloc seras traiter individuellement, si c’est une image couleur il faut
avant tout faire une transformation couleur ensuite un sous échantillonnage, nous n’allons pas
s’étaler sur ce sujet. Exep :

clear; clc;
M=16;N=16;
m=rand(M,N)
[M N]=size(m);
dimension = (M/8) * (N/8)
bloc=zeros(8,8,dimension);
k=1;
for i = 0 : M/8-1
for j = 0 : N/8-1
bloc(:,:,k) = m(i*8+1:i*8+8,j*8+1:j*8+8);
k= k+1;
end
end
bloc

Application de la DCT :
L’étape suivante, Appliquer à chaque sous bloc la transformé DCT 2D ( DCT II )N= 8 (ou
N=16) ,le résultat une matrice de 8x8 fréquences (ou 16x16),cette transformé va permettre de
séparer les hautes fréquences des basses fréquences, on aura 64 coefficients
coefficients (ou 256), le
premier coefficient de la matrice représente le coefficient continue DC ou le fondamental du
sous bloc de l’image, c’est le coefficient de la fréquence nulle dont l’amplitude est la plus
élevée et le reste des coefficients ce sont des coefficients
coefficients AC décroissant si on tend vers les
hautes fréquences. Le fait de séparer les fréquences hautes et les fréquences basses va ainsi
permettre la dé corrélation des pixels de chaque sous bloc de l’image et ainsi réduire la
redondance inter pixel, sachant
sachant que la transformation seul sans quantification et codage n’est
pas une compression, ce n’est juste qu’une étape post-compression
post !
Quantification :
La prochaine étape, la quantification, on fait une division euclidienne entre les blocs DCT et
une table dee quantification déjà calculée sur la base d’un facteur de qualité
Ḟ=round (F/Q)
Cela a pour but d’éliminer les coefficients haute fréquence dont l’œil humain est peu sensible,
seulement ceux présent en dessous du seuil définis par la table de quantificat
quantification auront des
amplitudes très faibles (éliminatoire), ces coefficients seront arrondis à l’entier prêt qui est
souvent 0, d’ailleurs, si on prend par exemple la table de quantification de luminosité
normalisée standard JPEG suivante calculé sur un facteur de qualité FQ = 5:
[
16 11 10 16 24 40 51 61
12 12 14 19 26 58 60 55
14 13 16 24 40 57 69 56
14 17 22 29 51 87 80 62
18 22 37 56 68 109 103 77
24 35 55 64 81 104 113 92
49 64 78 87 103 121 120 101
72 92 95 98 112 100 103 99 ];
On remarque que les coefficients
ents en hautes fréquences seront divisés sur un nombre élevée
(en rouge), et ceux en basses fréquences seront diviser sur un nombre moins élevé (noir).

Codage des coefficients DC et AC :


Maintenant qu’on a les coefficients DCT quantifiés et arrondis, les coefficients AC et
coefficients DC auront deux codages différents avant de subir le codage entropique de
Huffman.

Les coefficients AC seront récupérer sur un vecteur par un scan en zig-zag


zig zag de la matrice de
chaque sous bloc afin de mettre les coefficients élevées en premier et les zéros en fin comme
illustré dans la figure
Exemple zig-zag :

t=0;

for d=2:64

c=rem(d,2); %checking whether even or odd

for i=1:8

for j=1:8

if((i+j)==d)
t=t+1;
t;
if(c==0)
new(t)=dctq(j,d-j);
else
new(t)=dctq(d-j,j);
end
end
end
end
end
dctq
new
Résultats:
new =
[ 11 -5 -4 8 1 13 -3 -3 -3 -3 4 1 0 0 3 0 -1 0 0 -1 0
1 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]

odage RLE :
Le codage RLE (run-length encoding) consiste à remplacer la répétition d'un même code par
une balise et le nombre d'occurrences de ce code :
Pour le JPEG, le codage RLE ne sera appliqué que pour les séquences de 0. Exemple :
la séquence : 150000000008
Séquence RLE : 15#98
On se rend compte du gain considérable que l'on peut réaliser en codant chaque bloc 8x8 passé
en DCT, puis quantifié.
Codage Huffman :
L’étape finale, c’est le codage Huffman, qui va compresser le vecteur RLE à la limite de la
compression sans perte (VLC).Le codage Huffman se déroule en deux étapes :
1ére étape : Construire l’arbre de Huffman en classant les probabilités de chaque symbole de
haut en bas, et on additionnant les probabilités faibles pour obtenir un autre symbole et ainsi
de suite jusqu’à il en reste que deux probabilités.
2éme étapes : consiste en l’encodage des symboles en partant de l’inverse où on s’est arrêté
on assignant des 0 et 1 à chaque symbole jusqu’à construire la table de codage de chaque
symbole.
En général cela est basé sur une table Huffman standard au JPEG déjà prête, mais dans notre
cas, on va calculer nos tables de codage. Au final nous auront un vecteur de suite de 1 et 0 qui
représente l’image compressée JPEG.
Dans le processus de décodage, c’est l’inverse de toutes les étapes précédente en commençant
par le décodage Huffman jusqu’à la DCT inverse (IDCT) pour reconstituer finalement
l’image.
Le code Matlab final :
% \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
% Programme basique sur la compression JPEG d'image fixe monochrome
% Version : 1.0
% Par: AzougSeifEddine
% http://dynelectrons.net76.net
% dynelectrons@dynelectrons.net76.net
% Fait le: 01/01/2011
% \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
clear
% Chargement de la matrice image monochrome sur Matlab qui seras sous format entier
uint8
% et la convertir en double pour les calcul
img_originale = double(imread('zohrap.bmp'));
% Si Image a un espace de couleur RVB ou autre que monochrome,elle doit étre
convertie
% img_originale = rgb2gray(img_originale);
dim_bloc = 8; %dimension 8x8 des sous blocs
init_jpeg; % Déclaration et initialisation des variables nécéssaires (voir:
init_jpeg.m)

%Décodage et décompression (Voir: codage_jpeg.m)


codage_jpeg
%Décodage et décompression (Voir: decodage_jpeg.m)
decodage_jpeg
%Affichage de l'image originale,de sa DCT,et de l'image décompressé.
figure(1)
subplot(1,3,1)
imshow(uint8(img_originale))
title('Image Originale');
subplot(1,3,2)
imshow(jpeg)
title('DCT');
subplot(1,3,3)
imshow(uint8(img_decompresse))
title('Image décompressée');
figure(2)
subplot(2,2,1)
imshow(uint8(img_originale(112:120,120:128)))
title('Sous bloc de l''mage Originale');
subplot(2,2,2)
imshow(uint8(img_decompresse(112:120,120:128)))
title('Sous bloc de l''mage Compressée');
%Evalutation du Taux de compression
for i=1:8:m
for j=1:8:n
eval([ sprintf('taille_img_compresser = taille_img_compresser +
numel(hcode_%d_%d);',i ,j)]);
end
end
taille_originale = dim_img
taille_img_compresser
taux_compression = taille_originale / taille_img_compresser
%Evaluation de l'erreur quandratique moyenne EQM
somme=0;
for(i=1:m)
for(j=1:n)
somme=somme + ((img_originale(i,j) - img_decompresse(i,j))^2);
end
end
EQM=somme/(m*n)
%Calcul de la valeur créte du rapport signal sur bruit Peak to noise ratio PSNR
bit=8;
PSNR=10*log10(((2^bit-1)^2)/EQM)
%Calcul des bits par pixel Bpp.
bpp = taille_img_compresser / dim_img% Fichier image compressé / nombre de pixels
% Déclaration des variables et initialisation des constantes
jpeg = ones(size(img_originale)); % Matrice JPEG qui va contenir l'image compressée
jpeg_deco = ones(size(jpeg)); % Matrice qui va contenir l'image décompressé
offset = ones(dim_bloc,dim_bloc)*128; %Matrice 8x8 pour "LevelShifting".
DCT = dctmtx(dim_bloc); % Matrice C pour le calcul de F
% récupération des dimensions de l'image.
[m,n] = size(img_originale);
dim_img = m*n;
%Matrice ou table de quantification Q (Standard JPEG)
quantizer =...
[...
16 11 10 16 24 40 51 61; ...
12 12 14 19 26 58 60 55; ...
14 13 16 24 40 57 69 56; ...
14 17 22 29 51 87 80 62; ...
18 22 37 56 68 109 103 77; ...
24 35 55 64 81 104 113 92; ...
49 64 78 87 103 121 120 101; ...
72 92 95 98 112 100 103 99 ... ];
%Vecteur du scan Zigzag
zigzag = ones([1 dim_img]);
%Fonction de récupération des indices du scan zigzag (voir init_indices_zigzag.m)
[col lig] = init_indices_zigzag(dim_bloc);
%Vecteur du codage/décodage RLE et codage/décodage Huffman
rle = [];
rle_deco = [];
huff_deco = [];
% Constantes utiles
taux_compression = 0;
taille_img_compresser = 0;
dec_l = 0;
dec_c = 0;
redondance = 0;
col_rle_p = 1;
k = 1;
z =1;
d=0;

%Cette fonction permet de créer deux matrices


%Une matrice ligne lig et une matrice colone "col"
%Chaque matrice va contenir respectivement indices ligne et colonnes
%Ces indices vont aidéa faire le scan zig zag pour un sous bloc 8x8.
function[col,lig]=init_indices_zigzag(dim_bloc)
col = ones([1 (dim_bloc * dim_bloc)]);
lig = ones([1 (dim_bloc * dim_bloc)]);
lig(1) = 1;
k=2;
r=1;
for x=3:2:dim_bloc
for j=1:x
lig(k) = j;
k = k + 1;
end
for j=x-1:-1:1
lig(k) = j;
k = k + 1;
end
for j=1:x-1
col(r) = j;
r = r + 1;
end
for j=x-2:-1:1
col(r) = j;
r = r + 1;
end
if(x == 7 ),
x = x+1;
for j=1:x
lig(k) = j;
k = k + 1;
col(r) = j;
r = r + 1;
end
for j=x-1:-1:1
col(r) = j;
r = r + 1;
end
for z=2:2:x
for j=x:-1:z+1
lig(k) = j;
k = k + 1;
end
for j=z:x
lig(k) = j;
k = k + 1;
end
for j=z:x
col(r) = j;
r = r + 1;
end
if(z ~= dim_bloc)
for j=x:-1:z+1
col(r) = j;
r = r + 1;
end
end
end
end
end;
codage_jpeg.m
%Boucle général qui va parcourir l'image en sous bloc 8x8
for i=1:dim_bloc:m
dec_l = i-1; %Décalage vertical des sous blocs
for j=1:dim_bloc:n
dec_c = j-1; %Décalage vertical des sous blocs
jpeg(i:i+7,j:j+7) = img_originale(i:i+7,j:j+7) - offset; % Effectuer le "Level
Shifting".
jpeg(i:i+7,j:j+7) = DCT * jpeg(i:i+7,j:j+7) * DCT'; % Appliquer DCT
jpeg(i:i+7,j:j+7) = jpeg(i:i+7,j:j+7) ./ quantizer; % Division par la table
Q.
jpeg(i:i+7,j:j+7) = round(jpeg(i:i+7,j:j+7)); % Arrondir à l'entier
le plus prés.
for q =1:64
zigzag(k) = jpeg(lig(q)+dec_l,col(q)+dec_c); % Effectuer un scan
ZigZag.
k = k + 1;
end
d = k - 64;
q = 1;
while(q <= 64) % Boucle While qui effectue un codage RLC sur chaque
sous bloc
if (d <dim_img) && (zigzag(d) ~= zigzag(d+1))
rle(z) = zigzag(d);
d = d + 1;
q = q + 1;
z = z + 1;
elseif(d <dim_img) && (zigzag(d) == zigzag(d+1)) &&
(zigzag(d+1) ~= zigzag(d+2))
rle(z) = zigzag(d);
rle(z+1) = zigzag(d+1);
d = d + 2;
q = q + 2;
z = z + 2;
elseif(d <dim_img) && (zigzag(d) == zigzag(d+1)) &&
(zigzag(d+1) == zigzag(d+2))&& (zigzag(d+2) ~= zigzag(d+3))
rle(z) = zigzag(d);
rle(z+1) = zigzag(d+1);
rle(z+2) = zigzag(d+2);
d = d + 3;
q = q + 3;
z = z + 3;
elseif(d <dim_img) && (zigzag(d) == zigzag(d+1)) &&
(zigzag(d+1) == zigzag(d+2))&& (zigzag(d+2) == zigzag(d+3))
redondance = 4;
rle(z) = 257;
rle(z+1) = redondance;
rle(z+2) = zigzag(d);
d = d + 3;
q = q + 4;
while(q <= 64) && (d <dim_img) && (zigzag(d) == zigzag(d+1))
redondance = redondance + 1;
q = q + 1;
d = d + 1;
end
rle(z+1) = redondance;
d = d + 1;
z = z + 3;
end
if(q == 64)
q = q+1;
end
end
% Début du codage Entropique de Huffman.
col_rle = z-1;
%Extraction des symboles uniques présent dans le vecteur
%RLC.
symboles = unique(rle(col_rle_p:col_rle));
nbr_symboles = numel(symboles);
taille_block = numel(rle(col_rle_p:col_rle));

%Calcul des probabilités de chaque symboles.


table_p = ones(1,nbr_symboles);
for q = 1:nbr_symboles
itter = 0;
for r = col_rle_p:col_rle
if(rle(r) == symboles(q))
itter = itter + 1;
end
end
table_p(q) = itter / taille_block;
end
%Dressage de l'arbre de huffman et codage de chaque
%symbole de chaque sous bloc.
eval([ sprintf('dico_%d_%d = huffmandict(symboles,table_p);', i ,j)]);
eval([ sprintf('hcode_%d_%d = huffmanenco(rle(col_rle_p:col_rle),dico_%d_%d);', i
,j,i
,j)]);
col_rle_p = col_rle+1;
end
end

%Décodage Huffman
for i=1:dim_bloc:m
for j=1:dim_bloc:n
eval([ sprintf('huff_deco = [huff_decohuffmandeco(hcode_%d_%d,dico_%d_%d)];', i
,j,i ,j)]);
end
end
%Décodage RLE
i = 1;
k = 1;
while(k <= numel(huff_deco))
if(huff_deco(k) == 257)
rle_deco(i:(i-1+huff_deco(k+1))) = huff_deco(k+2);
i = i + huff_deco(k+1);
k = k +3;
else
rle_deco(i) = huff_deco(k);
i = i +1;
k = k +1;
end
end
k=1;
for i=1:dim_bloc:m
dec_l = i-1;
for j=1:dim_bloc:n
dec_c = j-1;
%Scan zigzag inverse
for q =1:64
img_decompresse(lig(q)+dec_l,col(q)+dec_c)
sse(lig(q)+dec_l,col(q)+dec_c) = rle_deco(k);
k = k + 1;
end
%quantification inverse + IDCT + Remises des niveaux (Inverse
%LevelShifting)
img_decompresse(i:i+7,j:j+7) = img_decompresse(i:i+7,j:j+7) .* quantizer;
img_decompresse(i:i+7,j:j+7) = DCT' * img_decompresse(i:i+7,j:j+7)
img_decompresse(i:i+7,j:j+7) * DCT;
img_decompresse(i:i+7,j:j+7) = img_decompresse(i:i+7,j:j+7) + offset;
end
end

Résultats :

Conclusion :
La compression JPEG pour qu’elle soit efficace doit être effectuée de façon optimale afin de
ne pas perdre trop en qualité de l’image et en parallèle réduire le poids de l’image, c’est
c’est-à-dire
trouver un compromis rapport taille/qualité qu’est le standard JPEG.
Le format JPEG, très couramment utilisé pour le codage des images bitmap et des photos, est
un format de compression très efficace. La perte de qualité d'image occasionnée par
l'algorithme de compression peut être maîtrisée car le taux de compression des fichiers .jpeg
est réglable. Le format JFIF, plus connu sous le nom de format JPEG, est complémentaire des
formats GIF et PNG pour la publication d'images sur le Web: il sauvegarde plus
d'informations couleur que le format GIF et permet de comprimer des photographies ou des
images lourdes.
Le principal avantage de ce format est le taux de compression réglable
réglable qui permet à
l'utilisateur de trouver un compromis entre le taux de compression et la qualité de l'image.

Remarque : M. j'ai un problème dans matlab (commande imread) ne fonctionner


pas donc j’ai utilisé la photo qui trouve avec le program