본문 바로가기

CLASS

[OpenCV] OpenCV 를 이용한 Hough Transform 중급강좌



Hough Transform 이란 영상에 있는 점들이 이루는 직선들 중 가장 많이 겹치는 부분을 추출하는 변환규칙입니다.

수학이 힘을 발휘하는 부분으로서 간단하게 (x, y) 를 (a, b) 라 하고 새로운 좌표계에 y' = ax' + b 를 그리면 여러개의 직선들이 존재하게되는데 이중 가장 많은 직선이 지나는 점 (x', y') 를 다시 (x, y) 좌표계로 변환하면 점들이 지나는 직선을 구해낼 수 있는 규칙입니다.

정말로 간단하면서도 신기하지요. OpenCV 에는 간단하게 cvHoughLines2() 함수를 제공하고 있고요.

코딩에는 Media Systam Lab. 의 서종훈 연구원(flamme4u) 님이 수고해 주셨습니다.

제가 연구실 세미나 때 제가 발표했던 자료 중 핵심 입니다.

핵심을 정리하면,

Hough Transform 은 픽셀기반의 raster image 에서 기하학적 성분 geometric primitives 추출하는 방법이다.
Hough 변환은 직선 뿐만 아니라 원, 타원 등 도형을 위한 특징 추출법으로 “점<->직선” 변환을 하는 방법
xy 평면상에 직선이 있으면 y=ax+b 로 표현이 되고 이를 ab 평면상으로 옮기면 (a,b) 좌표계가 된다.


- 소스코드

HoughLines.zip

//
// Hough Lines
//
// Jong-Hoon Seo, Dong-Chul Kim
// Media System Lab., Yonsei University
//
http://msl.yonsei.ac.kr
// http://opencv.co.kr
//

#include "stdafx.h"

int main()
{
IplImage* src0;
CvCapture* captue = cvCaptureFromCAM(0);

while(1){
cvGrabFrame(captue);
if(  (src0=cvRetrieveFrame(captue)) != 0)
{
  IplImage* dst = cvCreateImage( cvGetSize(src0), 8, 1 );
  IplImage* color_dst = cvCreateImage( cvGetSize(src0), 8, 3 );
 
  IplImage* src = cvCreateImage( cvGetSize(src0), IPL_DEPTH_8U, 1);
           
  cvCvtColor(src0, src, CV_RGB2GRAY);

  CvMemStorage* storage = cvCreateMemStorage(0);

  CvSeq* lines = 0;

  cvCanny( src, dst, 50, 200, 3 );
  cvCvtColor( dst, color_dst, CV_GRAY2BGR );
  lines = cvHoughLines2( dst, storage, CV_HOUGH_STANDARD, 1, CV_PI/180, 100, 0, 0 );

  for( int i = 0; i < MIN(lines->total,100); i++ )
  {
   float* line = (float*)cvGetSeqElem(lines,i);
   float rho = line[0];
   float theta = line[1];
   CvPoint pt1, pt2;
   double a = cos(theta), b = sin(theta);
   double x0 = a*rho, y0 = b*rho;
   pt1.x = cvRound(x0 + 1000*(-b));
   pt1.y = cvRound(y0 + 1000*(a));
   pt2.x = cvRound(x0 - 1000*(-b));
   pt2.y = cvRound(y0 - 1000*(a));
   cvLine( color_dst, pt1, pt2, CV_RGB(255,0,0), 3, 8 );
  }
  lines = cvHoughLines2( dst, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI/180, 80, 30, 10 );
  for( i = 0; i < lines->total; i++ )
  {
   CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);
   cvLine( color_dst, line[0], line[1], CV_RGB(255,0,0), 3, 8 );
  }
  cvNamedWindow( "Source", 0 );
  cvShowImage( "Source", src );

  cvNamedWindow( "Hough", 0 );
  cvShowImage( "Hough", color_dst );
 
  cvReleaseMemStorage(&storage);
}
if(cvWaitKey(10) >= 0) break;

}
cvDestroyAllWindows();
cvReleaseCapture(&captue);
  return 0;
}

Copyrights (c) 2006 OpenCV.co.kr. All rights reserved.

Media System Lab., Yonsei University.  http://msl.yonsei.ac.kr

by Dong-Chul Kim, e-mail: opencv at opencv.co.kr

- T9T9.com

  • 노형석 2007.12.03 17:27

    재밌게 보았습니다.

    픽셀기반이면 구하는데 좀 느린감에 있겠네요..

    그냥 생각만으로..

    매트랩에서 이것을 써보았는데..

    신기하더라구요 ㅎㅎ

  • BlogIcon Kwangswei 2009.07.21 03:56

    Hough Transform 관련 자료 찾다가 방문하게 되었습니다.

    쉽게 개념을 잡을 수 있도록 잘 설명해놓으셔서 잘 보고 갑니다.

    감사합니다 ^^

  • roboinside 2010.11.29 20:37

    쉽고 좋은 설명, 자료 감사합니다.