Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

OpenCV kirjaston käyttö kannattaa yleensä aloittaa käymällä läpi OpenCV sivuston opetuskurssit. Nämä ovat erittäin hyvin ajantasalla, niiden käyttö on pyritty tekemään helpoksi ja ne on selostettu erittäin hyvin. Metropolian kirjaston tarjoaman SpringerLinkin kautta löytyy myös hyvä Practical OpenCV kirja, joka kannattaa ladata opiskelua varten.

Tällä sivustolla käsitellään kaikkein yksinkertaisimmat esimerkit kuten kuvan lataaminen ja muutamia suodattimia. Lisäksi käydään läpi asioita, joille sivustolta ei löydy esimerkkejä kuten Qt käyttöliittymän hyödyntäminen ja erilaisten kameroiden käyttö OpenCV kanssa.

Table of Contents
outlinetrue

Console sovellus QT:lla

console-sovellus Qt:lla

Kuvan lataaminen

Kuvan lataamiseen löytyy useita eri funktioista jotka löytyvät OpenCV dokumentaatiosta, nämä tehdään yleensä highgui luokalla. OpenCV käyttää Mat datatyyppiä kuville, se on matriisityyppinen datarakenne, jonne kuvat tallennetaan yleensä BGR väriformaatissa.

Kuvatiedosto

Kuvatiedoston lataaminen tapahtuu yleensä seuraavalla komennolla, jossa ensimmäinen parametri on kuvatiedoston nimi/polku ja toisella voidaan vaikuttaa siihen missä formaatissa kuva ladataan, 0 on harmaasävy- ja 1 on värikuva.

Mat image =  imread(const string& filename, int flags=1 );

Kuva voidaan myös ladata tietokoneen suoraan tietokoneen muistista OpenCV käyttöön, tämä tapahtuu imdecode funktiolla. Sen avulla voidaan välttää ylimääräinen kovalevylle tallentaminen esimerkiksi kompaktikameraa käyttäessä, jollon etälaukaisulla otetaan kuva ja luetaan se muistiin, jonka jälkeen se voidaan purkaa seuraavalla komennolla. Tämä on tarpeen vain siinä tilanteessa, jos kuva on pakatussa muodossa. Pakkaamattoman kuvan dataa voi käyttää myös suoraan sellaisenaan Mat muuttujassa.

Mat image = imdecode(InputArray buf, int flags);

OpenCV pystyy myös tallentamaan kuvatiedostoja imwrite funktiolla.

Kamera ja video

OpenCV käsittelee perinteistä verkkokameraa ja videotiedostoa samalla tavalla, siinä avataan videostream ja siitä otetaan frameja tietyin väliajoin. Seuraavassa esimerkissä on hyvin yksinkertaistettuna tämän toiminta jossa otetaan vain yksi frame ja if lausekkeella varmistetaan, että stream on auennut. 

VideoCapture cap(0)
if(!cap.isOpened()) return -1;
Mat frame;
cap >> frame;

VideoCapturen parametrinä voidaan käyttää myös videotiedostoa, tässä esimerkissä oleva 0 on oletus verkkokamera ja se voidaan myös muuttaa, jos tietokoneesta löytyy useampi kamera.

Suodattimet

Kuvasta häiriönpoisto ja tärkeiden asioiden erottaminen erilaisella kuvankäsittelyllä on erittäin tärkeää konenäössä. Tätä varten OpenCV sisältää oman imgproc moduulin, joka sisältää useita erilaisia funktioita joiden avulla kuvaa pystytään käsittelemään.

Häiriönpoisto

Häiriönpoisto tapahtuu usein pehmentämällä kuvaa, tätä varten on olemassa useita erilaisia toimintoja jotka toimivat hieman erilaisilla algoritmeilla. Yllä olevasta linkistä löytyy esimerkki näiden käytöstä ja teoriasta niiden taustalla.

Sivustolla oleva ohjelma käy muutamia näistä läpi ja muuttaa niiden parametreja, joilla se esittelee näiden toimintaa. Yksinkertaistettuna näiden käyttö kuitenkin tapahtuu seuraavien funktioiden avulla.

GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, intborderType=BORDER_DEFAULT )

medianBlur(InputArray src, OutputArray dst, int ksize)

blur(InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT )

bilateralFilter(InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, intborderType=BORDER_DEFAULT )

InputArray ja OutputArray on Mat muuttujia, input on kuva jolle suodatus tehdään ja output on matriisi johon se tallennetaan. Näissä voi käyttää myös samaa matriisia, jolloin suodatettu korvaa alkuperäisen. Parametrit ovat kaikissa vähän erilaiset ja niistä lisätietoa löytyy osoitteesta. http://docs.opencv.org/modules/imgproc/doc/filtering.html

Mat image = imread("kuva.jpg",0); //Ladataan kuva.jpg harmaasävykuvana

blur(image,image,Size(3,3)); //Suodatetaan blur funktiolla 3x3 kokoisella kernelillä

Threshold

