La libreria OpenCV - 6 - Feature Detection

Prima di iniziare il tutorial volevo precisare che le funzioni utilizzate all'interno del codice di esempio prevedono l'utilizzo di oggetti di tipo Mat (come avevo spiegato in un precedente tutorial). Per questo motivo i nomi delle funzioni potrebbero variare rispetto a quelle già viste. Ad ogni modo, il risultato finale rimane lo stesso e se avete seguito i precedenti tutorial non sarà complicato intuire il funzionamento di questi metodi. Mi riferisco alle funzioni imread(), namedWindow(), imshow() e waitKey().

Questo tutorial si focalizzerà su una funzione della libreria OpenCV molto utile sia per task di matching (confronto di immagini) che per task di tracking (individuare un oggetto all'interno di una sequenza video). Questa funzione non è chiaramente l'unica utilizzabile per questi scopi: vi basterà guardare all'interno del file imgproc.hpp per trovare almeno altre 7 funzioni con lo scopo simile a quella presentata. Ho scelto di parlarvi di questa in particolare perchè sarà utilizzata in futuro quando io e Marco Paciscopi mi mostreremo il nostro lavoro sul flusso ottico.

La funzione di cui vi sto parlando è goodFeaturesToTrack.

void goodFeaturesToTrack(InputArray image, OutputArray corners,
                         int maxCorners, double qualityLevel,
                         double minDistance,
                         InputArray mask=noArray(),
                         int blockSize=3,
                         bool useHarrisDetector=false,
                         double k=0.04 )

Come spiegato nella documentazione di OpenCV, lo scopo della funzione è quello di trovare i migliori punti di corner all'interno dell'immagine, o in specifiche regioni di questa.
Data un'immagine I, un punto (x,y) di I è un punto di corner se il valore di intensità luminosa I(x,y) nel punto è diverso dal valore di intensità in punto I(x+d,y+d) leggermente spostato dal punto iniziale sia lungo X che lungo Y. Esistono differenti metodi matematici per rilevare punti di corner all'interno di un'immagine. Tra i più famosi vi è l'Harris Corner Detector che sfrutta la teoria sugli autovalori. I passi del metodo sono spiegati molto bene anche nella documentazione di OpenCV e per questo motivo preferisco non dilungarmi ulteriormente in questo articolo.

Corner

Nell'immagine troviamo in alto un punto di corner, sul cateto minore un punto di edge e all'interno un punto costante dell'immagine.

Passando ai parametri della funzione, img è l'immagine sulla quale vogliamo ricercare i corner; corners è un vettore dei punti di corner trovati; maxCorners è il massimo numero di punti di corner da restituire (se ce ne sono di più, sono presi i punti di corner "più forti"); qualityLevel è un parametro che ci indica il minimo livello accettato affinchè un punto sia di corner; minDistance è il minimo valore di distanza (euclidea) che deve esserci fra due corner distinti; mask è un valore opzionale grazie al quale è possibile specificare se applicare la funzione solo ad una specifica regione dell'immagine; blockSize indica la dimensione del blocco utilizzato per calcolare la derivata della funzione di intensità luminosa dell'immagine; useHarrisDetector è un valore booleano che ci indica se usare o meno il metodo di Harris per ricercare i corner; k è un parametro libero del metodo di Harris che pesa lo score di "cornerness" di un punto dell'immagine.


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

using namespace std;
using namespace cv;

int main() {

	Mat img = imread("lena1.jpg", CV_LOAD_IMAGE_GRAYSCALE);

	int cornerCount = 100;
	vector<Point2f> corners;
	double qualityLevel = 0.01;
	double minDistance = 5;
	int blockSize = 20;
	int useHarris = false;

	goodFeaturesToTrack(img, corners, cornerCount,
			qualityLevel, minDistance, noArray(), blockSize, useHarris);


	for (int i = 0; i < cornerCount; i++){
		float x = corners[i].x;
		float y = corners[i].y;
		cout << x << " " << y << endl;
		circle(img,Point(x,y),5,Scalar(255, 0, 0, 0),2,8,0);

	}

	namedWindow("Window",CV_WINDOW_AUTOSIZE);
	imshow("Window", img);
	waitKey(0);

	return 0;

}

Il codice presentato carica un'immagine e la trasforma in scala di grigi (fondamentale per utilizzare la funzione goodFeaturesToTrack). Dopo l'inizializzazione del parametri, viene chiamata la suddetta funzione ed è così creato il vettore di punti di corner. Dopodichè i punti vengono sia stampati sulla console che disegnati (tramite la funzione circle()) sull'immagine stessa. Il risultato dell'operazione è mostrato in figura.

Lena

Per ulteriori informazioni riguardo la funzione vi invito a dare un'occhiata all'articolo di Shi e Tomasi o a fare domande tramite commenti a questo articolo

AGGIORNAMENTO ALL'ARTICOLO 19 APRILE 2013:
Inserisco anche il codice che ha riscritto Andrea Salvi per applicare le stesse funzioni ai video.

#include <iostream>
#include <cv.h>
#include <highgui.h>

using namespace std;
using namespace cv;

int main() {
    int cornerCount = 100;
    double qualityLevel = 0.01;
    double minDistance = 5;
    int blockSize = 20;
    int useHarris = false;

    VideoCapture capture("input.avi");
    string window_name = "result";
    namedWindow(window_name, CV_WINDOW_AUTOSIZE);
    Mat frame;
    for (;;) {
        vector<Point2f> corners;
        capture >> frame;
        if (frame.empty())
            break;
        cvtColor(frame,frame,CV_RGB2GRAY);
        goodFeaturesToTrack(frame, corners, cornerCount, qualityLevel,
                            minDistance, noArray(), blockSize,
                            useHarris);
        for (int i = 0; i < cornerCount; i++){
            float x = corners[i].x;
            float y = corners[i].y;
            circle(frame,Point(x,y),5,Scalar(255, 0, 0, 0),2,8,0);
        }
        imshow("result", frame);
        waitKey(10);
    }
    return 0;
}

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 - 6 - Feature Detection ultima modifica: 2012-12-17T14:46:20+01:00 da Alessio Antonielli


Advertisment ad adsense adlogger