Alpha Blending


알파 블랜딩을 OpenCV에서 하는 것을 구현해 보았습니다.

코드를 읽어가면서 정리하였습니다.


1. 프로그램의 순서


순서는 다음과 같습니다.


(1) 이미지 화일을 읽어들이고

      ...

      cvLoadImage

  ...

(2) 알파블랜딩할 이미지를 만듭니다. - 이경우는 만들었지만 다른 이미지를 사용해도 됩니다.

...

cvFillPoly

...


(3) 원본 이미지와 알파블랜딩할 이미지의 크기가 틀리다면

      ROI로 서로의 크기를 맞추어 줍니다.

.....

cvSetImageROI

....

cvResetImageROI

...


(4) 적절한 비율로 블랜딩합니다.

....

cvAddWeighted

....


(5) 이후에 정리합니다.

  cvSaveImage(argv[2] , imgA );

  .....

      cvReleaseImage(&imgA);

      cvReleaseImage(&imgB);



2. 새로운 함수


2.1 cvFillPoly


여기에서 새로 나온 이미지 처리 함수는 다음과 같습니다.


cvFillPoly


2차원 폴리곤을 만들어서 그 폴리곤을 그리고 내부를 채웁니다.

폴리곤의 꼭지점 개수는 제한이 없습니다. 다만 시작하기 전에 해당 폴리곤의 꼭지점 개수를 알려주어야 합니다.



이 함수를 사용하기 위해서 다음과 같은 순서로 합니다.


(1)  폴리곤을 만듭니다. 이 프로그램에서 코드는 아래와 같습니다.

  ....

  CvPoint imgb_rectangle_pts[4] = { cvPoint( 0, 0) ,

    cvPoint(0,imgb_size.width),

    cvPoint(imgb_size.height,imgb_size.width),

    cvPoint(imgb_size.height,0)

  };

   ...

  CvPoint *PointArray[2] = { & imgb_rectangle_pts[0]  , 0 } ;

  ...


 (2) 폴리곤의 개수와 각 폴리곤의 꼭지점 개수를 정합니다.

       

  int PolyVertexNumber[2] = { 4 , 0 } ;

  int PolyNumber = 1 ;


  지금은 하나뿐이므로, 한개의 폴리곤만을 지정한다.

 

 (3) 그리고 함수를 호출합니다.


  cvFillPoly(imgB ,

    PointArray ,

    PolyVertexNumber ,

    PolyNumber,

    CV_RGB(5,5,5),8,0);



2.2 cvAddWeighted


알파블랜딩을 해주는 함수입니다.

사용은 쉽습니다.

각 이미지 별로 가중치를 곱해서 더하는 것입니다


호출은 아래와 같습니다.

  ......

  double alpha = 0.5 ;

  double beta  = 1.0 - alpha ;

  cvAddWeighted(imgA, alpha , imgB , beta , 0.0 , imgA );

  ......







3. 전체 코드


전체 코드는 아래와 같습니다.


--------------------------------------------------------------------------------------------------


#include <stdio.h>

#include <unistd.h>

#include <string.h>

#include <errno.h>


#include <opencv/cv.h>

#include <opencv/highgui.h>