Threshold funktiota voidaan käyttää binäärikuvien luomiseen. Yksinkertaisimmillaan siinä voidaan asettaa arvo, jonka ylittävät kuvapisteen arvot asetetaan ykkösiksi ja alittavat asetetaan nollaksi.

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

Ylläolevan linkissä on selkeästi esitetty funktion parametrit, tämän kanssa voidaan käyttää myös Otsun metodia threshold arvon määrittämiseen seuraavan esimerkin mukaisesti. Se hakee kuvasta automaattisesti kuvasta histogrammin avulla tummat ja vaaleat alueet ja asettaa threshold arvon niiden väliin.

 threshold(image,image,0,255,CV_THRESH_BINARY|CV_THRESH_OTSU);

Lisäksi löytyy adaptiveThreshold johon kannattaa tutustua, siinä jokaisen kuvapisteen kohdalla haetaan arvo pisteelle ympäröivien kuvapisteiden mukaan.

Morphology

http://docs.opencv.org/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.html

http://docs.opencv.org/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.html

Dilate, Erode, Open, Close

Kuvista tunnistaminen

HoughCircles, matchTemplate, findContours käydään läpi ja linkitetään machine learning, findobjects ja features2d luokkien esimerkit. Ehkä liikkuva kuva.

Qt-käyttöliittymä

OpenCV käyttö on myös mahdollista Qt:lla tehdyissä käyttöliittymissä, tämä helpoittaa laadukkaan käyttöliittymän luomisessa. Joitakin asioita on kuitenkin otettava huomioon, kuten reaaliaikasen kuvan käsittely ja kuvan näyttäminen. OpenCV esimerkeissä reaaliaikaista kuvaa tai videota käsitellessä ohjelma jätetään pyörimään While looppiin, joka ei ole mahdollista Qt:n kanssa ja ohjelma kaatuu. 

Reaaliaikainen kuva

Qt:n kanssa reaaliaikaista voidaan kuitenkin käyttää QTimer ajastimella tai vaihtoehtoisesti aina kun kuva on käsitelty lähetetään signaali että ladataan uusi kuva. Seuraavassa esimerkissä on esitettynä kuinka QTimeria käytetään kuvan lukemiseen.

 timer=new QTimer(this); //timerin luonti
 connect(timer,SIGNAL(timeout()),this,SLOT(getFrame())); //Timerin timeout signaalin yhdistäminen uuden kuvan lukemiseen
 timer->start(50);//Ajastimen käynnistys ja timeout() viive millisekunteina

Kuvan näyttäminen

Kuvan voidaan näyttää Qt käyttöliittymässä lukemalla kuva OpenCV:n Mat datasta kuva QImage muotoon, jolloin kuva voidaan piirtää Qt-käyttöliittymään. OpenCV lataa kuvat oletuksena BGR väriformaatilla, kun Qt taas käyttää oletuksena RGB väriformaattia. Kuva tulee muuttaa RGB muotoon, jotta se näkyy oikein. Seuraavassa esimerkkikoodissa on esitettynä kuvan lukeminen Mat datasta QImage dataan.

 cv::Mat _image=imread("esimerkki.jpg");
 QImage qimg;
 if(_image.channels()==1) //Katsotaan värikanavien määrä, harmaasävy kuvassa 1 ja RGB 3.
 {
 qimg = QImage((uchar*)_image.data,_image.cols,_image.rows,_image.step,QImage::Format_Indexed8); 
 //Kuvan luetaan QImage muotoon, formaatti (*data,width,height,bytesperline,format)
 }
 else if(_image.channels()==3)
 {
 cv::cvtColor(_image,_image,CV_BGR2RGB);
 //Muunnetaan kuva Qt:n käyttämään RGB väriformaattiin.
 qimg = QImage((uchar*)_image.data,_image.cols,_image.rows,_image.step,QImage::Format_RGB888);
 }

Kuvan näyttämiseen käyttöliittymässä voidaan käyttää esimerkiksi QGraphicsView tai label widgetteja. Seuraavassa esimerkkikoodissa on yksinkertaisemman label widgetin käyttö.

 ui->imgLabel->setPixmap(QPixmap::fromImage(img));
 //Kuvan piirto label widgetiin.

GraphicsView taas on vähän monipuolisempi widget jossa pystytään esittämään 2D kuvaa, siitä pystyy valitsemaan kuva-alueita ja vierittämään suurempiakin kuvia joten sen käyttö on usein suositeltavaa. Sille täytyy ohjelmassa esittää QGraphicsScene, johon kuva päivitetään. GraphicsView seuraa kokoajan scenen muutoksia, joten esittelyn jälkeen riittää, että sceneen päivittää uuden kuvan.

 scene=new QGraphicsScene(); //Luodaan QGraphicsScene
 ui->graphicsView->setScene(scene); //Asetetaan scene graphicsView widgettiin
 scene->addPixmap(QPixmap::fromImage(qimg)); //Lisätään kuva sceneen, tätä käytetään myös kuvan päivittämiseen.