Prima di osservare il codice facciamo una piccola premessa spiegando di cosa stiamo parlando e per farlo prendiamo in considerazione un’immagine in bianco e nero come quella dell’esempio sottostante.

L’operazione di equalizzazione consiste nell'”allargare” la curva dell’istogramma in modo da sfruttare l’intera scala di grigi disponibile. Questo permette una migliore distinzione degli oggetti (l’immagine risulta più contrastata) e solitamente può esser d’aiuto nell’elaborazione di un’immagine sottoesposta o sovraesposta.
A livello teorico, l’equalizzazione tenta di realizzare un istogramma piatto, portando verso una soglia uguale tutti i livelli di grigio, cosa ovviamente non possibile quando lavoriamo nel discreto.

Matematicamente l’algoritmo tenterà di definire inizialmente la densità di probabilità p(rj) di ogni livello di grigio e poi costruirà la nuova immagine attraverso una funzione di passaggio basata su questo valore, punto per punto.
% Equalizzazione di una immagine.
% Per l'esempio sfruttiamo una immagine in scala di grigi presente
% di default in MATLAB.
% Carico l'immagine:
im=imread('cameraman.tif');
% Imposto il numero di livelli di grigio:
L=256;
% Salvo in due variabili la dimensione dell'immagine:
[m n]=size(im);
% Salvo in una variabile il numero di pixel totali dell'immagine:
N=m*n;
% Imposto una vettore colonna lungo 256 righe:
ist=zeros(L,1);
% Popolo il vettore assegnando in ogni riga il numero di occorrenze
% di ogni livello di grigio:
for i=1:L
ist(i)=sum(sum(im==i-1));
end
% Creo un vettore colonna contenente i numeri da 0 a 1 con passo 1/255:
r=[0.0:1/(L-1):1.0]';
% Effettuo la somma cumulativa del vettore 'ist' dividendolo per il numero di pixel
% in modo da ottenere la probabilità incrementale di ogni livello:
s=cumsum(ist)/N;
% Creo un vettore colonna contenente i numeri da 0 a 255:
ss=[0:L-1]';
% Effettuo la traslazione di ogni livello di grigio seguendo la probabilità:
ss=round(ss+(s-r)*(L-1));
% Converto la matrice dell'immagine originale in un vettore colonna di lunghezza N:
im_vett=reshape(im,m*n,1);
% Disegno l'immagine di output (equalizzata) richiamando per ogni pixel il
% corrispettivo valore calcolato:
im_out=uint8(reshape(ss(im_vett),m,n));
% Mostro a schermo il risultato:
subplot(1,2,1);
imshow(im);
subplot(1,2,2);
imshow(im_out);
Il risultato finale sarà quello mostrato nell’immagine qui sotto. A sinistra l’immagine originale, a destra quella equalizzata.

Abbiamo – finalmente – scoperto cosa facciano i nostri programmi di foto ritocco quando andiamo a modificare una immagine semplicemente pressando un pulsante… 🙂
Emanuele
PS: è interessante notare come l’equalizzazione possa comportare l’aumento di rumore e la creazione di falsi contorni da sistemare attraverso opportuni algoritmi di riduzione del rumore.