La libreria OpenCV - 9 - Thresholding

L'argomento di questo articolo è la sogliatura (o in inglese, thresholding), il metodo più semplice per effettuare una rapida segmentazione di un'immagine. Per segmentazione di un'immagine si intende il processo di partizionamento di un'immagine in regioni significative. La partizione è utilizzata in task di object recognition o per rappresentare in maniera più compatta l'immagine. Avevamo già introdotto il concetto di soglia quando abbiamo spiegato il funzionamento dell'algoritmo di Canny, anche se in quel contesto si vede una sua estensione (l'isteresi) utilizzata per ottenere migliori risultati nell'edge detection.

Durante una sogliatura, per ogni pixel dell'immagine si compara il suo valore di grigio (o la sua intensità) con un valore di soglia. Il risultato varierà a seconda se il valore di grigio è maggiore o minore della soglia impostata. In generale però da un thresholding a singola soglia si ottiene un'immagine binaria, con pixel di valore 0 o 1 (o 255 a seconda del tipo con cui si sta lavorando).

Quindi, data un'immagine e scelta una soglia , l'immagine binaria è ottenuta nel seguente modo:


\begin{equation}
I_{bin}(p)=\left\{\begin{matrix}
0 \; if \; I_{gray}(p)\leq s\\
1 \; if \; I_{gray}(p)>s
\end{matrix}\right.
\end{equation}

Questo è l'esempio più semplice di sogliatura. Ridefinendo il sistema di Equazione (1) è possibile ottenere risultati differenti, adattabili a più esigenze.

Esiste una versione meno "rigida" della tecnica presentata in precedenza: la sogliatura adattiva, o adaptive thresholding. In questo caso, prima di effettuare la sogliatura vera e propria, è convoluta con un particolare operatore (mediano, gaussiano, ecc...). Alla immagine risultante è sottratto un valore costante , ottenendo . La sogliatura è quindi applicata a . Si sceglie di utilizzare la sogliatura adattiva in situazioni di illuminazione non uniforme, come quella mostrata nell'immagine sottostante.

Immagine di esempio con illuminazione non omogenea.

Vediamo adesso le due funzioni OpenCV inerenti a questi due tipi di sogliature. Prima di provare il codice ricordatevi di aggiungere la libreria imgproc nelle proprietà del progetto.

per effettuare il threshold classico abbiamo:

double threshold( InputArray src, OutputArray dst, double thresh, 
                  double maxval, int type );

Molto intuitivamente, i primi due parametri specificano rispettivamente l'immagine su cui fare la sogliatura ed il risultato di questa. Dopodichè è specificato il valore della soglia ed il valore di intensità da sostituire a seconda della condizione. L'ultimo parametro serve a definire il tipo di thresholding. Per i valori delle costanti vi invito come sempre a visitare la pagina di documentazione OpenCV.

Per l'adaptive threshold:

void adaptiveThreshold( InputArray src, OutputArray dst,
                        double maxValue, int adaptiveMethod,
                        int thresholdType, int blockSize, double C );

Rispetto al caso precedente abbiamo i parametri adaptiveMethod per specificare il metodo di thresholding adattivo utilizzato (nel caso di OpenCV, gaussian o mean); blockSize indica la dimensione del neighborhood usato per calcolare il valore threshold per il pixel; C è infine il valore sottratto all'immagine calcolata prima di sogliarla.

Il codice che segue mostra i risultati di entrambi i metodi. Vi invito a provarlo utilizzando l'immagine mostrata in precedenza così che possiate vedere le differenze sostanziali nei risultati per i due metodi.

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


using namespace std;
using namespace cv;

int main(int argc, char *argv[]) {
	Mat imgInput;
	Mat imgThreshold;
	Mat imgAdThreshold;

	imgInput = imread("bible.jpg", CV_LOAD_IMAGE_GRAYSCALE);
	imgThreshold = Mat(imgInput.cols, imgInput.rows, IPL_DEPTH_8U, 1);
	imgAdThreshold = Mat(imgInput.cols, imgInput.rows, IPL_DEPTH_8U, 1);

	namedWindow("Input", CV_WINDOW_AUTOSIZE);
	namedWindow("Threshold", CV_WINDOW_AUTOSIZE);
	namedWindow("Adaptive Threshold", CV_WINDOW_AUTOSIZE);

	//Sogliatura classica
	threshold(imgInput, imgThreshold,100,255,CV_THRESH_BINARY);
	//Sogliatura adattiva
	adaptiveThreshold(imgInput, imgAdThreshold, 255, 
                          CV_ADAPTIVE_THRESH_GAUSSIAN_C, 
                          CV_THRESH_BINARY, 75, 25);

	imshow("Input", imgInput);
	imshow("Threshold", imgThreshold);
	imshow("Adaptive Threshold", imgAdThreshold);
	waitKey(0);
	return 0;
}

RIsultato della sogliatura classica

Risultato della sogiatura adattiva

Come sempre, vi invito a lasciare commenti per domande o eventuali errori riscontrati nell'articolo.

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 - 9 - Thresholding ultima modifica: 2013-04-19T14:47:21+01:00 da Alessio Antonielli


Advertisment ad adsense adlogger