Faire l'histogramme d'une image, c'est compter combien il y a de pixel pour chaque valeur possible que peut prendre un pixel.
Si nous avons une image en niveau de gris où les valeurs sont représentées sur 8 bits, nous aurons un histogramme de 255 valeurs.
8 bits donne 28 valeurs possibles.
Pour réaliser ce traitement, nous allons créer un vecteur hist dont la taille est définie par le nombre possible de valeurs
différentes de pixel (soit taille = 2k où k est le nombre de bits pour le niveau de gris) et nous mettons tout à zéro,
puis nous devons parcourir l'image en entier, ligne à ligne et colonne à colonne. Pour chaque valeur d'un pixel, nous allons augmenter la valeur de l'histogramme
associé à cette valeur. Par exemple si la valeur du pixel trouvé est 200 alors hist(200) = hist(200)+1.
voici le programme qui réalise l'histogramme. Les commentaires devraient suffire à le comprendre.
clear all; close all;
[filename, pathname] = uigetfile({'*.jpg;*.tif;*.PNG;*.gif;*.bmp','All Image Files';...
'*.*','All Files' },'mytitle',...
'C:\Work\myfile.jpg') % récupération du chemin du fichier
x = imread(filename); % récupération des données
if (length(size(x))>2)% si l'image en niveau de gris est sur 3 composantes couleurs
x=x(:,:,1);% on prend un seul plan
end
% nombre de bit de la valeur des pixels
k = whos('x');
if k.class == 'uint8'
k=8;
elseif k.class == 'int16'
k=16;
elseif k.class == 'int32'
k=32;
elseif k.class == 'int64'
k=64
end
%taille de la matrice
[ligne colonne]=size(x);
hist = zeros(2^k,1);% création du vecteur de résultat
for i=1:ligne %on parcourt toutes les lignes
for j=1:colonne %on parcourt toutes les colonnes
hist(x(i,j)+1) = hist(x(i,j)+1)+1;% on compte les valeurs
end
end
% affichage de l'image et de l'histogramme
figure(1)
subplot(222)
imshow(x)
subplot(221)
plot([0:(2^k)-1],hist)
Le programme a été appliqué sur l'image de gauche et nous voyons le résultat à droite.
L'histogramme nous donne une information sur la répartition des valeurs des pixels dans l'image. Un histogramme
avec beaucoup de valeurs proches de zéro traduira une image pas sous-exposée (image très sombre) alors qu'un histogramme
dont les valeurs sont élevées traduira une image sur-exposée (image très éclairée). La moyenne de cet histogramme montre où se trouve
la valeur qui sépare l'histogramme en deux. Elle montre où se situe la majorité des pixels. Avec l'exemple précédant nous obtenons une valeur moyenne de
116.9947, elle est appelée Average Optical Density (AOD) elle est calculée comme suit dans le programme.
aod=sum(hist.*[0:(2^k)-1]')/(ligne*colonne)
Sur certaines images l'histogramme permet d'appliquer une correction sur l'image. Imaginons une image où la grande
majorité (voir la totalité) des pixels se situent sur une petite partie des valeurs possibles. Exemple seulement de 30 à 100 pour une
image sur 8 bits (255 valeurs en tout). Dans ce cas, les couleurs (niveau de gris) sont réparties sur une très faible gamme. L'oeil a donc du mal à les
différencier. La rectification va permettre de répartir les couleurs sur la gamme entière. Avec l'exemple précédant les pixels dont les valeurs sont 30 seront
amenés à une valeur de zéro quant aux autres ils seront réparties sur toutes les valeurs jusqu'au maximum possible soit 255.
for i=1:ligne
for j=1:colonne
img(i,j) = round((img(i,j)-bas)*(255/haut));
end
end
Où bas est la valeur qui passera à zéro et haut la valeur qui passera à 255 (ou au maximum)
Observons le résultat sur une image sous exposée.
Ce type de correction s'applique aux images ayant une forte concentration de points soit dans le sombre (proche
de zéro) soit dans le clair (proche de 255). Le but est de repartir les pixels de manière non linéaire. S'il s'agit
d'une image sombre nous allons plus espacer les valeurs des pixels si la valeur est faible et de les rapprocher quand elles sont élevées.
La même méthodologie s'applique si l'image est claire mais dans le raisonnement inverse (inverser la fonction logarithme).
Comment fait-on ? Nous allons faire comme la rectification linéaire mais au lieu d'appliquer une fonction proportionnelle, elle sera logarithmique.
exemple pour une image ou k=8, Le logarithme va de 0 à 255, on a l'équation suivante :
for i= 1:255
hist(i)=round(log(i)*((2^k)/log(2^k)));
end
plot(hist)
On retrouve la courbe suivante :
On va encore une fois parcourir tous les pixels et pour chaque valeur du pixel trouvé (abscisse), on lui associe
la valeur en logarithme (ordonnée). De cette manière les pixels sombres sont plus espacés dans l'espace de couleur et l'oeil
les perçoit mieux. Quant aux pixels blancs, qui sont beaucoup moins nombreux ils sont condensés sur très peu de valeur (ils sont moins importants car moins nombreux).
Le résultat :
Cette fois-ci, nous allons utiliser l'histogramme de l'image d'origine pour construire une fonction non linéaire. Pour faire cette fonction nous allons suivre plusieurs étapes.
Puis comme pour les corrections précédentes, nous appliquons la fonction pour chaque pixel.
Le programme Matlab :
clear all; close all;
[filename, pathname] = uigetfile({'*.jpg;*.tif;*.PNG;*.gif;*.bmp','All Image Files';...
'*.*','All Files' },'mytitle',...
'C:\Work\myfile.jpg') % récuperation du chemin du fichier
x = imread(filename); % récuperation des données
if (length(size(x))>2)% si l'image en niveau de gris est sur 3 composantes couleurs
x=x(:,:,1);% on prend un seul plan
end
% nombre de bit de la valeur des pixel
info = whos('x');
if strcmp(info.class,'uint8')
k=8;
elseif strcmp(info.class,'uint16')
k=16;
elseif strcmp(info.class,'uint32')
k=32;
elseif strcmp(info.class,'uint64')
k=64;
end
%taille de la matrice
[ligne colonne]=size(x);
hist = zeros(2^k,1);% création du vecteur de résultat
for i=1:ligne %on parcourt toutes les lignes
for j=1:colonne %on parcourt toutes les colonnes
hist(x(i,j)+1) = hist(x(i,j)+1)+1;% on compte les valeurs
end
end
%normalisation d'histogramme
hist=hist/(ligne*colonne);
%somme cumulative de l'histogramme normalisé
histsum = cumsum(hist);
% dénormalisation
histsum=round(histsum*2^k);
% affichage de l'image et de l'histogramme
figure(1)
subplot(222)
imshow(x)
subplot(221)
plot([0:(2^k)-1],hist)
for i=1:ligne
for j=1:colonne
x(i,j) = histsum(x(i,j)+1);
end
end
hist = zeros(2^k,1);
for i=1:ligne
for j=1:colonne
hist(x(i,j)+1) = hist(x(i,j)+1)+1;
end
end
subplot(224)
imshow(x)
subplot(223)
plot([0:(2^k)-1],hist)
Et un résultat
Copyright © 2010-2014, tous droits réservés, contact : operationpixel@free.fr