int main(int argc , char * argv[] ){


  // 파라미터를 체크합니다.

  // 귀찮으니까 간단하게 개수만 체크합니다.

  if( argc < 2 )

   {

      printf("usage : alpha src dst\n");

      exit(0);

   }


  // 원본 이미지를 읽어들입니다.

  IplImage *imgA = cvLoadImage( argv[1] , 1);

  //알파 블랜딩할 이미지를 만듭니다. 사각형으로 만들기로 하겠습니다.

  //입력되는 이미지의 크기가 정해진 것이 아니므로,

  //입력 이미지의 크기를 갖고 와서 상대적으로 높이를 맞춥니다.

  //넓이는 150 픽셀 정도로 맞춥니다.

  CvSize imga_size = cvGetSize(imgA);

  CvSize imgb_size = cvSize(150,imga_size.height);

  IplImage *imgB = cvCreateImage( imgb_size  , IPL_DEPTH_8U, 3);


  // 이제 내부에 채워지는 4각형을 만듭니다.

  // 사용할 함수는 cvFillPoly 입니다.

  CvPoint imgb_rectangle_pts[4] = { cvPoint( 0, 0) ,

    cvPoint(0,imgb_size.width),

    cvPoint(imgb_size.height,imgb_size.width),

    cvPoint(imgb_size.height,0)

  };



  CvPoint *PointArray[2] = { & imgb_rectangle_pts[0]  , 0 } ;

  int PolyVertexNumber[2] = { 4 , 0 } ;

  int PolyNumber = 1 ;

  cvFillPoly(imgB ,

    PointArray ,

    PolyVertexNumber ,

    PolyNumber,

    CV_RGB(5,5,5),8,0);


  // 원본 이미지와, 채울 이미지의 크기가 틀리기 때문에 원본 이미지에서 관심 대상

  // 영역을 설정합니다.

  cvSetImageROI(imgA, cvRect(0,0,imgb_size.width,imgb_size.height));


  // 드디어 알파블랜딩을 합니다. 

  double alpha = 0.5 ;

  double beta  = 1.0 - alpha ;

  cvAddWeighted(imgA, alpha , imgB , beta , 0.0 , imgA );

 

  // 이제 관심 영역으로 설정된 것을 풉니다.

  cvResetImageROI(imgA);



  // 폰트를 정합니다.

  CvFont font1;

  double hscale = 0.5;

  double vscale = 0.5;

  double shear = 0.0;

  int thickness = 1;

  int line_type = CV_AA;


  cvInitFont(&font1,CV_FONT_HERSHEY_COMPLEX,hscale,vscale,shear,thickness,line_type);


  // 글을 집어 넣습니다.

  cvPutText(imgA,"GUNDAM",cvPoint( 0,100) ,&font1,CV_RGB(255,255,255));

  cvPutText(imgA,"Red Commet",cvPoint( 0,120) ,&font1,CV_RGB(255,255,255));


  // 화면에 출력하고

  cvNamedWindow( "ImageA-1", 1) ;

  cvShowImage( "ImageA-1", imgA );

 

  cvWaitKey(0);

  cvDestroyWindow("ImageA-1");


  // 파일은 따로 저장합니다.

  cvSaveImage(argv[2] , imgA );


  // 그리고 끝냅니다.

  cvReleaseImage(&imgA);

  cvReleaseImage(&imgB);


 

}//end of main


--------------------------------------------------------------------------------------------------


4. 처리 결과


다음 그림은 그 결과입니다.

사용자 삽입 이미지

2009/04/25 15:04 2009/04/25 15:04
GUNDAM 이 작성.

당신의 의견을 작성해 주세요.

[로그인][오픈아이디란?]

OpenCV Convert Image


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


영상 처리를 하기 위해서는 때때로 컬러 공간을 바꾸어 줘야 할 때가 많습니다.

영상에서 필요한 정보를 찾아서 추출하기 위해서는 RGB공간에서 얻을 수 없는 정보를

다른 컬러 공간에서 얻어낼 수 있기 때문입니다.

예를들어서 사진에서 휘도를 바꾸고 싶을 경우

YCbCr로 바꾼후에 Y를 변경하고 다시 이것을 RGB로 바꾸는 과정을 거치게 됩니다.

이럴 경우 컬러 공간을 변환하는 함수가 있어야 하는데

OpenCV에서는 아래 함수가 그 동작을 도와줍니다.

cvCvtColor( 입력 이미지 , 출력 이미지 , 옵션 ); 


옵션은 아주 많이 있지만 아래에 몇가지 중요한 옵션을 설명하였습니다.


  CV_RGB2GRAY  : 흑백으로 바꾸기

                            수식은 다음과 같다.

