Come equalizzare una immagine in MATLAB.

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.

Equalizzare una immagine

L’operazione di equalizzazione consiste nell'”allargarela 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.

Equalizzazione 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.

Esempio equalizzazione: cameraman

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.

11 commenti » Scrivi un commento

  1. Bella materia, per me era a scelta e l’ho inserita nel mio piano di studi.
    Quell’immagine è rimasta sempre la stessa!
    Stai preparando una tesina sull’argomento? La mia era fighissima :joy:

    • Beh quell’immagine è sempre la stessa perché è inclusa in MATLAB di default… ce ne sono anche altre… 😛
      Non sto preparando una tesina ma domani ho l’esame orale e spero vada bene visto che m’è piaciuto parecchio studiarla!
      Con la tesina che avevi preparato tu?
      Ciao,
      Emanuele

  2. DAi che va benissimo. Non ricordavo se fosse sulle dispense del prof o sul matlab, in effetti.
    Io avevo preparato una tesina sul riconoscimento dei colori in un immagine, non ricordo poi benissimo perchè è passato un bel pò di tempo. Ricordo solo che poi un paio di colleghi hanno preso la materia grazie alla mia tesina però!

    • Beh dai, riconoscere i colori non è difficile! Carichi l’immagine, se è a colori avrai più matrici (RGB son 3) e lavori su quelle… poi immagino che interpolavi punto per punto le 3 matrici e ottenevi il colore corrispondente…
      Già l’immagino l’esercizio! 🙂
      Comunque vedremo… oggi ho ripetuto nuovamente un po’ tutto e domani come va va… spensierati! :joy:
      Ciao,
      Emanuele

  3. Non ricordo se era proprio questa, in realtà, però mi hai fatto venire il desiderio di andare a guardare cos’era.
    Dai sei molto preparato comunque.

    • Così preparato che c’ho il voto in sospeso! Il professore è stato gentilissimo (non scherzo) nel conservarmelo fino al prossimo appello però preferiva che tornassi a far l’esame. Purtroppo ho fatto la parte di MATLAB molto bene ma mi son confuso un po’ nel dominio della frequenza e il filtraggio passa-basso. Prendere o lasciare? 😐
      Ciao,
      Emanuele

  4. Che voto ti ha proposto?
    Guarda, l’unica cosa che ti posso dire è che il voto non è cosi importante.
    Se pensi che ti possa far perdere troppo tempo in futuro facendoti spostare la preparazione di un altro esame allora prendilo subito se invece pensi che ci sia soltanto qualcosa da rivedere allora magari puoi anche lasciare e riprovare tra un pò.
    Che dici?
    Quante te ne mancano?

    • Si infatti farò proprio così… se riesco a dargli una bella ripassata e l’esame non coincide con altri, allora mi presenterò nuovamente (anche perché il professore mi sembra molto gentile), altrimenti – ahimè – accetterò. Mi dispiace perché credo di saperla meglio di com’è stata valutata (il voto è 22) e perché in MATLAB ho risolto l’esercizio in un attimo…
      Quante me ne mancano? Stanno già su una mano… 😉
      Ciao,
      Emanuele
      PS: domani notte arrivo a Milano, poi ci organizziamo per una birra!

  5. Pingback: Aree comuni tra matrici in MATLAB. - …time is what you make of it…

  6. c’è un errore!ho provato ma non riesco a correggerlo! 😥
    come sarebbe?
    grazie, vale

    Error in ==> equa at 17
    ist(i)=sum(sum(im==i-1));

    ??? In an assignment A(:) = B, the number of elements in A and B
    must be the same.

  7. Anche questo funziona correttamente e forse è un pò più semplice… però il concetto è lo stesso:

    img = imread(‘immagine.jpg’);
    %ovviamente al posto di immagine.jpg va messo il nome dell’immagine che
    %si vuole equalizzare!(NB: img deve essere in bainco e nero!)

    L=2^8;
    %se si vuole usare un’immagine a 8 bit… se se ne vuole usare una a 16
    %basta cambiare l’esponente e scrivere uint16 al posto di uint8
    %nel risultato

    [h,w]=size(img);
    %se img è un’immagine di MxN pixel allora h = M e w = N

    [n,x] = imhist(img);
    %n è un vettore contenente il numero di occorrenze di quel livello di
    %grigio: n(0) è il numero di volte in cui c’è il livello 0, n(1) il
    %numero di volte che c’è il livello di grigio 1, n(2) il 2 ecc…
    %fino a n(255) che sarà il numero di volte che c’è 255 (ovviamente
    %nel caso di immagini a 8 bit, se no n risulta più o meno lungo) quindi
    %di fatto n è l’istogramma di img!

    cum = cumsum(n)/(h*w);
    %cum contiene la cumulativa dell’istogramma normalizzata (se non sapete
    %cos’è una cumulativa andatevi a vedere la definizione di cumulativa di
    %una densità di probabilità)

    s = round(cum * (L-1));
    %visto che cum contiene numeri tra 0 e 1 senza deformarne la forma la
    %allargo tra 0 e 255, e poi arrotondo all’intero più vicino

    img_vett = reshape(img,h*w,1);
    %img_vett contiene tutti i pixel di img, solo che invece di averli in
    %una matrice hxw li ha tutti in fila in un unico vettore lungo h*w

    img_out = uint8(reshape(s(img_vett+1),h,w));
    %questo è difficile da spiegare, ma se vi fate un esempio su un foglio con %qualche numero si capisce benissimo! 😀

Lascia un commento

I campi richiesti sono marcati con *.