La libreria OpenCV - 11 - lavorare con gli istogrammi

L'istogramma è un tipo di rappresentazione compatta molto utile per l'elaborazione delle immagini. In generale, un istogramma rappresenta graficamente la distribuzione dei dati. E' un grafico bidimensionale in cui sull'asse delle ascisse troviamo le classi dei dati, mentre sulle ordinate i valori di frequenza. Un esempio pratico nel caso dell'elaborazione di immagini si ha se prendiamo un'immagine in scala di grigio: il suo istogramma dei valori di grigio avrà sulle X i valori di intensità da 0 a 255, e sulle Y saranno rappresentati le frequenze di questi valori all'interno dell'immagine. Avremo così una raffigurazione intuitiva della distribuzione dei valori di grigio dell'immagine.

Esempio di istogramma dei vaori di grigio - tratto da www.songho.ca/

Si può estendere quanto detto al caso di immagini RGB considerando un istogramma bidimensionale per ogni canale dell'immagine. Un istogramma può essere usato banalmente per confrontare due immagini in base alla distribuzione dei colori. Oppure per trovare il valore di soglia per il thresholding per poi effettuare una segmentazione dell'immagine.

All'interno di OpenCV esistono tre funzioni fondamentali per lavorare con gli istogrammi: la funzione per creare un istogramma, la funzione per confrontare due istogrammi e la funzione per equalizzare un istogramma (di cui parleremo alla fine di questo articolo). Per le prime due funzioni, abbiamo il seguente codice:

#include <stdio.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char** argv) {

// carichiamo due immagini
	Mat src1 = imread("img1.jpg");
	Mat src2 = imread("img2.jpg");

// creiamo i due oggetti che conterranno gli istogrammi
	MatND hist1;
	MatND hist2;

// parametri di inizializzazione per la creazione degli istogrammi
	int bins = 256; // numero di classi (bin) dell'istogramma
	int histSize[] = { bins, bins, bins }; // numero di classi per ogni canale dell'istogramma
	float range[] = { 0, 255 }; // intervallo di valori a cui deve appartenere l'altezza (frequenza) di ogni bin
	const float* ranges[] = { range, range, range }; // range per ogni canale dell'istogramma
	int channels[] = { 0, 1, 2 }; // identificativi dei canali

// calcoliamo gli istogrammi e immagazziniamo il risultato nei due oggetti della clase MatND
	calcHist(&src1, 1, channels, Mat(), hist1, 1, histSize, ranges, true,
			false);

	calcHist(&src2, 1, channels, Mat(), hist2, 1, histSize, ranges, true,
			false);

// calcoliamo la similarità tra i due istogrammi e stampiamola a video
	double rankTotal = compareHist(hist1, hist2, CV_COMP_CORREL);
	cout << rankTotal << endl;

}

Molto banalmente il programma confronta due istogrammi e ne restituisce un valore di similarità a seconda del kernel utilizzato per il confronto.

void calcHist(const Mat* images, int nimages, const int* channels,
              InputArray mask, OutputArray hist, int dims,
              const int* histSize, const float** ranges,
              bool uniform=true, bool accumulate=false )

Questa è la funzione per calcolare l'istogramma relativo alla/alle immagine/i images. Devono essere specificati in ordine il numero di immagini, gli identificatori dei canali dell'istogramma attraverso un array di interi, una maschera (opzionale), l'istogramma risultante, il numero di dimensioni dell'istogramma, il numero di bin per ogni canale dell'istogramma, i range di valori per tutti i canali dell'istogramma.

La funzione compareHist restituisce un valore di similarità per i due istogrammi confrontati. Per calcolare il risultato possono essere usati differenti kernel. Nell'esempio ho utilizzato una correlazione tra istogrammi, ma esiste anche l'intersezione, la distanza chi-squared, e altre a seconda del parametro specificato.

void equalizeHist(InputArray src, OutputArray dst)

Per equalizzazione di un istogramma si intende una procedura per distribuire in modo "migliore" i valori di intensità di un istogramma. Il risultato che si ha è in generale una immagine dal contrasto aumentato. Si ottiene tale risultato "stretchando" le frequenze lungo tutto il range dell'istogramma. La funzione esposta in precedenza effettua questa operazione.

Alessio Antonielli

Ingegnere informatico, appassionato di cinema, musica, videogiochi e serie tv. Insomma, le solite cose che vi aspettereste da un ex studente di Ingegneria Informatica, giusto per rafforzare lo stereotipo…

La libreria OpenCV - 11 - lavorare con gli istogrammi ultima modifica: 2013-05-24T15:40:01+01:00 da Alessio Antonielli


Advertisment ad adsense adlogger