RGB[A]->Gray: Y<-0.299*R + 0.587*G + 0.114*B


  CV_RGB2YCrCb : YCrCb로 바꾸기

    Y <- 0.299*R + 0.587*G + 0.114*B

  Cr <- (R-Y)*0.713 + delta

  Cb <- (B-Y)*0.564 + delta


  CV_RGB2HLS    : ( Hue Lightness Saturation ) 으로 변환한다.

   // In case of 8-bit and 16-bit images

  // R, G and B are converted to floating-point format and scaled to fit 0..1 range

  V,,max,, <- max(R,G,B)

  V,,min,, <- min(R,G,B)

  L <- (V,,max,, + V,,min,,)/2

  S <- (V,,max,, - V,,min,,)/(V,,max,, + V,,min,,)  if L < 0.5

        (V,,max,, - V,,min,,)/(2 - (V,,max,, + V,,min,,))  if L = 0.5

           (G - B)*60/S,  if V,,max,,=R

  H <- 180+(B - R)*60/S,  if V,,max,,=G

        240+(R - G)*60/S,  if V,,max,,=B

  if H<0 then H<-H+360

  On output 0=L=1, 0=S=1, 0=H=360.

  The values are then converted to the destination data type:

      8-bit images:

           L <- L*255, S <- S*255, H <- H/2

      16-bit images (currently not supported):

          L <- L*65535, S <- S*65535, H <- H

      32-bit images:

          H, L, S are left as is


  CV_RGB2HSV : RGB 값을 HSV로 바꾼다. HSV란 Hue Saturation Value를 의미한다.


  // In case of 8-bit and 16-bit images

  // R, G and B are converted to floating-point format and scaled to fit 0..1 range

  V <- max(R,G,B)

  S <- (V-min(R,G,B))/V   if V?0, 0 otherwise

           (G - B)*60/S,  if V=R

  H <- 120+(B - R)*60/S,  if V=G

       240+(R - G)*60/S,  if V=B

  if H<0 then H<-H+360

  On output 0=V=1, 0=S=1, 0=H=360.

  The values are then converted to the destination data type:

      8-bit images:

          V <- V*255, S <- S*255, H <- H/2 (to fit to 0..255)

      16-bit images (currently not supported):

          V <- V*65535, S <- S*65535, H <- H

      32-bit images:

          H, S, V are left as is

  CV_RGB2Lab : CIE Lab Color로 변환한다.

  // In case of 8-bit and 16-bit images

  // R, G and B are converted to floating-point format and scaled to fit 0..1 range

  // convert R,G,B to CIE XYZ

  |X|    |0.412453  0.357580  0.180423| |R|

  |Y| <- |0.212671  0.715160  0.072169|*|G|

  |Z|    |0.019334  0.119193  0.950227| |B|

  X <- X/Xn, where Xn = 0.950456

  Z <- Z/Zn, where Zn = 1.088754

  L <- 116*Y^1/3-16      for Y>0.008856

  L <- 903.3*Y           for Y<=0.008856

  a <- 500*(f(X)-f(Y)) + delta

  b <- 200*(f(Y)-f(Z)) + delta

  where f(t)=t^1/3^              for t>0.008856

        f(t)=7.787*t+16/116   for t<=0.008856

  where delta = 128 for 8-bit images,

                0 for floating-point images

  On output 0=L=100, -127=a=127, -127=b=127

  The values are then converted to the destination data type:

      8-bit images:

          L <- L*255/100, a <- a + 128, b <- b + 128

       16-bit images are currently not supported

       32-bit images:

          L, a, b are left as is


  •   CV_RGB2Luv  CIE Luv Color로 변환한다.

  // In case of 8-bit and 16-bit images

  // R, G and B are converted to floating-point format and scaled to fit 0..1 range

  // convert R,G,B to CIE XYZ

  |X|    |0.412453  0.357580  0.180423| |R|

  |Y| <- |0.212671  0.715160  0.072169|*|G|

  |Z|    |0.019334  0.119193  0.950227| |B|

  L <- 116*Y^1/3^      for Y>0.008856

  L <- 903.3*Y      for Y<=0.008856

  u' <- 4*X/(X + 15*Y + 3*Z)

  v' <- 9*Y/(X + 15*Y + 3*Z)

  u <- 13*L*(u' - u,,n,,), where u,,n,,=0.19793943

  v <- 13*L*(v' - v,,n,,), where v,,n,,=0.46831096

  On output 0=L=100, -134=u=220, -140=v=122

  The values are then converted to the destination data type:

      8-bit images:

          L <- L*255/100, u <- (u + 134)*255/354, v <- (v + 140)*255/256

      16-bit images are currently not supported

      32-bit images:

          L, u, v are left as is


코드는 아래와 같습니다.


#include <stdio.h>

#include <unistd.h>

#include <string.h>

#include <errno.h>


#include <opencv/cv.h>

#include <opencv/highgui.h>


int main(int argc , char *argv[]){


  IplImage *imgB ;





  if (argc < 3 )

        {

                printf("usage : colorcvt.elf srcimage dstimage option \n");

                printf("      srcimage : source image file name\n");

                printf("      dstimage : destination image file name\n");

                printf("      option   : 0 : CV_RGB2GRAY \n");

                printf("                 1 : CV_RGB2YCrCb \n");

                printf("                 2 : CV_RGB2HLS \n");

                printf("                 3 : CV_RGB2HSV \n");

                printf("                 4 : CV_RGB2Lab \n");

                printf("                 5 : CV_RGB2Luv \n");

                exit(0);

        }


  // 이미지 읽기

  IplImage *imgA = cvLoadImage( argv[1] , 1);


  // 대상 이미지 확정

  switch( *argv[3] )

  {

   case '0' :

              imgB = cvCreateImage( cvGetSize( imgA), IPL_DEPTH_8U, 1);

              cvCvtColor(imgA , imgB , CV_RGB2GRAY );

              break;

   case '1' :

              imgB = cvCreateImage( cvGetSize( imgA), IPL_DEPTH_8U, 3);

              cvCvtColor(imgA , imgB , CV_RGB2YCrCb  );

              break;

   case '2' :

              imgB = cvCreateImage( cvGetSize( imgA), IPL_DEPTH_8U, 3);

              cvCvtColor(imgA , imgB , CV_RGB2HLS  );

              break;

   case '3' :

              imgB = cvCreateImage( cvGetSize( imgA), IPL_DEPTH_8U, 3);

              cvCvtColor(imgA , imgB , CV_RGB2HSV  );

              break;

   case '4' :

              imgB = cvCreateImage( cvGetSize( imgA), IPL_DEPTH_8U, 3);

              cvCvtColor(imgA , imgB , CV_RGB2Lab  );

              break;

   case '5' :

              imgB = cvCreateImage( cvGetSize( imgA), IPL_DEPTH_8U, 3);

              cvCvtColor(imgA , imgB , CV_RGB2Luv  );

              break;


  }



  cvNamedWindow("Converted Image",0);

  cvShowImage("Converted Image",(CvArr*)imgB);

  cvWaitKey(0);

  cvDestroyWindow("Converted Image");


  cvSaveImage( argv[2] , imgB);

  cvReleaseImage( &imgA );

  cvReleaseImage( &imgB );

  return 0;

}


아래는 각각의 옵션으로 했을때의 그림입니다.

컬러 스페이스가 틀린것을 강제로 출력한 형태이므로 다른 컬러 공간의 그림은 정확하게 표현되지는 않습니다. 그냥 이렇게 되었다는 것만 보면 될 듯 합니다.


원본 이미지


사용자 삽입 이미지


흑백으로 변환 이미지

사용자 삽입 이미지



사용자 삽입 이미지

사용자 삽입 이미지


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










2009/04/11 17:41 2009/04/11 17:41
GUNDAM 이 작성.

당신의 의견을 작성해 주세요.

[로그인][오픈아이디란?]

OpenCV - Extract

2009/03/12 09:17 / Computer Vision

() 글을 읽기 전에 

 글은 저와 같은 OpenCV초보자를 위해서 정리하는 것입니다.

전문가시라면 굳이 읽을 필요가 없습니다.

공부하면서 정리하는 글이라서 서툰 부분이 많이많이 보입니다.


이미지에서 특정 부분 추출하기


cvCopy(

const CvArr * src,

CvArr *          dst,

const CvArr * mask = NULL

);


이것은 원본과 복사 대상이 같은 크기와 , 같은 타입의 이미지라는 전제하에서 이루어 집니다.



이미지의 크기가 틀리다면, 다음 함수를 써서 원본의 이미지중에 일부를 추출할 수 있습니다.


void cvSetImageROI( IplImage* image, CvRect rect );


CvRect는 사각형 영역을 설정하는 것입니다.


cvRect는 다음과 같이 정의되어 있습니다.


 typedef struct CvRect

    {

        int x; /* x-coordinate of the left-most rectangle corner[s] */

        int y; /* y-coordinate of the top-most or bottom-most

                  rectangle corner[s] */

        int width; /* width of the rectangle */

        int height; /* height of the rectangle */

    }

    CvRect;


그럼 이제 이미지를 복사하여 만들어 보는 것을 해보겠습니다.


소스는 간단해서 그닥 어려운 부분이 없습니다.

원본에서 ROI를 지정한 뒤에 복사하면 잘 됩니다.


--------------------------------------------------------------------------------


#include <stdio.h>

#include <unistd.h>

#include <string.h>

#include <errno.h>


#include <opencv/cv.h>

#include <opencv/highgui.h>


#define IMG_WIDTH 400

#define IMG_HEIGHT 400


int main(int argc , char *argv[]){




  // 이미지 읽기 

  IplImage *imgA = cvLoadImage( "4390m.jpg", 1);

  // 대상 이미지 확정

  IplImage *imgB = cvCreateImage( cvSize(IMG_WIDTH ,IMG_HEIGHT ),

  IPL_DEPTH_8U, 3);


  // ROI 설정한다.

  cvSetImageROI( imgA , cvRect(200,200,IMG_WIDTH,IMG_HEIGHT ));

  // 이미지를 복사한다.

  cvCopy(imgA,imgB,0);


  ////////////////////////////////////////////////////////////


  cvSaveImage( "image_result.jpg", imgB);

  cvNamedWindow("Extract Image",0);

  cvShowImage("Extract Image",(CvArr*)imgB);

  cvWaitKey(0);

  cvDestroyWindow("Extract Image");


  cvReleaseImage( &imgA );

  cvReleaseImage( &imgB );


  return 0;

}


아래 그림은 결과 이미지입니다


사용자 삽입 이미지

2009/03/12 09:17 2009/03/12 09:17
GUNDAM 이 작성.
TAGS ,

당신의 의견을 작성해 주세요.

  1. Comment RSS : http://newtypeunion.com/rss/comment/29
  2. babyworm 2009/03/17 08:53  편집/삭제  댓글 작성  댓글 주소

    ROI를 rate on investment로 보다니.. 병이죠?
    여담인데, 이 라이브러리에서 perspective transform도 되죠?

  3. GUNDAM 2009/03/17 17:45  편집/삭제  댓글 작성  댓글 주소

    예 잘 됩니당.. Learn OpenCV에 보심 잘 설명되어 있어요
    나중에, 진행하면서 정리할께요.
    초보자 수준이라 부끄러버서

[로그인][오픈아이디란?]

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


OpenCV로 하는 Rotate를 해보도록 하겠습니다.

1) 공간 확보와 정리
먼저 생성될 공간을 확보해야 하는데요
IplImage *image = cvCreateImage(cvSize(width, height), depth, nChannels);
size는 말 그대로 창의 크기를 말합니다.
depth는 영상을 표현하는 정보의 내용을 의미합니다.
 • IPL_DEPTH_1U : 1비트 양의 정수영상
 • IPL_DEPTH_8U : 8비트 양의 정수영상
 • IPL_DEPTH_16U : 16비트 양의 정수영상
 • IPL_DEPTH_32U : 32비트 양의 정수영상

이 됩니다.

nChannels는 색의 종류를 의미하는 것으로 1이면 흑백 3이면 컬러가 됩니다.

사용을 다 하면 정리해줘야 합니다.
물론 프로그램을 빠져나갈때 정리를 하지 않아도 O/S가 뒤져서 찾아가는 경우도 있지만
원칙은 사용한 프로그램이 다시 그것을 O/S에 돌려줘야 한다는 것입니다.

cvReleaseImage(&image);

를 하여서 정리합니다.

(2) cvPoint2D32f
 2차원 좌표 상에서 32비트 플로팅 포인트로 x와 y좌표를 설정합니다.


(3) WrapAffine
affine transform을 수행합니다.
인자는 다음과 같습니다.

void cvWarpAffine(
 const CvArr* src,  당연히 원본 이미지
 CvArr* dst,    이것도 당연히 결과를 받아내는 이미지
 const CvMat* map_matrix, affine transform을 하는 매트릭스
    int flags=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS, 이것은 인터폴레이션을 선택
    CvScalar fillval=cvScalarAll(0)     채워지는 값
);

결과 그림은 아래와 같습니다.

사용자 삽입 이미지

끝으로 아래 사이트에 가시면 몇가지 다른 예제를 볼 수 있습니다.
공부에 참고하시기 바랍니다.
http://dasl.mem.drexel.edu/~noahKuntz/openCVTut5.html


아래 코드는 완성된 버전입니다.



 

 #include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

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



int main(int argc , char * argv[] ){

    // 이미지 읽기
  IplImage *imgA = cvLoadImage( "4390m.jpg", 1);
  // 대상 이미지 확정
  IplImage *imgB = cvCreateImage( cvGetSize( imgA), IPL_DEPTH_8U, 3);

  const double angle  = 80.0; // 회전 각도를 설정
  const double scale  = 0.8;  // 확대 크기를 설정
 
  // 중심 축은 가운데로...
  CvPoint2D32f center = cvPoint2D32f( imgA->width/2.0, imgA->height/2.0);//회전중심설정
 
  // 그에 따른 매트릭스 만들기
  CvMat *rot_mat = cvCreateMat( 2, 3, CV_32FC1);

  //매트릭스 계산
  cv2DRotationMatrix(
       center, // Source Image의 센터를 정한다.
       angle,  // 이것은 각도 + 값은 시계 반대 반대 방향을 의미한다.
       scale,  // 이미지 크기...
       rot_mat) // 결과를 저장하는 매트릭스 이다.
    ; // 메트릭스 변환


  // affine transform
  cvWarpAffine( imgA,
  imgB,
  rot_mat,
  CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS,
  cvScalarAll(0)); // 선형보간
  cvSaveImage( "image_result8.bmp", imgB);

  cvNamedWindow("Rotated Image",0);
  cvShowImage("Rotated Image",(CvArr*)imgB);
  cvWaitKey(0);
  cvDestroyWindow("Roated Image");

  cvReleaseImage( &imgA );
  cvReleaseImage( &imgB );
  cvReleaseMat( &rot_mat);
  return 0;
}

2009/03/10 19:14 2009/03/10 19:14
GUNDAM 이 작성.

당신의 의견을 작성해 주세요.

[로그인][오픈아이디란?]

유클리드 제곱 거리


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


http://www.cherrynet.co.kr/bbs_view.php ··· mnid%3D1



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

다차원이라고 해도 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 )


