'SIFT'에 해당되는 글 7건

  1. 2010.06.22 SURF Lib 3
  2. 2009.06.21 Rob Hess의 SIFT [8] 7
  3. 2009.04.30 Rob Hess의 SIFT [7] 1
  4. 2009.04.18 Rob Hess의 SIFT [6]
  5. 2009.03.02 Rob Hess의 SIFT [5] 2
  6. 2009.02.23 Rob Hess의 SIFT [3] 2
  7. 2009.02.16 Rob Hess의 SIFT [1] 1
Computer Vision2010. 6. 22. 01:49
SURF는 2006년 호주의 Garz가 제일 먼저 제안한 알고리즘입니다.
SIFT보다 계산량을 단순화 시키고 (특정 논문에서는 4배 정도 빠르다고 결과를 발표하였습니다)
대신 결과의 퀄리티는 비슷하다고 강조하고 있습니다.


http://www.vision.ee.ethz.ch/~surf/
  비 상업용으로 쓰인다는 전제 하에서 Linux용 C코드와  Windows용 DLL을 제공하고 있습니다.

http://www.chrisevansdev.com/computer-vision-opensurf.html
  Chris evans가 정리한 SURF 관련 자료 및 C++과 C#으로 쓰여진 라이브러리를 제공
  오픈 라이브러리인 만큼 라이브러리에 대한 용법이 설명된 매뉴얼도 제공됩니다

http://www.springerlink.com/content/tg61524386764t2t/
 관련 논문을 참조하기 바라고, (해당 사이트에 있습니다.)
 병렬처리로 빠르게 한다는 기본 개념입니다.

http://labe.felk.cvut.cz/~tkrajnik/fpga-surf/
  FPGA에 SURF를 넣은 자료
  2009년에 발표했으며 관련 논문과 FPGA자료를 오픈하고 있습니다.
  소스코드라고 하지만 실제로는 Netlist이며 (어찌보면 당연한 말씀..)
  논문이 참고할 만한 자료입니다.
  코드로 구현한다면 논문보고 하드웨어로 만드는게 더 빠를듯..


아래는 간단한 동영상




'Computer Vision' 카테고리의 다른 글

OpenCV 2.3 Computer vision (1)  (2) 2011.09.05
OpenCV 2.1 맥에서 빌드하기  (0) 2010.09.04
Rob Hess의 SIFT [8]  (7) 2009.06.21
Rob Hess의 SIFT [7]  (1) 2009.04.30
OpenCV - Alpha Blending cvAddWeighted , cvFillPoly  (2) 2009.04.25
Posted by GUNDAM_IM
Computer Vision2009. 6. 21. 03:40

Rob Hess의 SIFT 8번째


() 글을 읽기 전에
글은 저와 같은  초보자를 위해서 정리하는 것입니다.
전문가시라면 굳이 읽을 필요가 없습니다.
공부하면서 정리하는 글이라서 서툰 부분이 많이 보입니다. 이해하여 주시고

틈틈이 새로운 것을 알게 되면 그때 그때 업데이트 하겠습니다.



(주) 시작하기 전에

실제 코드를 한번 따라가기 전에 SIFT 알고리즘을 간략하게 정리하여둡니다.

코드를 기계적으로 따라가는것 보다는 알고리즘을 이해하고 따라가는 것이 유용하기 때문입니다.

물론 그렇다고 제가 알고리즘을 다 이해하는 것은 아닙니다.

그냥 초보 수준에서 아는 것들만 정리하였습니다.



PPT 발표 자료는 이 페이지를 참조 하세요 : SIFT 정리.PPT



발표자료를 기반으로 하여서 추가적으로 정리한 내용입니다.



1. Harris Corner Detector

특징으로는 다음과 같습니다.

  Rotation 에 대해 검출이 가능하다.

  부분 이미지로도 검출이 가능하다.

{

해석 :

이상의 말을 풀이하면

H.C.Detector는 영상이  회전된 것 그리고 밝기의 변화와 이미지 상에서 노이즈가 있어도

어느정도 이를 견디어 내며 원하는 포인트를 찾아낼 수 있다는 의미가 됩니다.

H.C.Detector는 Local Auto Correlation Function에 기반합니다.

기본적인 아이디어는 전체 이미지를 한방에 뒤지는 것이 아니고

주어진 이미지 영역에서 작은 이미지 영역 (부분 영역)을 설정하여 이 윈도우를 주변 영역과 비교하여

커다란 차이점이 있는 부분을 찾아내는 방식입니다.

설정된 이미지에 대해서 뒤지는 방향은 아무 방향이나 상관이 없습니다. 다만 주어진 부분 영역에 대해서

큰 변화가 생기는 방향으로 이동해야 하곘지요


아래 그림을 보면 쉽게 이해됩니다.

사용자 삽입 이미지


 

제일 왼쪽 그림은 뒤져서 변화가 없으므로 “Flat”으로 보게 됩니다.

가운데 그림은 상하로만 선분이 있다는 것을 알게 됩니다.

- 에지 방향으로 변화가 없다는 것은 에지가 존재한다는 의미가 됩니다.

오른쪽 그림은 모든 방향으로 변화가 존재하기 때문에

“Conor”라고 보는 것 입니다.


- 수학적인 의미는 다음에 하기로 하고 여기선 패스 합니다.

- SIFT가 우선이므로, H.C.Detector는 이정도에서 정리합니다.


매트랩에 대한 코드는 아래를 참고하시기 바랍니다.

http://ipl.cnu.ac.kr/mayadata/harris/harris_corner_detector.htm


}


