In questo tutorial prenatalizio non ci sarà bisogno di parti teoriche lunghe e complesse. Al limite solo un po' di geometria euclidea, ma niente di preoccupante. Vedremo alcune delle funzioni di disegno della libreria OpenCV (Drawing Functions), ovvero metodi che vi consentiranno di aggiungere alle immagini forme geometriche come linee, cerchi, ellissi o rettangoli. In più, sarà mostrata una funzione per aggiungere del semplice testo alle immagini. Ovviamente non sono funzioni fondamentali per poter fare un'eccezionale analisi delle immagini, ma sono tutti metodi molto utili se in futuro avrete bisogno di "annotare" o rendere "ben visibili" parti di un'immagine o di un video. Esempio: avete fatto un bel programmino che vi trova tutti i punti di corner all'interno di un'immagine. Sarebbe molto carino se questi punti venissero evidenziati con un cerchietto o, più vistosamente, con un testo "HERE'S YOUR BLOODY CORNER!!!". Si parte perciò dalla struttura dati di base per questo tipo di funzioni: il punto.
Per dichiarare un punto (oggetto Point della libreria), vi basteranno le seguenti linee di codice
Point pt; pt.x = 0; pt.y = 0;
Adesso grazie all'oggetto pt potete fare rapido riferimento al punto di origine di un'immagine.
Data una coppia di punti, potete, per esempio, tracciare una linea tra questi. Per farlo, si utilizza la funzione line di OpenCV
void line(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0)
La funzione traccia una linea sull'immagine img dal punto pt1 al punto pt2 di colore color e spessore thickness. Per quanto riguarda la classe Scalar, in questo contesto è usata per indicare una tripletta di valori compresi fra 0 e 255 che indicano la componente di Rosso, Verde e Blu del colore usato per tracciare la linea.
Con un solo punto però potremmo decidere di tracciare una circonferenza di centro il punto dato.
void circle(Mat& img, Point center, int radius, const Scalar& color, int thickness=1, int lineType=8, int shift=0)
Intuitivamente, center è il centro della circonferenza, mentre radius è il raggio in pixel della stessa.
Se avete approfondito gli argomenti del precedente tutorial vi sarete accorti di come gli autovalori giochino un ruolo importante per la ricerca dei corner o in generale di keypoints. Potreste perciò voler tracciare delle ellissi che abbiano come lunghezza degli assi il reciproco dei valori degli autovalori trovati in uno specifico punto. Per disegnare ellisse vi serve la seguente funzione:
void ellipse(Mat& img, Point center, Size axis, double angle, double startAngle, double endAngle, const Scalar& color, int thickness=1, int lineType=8, int shift=0)
In questo caso sarà necessario specificare più parametri oltre all'immagine e al centro. Nell'oggetto della classe Size devono essere specificate le lunghezze degli assi dell'ellisse. Con angle si intende l'angolo d'inclinazione (specificato in gradi) dell'ellisse, mentre per startAngle ed endAngle si intendo gli angolo di inzio e fine "tracciatura" dell'ellisse (ad esempio, se volte tracciare l'ellisse completa, startAngle=0 endAngle=360).
Se avete due punti, potete tracciare un rettangolo che abbia come diagonale la linea che congiunge i due punti di partenza.
void rectangle(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0)
I parametri sono gli stessi usati per tracciare una linea fra i punti pt1 e pt2
Ultima funzionalità mostrata in questo tutorial: come inserire del testo semplice all'interno di un'immagine.
void putText(Mat& img, const string& text, Point org, int fontFace, double fontScale, Scalar color, int thickness=1, int lineType=8, bool bottomLeftOrigini=false)
In text è contenuto il testo da scrivere sull'immagine img. Per quanto riguarda fontFace, OpenCV mette a disposizioni diversi font cui corrisponde un intero o una definizione della libreria. Vi basterà vedere nei suggerimenti per avere l'elenco completo. La dimensione del testo è data da fontScale ed il colore da color.
Concludo il tutorial con un semplice codice che vi permetterà di provare tutte le funzionalità mostrate in precedenza. Se trovate imprecisioni o volete semplicemente fare domande vi invito come sempre a lasciare un commento all'articolo. Buone feste a tutti quanti!
#include <iostream> #include <opencv/cv.h> #include <opencv/highgui.h> using namespace std; using namespace cv; int main() { int _select; cout << "Press 1 for Line Tutorial" << endl; cout << "Press 2 for Circle Tutorial" << endl; cout << "Press 3 for Ellipse Tutorial" << endl; cout << "Press 4 for Rectangle Tutorial" << endl; cout << "Press 5 for Text Tutorial" << endl; cin >> _select; Mat img = Mat::ones(Size(400, 400), CV_32F); Point pt1; Point pt2; pt1.x = 50; pt1.y = 50; pt2.x = 100; pt2.y = 150; switch (_select) { case 1: line(img, pt1, pt2, Scalar(0, 0, 0), 2); break; case 2: circle(img, pt1, 40, Scalar(0, 0, 0), 2); break; case 3: ellipse(img, pt1, Size(100, 50), 45, 360, 0, Scalar(0, 0, 0), 2); break; case 4: rectangle(img, pt1, pt2, Scalar(0, 0, 0), 2); break; case 5: putText(img, "Natale 2012", Point(100,100), FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 0, 0), 2); putText(img, "Buone Feste dallo staff", Point(15,250), FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 0, 0), 2); putText(img, "di Alla fine del Palo!!!", Point(30,300), FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 0, 0), 2); break; default: cout << "try again..." << endl; break; } namedWindow("Window", CV_WINDOW_AUTOSIZE); imshow("Window", img); waitKey(0); return 0; }