2009/03/02 11:05 2009/03/02 11:05
GUNDAM 이 작성.

당신의 의견을 작성해 주세요.

  1. Comment RSS : http://newtypeunion.com/rss/comment/26
  2. 조무열 2009/03/31 00:15  편집/삭제  댓글 작성  댓글 주소

    sift 관련글 잘 보고 있습니다^ ^ 새로운 글 올라오기만 손꼽고 있을께요~~ㅋ

    • GUNDAM 2009/03/31 09:05  편집/삭제  댓글 주소

      헉.. 아직 정리가 다 안끝났습니다.
      정리 끝나면 올리도록 하겠습니다.
      별반 않좋은 글에 관심을 가져 주셔서 감사합니다.

[로그인][오픈아이디란?]

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를 다시실행한다.

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


사용자 삽입 이미지


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



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

잘 동작하고 있습니다.

사용자 삽입 이미지





2009/02/16 14:59 2009/02/16 14:59
GUNDAM 이 작성.

당신의 의견을 작성해 주세요.

[로그인][오픈아이디란?]

MAC에서 OpenCV를 컴파일 하기


맥에서 OpenCV를 컴파일 


http://opencv.willowgarage.com/wiki/mac ··· ncv_port


이 페이지를 참조로 따라가면서 컴파일한다.