사용자 삽입 이미지

상기 그림을 실제 H.C.Detector에 걸면 다음과 같은 영상을 얻을 수 있습니다.

사용자 삽입 이미지


그리고 이 그림의 임계치 이상만을 검출하면 다음과 같습니다.


사용자 삽입 이미지


임계치 이상 영역에서 최대값만을 표시하면 다음과 같습니다.



사용자 삽입 이미지

요것이 바로 코너 포인트가 되는 것입니다.


  이 코너포인트를 원본 그림과 매핑하면 다음과 같습니다.


사용자 삽입 이미지


문제점 :

크기 변화에대해 대처하지 못한다.

사용자 삽입 이미지

   위의 그림처럼 원래 EDGE로 인식되는 것이 스케일을 작에 줄이면, 코너로 바뀌는 경우가 발생합니다.

   이처럼 크기가 변하는 것에 따러 검출되는 성분이 변하기 때문에 크기 변화에 대응하지 못하는 것이라고

   합니다. - 당연한 이야기 인듯..



관련 자료는 이페이지에 있습니다.

매트랩등등의 코드를 함께 제공하기 때문에 공부하실 분들은 이 페이지를 참고하여 주세요


http://ipl.cnu.ac.kr/mayadata/harris/harris_corner_detector.htm

그리고 위에 설명에 사용된 그림은

lect9-slides.pdf

을 참고하시기 바랍니다.



'Computer Vision' 카테고리의 다른 글

OpenCV 2.1 맥에서 빌드하기  (0) 2010.09.04
SURF Lib  (3) 2010.06.22
Rob Hess의 SIFT [7]  (1) 2009.04.30
OpenCV - Alpha Blending cvAddWeighted , cvFillPoly  (2) 2009.04.25
JPEG2AVI 를 맥에서 빌드하기  (0) 2009.04.24
Posted by GUNDAM_IM
Computer Vision2009. 4. 30. 00:07


SIFT의 동작은


아래와 같이 호출됩니다.


int sift_features( IplImage* img, struct feature** feat )

{

  return _sift_features( img, feat,

SIFT_INTVLS,

SIFT_SIGMA,

SIFT_CONTR_THR,

                         SIFT_CURV_THR,

SIFT_IMG_DBL,

SIFT_DESCR_WIDTH,

                         SIFT_DESCR_HIST_BINS );

}


영상과 feature는 포인터로 전달되고 나머지는  매크로로 정의되어 있습니다. 이렇게 하면

최상위 함수는 매크로에 따라 파라미터를 줄 수 있고 이하 하위 함수들은 인자들을 기반으로 할 수 있으므로

프로그램 테스트 등이 편리해집니다.


정의된 매크로들은 나중에 코드를 읽어가면서 새로운 그리고 필요한 매크로가 나온다면, 그때마다

하나씩 확인해 가기로 하고 여기서는 건너 뜁니다.


실제 호출은 위의 코드에서 보는 바와 같이 _sift_features를 호출하여 구동합니다.

이 함수는 다음과 같은 순서로 동작합니다.


1. 인자를 검사해서 오류가 있는지 확인을 합니다.

2. 주어진 이미지로 이미지 피라미드를 구축합니다.

3. 구축한 이미지 피라미드에서 DoG를 구축합니다.

4. DoG에서 특징점들을 추출하고

5. 특징점 을 좌표에 매핑하고,

6. 특징점 기술자들을 논문대로 정리한다.


이를 위한 호툴된 함수는 다음과 같습니다.

기계적으로 따라갑니다.


int _sift_features( IplImage* img, struct feature** feat, int intvls,

                    double sigma, double contr_thr, int curv_thr,

                    int img_dbl, int descr_width, int descr_hist_bins )

