본문 바로가기

CLASS

[OpenCV] 윤곽(contour) 추출, 에지(edge) 추출 중급강좌

다음은 윤곽(contour) 또는 에지(edge)를 찾는 주요 함수 부분에 대한 설명입니다.
윤곽선을 찾는 방법에는 1차 미분, 2차 미분, 템플릿 매칭(Template matching), 로버츠(Roberts), 소벨(Sobel), 라플라시안(Laplacian) 등이 있는데 그중 라플라시안 방법 중 한가지를 사용하였습니다.
윤곽 부분을 추출하기 위하여 이미지의 3 x 3 픽셀에 마스크(mask)를 씌워 계산후 중앙 픽셀의 값을 결정하게 됩니다. 즉, 아래와 같은 3 x 3 픽셀을 보고 특정 값이 들어가 있는 마스크를 곱하여 p5 를 계산하게 되는데
    p1  p2  p3
    p4  p5  p6
    p7  p8  p9
특정 값을 넣은 3 x 3 마스크는 다음과 같이 정의 합니다.
   -1  -1  -1
  -1   8   -1
  -1  -1  -1
마스크와 곱하여 p5 값을 계산하게 됩니다.
  p5 = p5 x 8 + ( p1 x -1 + p2 x -1 + p3 x -1 ...)
결국 p5 에는 새로운 값이 들어가게 되는데 주변에 값이 비슷하면 적은 값이 들어가게되고 주변 값이 급변하게 변하면 큰 값이 들어가게 되어 에지 또는 윤곽선을 추출하게 되는 것입니다.
- 실행 결과
- 소스코드
// contour 찾는 부분

IplImage* contour(IplImage* img)
{
  int di[8] = {-1,-1,-1, 0, 0, 1, 1, 1},
  dj[8] = {-1, 0, 1,-1, 1,-1, 0, 1};

  int mask[3][3]={{ -1, -1, -1 },
                           { -1,  8, -1 },
                           { -1, -1, -1 }};

  int p;
  Img2Aray(img);

  for(int i=1; i<img->height-1; i++){
       for(int j=1; j<img->width-1; j++){
           p = Map[i][j].r;
           p *= mask[1][1];

           for(int k=0; k<8; k++){
               p = p + ( (unsigned char)Map[i+di[k]][j+dj[k]].r * mask[1+di[k]][1+dj[k]] );
           }

           if(p > 255)  p = 255;
           else if(p < 0) p = 0;

           img->imageData[i*img->widthStep + j ] = (unsigned char)p;
       }
  }

  return img;

}


Copyrights (c) 2006 OpenCV.co.kr. All rights reserved.
Media System Lab., Yonsei University
by Dong-Chul Kim, e-mail: opencv at opencv.co.kr
- T9T9.com