l'image de fond

fr       en

Traitements d'Images en Niveau de Gris

L'histogramme

Méthode

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.
pre histogramme

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)

La correction linéaire

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.
histogramme d'une image

La correction logarithmique

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 :
histogrammelog1
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 :
histogramme logarithme

La correction par somme cumulative d'histogramme

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.


histogramme cumulé
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

histogramme d'une image

Copyright © 2010-2014, tous droits réservés, contact : operationpixel@free.fr