{

  IplImage* init_img;

  IplImage*** gauss_pyr, *** dog_pyr;

  CvMemStorage* storage;

  CvSeq* features;

  int octvs, i, n = 0;


  /* check arguments  

인자를 검사한다. NULL Pointer이면 에러를 출력한다.*/


  if( ! img )

    fatal_error( "NULL pointer error, %s, line %d",  __FILE__, __LINE__ );

  if( ! feat )

    fatal_error( "NULL pointer error, %s, line %d",  __FILE__, __LINE__ );


  /* build scale space pyramid; smallest dimension of top level is ~4 pixels

      이미지 피라미드를 구축한다.

     최상위 피라미드는 그 크기가 4 픽셀 정도이다.

   */


/* 최초의 이미지를 만들어 냅니다.

   이 이미지는 그레이 스케일로 생성됩니다.. */

  init_img = create_init_img( img, img_dbl, sigma );


  octvs = log( MIN( init_img->width, init_img->height ) ) / log(2) - 2;


/* 이미지를  가지고 가우시안 스케일 피라미드를 구성합니다. */

  gauss_pyr = build_gauss_pyr( init_img, octvs, intvls, sigma );


/* DoG 이미지 피라미드를 구성합니다. */

  dog_pyr = build_dog_pyr( gauss_pyr, octvs, intvls );


  storage = cvCreateMemStorage( 0 );


DoG에서 특징점들을 열심히 추출합니다.

  features = scale_space_extrema(

dog_pyr,

octvs,

intvls,

contr_thr,

                            curv_thr,

storage );


/* 추출된 특징들의 특성들을 계산합니다. */

  calc_feature_scales( features, sigma, intvls );


/*  이미지가 2배로 키워서 특징점들을 추출하였을 경우 이를 다시 조절합니다. */

  if( img_dbl )

    adjust_for_img_dbl( features );


/* 정규 좌표를 계산합니다. */

  calc_feature_oris( features, gauss_pyr );


/* Lowe’s Paper 6절에 따라서 특징점 기술자를 만들어냅니다. */

  compute_descriptors( features, gauss_pyr, descr_width, descr_hist_bins );



  /* sort features by decreasing scale and move from CvSeq to array */


  cvSeqSort( features, (CvCmpFunc)feature_cmp, NULL );


  n = features->total;


  *feat = calloc( n, sizeof(struct feature) );


  *feat = cvCvtSeqToArray( features, *feat, CV_WHOLE_SEQ );


  for( i = 0; i < n; i++ )

    {

      free( (*feat)[i].feature_data );

      (*feat)[i].feature_data = NULL;

    }


  cvReleaseMemStorage( &storage );

  cvReleaseImage( &init_img );

  release_pyr( &gauss_pyr, octvs, intvls + 3 );

  release_pyr( &dog_pyr, octvs, intvls + 2 );

  return n;


}


'Computer Vision' 카테고리의 다른 글

SURF Lib  (3) 2010.06.22
Rob Hess의 SIFT [8]  (7) 2009.06.21
OpenCV - Alpha Blending cvAddWeighted , cvFillPoly  (2) 2009.04.25
JPEG2AVI 를 맥에서 빌드하기  (0) 2009.04.24
OpenCV - cvSmooth  (2) 2009.04.22
Posted by GUNDAM_IM
Computer Vision2009. 4. 18. 15:08

() 글을 읽기 전에
글은 저와 같은  초보자를 위해서 정리하는 것입니다.
전문가시라면 굳이 읽을 필요가 없습니다.
공부하면서 정리하는 글이라서 서툰 부분이 많이 보입니다. 이해하여 주시고

틈틈이 새로운 것을 알게 되면 그때 그때 업데이트 하겠습니다.



(주) 시작하기 전에

실제 코드를 한번 따라가기 전에 SIFT 알고리즘을 간략하게 정리하여둡니다.

코드를 기계적으로 따라가는것 보다는 알고리즘을 이해하고 따라가는 것이 유용하기 때문입니다.

물론 그렇다고 제가 알고리즘을 다 이해하는 것은 아닙니다.

그냥 초보 수준에서 아는 것들만 정리하였습니다.



PPT 발표 자료는 이 페이지를 참조 하세요 : SIFT정리.ppt

발표자료를 기반으로 하여서 추가적으로 정리한 내용입니다.



1. Harris Corner Detector

특징으로는 다음과 같습니다.

  Rotation 에 대해 검출이 가능하다.

  부분 이미지로도 검출이 가능하다.

{

해석 :

이상의 말을 풀이하면

H.C.Detector는 영상이  회전된 것 그리고 밝기의 변화와 이미지 상에서 노이즈가 있어도

어느정도 이를 견디어 내며 원하는 포인트를 찾아낼 수 있다는 의미가 됩니다.

H.C.Detector는 Local Auto Correlation Function에 기반합니다.

기본적인 아이디어는 전체 이미지를 한방에 뒤지는 것이 아니고

주어진 이미지 영역에서 작은 이미지 영역 (부분 영역)을 설정하여 이 윈도우를 주변 영역과 비교하여

커다란 차이점이 있는 부분을 찾아내는 방식입니다.

설정된 이미지에 대해서 뒤지는 방향은 아무 방향이나 상관이 없습니다. 다만 주어진 부분 영역에 대해서

큰 변화가 생기는 방향으로 이동해야 하곘지요


아래 그림을 보면 쉽게 이해됩니다.


사용자 삽입 이미지

 

제일 왼쪽 그림은 뒤져서 변화가 없으므로 “Flat”으로 보게 됩니다.

가운데 그림은 상하로만 선분이 있다는 것을 알게 됩니다.

- 에지 방향으로 변화가 없다는 것은 에지가 존재한다는 의미가 됩니다.

오른쪽 그림은 모든 방향으로 변화가 존재하기 때문에

“Conor”라고 보는 것 입니다.


- 수학적인 의미는 다음에 하기로 하고 여기선 패스 합니다.

- SIFT가 우선이므로, H.C.Detector는 이정도에서 정리합니다.


매트랩에 대한 코드는 아래를 참고하시기 바랍니다.

http://ipl.cnu.ac.kr/mayadata/harris/harris_corner_detector.htm


}


사용자 삽입 이미지

상기 그림을 실제 H.C.Detector에 걸면 다음과 같은 영상을 얻을 수 있습니다.

사용자 삽입 이미지


그리고 이 그림의 임계치 이상만을 검출하면 다음과 같습니다.


사용자 삽입 이미지


