☰ Menu

Scene.hu

Magyar demoscene portál – grafikusok, zenészek, programozók alkotói közössége

Előfeldolgozás OpenCV-vel. Második rész

Posted by Travis on 2012-10-24, 13:50

Az OpenCV képfeldolgozás cikksorozat első része után itt a folytatás, de csak a tovább után…

Nyers kép

Ha birtokunkban vannak a feldolgozandó képi információk, az első lépés, hogy ezt a programunk számára elérhetővé kell tenni. Három különböző módon olvashatunk be képeket:

Webkameráról a cvCaptureFromCAM, videóról a cvCaptureFromFile használható. Mindkét parancs egy CvCapture struktúrát ad vissza, ahonnan a cvQueryFrame segítségével kinyerhetjük az egyes képkockákat. Ha csak egyetlen képpel dolgozunk, akkor a cvLoadImage betölti nekünk azt.

Amennyiben egy köztes állapotot tárolására nekünk kell létrehozni egy képet, a cvCreateImage-t használhatjuk.

Bármelyik módszert is használjuk, eredményül egy IplImage-t kapunk. Ez a nyers képünk. Attól függően, hogy mi a célunk, a képet különböző előfeldolgozásnak kell alávetni. Sok parancs hatása hasonló, mintha Photoshop szűrőket használnánk, tehát gondolhatunk úgy is az OpenCV-re ezek alapján, mint egy programozható grafikus alkalmazásra.

Photoshop imitálás

Az egyik legfontosabb feladat, hogy különböző színterek között át tudjuk alakítani a kapott képet. Erre szolgál a cvCvtColor függvény. Három paramétere közül az első kettő a kép, amiről konvertálunk, a kép, amire konvertálunk. Az utolsó paraméterrel adjuk meg a konvertálás módját. A módokat konstansokkal adhatjuk meg. Ha szürkeárnyalatos képet akarunk kapni egy RGB színterű képből, a következő konstanst használhatjuk: CV_RGB2GRAY.

Szintén alapvető fontosságú feladat a képek átméretezése. A cvResize segítségével könnyedén átméretezhetjük képünket. A forrás és célképek megadása után már csak az átméretezés módját kell megadni egy konstans segítségével.

Egy másik, a grafikus programokban gyakran használt művelet az elmosás, amihez a cvSmooth használható. Megadjuk a forrást, célt, valamint az elmosás típusát (pl: CV_GAUSSIAN, CV_MEDIAN). Az utolsó négy paraméterrel szabályozhatjuk magát az algoritmust.

Az utolsó két ismertetésre kerülő függvény közös jellemzője, hogy egy úgynevezett konvolúciós kernelt használ a kép módosítására. A kernel előállítására a cvCreateStructuringElementEx-t használjuk. Ez egy egyszerűsített módszer a kernel létrehozására. Ahelyett, hogy a mátrixot elemek szerint adnánk meg (bár erre is van lehetőség), csak a méretét, alakját és a kernel horgonypontjait (anchor point) állítjuk be. Amennyiben elég profik vagyunk, az utolsó paraméterrel mi magunk is beállíthatunk egy kernelt.

Az így elkészített kernelt azután felhasználhatjuk a cvErode és a cvDilate függvényekhez. Anélkül, hogy a részletekbe merülnék, ez a két függvény egyfajta zajszűrőnek tekinthető. A cvErode segítségével a kisebb hibákat (foltokat, karcolásokat) tüntethetünk el, míg a cvDilate segítségével a struktúrális különbségek jobban kiemelhetőek.

Rajzolás

Új elemeket is felvehetünk a képünkre. A legegyszerűbb alakzat, amit elhelyezhetünk a képünkön, a vonal. A cvLine segítségével nem csak a színt, de a vonal vastagságát és stílusát is beállíthatjuk. Nagyon hasonló a négyzeteket rajzoló függvény (cvRectangle) paraméterezése is.

Bináris képek

Ebben a fejezetben a kép szegmentálásával foglalkozunk. Ezek alacsony szintű műveletek lesznek, nem próbáljuk meg felismerni a képen található elemeket, csupán színek alapján elkülönítjük az egyes területeket. A feltételeknek megfelelő régiók fehér színűek lesznek, míg amelyek nem felelnek meg, feketék. Ha színes képpel dolgozunk, akkor az cvInRangeS függvényt használhatjuk. Segítségével felállíthatunk két színkorlátot és minden, ami azon belülre esik, fehérként jelenik meg a cél képen.

Érdemes megjegyezni, hogy sokkal realisztikusabb eredményt kapunk, ha nem RGB, hanem HSV színtérbe konvertáljuk képünket. Nekem az a tapasztalatom, hogy nagyon nehéz olyan szűrőt készíteni, amelyik egy színt és a hozzá közel eső árnyalatokat is nagy pontossággal kiszűri.

Szürkeárnyalatos kép esetén a cvThreshold vagy cvAdaptiveThreshold függvények használhatók. Előbbi a pixelenként hajtja végre a műveletetet, utóbbi pixel blokkonként. Mindkét függvény elég rugalmasságot biztosít, hogy miként kívánunk szűrni. A következő példaprogram ezt szemlélteti a webkameránk képével:

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

int type = CV_THRESH_BINARY;

void processImage(IplImage *raw, IplImage *gray){
  cvCvtColor(raw, gray, CV_RGB2GRAY);
  cvThreshold(gray, gray, 128, 255, type);
}

int main(){
  CvCapture *capture;
  IplImage *frame;
  IplImage *gray;
  int run = 1;

  capture = cvCaptureFromCAM(CV_CAP_ANY);
  cvNamedWindow("win", CV_WINDOW_AUTOSIZE);
  frame = cvQueryFrame(capture);
  gray = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1);

  while(run){
    frame = cvQueryFrame(capture);
    processImage(frame, gray);
    cvShowImage("win", gray);

    switch(cvWaitKey(10)){
      case 97:
        type = CV_THRESH_BINARY;
        break;
      case 115:
        type = CV_THRESH_BINARY_INV;
        break;
      case 100:
        type = CV_THRESH_TRUNC;
        break;
      case 102:
        type = CV_THRESH_TOZERO;
        break;
      case 103:
        type = CV_THRESH_TOZERO_INV;
        break;
      case 27:
        run = 0;
    }
  }

  cvReleaseCapture(&capture);
  cvDestroyWindow("win");
  cvReleaseImage(&gray);

  return EXIT_SUCCESS;
}

Az a,s,d,f,g billentyűkkel változtathatjuk a cvThreshold paraméterét. ESC-re a program kilép. A következő fejezetben az előfeldolgozott képeken fogunk tovább műveleteket végrehajtani: kontúrvonalakat keresünk, időjárás bemondóvá válunk és kiváltjuk Aha-t egy programmal.

Categories: Programozás | Tags: ,

3 Responses so far.

  1. avatar Murphy says:

    Experience-re fogja valaki használni az itt tanultakat?

  2. avatar Gargaj says:

    Nem bantaskepp de ha mar peldakod akkor nem lehetne a “case 97” helyett mondjuk “case ‘a'”? :D

  3. avatar Travis says:

    Tudod, hogy van ez Gargaj:
    “All I see now is blonde, brunette, redhead.”
    :-)

Leave a Reply

You must be logged in to post a comment.

Ugrás a lap tetejére Ugrás a lap aljára