본문 바로가기
[Public] 신호처리/영상 객체검출

[SIFT] 컨볼루션의 성질

by 차출발 2010. 3. 17.
반응형
SIFT 표준 소스를 보면 다음과 같은 구문이 나온다.


sig[0] = sigma;
k = pow( 2.0, 1.0 / intvls );
for( i = 1; i < intvls + 3; i++ )
{
sig_prev = pow( k, i - 1 ) * sigma;
sig_total = sig_prev * k;
sig[i] = sqrt( sig_total * sig_total - sig_prev * sig_prev );
}

이는 Gaussian을 만드는데 있어서 왜 이렇게 하는지 궁금증이 생길 것이다.

이는 우선 컨볼루션에 대한 기본적인 사항을 알아야한다. 
 
scale 이 s1 인 가우시안으로 컨볼루션된 이미지를 다시
scale 이 s2 인 가우시안으로 컨볼루션하면
scale 이 sqrt(s1 * s1 + s2 * s2) 으로 컨볼루션 하는 이미지와 동일한 결과를 얻는다.

이는 속도를 중시 하는 SIFT 연산에서는 

원본 이미지에서 스케일을 바꾸면서 컨볼루션을 바꾸는 것 보다
이미 컨볼루션 된 이미지를 이용하여 다음 컨볼루션된 이미지를 만드는게
SIFT 구조상 훨신 경제적이기 때문에 위의 소스를 추가 한것이다.

정말로 컨볼루션의 성질이 성립하는지 간단한 실험을 해보았다.

1.0 가중치의 가우시안 컨볼루션을 연속으로 2회 한것과
sqrt(2.0) 의 가중치를 컨볼루션 한 결과의 차이 연산이다.(검은색 보다 보기 좋게 하기 위해 반전하였다.)

실험 결과 
1은 원본사진
2은 1에다 1.0 컨볼루션
3은 2에다 1.0 컨볼루션
4는 1에다 sqrt(1.0*1.0 + 1.0*1.0) 컨볼루션
5는 왼쪽은 2 와 4 의 차이연산
    오른쪽은 3 과 4의 차이연산


5의 왼쪽은 비교를 위하여 2와 4를 비교한것이다. (역시나 코 부분과 입, 눈부분에는 DOG 영상을 찾을 수 있다.)
5의 오른쪽은 우리가 알아보려고 하는 것으로 3과 4를 비교한 것이다.

거의 컨볼루션의 성질이 옳음을 확인할 수 있었다.

내부 픽셀은 조사하지 않고 눈안으로만 조사하였다. 

더 궁금하다면 직접 실험을 더 해보아라 . 



#include "cv.h"
#include "highgui.h"
int main(int argc, char **argv)
{
cvNamedWindow("1");
cvNamedWindow("2");
cvNamedWindow("3");
cvNamedWindow("4");
cvNamedWindow("5");

IplImage* img = cvLoadImage(argv[1]);
IplImage* img1 = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);

if( img->nChannels == 1 )
img1 = (IplImage *)cvClone( img );
else
cvCvtColor( img, img1, CV_BGR2GRAY );

IplImage* img2 = cvCreateImage(cvGetSize(img1), IPL_DEPTH_8U, 1);
IplImage* img3 = cvCreateImage(cvGetSize(img1), IPL_DEPTH_8U, 1);
IplImage* img4 = cvCreateImage(cvGetSize(img1), IPL_DEPTH_8U, 1);
IplImage* img5 = cvCreateImage(cvGetSize(img1), IPL_DEPTH_8U, 1);

cvSmooth(img1, img2, CV_GAUSSIAN, 0, 0, 1.0, 1.0);
cvSmooth(img2, img3, CV_GAUSSIAN, 0, 0, 1.0, 1.0);
cvSmooth(img1, img4, CV_GAUSSIAN, 0, 0, sqrt(2.0), sqrt(2.0));


cvSub(img3, img4, img5,  NULL);
cvNot(img5, img5);
cvShowImage("1", img1);
cvShowImage("2", img2);
cvShowImage("3", img3);
cvShowImage("4", img4);
cvShowImage("5", img5);

cvWaitKey(0);
cvReleaseImage(&img);
cvReleaseImage(&img1);
cvReleaseImage(&img2);
cvReleaseImage(&img3);
cvReleaseImage(&img4);
cvReleaseImage(&img5);

cvDestroyWindow("1");
cvDestroyWindow("2");
cvDestroyWindow("3");
cvDestroyWindow("4");
cvDestroyWindow("5");
return 0;
}