임계치 이상 영역에서 최대값만을 표시하면 다음과 같습니다.

사용자 삽입 이미지

요것이 바로 코너 포인트가 되는 것입니다.


  이 코너포인트를 원본 그림과 매핑하면 다음과 같습니다.


사용자 삽입 이미지

문제점 :

크기 변화에대해 대처하지 못한다.

사용자 삽입 이미지
위의 그림처럼 원래 에지로 인식하는 것이 크기가 줄어들면서 Coner로 인식이 되는 경우가 발생합니다.

혹은 그 역으로도 발생합니다.


따라서 H.C.Detector는 크기의 변경에 따라서 검출되는 정보가 변하므로,

        크기 변화에 대처하지 못하는 것입니다.

   

       SIFT는 이러한 문제점을 개선하기 위해서 나온 것입니다.

       본격적인 이야긴 다음편에서~~      



    이번 내용에 대해서 추가적인 자료는 다음과 같습니다.


      매트랩등등의 코드를 함께 제공하기 때문에 공부하실 분들은 이 페이지를 참고하여 주세요


http://ipl.cnu.ac.kr/mayadata/harris/harris_corner_detector.htm

그리고 위에 설명에 사용된 그림과 수식등은


lect9-slides.pdf


      을 참고하시기 바랍니다.


      ----------

      자료 정리하던 프로그램이 Expire되어 버렸습니다.

      잘 정리(?) 된 줄 알았는데 근본적으로 Time Limit이 되어 있더군요

      좋은 프로그램인데 넘 고가여서.. .쩝..


      그래서 한단계 낮은 프로그램을 구입했습니다.

      그바람에 그동안 정리했던 것 옮기느라 많이 늦어졌네요

      

'Computer Vision' 카테고리의 다른 글

JPEG2AVI 를 맥에서 빌드하기  (0) 2009.04.24
OpenCV - cvSmooth  (2) 2009.04.22
OpenCV - Convert Image  (0) 2009.04.11
OpenCV - Image Mask  (0) 2009.03.16
OpenCV - Extract  (2) 2009.03.12
Posted by GUNDAM_IM
Computer Vision2009. 3. 2. 11:05

유클리드 제곱 거리


이 부분의 구성은 이곳에서 인용하였습니다.


http://www.cherrynet.co.kr/bbs_view.php?s=37&pseq=11&mnid=1



다차원 공간 상에서 두점 사이의 거리를 구하는 것을 말합니다.

다차원이라고 해도 2차원상의 거리를 구하는 것과 비슷한 방법입니다.


점을 (p1, p2, p3, p4,...) (q1, q2, q3, q4, ...) 표기한 경우 유클리디안 거리 공식은 아래와 같습니다.


사용자 삽입 이미지

def euclidean(p,q) :

     sumSq = 0.0


     # 차의 제곱을 더함

       for i in range( len(p) ) :

                sumSq += ( p[i] - q[i] ) **2


     # 루트를 취함

       return ( sumSq**0.5 )


'Computer Vision' 카테고리의 다른 글

OpenCV - Extract  (2) 2009.03.12
OpenCV - Image Rotation & Scale  (0) 2009.03.10
Rob Hess의 SIFT [4]  (0) 2009.02.25
Rob Hess의 SIFT [3]  (2) 2009.02.23
Rob Hess의 SIFT [2]  (0) 2009.02.18
Posted by GUNDAM_IM
Computer Vision2009. 2. 23. 08:23

Rob Hess의 SIFT


앞서 두번에 걸쳐서 Rob의 코드를 컴파일해서 정상적으로 움직이는 것을 확인하였습니다.

이제 코드 내부가 어떻게 동작하는지 확인을 해보겠습니다.

SIFT자체는 나중에 따로 정리하기로 하고 전체 맥락을 한번 따라가는 형식으로 정리하였습니다.



이번에는 전체 코드를 한번 찬찬히 따라가면서 정리하였습니다.

그냥 코드를 읽는 수준이므로 큰 무리 없이 따라가면 됩니다.

OpenCV에 기반하므로, 그냥 이런 함수가 있다고 보고 읽어 가면 됩니다.


1. dspFeat의 분석


dspFeat를 먼저 코드를 보곘습니다.

이 프로그램은 그냥 SIFT를 대상 이미지에 올리는 그림입니다.

별다른 어려운 부분이 없읍니다.


시작 부분에서 두개의 파일을 먼저 설정하고 있습니다.


char* feat_file = "..\\beaver.sift";

char* img_file = "..\\beaver.png";


앞서의 것은 beaver.sift 의 결과물입니다. 텍스트 파일로 되어 있네요

두번째 것은 png format 으로 되어 있는 이미지 파일입니다.



int main( int argc, char** argv )

{

IplImage* img;

struct feature* feat;

char* name;

int n;


img = cvLoadImage( img_file, 1 );  // 먼저 이미지 파일을 로딩한다.


if( ! img )

fatal_error( "unable to load image from %s", img_file );


n = import_features( feat_file, feat_type, &feat ); // 피쳐 파일을 로딩한다.

if( n == -1 )

fatal_error( "unable to import features from %s", feat_file );


name = feat_file;


draw_features( img, feat, n );  // SIFT를 그린다.

cvNamedWindow( name, 1 );  // 창을 열고~~~

cvShowImage( name, img );   // 그림을 그린다. 이때 그림은  draw_feature로 그린것이다.

cvWaitKey( 0 );   // 글고 키 값을 기다린다. 

return 0;

}


