Opencv: HSV color filter

Ocv

In ambito robotico e non solo la visione artificiale assume un ruolo fondamentale. Spesso il riconoscimento di un  oggetto è basato sulla segmentazione del colore, in cui l’immagine viene partizionata in insiemi di pixel aventi una caratteristica comune: colore.

In questo modo creando un filtro ad esempio giallo, è possibile estrarre dall’immagine tutti gli oggetti appartenenti a tale colore.

OBIETTIVO

Il filtraggio per colore nello spazio HSV, in OpenCv avviene per mezzo della funzione inRange. Spesso tuttavia i valori esatti  per il filtraggio di un colore specifico non sono noti. Inoltre vi è anche da considerare che normalmente i range del canale H va da 0° a 360°, in OpenCv invece lo spettro del canale H varia da 0° a 180°. A tale scopo è stata sviluppata un’applicazione che rende semplice e immediata, l’estrazione dei sei valori HSV min e HSV max, e ne mostra immediatamente l’effetto applicando un threshold su tale range. (per mezzo della funzione inRange). 

HSV_2

source2

SVILUPPO

Gli step del codice sviluppato sono i seguenti:

[*] Creazione delle 3 finestre contenenti le immagini (stream originale, filtrato e immagine contenete lo spazio HSV), e dei trackbar per i valori di HSV min e max

[cpp] int main(int, char**)
{
namedWindow("HSV_color_space");
namedWindow("source");
namedWindow("source_filtered");

//creazione dei 6 trackbar con funzione di
//callback "camera_sweep"
createTrackbar( "H_m", "HSV_color_space", &Hm, 180, camera_sweep );
createTrackbar( "S_m", "HSV_color_space", &Sm, 255, camera_sweep );
createTrackbar( "V_m", "HSV_color_space", &Vm, 255, camera_sweep );
createTrackbar( "H_M", "HSV_color_space", &HM, 180, camera_sweep );
createTrackbar( "S_M", "HSV_color_space", &SM, 255, camera_sweep );
createTrackbar( "V_M", "HSV_color_space", &VM, 255, camera_sweep );

//definizione dell’elemento strutturante utile nell’operazione
//morfologica di opening
element = getStructuringElement(CV_SHAPE_RECT,Size(2,2),Point(1,1));
[/cpp]

[*] Inizializzazione dello stream video

[cpp] //apertura dello stream video
VideoCapture cap(0);
//verifica dell’apertura
if(!cap.isOpened())
return -1;
[/cpp]

[*] Loop di elaborazione

[cpp] for(;;)
{
//salvataggio del frame acquisito
cap >> src_camera;
//flip immagine
flip(src_camera,src_camera,1);
//cambio spazio di colore
cvtColor(src_camera, src_cam_HSV, CV_BGR2HSV);
//lettura immagine spazio di colori HSV
Mat src= imread("./hsvd.jpg");
if( !src.data )
printf("error\n");
//cambio spazio di colore
cvtColor(src, src_HSV, CV_BGR2HSV);
//salvataggio del tasto premuto
key=waitKey(3);

//quando viene premuto il tasto +
//il range di filtraggio del canale H
//viene incrementato di 5 sia per il valore
//minimo che massimo. La posizione dei due
//trackbar viene automaticamente aggiornata
//e lo stream video viene filtrato secondo i
//valori di HSV min e max appena aggiornati

if(key==’+’ && HM0)
{
HM-=5;
Hm-=5;
setTrackbarPos("H_m", "HSV_color_space", Hm);
setTrackbarPos("H_M", "HSV_color_space", HM);
}

sweep(1,0);

//funzione di callback per l’aggiornamento
//dei parametri
camera_sweep(1,0);

//sovrapposizione del contorno di colore
//all’immagine HSV
src|=hull_im;

//visualizzazione stream senza filtro
imshow("source",src_camera);

//operazioni di AND e NOT al fine di mostrare
//lo stream filtrato dal colore
bitwise_not(src_cam_inR, src_cam_inR);
bitwise_and(src_camera, 0, src_camera,src_cam_inR);

//visualizzazione delle immagini HSV e
//stream filtrato
imshow("HSV_color_space",src);
imshow("source_filtered",src_camera);
}
return 0;
}
[/cpp]

[*] Callback function

[cpp] void camera_sweep(int, void*)
{
//il Blur dell’immagine serve a rimuovere rumore
medianBlur(src_cam_HSV, src_cam_HSVB, 3);
//l’inRange function effettua il filtraggio dello stream video
//secondo i valori HSV min e max presenti nei trackbar
inRange(src_cam_HSVB, Scalar(Hm,Sm,Vm,0), Scalar(HM,SM,VM,255),src_cam_inR);
//operazione morfologica di opening per la rimozione di rumore
morphologyEx(src_cam_inR, src_cam_inR, 2, element, Point(-1,-1), 4);

}
[/cpp]

[*] Funzione Sweep

Se nella funzione camera_sweep il filtro colore veniva applicato allo stream video, nella funzione sweep il filtraggio avviene sull’immagine rappresentante lo spazio di colore HSV secondo i valori presenti nelle trackbar. In questo modo l’immagine restituita dalla inRange function sarà scura con un gruppo di pixel bianchi rappresentati il range HSV filtrato. A questo punto di questo insieme di pixel se ne trova il contorno esterno con le funzioni di findContours e convexHull. L’operazione finale è quella di disegnare il contorno in una immagine, la quale viene successivamente sovrapposta a quella rappresentate lo spazio HSV al fine di mostrare per mezzo di un contorno il range HSV che si sta filtrando.

[cpp] void sweep(int, void*)
{
medianBlur(src_HSV, src_HSVB, 3);
inRange(src_HSVB, Scalar(Hm,Sm,Vm,0), Scalar(HM,SM,VM,255),src_inR);

findContours( src_inR, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

vector<vector >hull( contours.size() );
hull_im = Mat::zeros( src_HSV.size(), CV_8UC3 );

for( size_t i = 0; i < contours.size(); i++ ){
convexHull( Mat(contours[i]), hull[i], false );
drawContours( hull_im, hull, i, Scalar(255,255,255), 1, 8, hierarchy, 0, Point() );
}
}

[/cpp]

CODICE FINALE

[Download not found]

COMPILAZIONE

Per eseguire il codice, aprire il terminale (ctrl+alt+t) posizionarsi sulla cartella estratta “Sweep” contenente il sorgente scaricato, digitare:

[cpp] g++ `pkg-config –cflags opencv` Sweep.cpp -o Sweep `pkg-config –libs opencv`
./Sweep
[/cpp]
Francesco Celiberti
Ciao a tutti,

mi chiamo Francesco, sono laureato in Ing. Informatica e dell'Automazione. Sono attualmente coinvolto in un progetto di ricerca Europeo, MOTORIST. www.motorist-ptw.eu
Tags: ,
By Francesco Celiberti | gennaio 30th, 2013 | SHOW COMMENTS (4)

4 Responses

  1. Ale says

    tutorial molto utile.
    E’ possibile fare il download dell’immagine hsvd.jpg?

    Grazie Francesco

    • Francesco Celiberti
      fra_celi says

      certo te la mando per email!

      • Pablo says

        Ciao Francesco ,

        Ottimo tutorial ! Ero alla ricerca di regolazione un’immagine HSV trackbar e in C ++ , grazie!

        Non riesco a scaricare il codice finale dal sito web , Potresti inviare il codice via e-mail ? Abbiamo davvero apprezzato la 🙂

        Saluti e scusate il mio italiano

  2. Antonio says

    Grazie Francesco 🙂
    Ottimo tutorial