1. 시작은 OpenCV의 위키 페이지에서 시작한다.

   

    http://opencv.willowgarage.com/wiki/


   여기에서 올려져 있는 글을 찬찬이 읽어보면 많은 도움이 된다.


2. Learning OpenCV: Computer Vision with the OpenCV Library

  • by Gary Bradski and Adrian Kaehler, O'Reilly Press, October, 2008.
  •    
  •    책으로 잘 나온 것은 오라일리의 책입니다. 사실상 매뉴얼이라고 생각되고요,  OpenCV사이트에서도
  •    매뉴얼 대신으로 추천해주는 책입니다.

3.   다운로드는 SVN으로 한다. 


     http://sourceforge.net/svn/?group_id=22870

 

     페이지에 가면 다운 받을 수 있는 커맨드가 있다. 이것을 이용하여 다운 받는다.


    svn co https://opencvlibrary.svn.sourceforge.net/svnroot/opencvlibrary opencvlibrary


  이 커맨드는 전체를 모두 다운 받는 것이다. 전체라 함은 브랜치라던가 프리베타 버전과 같은 불필요한 부분까지 모두 다운 받은 것을 말합니다.

   처음에는 폴더 구조 가은 것을 잘 모르므로, 그냥 한번 정도는 다운 받아 폴더 구조를 보는 것도 도움이 된다.


   위의 커맨드를 넣으면 OpenCV를 다운 받을 수 있다.


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


   http://sourceforge.net/project/showfile ··· %3D22870


   이 글을 쓰는 현재 시점에서 최신 버전은 1.1pre 버전이다.


   여기서는 후자인 tar파일을 직접 다운받아서 진행한다.


   