이다. 큰 문제점은... 은 없네요~ 


draw_feature()함수를 나중에 따로 정리하여야 하겠습니다.

이것은 SIFT를 정리하면서 하면 되므로 여기서는  SKIP...



2. match의 코드 따라가기


그럼 이제 두번째로 match를 한번 따라가 보겠습니다.



/******************************** Globals ************************************/


char img1_file[] = "..\\beaver.png"; // 찾고자 하는 이미지  파일이다.

char img2_file[] = "..\\beaver_xform.png"; // 비교 대상 파일이다.


/********************************** Main *************************************/



int main( int argc, char** argv )

{

IplImage* img1, * img2, * stacked;

struct feature* feat1, * feat2, * feat;

struct feature** nbrs;

struct kd_node* kd_root;

CvPoint pt1, pt2;

double d0, d1;

int n1, n2, k, i, m = 0;


img1 = cvLoadImage( img1_file, 1 ); // 찾는 이미지를 먼저 로딩한다.

if( ! img1 )

fatal_error( "unable to load image from %s", img1_file );


img2 = cvLoadImage( img2_file, 1 ); // 대상 이미지를 로딩한다.

if( ! img2 )

fatal_error( "unable to load image from %s", img2_file );


stacked = stack_imgs( img1, img2 ); // 두개의 이미지를 합쳐서 하나의 이미지로 만든다.

    // 그렇다고 이미지를 겹치는 것이 아니라 상하로 포개는 것이다.


fprintf( stderr, "Finding features in %s...\n", img1_file );

n1 = sift_features( img1, &feat1 ); // 이제 FEATURE를 찾기...


fprintf( stderr, "Finding features in %s...\n", img2_file );

n2 = sift_features( img2, &feat2 ); // 피쳐를 더 찾기...


kd_root = kdtree_build( feat2, n2 ); // 키포인트 배열에서 원하는 kd tree로 구성한다.


for( i = 0; i < n1; i++ ) // 찾고자 하는 이미지 1의 특징점을 대상으로 반복한다.

{

feat = feat1 + i;

k = kdtree_bbf_knn( kd_root, feat, 2, &nbrs, KDTREE_BBF_MAX_NN_CHKS );

// 특징점에서 NN방식으로 하여 찾아낸다.

if( k == 2 ) // k가 2라면.. 찾아낸 것이므로.. 

{

d0 = descr_dist_sq( feat, nbrs[0] ); // nn과 두번째 nn사이의 

      // 유클리드 제곱 거리를 구한다.

d1 = descr_dist_sq( feat, nbrs[1] );

if( d0 < d1 * NN_SQ_DIST_RATIO_THR ) // 임계치보다 크다면.. 

{

// 두개의 포인트로 선을 그린다. 

pt1 = cvPoint( cvRound( feat->x ), cvRound( feat->y ) );

pt2 = cvPoint( cvRound( nbrs[0]->x ), cvRound( nbrs[0]->y ) );

pt2.y += img1->height;

cvLine( stacked, pt1, pt2, CV_RGB(255,0,255), 1, 8, 0 );

m++;

feat1[i].fwd_match = nbrs[0];

}

}

free( nbrs );

}


// 다 찾았으면 이미지를 그린다.

fprintf( stderr, "Found %d total matches\n", m );

cvNamedWindow( "Matches", 1 );

cvShowImage( "Matches", stacked );

cvWaitKey( 0 );



/*  

       이 것은 RANSAC함수가 어떻게 움직이는지 보기 위해서 만든 것입니다.

       아래 주석 처리가 된 블럭을 풀면 됩니다.

UNCOMMENT BELOW TO SEE HOW RANSAC FUNCTION WORKS


Note that this line above:


feat1[i].fwd_match = nbrs[0];


is important for the RANSAC function to work.

*/

/*

{

CvMat* H;

H = ransac_xform( feat1, n1, FEATURE_FWD_MATCH, lsq_homog, 4, 0.01,

homog_xfer_err, 3.0, NULL, NULL );

if( H )

{

IplImage* xformed;

xformed = cvCreateImage( cvGetSize( img2 ), IPL_DEPTH_8U, 3 );

cvWarpPerspective( img1, xformed, H, 

CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS,

cvScalarAll( 0 ) );

cvNamedWindow( "Xformed", 1 );

cvShowImage( "Xformed", xformed );

cvWaitKey( 0 );

cvReleaseImage( &xformed );

cvReleaseMat( &H );

}

}

*/


//모두 해제합니다.

cvReleaseImage( &stacked );

cvReleaseImage( &img1 );

cvReleaseImage( &img2 );

kdtree_release( kd_root );

free( feat1 );

free( feat2 );

return 0;


여기서는 KDTree를 이용해서 공간상에서 dB를 구축하였음을 알수 있습니다.

다음에는 이것을 좀더 자세하게 따라가 보겠습니다.


'Computer Vision' 카테고리의 다른 글

Rob Hess의 SIFT [5]  (2) 2009.03.02
Rob Hess의 SIFT [4]  (0) 2009.02.25
Rob Hess의 SIFT [2]  (0) 2009.02.18
Rob Hess의 SIFT [1]  (1) 2009.02.16
MAC에서 OpenCV를 컴파일 하기  (0) 2009.01.06
Posted by GUNDAM_IM
Computer Vision2009. 2. 16. 14:59

Rob HessSIFT


1. 살펴 보기


SIFTScale ... 을 의미하는 것이고...자세한 내용은 다음에 기회되는 대로 정리해서 올리도록 하겠습니다.



인터넷에 찾아보면 여러가지 버전의 구현된 코드를 찾아볼 수 있습니다.

귀찮게도 C로 되어 있는것 보단 MATLAB이나 C#같은 것으로 되어 있어서 상당히 귀찬습니다.


이번에 발견하여 분석한 코드는 Rob Hess의 코드이며, C로 되어 있습니다. 


Rob Hess는 오래곤 주립대학의 컴퓨터 공학과 박사과정 학생으로 컴퓨터 비젼을 전공으로 하고 있습니다.

홈 페이지는 이곳에 있습니다.


http://web.engr.oregonstate.edu/~hess/index.html


홈페이지에 보면 몇가지 알고리듬을 공부하고 올려놓았지만, 가장 관심이 가는것은  SIFT입니다.


최신 버전은 2009년 1월에 1.1.1을 만들었습니다. 이전 버전과 바뀐 부분은


라이브러리를 정적으로 만들 수 있도록 Makefile을 수정한 부분과,

Visual C를 VC2005에서 컴파일 되도록 하였다는 부분

그외에 API들을 수정하여서 버그들을 정리했다고합니다.


소스 코드는 리눅스 버전과 윈도우즈 버전의 코드를 가지고 있고 각각 이 곳에서 받을 수 있습니다.


리눅스 버전 : TAR.GZ

윈도우즈 버전 : ZIP


이 SIFT 버전은 OpenCV 에 기반하고 있으며  RANSAC 은 GNU Scientific Lib에 기반하고 있습니다.

이제 아래 그램을 보면 SIFT가 무엇을 하는 지에 대해서 알 수 있습니다



    

사용자 삽입 이미지 사용자 삽입 이미지

왼쪽의 카드를 오른쪽의 그림 더미에서 찾아내는 것입니다.

아래 그림을 다시 보면


    

사용자 삽입 이미지 사용자 삽입 이미지


이 되어서 원하는 이미지가 있는 위치를 정확하게 찾아 낼 수 있습니다.


1. 코드의 컴파일


컴파일을 할려면 Visual C++에서 먼저 컴파일을 하였습니다.

우선 VC Project 를 로드하여 컴파일을 하면 다음과 같이 에러가 발생합니다.


LINK : fatal error LNK1104: cannot open file 'cvd.lib'


해당 라이브러리를 찾을 수 없다는 의미이고,

이 라이브러리는 opencv debug lib을 의미합니다.



2. OpenCV 설치



2.1 다운로드 및 설치


OpenCV를 다운로드 합니다.


Source Forge에서 다운로드 합니다.

아래 사이트에서 다운 받을 수 있습니다.


http://sourceforge.net/projects/opencvlibrary


여기서 윈도우즈 버전을 다운받아서 설치합니다. 실행 파일로 되어 있으므로 그렇게 어렵지는 않을듯 합니다.

설치 중간에 환경 변수 세팅을 물어보므로, 그때 YES라고 해서 설치를 합니다.


설치가 끝나면 View Documents를 보게 됩니다.


C:\Program Files\OpenCV\docs\index.htm


링크이므로 틈틈히 찾아보면 정보를 얻을 수 있습니다.


2.2 디버깅 라이브러리 만들기



설치된 코드는 실행 코드이다. 개발시에는 디버깅용 코드가 필요하므로 디버깅 버전의 라이브러리를 만드러야 한다.


c:\Program Files\OpenCV\_make


폴더에 가서 opencv.dsw를 클릭합니다.


그러면 버전문제에 대한 문의 다이얼로그가 나타난다. 모두 YES라고 선택하면 된다.

그러면 다음과 같은 창이 나타난다.


사용자 삽입 이미지


그럼 이제 BUILD->Batch Build를 선택하면 다음과 같은 창이 나타난다.


사용자 삽입 이미지


그럼 win32 ReleaseWin 32 Debug를 모두 선태한다.

이후에 Build를 눌러서 라이브러리를 모두 컴파일 한다.



경고도 나타나지만 무시하고 진행하면 컴파일이 완료된다.


2.3 라이브러리 오류 수정


실제로 깨끗하게 완료된것이 아니다.


ompiling...

cvbgfg_acmmm2003.cpp

.\cvbgfg_acmmm2003.cpp(464) : error C2039: 'foreground_regions' : is not a member of 'CvFGDStatModel'

        c:\Program Files\OpenCV\cvaux\include\cvaux.h(1301) : see declaration of 'CvFGDStatModel'

.\cvbgfg_acmmm2003.cpp(470) : error C2039: 'foreground_regions' : is not a member of 'CvFGDStatModel'

        c:\Program Files\OpenCV\cvaux\include\cvaux.h(1301) : see declaration of 'CvFGDStatModel'

cvbgfg_gaussmix.cpp

.\cvbgfg_gaussmix.cpp(348) : error C2039: 'foreground_regions' : is not a member of 'CvGaussBGModel'

        c:\Program Files\OpenCV\cvaux\include\cvaux.h(1365) : see declaration of 'CvGaussBGModel'

Generating Code...


과 같이 오류가 발생합니다. 이전 버전에도 있던 오류인데 아직도 살아있다는게 놀라울 따름입니다.

하여튼 수정합니다.


cvaux.h : 1159 행 부근을 보면


#define CV_BG_STAT_MODEL_FIELDS()                                                   \

    int             type; /*type of BG model*/                                      \

    CvReleaseBGStatModel release;                                                   \

    CvUpdateBGStatModel update;                                                     \

    IplImage*       background;   /*8UC3 reference background image*/               \

    IplImage*       foreground;   /*8UC1 foreground image*/                         \

    IplImage**      layers;       /*8UC3 reference background image, can be null */ \

    int             layer_count;  /* can be zero */                                 \

    CvMemStorage*   storage;      /*storage for 밼oreground_regions?/              \

    CvSeq*          foreground_regions /*foreground object contours*

/


이 있습니다. 여기서


    CvMemStorage*   storage;      /*storage for 밼oreground_regions?/              \



    CvMemStorage*   storage;      /*storage for 밼oreground_regions*/              \


으로 바꿉니다.


이번에는 잘 진행합니다.


2.4 라이브러리 오류 수정


컴파일 끝에 2개가 컴파일이 안되었다고 나옵니다.

나온것을 보면


   Creating library ..\..\lib/highgui.lib and object ..\..\lib/highgui.exp

cvcap.obj : error LNK2019: unresolved external symbol "struct CvCapture * __cdecl cvCreateCameraCapture_DShow(int)" (?cvCreateCameraCapture_DShow@@YAPAUCvCapture@@H@Z) referenced in function _cvCreateCameraCapture

..\..\bin/highgui110.dll : fatal error LNK1120: 1 unresolved externals

Build log was saved at "file://c:\Program Files\OpenCV\_temp\highgui_Release\BuildLog.htm"

highgui - 2 error(s), 0 warning(s)

------ Build started: Project: highgui, Configuration: Debug Win32 ------

Linking...

   Creating library ..\..\lib/highguid.lib and object ..\..\lib/highguid.exp

cvcap.obj : error LNK2019: unresolved external symbol "struct CvCapture * __cdecl cvCreateCameraCapture_DShow(int)" (?cvCreateCameraCapture_DShow@@YAPAUCvCapture@@H@Z) referenced in function _cvCreateCameraCapture

..\..\bin/highgui110d.dll : fatal error LNK1120: 1 unresolved externals

Build log was saved at "file://c:\Program Files\OpenCV\_temp\highgui_Debug\BuildLog.htm"


으로 되어 있습니다.


이것은 cvcap_dshow.cpp 파일이 highgui project에 포함되어 있지 않아서 생긴 오류이다.

src에 이것을 추가합니다.


사용자 삽입 이미지

위의 그림처럼 추가하면 됩니다.


그래도 오류가 발생하는데 일단 라이브러리를 추가합니다.


C:\Program Files\OpenCV\otherlibs\_graphics\lib


그리고 다시 컴파일을 하면 역쉬 에러가 나옵니다.


cvcap_dshow.obj : error LNK2019: unresolved external symbol "public: void __thiscall videoInput::stopDevice(int)" (?stopDevice@videoInput@@QAEXH@Z) referenced in function "public: virtual void __thiscall CvCaptureCAM_DShow::close(void)" (?close@CvCaptureCAM_DShow@@UAEXXZ)

cvcap_dshow.obj : error LNK2019: unresolved external symbol "public: bool __thiscall videoInput::isDeviceSetup(int)" (?isDeviceSetup@videoInput@@QAE_NH@Z) referenced in function "public: virtual bool __thiscall CvCaptureCAM_DShow::open(int)" (?open@CvCaptureCAM_DShow@@UAE_NH@Z)

cvcap_dshow.obj : error LNK2019: unresolved external symbol "public: bool __thiscall videoInput::setupDevice(int)" (?setupDevice@videoInput@@QAE_NH@Z) referenced in function "public: virtual bool __thiscall CvCaptureCAM_DShow::open(int)" (?open@CvCaptureCAM_DShow@@UAE_NH@Z)

cvcap_dshow.obj : error LNK2019: unresolved external symbol "public: bool __thiscall videoInput::getPixels(int,unsigned char *,bool,bool)" (?getPixels@videoInput@@QAE_NHPAE_N1@Z) referenced in function "public: virtual struct _IplImage * __thiscall CvCaptureCAM_DShow::retrieveFrame(void)" (?retrieveFrame@CvCaptureCAM_DShow@@UAEPAU_IplImage@@XZ)

cvcap_dshow.obj : error LNK2019: unresolved external symbol "public: int __thiscall videoInput::getHeight(int)" (?getHeight@videoInput@@QAEHH@Z) referenced in function "public: virtual struct _IplImage * __thiscall CvCaptureCAM_DShow::retrieveFrame(void)" (?retrieveFrame@CvCaptureCAM_DShow@@UAEPAU_IplImage@@XZ)

cvcap_dshow.obj : error LNK2019: unresolved external symbol "public: int __thiscall videoInput::getWidth(int)" (?getWidth@videoInput@@QAEHH@Z) referenced in function "public: virtual struct _IplImage * __thiscall CvCaptureCAM_DShow::retrieveFrame(void)" (?retrieveFrame@CvCaptureCAM_DShow@@UAEPAU_IplImage@@XZ)

cvcap_dshow.obj : error LNK2019: unresolved external symbol "public: bool __thiscall videoInput::setupDevice(int,int,int)" (?setupDevice@videoInput@@QAE_NHHH@Z) referenced in function "public: virtual bool __thiscall CvCaptureCAM_DShow::setProperty(int,double)" (?setProperty@CvCaptureCAM_DShow@@UAE_NHN@Z)

cvcap_dshow.obj : error LNK2019: unresolved external symbol "public: static void __cdecl videoInput::setVerbose(bool)" (?setVerbose@videoInput@@SAX_N@Z) referenced in function "public: __thiscall SuppressVideoInputMessages::SuppressVideoInputMessages(void)" (??0SuppressVideoInputMessages@@QAE@XZ)

cvcap_dshow.obj : error LNK2019: unresolved external symbol "public: __thiscall videoInput::videoInput(void)" (??0videoInput@@QAE@XZ) referenced in function "void __cdecl `dynamic initializer for 'protected: static class videoInput CvCaptureCAM_DShow::VI''(void)" (??__E?VI@CvCaptureCAM_DShow@@1VvideoInput@@A@@YAXXZ)

cvcap_dshow.obj : error LNK2019: unresolved external symbol "public: __thiscall videoInput::~videoInput(void)" (??1videoInput@@QAE@XZ) referenced in function "void __cdecl `dynamic atexit destructor for 'protected: static class videoInput CvCaptureCAM_DShow::VI''(void)" (??__F?VI@CvCaptureCAM_DShow@@1VvideoInput@@A@@YAXXZ)

..\..\bin/highgui110d.dll : fatal error LNK1120: 10 unresolved externals


과 같이 에러가 발생한다.


소스 파일을 찾아서 잘 보면 모두 VIDEO INPUT을 직접 받을때 사용하는 함수들 입니다. 

현시점에서 외부에서 직접 비디오 입력을 받을 일이 없으므로 그냥 넘어가서


_highgui,h파일에서 다음과 같이 수정한다.


#if _MSC_VER >= 1400 && !defined WIN64

#define HAVE_VIDEOINPUT 1

#endif



#if _MSC_VER >= 1400 && !defined WIN64

#ifdef HAVE_VIDEOINPUT

#  undef HAVE_VIDEOINPUT

#endif


//#define HAVE_VIDEOINPUT 1


#endif


으로 수정해서 막아버리고 컴파일 하면.. 잘 됩니다.




3 OpenCV 환경 설정


할때마다 컴파일 환경을 잡아주는 것이 귀찮으므로 일단 전체 환경 설정을 한번 하여줍니다.


3.1 헤더 파일 폴더의 추가


Tools-> Opetions을 선택하여 나타난 다이얼로그 박스에서 Directories 탭을 선택합니다

Tools->Options을 선택하여 나타난 다이얼로그 박스에서 Projects and Solutions 항목의 VC++ Directories를 선택하면 아래와 같은 창이 됩니다.


사용자 삽입 이미지



Platform에 Win 32를 Show Directories에 Includes files를 선택한 후에

새로운 Header File Folder를 선택합니다.


C:\Program Files\OpenCV\_make

C:\Program Files\OpenCV\cv\include

C:\Program Files\OpenCV\cvaux\include

C:\Program Files\OpenCV\cxcore\include

C:\Program Files\OpenCV\ml\include

C:\Program Files\OpenCV\otherlibs\highgui

C:\Program Files\OpenCV\otherlibs\ffopencv

C:\Program Files\OpenCV\otherlibs\_graphics\include


을 모두 설치합니다.



3.2 라이브러리 폴더 추가


이번에는 라이브러리 폴더를 같은 방법으로 추가합니다.


사용자 삽입 이미지


위의 그림과 같이 Library Files를 선택한 뒤에


C:\Program Files\OpenCV\lib


을 추가합니다.


이렇게 하면 준비가 끝났습니다.


4. 다시 컴파일


SIFT를 다시 컴파일 하면 이번엔 잘 된다.


실행하면 다음과 같은 오류가 나타난다.


사용자 삽입 이미지


이것은 환경 변수에 PATH를 다음것을 추가합니다.


C:\Program Files\OpenCV\bin



5. 다시 실행


이제 SIFT를 다시실행한다.

그럼 아래 그림이 나타난다.


사용자 삽입 이미지


이제 정상적으로 컴파일이 되었다.



아래 그림은 약간 수정한 코드로 만든 이미지입니다.

잘 동작하고 있습니다.

사용자 삽입 이미지





'Computer Vision' 카테고리의 다른 글

Rob Hess의 SIFT [3]  (2) 2009.02.23
Rob Hess의 SIFT [2]  (0) 2009.02.18
MAC에서 OpenCV를 컴파일 하기  (0) 2009.01.06
XcodeでOpenCV開発  (0) 2009.01.03
파노라마 구성하기  (0) 2009.01.03
Posted by GUNDAM_IM