Introduzione
Le Strutture Dati
Una Introduzione a
OpenCV
Prof. Michele Scarpiniti
Dipartimento di Ingegneria dell’Informazione, Elettronica e Telecomunicazioni
“Sapienza” Università di Roma
http://ispac.diet.uniroma1.it/scarpiniti/index.htm
[email protected]
M. Scarpiniti
Una Introduzione a OpenCV
1 / 53
Introduzione
Le Strutture Dati
1
Introduzione
Introduzione
I primi passi
2
Le Strutture Dati
Gestione delle matrici
L’Istogramma
M. Scarpiniti
Una Introduzione a OpenCV
2 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Introduzione
Introduzione
M. Scarpiniti
Una Introduzione a OpenCV
3 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Introduzione
L’obiettivo di queste slides è di introdurre ed illustrare il funzionamento di
un utile e potente framework per la gestione dei dispositivi video, noto come
OpenCV.
OpenCV è una libreria open-source, scritta in C, per lo streaming video
real-time ovvero la computer vision e gira sotto Windows, Linux e Mac
OS X.
Maggiori informazioni possono essere reperite al link http://opencv.willowg
com/wiki/ da cui è anche possibile scaricare l’intero codice in C++.
M. Scarpiniti
Una Introduzione a OpenCV
4 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Introduzione: la computer vision
La computer vision è una trasformazione dei dati provenienti da una fotocamera o videocamera verso una decisione o una loro nuova rappresentazione. Una tale trasformazione può essere effettuata per uno scopo qualsiasi. E’
anche possibile inserire nei dati, alcune informazioni riguardanti il contesto
in cui si opera.
M. Scarpiniti
Una Introduzione a OpenCV
5 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Introduzione: storia di OpenCV
Il framework OpenCV nasce da una iniziativa dell’Intel, mentre lavorava
su miglioramenti delle loro CPU per applicazioni intensive, ad esempio raytracing in tempo reale e proiezione 3D. Uno degli addetti della Intel, aveva
notato che in motle Università, tra cui il MIT Media Lab, avevano messo su
un’infrastruttura per la computer vision, il cui codice era passato da studente
a studente. A tal proposito si decise di iniziare a progettare, a partire da
questo codice, un framework per la computer vision per i processori Intel.
Il primo avvio di tale progetto, con la collaborazione di un team Intel russo,
fu nel 1999. La prima release ufficiale di OpenCV risale, invece, al 2006.
Nel 2011 è stata rilasciata la versione 2.2.0, che supporta anche Android.
Ora è disponibile la release 3.0.
M. Scarpiniti
Una Introduzione a OpenCV
6 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
OpenCV e le IPP
Per velocizzare OpenCV è possibile utilizzare la libreria IPP (Intel Performance Primitives). Infatti OpenCV è basato, internamente, su tali librerie
in quanto molti programmatori Intel ne fanno un forte uso. Le IPP sono
delle librerie altamente ottimizzate, che agiscono direttamente a livello delle
micro-istruzioni del processore, evitando qualsiasi perdita di tempo.
Se le IPP sono installate, OpenCV le rileverà in automatico e le includerà
al momento della compilazione, per ottimizzare al massimo il codice. Cosı̀
se, ad esempio è richiesto il calcolo di una FFT, verrà utilizzata la funzione
definita nelle IPP anzichè quella nativa di OpenCV.
Per verificare se le IPP sono installate e determinare la release di OpenCV
in uso, si può utilizzare il seguente codice
char * libraries ;
char * modules ;
c vG et M od ul eI n fo (0 , & libraries , & modules ) ;
printf ( " Libraries : % s / nModules : % s / n " , libraries , modules ) ;
M. Scarpiniti
Una Introduzione a OpenCV
7 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Installare OpenCV
Dopo aver scaricato e configurato (ad esempio attraverso l’utilizzo del software CMake (http://www.cmake.org/)) OpenCV è possibile aprire con
Microsoft Visual C++ il relativo file di soluzione e compilare il tutto. Il risultato della compilazione è una serie di librerie, che dovranno essere incluse
nel codice che verrà scritto. Le relative librerie dinamiche *.dll, andranno
distribuite insieme al programma compilato.
Nella cartella bin verranno compilati, inoltre, i numerosi esempi inclusi
nel framework, attraverso i quali è possibile scrivere facilmente un elevato
numero di applicazioni.
Nella cartella docs è invece possibile consultare un’abbondante documentazione in formato html oppure in formato pdf. E’ anche reperibile una documentazione Wiki, all’indirizzo http://opencvlibrary.SourceForge.
net.
M. Scarpiniti
Una Introduzione a OpenCV
8 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Struttura di OpenCV
La struttura di OpenCV consta delle seguenti 6 parti:
1
CXCORE: contiene la definizione di tutte le strutture dati e le
funzioni per gestire immagini e video.
2
CV: contiene tutte le funzioni per l’elaborazione e l’analisi delle
immagini, la calibrazione e il tracking.
3
ML (Machine Learning): contiene molte funzioni sul Machine
Learning e il pattern recognition, quali il clustering e la classificazione.
4
HighGUI: contiene le definizioni delle interfacce utenti (GUI).
5
CVCAM: contiene le interfacce per le webcam.
6
CVAUX: contiene algoritmi sperimentali per scopi diversi, ad esempio:
segmentazione, sottrazione del background, modelli HMM, ecc.
M. Scarpiniti
Una Introduzione a OpenCV
9 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Struttura di OpenCV
La struttura di OpenCV precedente può essere riassunta nella schematizzazione seguente.
CV
MLL
CXCORE
HighGUI
CVCAM
CVAUX
M. Scarpiniti
Una Introduzione a OpenCV
10 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Aprire una foto con OpenCV
Per aprire una foto, è possibile utilizzare il seguente codice:
# include " highgui . h "
int main ( int argc , char ** argv )
{
IplImage * img = cvLoadImage ( argv [1]) ;
cvNamedWindow ( " Esempio1 " , C V _ W I N D O W _ A U T O S I Z E ) ;
cvShowImage ( " Esempio1 " , img ) ;
cvWaitKey (0) ;
cvRe leaseIma ge (& img ) ;
c vD es tr o yW in do w ( " Esempio1 " ) ;
}
Tutte le funzioni utilizzate in questo script, sono definite nel file di header
highgui.h.
M. Scarpiniti
Una Introduzione a OpenCV
11 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Aprire una foto con OpenCV
La funzione chiave del precedente script è
IplImage * img = cvLoadImage ( " nome " ) ;
che legge una stringa e carica in una matrice img, di tipo IplImage, tutti i
pixel dell’immagine. Tale funzione determina in automatico il tipo di file e
alloca la memoria necessaria per contenere l’immagine (numero di righe, di
colonne e di colori). I formati supportati sono: BMP, DIB, JPEG, JPE,
PNG, PBM, PGM, PPM, SR, RAS e TIFF.
Tale funzione restituisce il puntatore alla struttura allocata, che contiene,
oltre ai dati, anche le informazioni relative dell’immagine.
M. Scarpiniti
Una Introduzione a OpenCV
12 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Aprire una foto con OpenCV
Per visualizzare la foto è necessario creare una finestra in cui collocarla. A
tal proposito, si utilizza la funzione
cvNamedWindow ( " Esempio1 " , C V _ W I N D O W _ A U T O S I Z E ) ;
che crea la finestra e la nomina come ‘‘Esempio1’’. Il secondo argomento (CV WINDOW AUTOSIZE) determina le dimensioni della figura. In questo
caso, la finestra sarà adattata alle dimensioni dell’immagini. Al contrario è
possibile inserire il valore 0: in questo caso la finestra ha una dimensione
standard e l’immagine sarà scalata alle dimensioni della finestra.
Per visualizzara l’immagine img nella finestra ‘‘Esempio1’’, si utilizza
quindi, la funzione
cvShowImage ( " Esempio1 " , img ) ;
Ovviamente la finestra ‘‘Esempio1’’ deve essere create precedentemente
la chiamata di cvShowImage().
M. Scarpiniti
Una Introduzione a OpenCV
13 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Aprire una foto con OpenCV
Per mettere in attesa il programma fino a che non si prema un tasto, si
utilizza il comando
cvWaitKey (0) ;
L’argomento 0 (o un numero negativo) significa che si aspetta la pressione
di un tasto. Al contrario, se si inserisce un numero positivo, il programma
aspetta, in millisecondi, il tempo indicato.
Quando viene premuto il tasto, bisogna rilasciare la memoria occupata e
porre il puntatore all’immagine img a NULL. Queste operazioni sono eseguite
dal comando
cvRe leaseIma ge (& img ) ;
Infine bisogna distruggere la finestra creata, e deallocare la memoria eventualmente occupata, utilizzando
c vD es tr o yW in do w ( " Esempio1 " ) ;
M. Scarpiniti
Una Introduzione a OpenCV
14 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Creare e salvare una foto con OpenCV
Per creare uno spazio di memoria che contenga un’immagine, è possibile
utilizzare il comando seguente:
IplImage * image = cvCreateImage ( CvSize size , int depth ,
int channels ) ;
Viene restituito un puntatore ad una strutture di tipo IplImage. Viene
richiesto, al contrario, la dimensione dell’immagine in size (come larghezza
- altezza), in numero di bit (in depth) e il numero di canali per pixel in
channels (1, 2, 3, o 4).
Per salvare un’immagine, si utilizza invece
int cvSaveImage ( char * filename , CvArr * image ) ;
che prende in ingresso il nome del file e il puntatore all’immagine da
salvare. Restituisce 1 se il salvataggio è andato a buon fine, 0 altrimenti.
M. Scarpiniti
Una Introduzione a OpenCV
15 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Aprire un video con OpenCV
Per aprire un video, è possibile utilizzare il seguente codice:
# include " highgui . h "
int main ( int argc , char ** argv )
{
cvNamedWindow ( " Esempio2 " , C V _ W I N D O W _ A U T O S I Z E ) ;
CvCapture * capture = c v C r e a t e F i l e C a p t u r e ( argv [1]) ;
IplImage * frame ;
while (1)
{
frame = cvQueryFrame ( capture ) ;
if (! frame ) break ;
cvShowImage ( " Esempio2 " , frame ) ;
char c = cvWaitKey (33) ;
if ( c == 27) break ;
}
c v R e l e a s e C a p t ur e (& capture ) ;
c vD es tr o yW in do w ( " Esempio2 " ) ;
}
M. Scarpiniti
Una Introduzione a OpenCV
16 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Aprire un video con OpenCV
Anche qui si crea un finestra attraverso la funzione cvNamedWindow(). La
funzione principale, quella che carica il file video, è la seguente
CvCapture * capture = c v C r e a t e F i l e C a p t u r e ( " nome_video " ) ;
Tale funzione carica un file video di tipo AVI e restituisce un puntatore
capture a idonea struttura CvCapture. Tale puntatore è quindi passato
alla funzione
frame = cvQueryFrame ( capture ) ;
che restituisce il frame corrente del video in un’immagine, descritta dal
puntatore frame alla struttura IplImage. Tale frame è quindi visualizzato
come immagine
cvShowImage ( " Esempio2 " , frame ) ;
M. Scarpiniti
Una Introduzione a OpenCV
17 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Aprire un video con OpenCV
Ogni 33 ms (cvWaitKey(33)) viene letto un nuovo frame e visualizzato,
ripetendo all’infinito il ciclo while(1)
char c = cvWait (33) ;
Si esce dal ciclo quando viene letto il carattere con codice ASCII pari a 27,
ovvero il tasto Esc.
Viene quindi rilasciata la memoria attraverso il comando
c v R e l e a s e C a p t ur e (& capture ) ;
e infine distrutta la finestra con
c vD es t ro yW in d ow ( " Esempio2 " ) ;
M. Scarpiniti
Una Introduzione a OpenCV
18 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Leggere da WebCam con OpenCV
Vediamo il codice per ottenere le immagini da una webcam.
# include " cv . h "
# include " highgui . h "
int main ( int argc , char ** argv ) {
cvNamedWindow ( " Esempio3 " , C V _ W I N D O W _ A U T O S I Z E ) ;
CvCapture * capture ;
if ( argc ==1) {
capture = c v C r e a t e C a m e r a C a p t u r e ( 0 ) ;
} else {
capture = c v C r e a t e F i l e C a p t u r e ( argv [1] ) ;
}
assert ( capture != NULL ) ;
IplImage * frame ;
M. Scarpiniti
Una Introduzione a OpenCV
19 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Leggere da WebCam con OpenCV
while (1) {
frame = cvQueryFrame ( capture ) ;
if ( ! frame ) break ;
cvShowImage ( " Esempio3 " , frame ) ;
char c = cvWaitKey (10) ;
if ( c == 27 ) break ;
}
c v R e l e a s e C a p t u re (& capture ) ;
c vDes tr o yW in do w ( " Esempio3 " ) ;
}
Dopo aver al solito creato una finestra con cvNamedWindow(), si crea un
puntatore capture alla struttura dati CvCapture. Il video da webcam viene
creato attraverso la funzione
capture = c v C r e a t e C a m e r a C a p t u r e ( 0 ) ;
M. Scarpiniti
Una Introduzione a OpenCV
20 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Leggere da WebCam con OpenCV
Se, al contrario, al programma precedente passo il nome di un file, viene
letto il video con quel nome.
Il resto del programma è identico al caso del filmato.
Ogni 10 ms (cvWaitKey(10)) viene letto un frame dal puntatore capture,
con
frame = cvQueryFrame ( capture ) ;
e quindi mostrato nella finestra
cvShowImage ( " Esempio3 " , frame ) ;
Infine, quando viene premuto il tasto Esc (codice ASCII 27 ), viene
rilasciata la memoria (cvReleaseCapture(&capture)) e distrutta la
finestra (cvDestroyWindow(‘‘Esempio3’’)).
M. Scarpiniti
Una Introduzione a OpenCV
21 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Scrivere un file video con OpenCV
Nella presente slide, si cercherà di descrivere un codice per la scrittura su file AVI.
# include " cv . h "
# include " highgui . h "
# include < stdio .h >
int main ( int argc , char * argv [] )
{
cvNamedWindow ( " Esempio4 " , C V _ W I N D O W _ A U T O SI Z E ) ;
cvNamedWindow ( " Log_Polar " , C V _ W I N D O W _ A U T O S I Z E ) ;
CvCapture * capture = c v C r e a t e F i l e C a p t u r e ( argv [1] ) ;
if (! capture ) {
return -1;
}
IplImage * bgr_frame = cvQueryFrame ( capture ) ;
double fps = c v G e t C a p t u r e P r o p e r t y ( capture , C V _C AP _P R OP _F PS ) ;
CvSize size = cvSize (
( int ) c v G e t C a p t u r e P r o p e r t y ( capture ,
CV_CAP_PROP_FRAME_WIDTH ),
( int ) c v G e t C a p t u r e P r o p e r t y ( capture ,
CV_CAP_PROP_FRAME_HEIGHT ) );
M. Scarpiniti
Una Introduzione a OpenCV
22 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Scrivere un file video con OpenCV
CvVideoWriter * writer = c v C r e a t e V i d e o W r i t e r (
argv [2] ,
CV_FOURCC ( ’D ’ , ’X ’ , ’V ’ , ’0 ’) ,
fps ,
size ) ;
IplImage * log polar_fr ame = cvCreateImage (
size ,
IPL_DEPTH_8U ,
3
);
while ( ( bgr_frame = cvQueryFrame ( capture ) ) != NULL )
{
cvShowImage ( " Esempio4 " , bgr_frame ) ;
cvLogPolar ( bgr_frame , logpolar_frame ,
cvPoint2D32f ( bgr_frame - > width /2 ,
bgr_frame - > height /2) ,
40 ,
C V_ IN TE R _L IN EA R + C V _ W A R P _ F I L L _ O U T L I E R S ) ;
cvShowImage ( " Log_Polar " , l ogpolar _frame ) ;
M. Scarpiniti
Una Introduzione a OpenCV
23 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Scrivere un file video con OpenCV
cvWriteToAVI ( writer , lo gpolar_ frame ) ;
char c = cvWaitKey (10) ;
if ( c == 27 ) break ;
}
c v R e l e a s e V i d e o W r i t e r ( & writer ) ;
cvRe leaseIma ge ( & bgr_frame ) ;
cvRe leaseIma ge ( & logp olar_fra me ) ;
c v R e l e a s e C a p t u re ( & capture ) ;
c vDes tr o yW in do w ( " Esempio4 " ) ;
c vDes tr o yW in do w ( " Log_Polar " ) ;
Il codice precedente carica e visualizza (nella finestra ‘‘Esempio4’’) un video
letto da file AVI. Contemporaneamente questo video verrà convertito in un
formato logaritmico-polare, visualizzato nella finestra ‘‘Log Polar’’ e scritto
su file, sempre di tipo AVI.
M. Scarpiniti
Una Introduzione a OpenCV
24 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Scrivere un file video con OpenCV
La funzione chiave del programma precedente è la seguente
CvVideoWriter * writer = c v C r e a t e V i d e o W r i t e r (
argv [2] ,
CV_FOURCC ( ’D ’ , ’X ’ , ’V ’ , ’0 ’) ,
fps ,
size ) ;
che restituisce un puntatore writer alla struttura CvVideoWriter. Tale
funzione accetta 4 parametri in ingresso:
1
il nome del file da scrivere (letto da linea di comando) argv[2];
2
il codec video con cui sarà compresso lo stream CV FOURCC();
3
il numero di frames per secondo fps;
4
la dimensionalità delle immagini (3 = a colori) size.
M. Scarpiniti
Una Introduzione a OpenCV
25 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Scrivere un file video con OpenCV: i codec
OpenCV supporta i seguenti tipi di codec video:
Codici
Descrizione
CV FOURCC(’P’,’I’,’M’,’1’)
MPEG-1 codec
motion-jpeg codec
CV FOURCC(’M’,’J’,’P’,’G’)
CV FOURCC(’M’, ’P’, ’4’, ’2’) MPEG-4.2 codec
CV FOURCC(’D’, ’I’, ’V’, ’3’) MPEG-4.3 codec
CV FOURCC(’D’, ’I’, ’V’, ’X’) MPEG-4 codec (Dvix)
CV FOURCC(’D’, ’X’, ’V’, ’0’) DVix vers 5 codec
CV FOURCC(’X’, ’V’, ’I’, ’D’) Xvid codec
CV FOURCC(’U’, ’2’, ’6’, ’3’) H263 codec
CV FOURCC(’I’, ’2’, ’6’, ’3’) H263I codec
CV FOURCC(’H’, ’2’, ’6’, ’4’) H264 codec
CV FOURCC(’F’, ’L’, ’V’, ’1’) FLV1 codec
M. Scarpiniti
Una Introduzione a OpenCV
26 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Scrivere un file video con OpenCV
La trasformazione logaritmico-polare dell’immagine avviene attraverso il comando:
cvLogPolar ( bgr_frame ,
logpolar_frame ,
cvPoint2D32f ( bgr_frame - > width /2 , bgr_frame - > height
/2) ,
40 ,
C V_ IN TE R _L IN EA R + C V _ W A R P _ F I L L _ O U T L I E R S ) ;
I primi due argomenti (bgr frame e logpolar frame) sono le immagini di origine e destinazione della trasformazione logaritmico-polare, descritta dalle seguenti
trasformazioni:
(x, y ) → (log r , θ),
p
−yc
in cui r = (x − xc )2 + (y − yc )2 e θ = arctan yx−x
e (xc , yc ) è il punto centrale
c
dell’immagine di partenza. Le coordinate di tale punto vengono passate alla
precedente funzione come terzo parametro. Il quarto parametro è un fattore di
scala che seleziona la regione di interesse nella visualizzazione del nuovo dominio.
Infine il quinto parametro seleziona il metodi di interpolazione utilizzato.
M. Scarpiniti
Una Introduzione a OpenCV
27 / 53
Introduzione
Le Strutture Dati
Introduzione
I primi passi
Scrivere un file video con OpenCV
A questo punto il frame appena trasformato viene salvato nella struttura
puntata da writer, attraverso
cvWriteToAVI ( writer , l ogpolar_ frame ) ;
Dopo la scrittura di tutti i frame, viene distrutto il puntatore alla struttura
video, tramite
c v R e l e a s e V i d e o W r i t e r (& writer ) ;
Infine viene rilasciata la memoria e distrutte le finestre:
cvRe leaseIma ge ( & bgr_frame ) ;
cvRe leaseIma ge ( & logpo lar_fra me ) ;
c v R e l e a s e C a p t ur e ( & capture ) ;
c vD es tr o yW in do w ( " Esempio4 " ) ;
c vD es tr o yW in do w ( " Log_Polar " ) ;
M. Scarpiniti
Una Introduzione a OpenCV
28 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
Le Strutture Dati
Le Strutture Dati
M. Scarpiniti
Una Introduzione a OpenCV
29 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
I tipi elementari
OpenCV utilizza le matrici per memorizzare immagini e frame. All’interno di tali
strutture troviamo i tipi elementari di punto, dimensione, rettangolo, che vengono
definiti come descritto nella seguente tabella.
Struttura
CvPoint
CvPoint2D32f
CvPoint3D32f
CvSize
CvRect
CvScalar
Contenuto
int x, y
float x, y
flaot x, y, z
int width, height
int x, y, width, height
double val[4]
Descrizione
Punto in un’immagine
Punto in R2
Punto in R3
Dimensioni di un’immagine
Porzione di un’immagine
Valore RGBA
Cosı̀ se si vuole disegnare un rettangolo (cvRectangle()) nell’immagine puntata
da myImg, si utilizzerà la chiamata
cvRectangle ( myImg , cvPoint (5 ,10) , cvPoint (20 ,30) ,
cvScalar (255 ,255 ,255) ) ;
M. Scarpiniti
Una Introduzione a OpenCV
30 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
La struttura CvMat
La struttura fondamentale è la CvMat, che può essere definita come
typedef struct CvMat {
int type ;
int step ;
int * refcount ; // per uso interno
union {
uchar * ptr ;
short * s ;
int * i ;
float * fl ;
double * db ;
} data ;
union {
int rows ;
int height ;
};
union {
int cols ;
int width ;
};
} CvMat ;
M. Scarpiniti
Una Introduzione a OpenCV
31 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
La struttura CvMat
Per creare un elemento di tipo CvMat è possibile eseguire il comando:
cvMat * cvCreateMat ( int rows , int cols , int type ) ;
E’ comunque possibile creare solamente l’header o i dati di una struttura
CvMat:
c v C r e a t e M a t H e a d e r ( int rows , int cols , int type ) ;
cvCreateData ( int rows , int cols , int type ) ;
o clonare una matrice
mat2 = cvCloneMat ( CvMat * mat1 ) ;
Infine, per deallocare la memoria, si utilizza
cvReleaseMat ( CvMat ** mat ) ;
M. Scarpiniti
Una Introduzione a OpenCV
32 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
La struttura IplImage
La struttura dati fondamentale per gestire le immagini è la IplImage, definita come segue:
typedef struct _IplImage {
int nSize ;
int ID ;
int nChannels ;
int alphaChannel ;
int depth ;
char colorModel [4];
char channelSeq [4];
int dataOrder ;
int origin ;
int align ;
int width ;
int height ;
struct _IplROI * roi ;
struct _IplImage * maskROI ;
void * imageId ;
struct _IplTileInfo * tileInfo ;
int imageSize ;
char * imageData ;
int widthStep ;
int BorderMode [4];
int BorderConst [4];
char * imageDataOrigin ;
} IplImage ;
M. Scarpiniti
Una Introduzione a OpenCV
33 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
La struttura IplImage
Il valore del numero di bit, descritti dalla variabile depth, può assumere una
delle seguenti alternative
Macro
Tipo di pixel
IPL DEPTH 8U
intero unsigned a 8 bit
IPL DEPTH 8S
intero signed a 8 bit
IPL DEPTH 16S intero signed a 16 bit
IPL DEPTH 32S intero signed a 32 bit
IPL DEPTH 32F float singola precisione a 32 bit
IPL DEPTH 64F float doppia precisione a 64 bit
M. Scarpiniti
Una Introduzione a OpenCV
34 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
Operazioni sulle immagini
Sulle immagini, che sono rappresentate da matrici in OpenCV è possibile
utilizzare un insieme di oltre cento funzioni predefinite, che permettono
di sommare, sottrare, ruotare, determinare quantità statistiche, norme, ecc.
L’utilizzo di tali funzioni è abbastanza immediato. Per maggiori informazioni
a riguardo, si rimanda alla guida di OpenCV, nonché a [1] e [2].
Vengono poi messe a disposizione alcune funzioni per disegnare figure più
o meno elementari su una determinata finestra contenete un’immagine. Ad
esempio: linee, cerchi, ellissi, poligoni e testo. Anche queste funzioni sono
di utilizzo abbastanza immediato.
Nel seguito vedremo alcune funzioni molto utili nelle applicazioni.
M. Scarpiniti
Una Introduzione a OpenCV
35 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
Operazioni sulle immagini: il resize
E’ possibile operare un’operazione di resize su una determinata immagine, attraverso la funzione
void cvResize (
const CvArr * src ,
cvArr *
dst ,
int
interpolation = CV _I N TE R_ LI N EA R
);
Nella precedente funzione src è l’immagine originaria mentre dst è la nuova
struttura di dimensioni opportune che conterrà l’immagine con le nuove
dimensioni. Poiché i pixel dell’immagine originale dovranno essere interpolati, è
possibile stabilire il metodo di interpolazione attraverso il terzo parametro
interpolation, le cui opzioni sono descritte nella seguente tabella:
Interpolazione
CV INTER NN
CV INTER LINEAR
CV INTER AREA
CV INTER CUBIC
M. Scarpiniti
Metodo
Pixel più vicino
Bilineare
Media su un’area
Bicubica
Una Introduzione a OpenCV
Descrizione
Il nuovo pixel assume il valore del pixel più vicino
Interpolazione bilineare
Il pixel è sostituito con la media dell’area coperta dai v
Interpolazione bicubica
36 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
Operazioni sulle immagini: la convoluzione
Essenziale per il filtraggio di immagini è l’operazione di convoluzione bidimensionale, ottenuta attraverso la funzione
void cvFilter2D (
const CvArr * src ,
cvArr *
dst ,
const CvMat * kernel ,
cvPoint
anchor = cvPoint ( -1 , -1)
);
Nella precedente funzione src è l’immagine originaria mentre dst è la
nuova struttura di dimensioni opportune che conterrà l’immagine filtrata.
kernal è una matrice contenente la risposta impulsiva del filtro. Il quarto
parametro, anchor, è opzionale è indica il punto in cui centrare il filtro
bidimensionale. L’opzione di default è il centro della matrice kernel.
M. Scarpiniti
Una Introduzione a OpenCV
37 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
Operazioni sulle immagini: la DFT
E’ possibile valuare la DFT bidimensionale
I (kx , ky ) =
NX
y −1
x −1 N
X
nx =0 ny
2πj
2πj
I (nx , ny ) exp −
kx nx exp −
ky ny ,
Nx
Ny
=0
attraverso la funzione
void cvDFT (
const CvArr *
cvArr *
int
int
);
src ,
dst ,
flags
nonzero_rows = 0
Nella precedente funzione src è l’immagine originaria mentre dst è la nuova struttura di
dimensioni opportune che conterrà l’immagine in frequenza. flags è un parametro che
seleziona la trasformata diretta (CV DXT FORWARD) e inversa (CV DXT INVERSE). L’ultimo
parametro, nonzero rows, serve per gestire lo zero padding. Utilizzando la precedente
funzione è possibile implementare la convoluzione tra due immagine come prodotto delle
relative DFT.
M. Scarpiniti
Una Introduzione a OpenCV
38 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
L’istogramma di un’immagine
Poiché moltissimi algoritmi di image processing si basano sul concetto di istogramma, diviene essenziale saper lavorare con questi ultimi in OpenCV. La struttura che
contiene l’istogramma è definita come segue
typedef struct CvHistogram
{
int
type ;
CvArr * bins ;
float
thresh [ CV_MAX_DIM ][2]; // for uniform histograms
float ** thresh2 ;
// for nonuniform histograms
CvMatND mat ;
// embedded matrix for array
histograms
} CvHistogram ;
Nella precedente struttura, type indica il tipo di istogramma, ovvero se
mono-dimensionale o multi-dimensionale; bins contiene i bin dell’istogramma. Le
matrici thresh e thresh2 sono le soglie utilizzate per creare l’istogramma, nel
caso uniforme e non uniforme, rispettivamente. Infine, mat contiene i valori
dell’istogramma.
M. Scarpiniti
Una Introduzione a OpenCV
39 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
L’istogramma di un’immagine
Dopo aver definita la struttura CvHistogram è possibile creare un istogramma
attraverso
CvHistogram * cvCreateHist (
int
dims ,
int *
sizes ,
int
type ,
float ** ranges = NULL ,
int
uniform = 1
);
Nella precedente funzione, dims indica il numero di dimensioni dell’istogramma.
sizes è un vettore di interi lungo quanto il numero di dimensioni, che indicano il
numero di bin da assegnare a ciascuna dimensione. type indica il tipo di
istogramma, ovvero se multidimensionale (CV HIST ARRAY) o di tipo sparso
(CV HIST SPARSE). La variabile ranges denota i limiti dell’istogramma, mentre la
variabile booleana uniform indica se stiamo utilizzando un istogramma uniforme
(valore positivo) oppure no (valore 0).
M. Scarpiniti
Una Introduzione a OpenCV
40 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
Manipolare un istogramma
Esistono alcune utili funzioni che consentono di manipolare un istogramma, precedentemente creato. Precisamente
cvNormalizeHist( CvHistogram* hist, double factor ); che consente di
normalizzare un istogramma di un fattore factor;
cvThreshHist( CvHistogram* hist, double thresh ); che consente di
applicare una soglia thresh;
void cvCopyHist( const CvHistogram* src, CvHistogram** dst );
permette di copiare un istogramma contenuto in src nella nuova variabile dst.
void c v G e t M i n M a x H i s t V a l u e (
const CvHistogram * hist ,
float *
min_value ,
float *
max_value ,
int *
min_idx = NULL ,
int *
max_idx = NULL ) ;
consente di ottenere il valore minimo min value e il valore massimo max value di
un istogramma hist. Le variabili min idx e max idx servono nel caso di
istogrammi multi-dimensionali.
M. Scarpiniti
Una Introduzione a OpenCV
41 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
Manipolare un istogramma
E ancora:
void cvCalcHist (
IplImage **
CvHistogram *
int
const CvArr *
image ,
hist ,
accumulate = 0 ,
mask
= NULL ) ;
consente di calcolare automaticamente l’istogramma hist di una immagine image.
Il parametro accumulate, se non zero, consente di mantenere in memoria
l’istogramma. mask consente di escludere alcuni pixel dal calcolo dell’istogramma.
void cvEqual izeHist (
const CvArr * src ,
CvArr *
dst ) ;
consente di equalizzare un’immagine migliorandone il contrasto, in modo tale che
l’immagine risultante dst abbia un istogramma più piatto dell’immagine di
partenza src.
M. Scarpiniti
Una Introduzione a OpenCV
42 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
Manipolare un istogramma
Infine, è fondamentale la seguente funzione
void cvCompareHist (
const CvHistogram * hist1 ,
const CvHistogram * hist2 ,
int
method
);
che consente di paragonare due istogrammi. La variabile method descrive la
particolare distanza utilizzata per paragonare i due istogrammi. I possibili valori
sono riassunti nella seguente tabella
Metodo
Descrizione
Espressione
CV COMP CORREL
Correlazione
dcorr (H1 , H2 ) =
P
CV COMP CHISQR
CV COMP INTERSECT
Chi-Quadro
Intersezione
CV COMP BHATTACHARYYA
Battacharria
qPi
(H1 (i)−mH1 )(H2 (i)−mH2 )
i (H1 (i)−mH1 )
2 (H (i)−m )2
2
H2
P (H (i)−H (i))2
dchi (H1 , H2 ) = i H1 (i)+H2 (i)
1
2
P
dint (H1 , H2 ) = r
2 (i))
i min (H1 (i), H√
P
H (i)H (i)
dBhatt (H1 , H2 ) = 1 − i √P 1 P2
i
M. Scarpiniti
Una Introduzione a OpenCV
H1 (i)·
i
H2 (i)
43 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
Back Projection
Con Back Projection si intende una tecnica con la quale si cerca di capire quanto
alcuni pixel di un’immagine o alcune aree di un’immagine abbiano un istogramma
simile ad un istogramma di riferimento.
Il primo scopo è raggiunto attraverso la funzione
void c v C a l c B a c k P r o j e c t (
IplImage **
image ,
CvArr *
back_project ,
const CvHistogram * hist
);
in cui image è l’immagine da analizzare, back project contiene i valori
dell’istogramma dell’immagine image e hist contiene l’istogramma di
riferimento.
M. Scarpiniti
Una Introduzione a OpenCV
44 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
Back Projection
Nel secondo caso, siamo interessati ad una regione di pixel, che magari appartengono ad
un oggetto noto. Infatti, applicando una finestra mobile ad una data immagine, è possibile
determinare in quali posizione l’istogramma della finestra è simile a quello di riferimento:
in questi casi, infatti, è altamente possibile che la regione di analisi appartiene all’oggetto
cercato. Tale funzione è definita come segue:
void c v C a l c B a c k P r o j e c t P a t c h (
IplImage **
image ,
CvArr *
dst ,
CvSize
patch_size ,
CvHistogram * hist ,
int
method ,
float
factor
);
in cui image è l’immagine da analizzare, dst conterrà l’istogramma valutato,
patch size è l’ampiezza della finestra mobile, hist è l’istogramma di riferimento,
method è il metodo con cui è valutata la distanza tra i due istogramma e, infine, factor
è il fattore di normalizzazione.
M. Scarpiniti
Una Introduzione a OpenCV
45 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
Template Matching
Una tecnica simile alla Back Projection, ma non basata sull’istogramma, è il Template Matching. Essa è basata sul far scorrere una piccola immagine target su
un’altra immagine da analizzare, al fine di capire se il target sia contenuta o meno
nell’immagine data. La funzione che implementa tale operazione è
void c vM at ch T em pl at e (
const CvArr * image ,
const CvArr * templ ,
CvArr *
result ,
int
method
);
in cui image è l’immagine da analizzare, templ è l’immagine target, result è
l’immagine risultato e method rappresenta l’algoritmo di calcolo dell’immagine
risultante, elencato nella seguente tabella (con relativa versione normalizzata).
Metodo
CV TM SQDIFF
CV TM CCORR
CV TM CCOEFF
M. Scarpiniti
Descrizione
Metodo della differenza quadratica
Metodo della correlazione
Metodo del coefficiente di correlazione
Una Introduzione a OpenCV
Metodo
CV TM
CV TM
CV TM
Normalizzato
SQDIFF NORMED
CCORR NORMED
CCOEFF NORMED
46 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
La calibrazione
Un passo fondamentale affinché il tutto funzioni correttamente, nel caso di utilizzo
una web-camera, è la procedura di calibrazione.
In pratica la calibrazione è effettuata identificando prima i bordi di una scacchiera
che viene mostrata alla camera e quindi invocando una funzione per la calibrazione.
M. Scarpiniti
Una Introduzione a OpenCV
47 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
La calibrazione
Le due funzioni precedenti sono, rispettivamente:
int c v F i n d C h e s s b o a r d C o r n e r s (
const void *
image ,
CvSize
pattern_size ,
CvPoint2D32f * corners ,
int *
corner_count = NULL ,
int
flags
= CV_CALIB_CB_ADAPTIVE_THRESH
);
void c v C a l i b r a t i o n C a m e r a 2 (
CvMat * object_points ,
CvMat * image_points ,
int *
point_counts ,
CvSize image_size ,
CvMat * intrinsic_matrix ,
CvMat * distorsion_coeffs ,
CvMat * r o t a t i o n _ v e c t o r s
= NULL ,
CvMat * t r a n s l a t i o n _ v e c t o r s = NULL ,
int
flags
= 0
);
Si rimanda a [1] per il significato di tutti i parametri.
M. Scarpiniti
Una Introduzione a OpenCV
48 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
Il Machine Learning
OpenCV mette a disposizione una libreria per il Machine Learning , in cui sono
contenuti molti algoritmi utili nelle applicazioni.
Di seguito sono elencati gli algoritmi messi a disposizione:
Mahalanobis;
Haar Classifier;
K-means;
Face detector;
Bayes Classifier;
Expectation Maximization (EM);
Binary decision trees;
K-nearest neighbors;
Boosting;
Multilayer Perceptron (MLP);
Random trees;
Support Vector Machines (SVM).
Di seguito esamineremo in dettaglio un paio di algoritmi significativi.
M. Scarpiniti
Una Introduzione a OpenCV
49 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
Il K-means
L’algoritmo K-means si applica attraverso la seguente funzione
void cvKMeans2 (
const CvArr *
int
CvArr *
CvTe rmCriter ia
);
samples ,
cluster_count ,
labels ,
termcrit
in cui samples è un array multidimensionale su cui applicare il K-means,
cluster count è il numero di cluster, labels è un array contenete l’indice del
cluster relativo e termcrit è il criterio di stop utilizzato.
M. Scarpiniti
Una Introduzione a OpenCV
50 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
Il Face Detector
OpenCV mette a disposizione un potente algoritmo di face detection, basato su un classificatore di Haar e proposto da Viola & Jones. Tutte le caratteristiche sono state
precedentemente apprese e salvate in un file distribuito con OpenCV.
La funzione per invocare il face detector è la seguente
CvSeq∗ c v H a a r D e t e c t O b j e c t s (
c o n s t CvArr∗
CvHaarClassifierCascade∗
CvMemstorage∗
double
int
int
CvSize
);
image ,
cascade ,
storage ,
scale factor
min neighbors
flags
min size
=
=
=
=
1.1 ,
3,
0,
cvSize (0 ,0)
in cui image è l’immagine a scala di grigi i cui cercare le facce, cascade contiene le
caratteristiche del classificatore, storage è un buffur utilizzato dall’algoritmo,
scale factor è un fattore di scale che indica quanto elevato è il salto tra una scala e la
successiva, min neighbors indica il numero di detection contemporanee affinché venga
stabilito che effettivamente ci sia una faccia. flags permette di eliminare alcune ragioni
dell’immagine dalla ricerca e, infine, min size indica la dimensione più piccola in cui
effettuare la ricerca.
M. Scarpiniti
Una Introduzione a OpenCV
51 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
Il Face Detector
A questo punto è possibile disegnare un rettangolo o un cerchio intorno
alla faccia o alle facce individuate dalla funzione cvHaarDetectObjects(),
per avere una rappresentazione grafica intuitiva del numero effettivo di facce
individuate.
M. Scarpiniti
Una Introduzione a OpenCV
52 / 53
Introduzione
Le Strutture Dati
Gestione delle matrici
L’Istogramma
Bibliografia
G. Bradski, A. Kaehler.
Learnin OpenCV: Computer Vision with the OpenCV Library.
O’Reilly, 2008.
R. Laganière.
OpenCV 2 Computer Vision - Application Programming Cookbook.
PACKT Publishing,2011.
H. Schildt.
La Guida completa C.
McGraw Hill, 2003.
P. Viola and M. J. Jones.
Rapid Object Detecting Using a Boosted cascade of Simple Features.
IEEE CVPR, 2001.
P. Viola and M. J. Jones.
Robust Real-time Face Detection.
International journal of Computer Vision, Vol. 57, pp. 137–154, 2004.
M. Scarpiniti
Una Introduzione a OpenCV
53 / 53