4. compile

    일단 다른 폴더에서 빌드를 한다.

    

     mkdir build

     cd build

     ../opencv-1.1.0/configure CPPFLAGS="-I/opt/local/include" LDFLAGS="-L/opt/local/lib"



      make


     한참을 컴파일 하고 끝난다.


   sudo make install


      끝나면 위와 같이 인스톨을 한다.

     

5. 테스트 해보기

     

    인스톨이 끝나면 다음과 같이 확인을 해 볼 수 있다.


    샘플용 소스 코드를 다운 받는다. 

    일일이 코딩하기 귀찮으므로 그냥 간단히 다운 받는다. 

    인터넷에서 OpenCV sample을 서치하면 아래 사이트를 발견할 수 있다.


    http://www.netaro.info/techinfo/OpenCV/src/index.html


    여기에 가면 적당한 예제가 있다. 다운 받은 폴더에 가면 ZIP파일로 되어 있고 이것을 압축을 푼다.


    컴파일을 하면 다음과 같은 오류가 발생한다.


GUNDAMMACPRO:edgedetect kevinIm$ make

gcc -c -g -Wall sampleEdge.c

gcc -o simpleedge sampleEdge.o -lhighgui -lopencv

ld: library not found for -lopencv


   Makefile 을 보면 몇가지 잘못된 옵션이 있다. 버전차이라고 생각된다.. 일단 Makefile을 아래와 같이 수정한다.


   gcc -o simpleedge sampleEdge.o -L/usr/local/lib -lhighgui -lcv -lcvaux -lcxcore


   == WAS == 

  LDFLAGS = -lhighgui -lopencv -L/usr/local/lib


   == IS ==

  LDFLAGS = -lhighgui -lcv -lcvaux -lcxcore -L/usr/local/lib


   그리고 컴파일하면 다음과 같이 나온다.


GUNDAMMACPRO:edgedetect kevinIm$ make

gcc -c -g -Wall InteractiveEdgeDetect.c

InteractiveEdgeDetect.c:18: warning: ‘ltval’ defined but not used

InteractiveEdgeDetect.c:19: warning: ‘htval’ defined but not used

gcc -o intedge InteractiveEdgeDetect.o -lhighgui -lcv -lcvaux -lcxcore -L/usr/local/lib


   실행은 간단하게 해본다.

 

아래 그림은 실행한 결과이다. 

윤곽선을 추출하는 예제이다.


사용자 삽입 이미지


사용자 삽입 이미지

2009/01/06 08:53 2009/01/06 08:53
GUNDAM 이 작성.
TAGS , ,

당신의 의견을 작성해 주세요.

[로그인][오픈아이디란?]
이번에 발견한 것은 OpenCV의 개발 환경을 XCODE에 통합하는 것입니다.  요기를참조

일본 사이트이고요.. .일본은 그나마 맥 환경이 우리보다는 좋아서 이런 저런 내용이 많이 있습니다.
일본어를 모르셔도.. .그림만 따라가면 해볼 수 있습니다.

요새는 일본 애니와 망가의 영향으로 일본어는 제 2 외국어가 아니기 땜에, 
큰 부담은 없으리라 생각합니다. 


2009/01/03 23:36 2009/01/03 23:36
GUNDAM 이 작성.
TAGS , ,

당신의 의견을 작성해 주세요.

[로그인][오픈아이디란?]