정보공간_1

[6기 강북 이보희] 디지털 영상처리 - Filter 편 #2 본문

IT 놀이터/Elite Member Tech & Talk

[6기 강북 이보희] 디지털 영상처리 - Filter 편 #2

알 수 없는 사용자 2014. 10. 10. 03:09

 안녕하세요. 강북멤버십 22-1기 이보희입니다.

 이번엔 저번 글에서 설명했던 Linear Filter에 이어서 다른 Filter들을 알아보겠습니다. Linear  Filter가 잡음을 제거하는 전처리 용도로 많이 쓰이는 필터라면, 이 필터들은 이미지에서 외곽선이나 코너와 같은 특징을 추출하는 방법입니다.


2. Edge Detection

 어떤 이미지에서 물체와 배경을 분리해 내려고 할 때, 가장 간단히 생각할 수 있는 방법은 외곽선을 추출하는 것입니다. 그렇다면 이미지에서 외곽선을 추출하기 위해서는 어떻게 해야할까요? 

 외곽선이란, 영역의 경계지점으로 픽셀 밝기가 급격하게 변하는 부분입니다. 이것을 수학적으로 정의해보겠습니다.

...①      ...②      ...③


 ① 그림은 원본 이미지를 나타냅니다. 이 이미지를 가로축으로 분석 하기 위래 빨간색 수평선을 선택하고 이 선의 데이터를 그래프로 그린 것이 ② 그림입니다. ② 그림을 보면 외곽선에 해당하는 부분에서 기울기가 커지는 것을 볼 수 있고 이 그래프를 한번 더 미분하면 ③과 같은 그래프를 얻을 수 있습니다. 이때 극값에 해당하는 부분이(빨간색 동그라미 부분) 외곽선인 것을 알 수 있습니다. 

 이렇게 외곽선의 존재를 판단하기 위해서는 이미지에 미분을 적용하면 되고, 2차원 함수 f(x,y)의 미분을 수식으로 나타내면 다음과 같습니다.

 이미지 데이터는 이산데이터기 때문에 위 수식을 그대로 적용할 수 없으므로 finite difference로 근사해서 다시 표현하면 다음과 같은 수식을 얻을 수 있습니다.

 이런 수식을 통해 나온 엣지 검출 필터로는 Prewitt, Sobel, Roberts filter가 있습니다.

  Linear filter와는 다르게 위 필터들은 box filter를 이루는 숫자들의 합이 1이 아니라 0인 것을 볼 수 있습니다. 그 이유는 가중평균을 구하는 Linear filter와는 다르게 주변 픽셀값들의 차이를 구하기 때문인데요, 따라서 엣지의 크기는 다음 수식에 의해서 결정됩니다.

 Prewitt filter는 수직과 수평 방향의 미분값을 찾기 위한 filter이고, Sobel은 여기서 한 단계 더 나아가 filter의 중심에 가까운 픽셀에 조금 더 큰 값을 주는 것으로 더 정확한 경계선을 검출할 수 있게 한 것입니다. Roberts는 대각선 방향의 엣지를 찾으며, Prewitt, Sobel filter와 함께 사용할 수 있습니다.


 OpenCV에서 Sobel, Roberts filter를 사용하는 방법은 다음과 같습니다.


1) Sobel filter

  Sobel filter는 openCV에서 제공하며 함수의 원형은 다음과 같습니다.

void cvSobel(const CvArr* src, CvArr* dst, int xorder, int yorder, int apertureSize=3);

Parameters:

src – Source image of type CvArr*

dst – Destination image

xorder – Order of the derivative x

yorder – Order of the derivative y

apertureSize – Size of the extended Sobel kernel, must be 1, 3, 5 or 7



 2) Roberts filter
 Roberts filter는 아래의 함수를 사용할 수 있습니다.

IplImage* roberts(IplImage *src)
{
IplImage *dst = cvCloneImage(src);

int height = dst->height;
int width = dst->width;

uchar* dstPtr = (uchar*)(dst->imageData); // 결과 이미지 데이터의 첫번째 주소 저장
int x,y,idxX, idxY;
int temp[4] = {0, };

for(y=0; y<height-1; y++)
{
for(x=0; x<width-1; x++)
{
for(idxX=0; idxX<2; idxX++)
{
for(idxY=0; idxY<2; idxY++)
{
temp[idxY*2+idxX] = *(dstPtr+((y+idxY)*src->widthStep)+x+idxX); // 필터 처리를 위한 데이터 임시 저장.
}
}

int tempX = abs( temp[1] - temp[2] ); // x축방향의 roberts filter
int tempY = abs( temp[0] - temp[3] ); // y축방향의 roberts filter
int tempR;
tempR= (int)sqrt(float(tempX*tempX)+float(tempY*tempY));
*(dstPtr + (y*dst->widthStep) + x) = tempR;
}
}

return dst;
}


두 알고리즘을 사용한 메인 코드와 결과는 다음과 같습니다.

void main()
{
IplImage* img;
img = cvLoadImage("camera.bmp", -1); // 이미지 읽기
int width = img->width;
int height = img->height;
IplImage* imgSobelX = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
IplImage* imgSobelY = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
IplImage* imgSobel = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
IplImage* imgRoberts = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);

if( img != 0 )
{
cvNamedWindow("camera", 1);
cvShowImage("camera", img); // 원본 이미지 출력
cvSobel(img, imgSobelX, 1, 0, 3); // Sobel filter를 X축에 대해서 연산
cvNamedWindow("Sobel Filter - X", 1);
cvShowImage("Sobel Filter - X", imgSobelX);
cvSobel(img, imgSobelY, 0, 1, 3); // Sobel filter를 Y축에 대해서 연산
cvNamedWindow("Sobel Filter - Y", 1);
cvShowImage("Sobel Filter - Y", imgSobelY);

cvAddWeighted(imgSobelX, 0.5, imgSobelY, 0.5, 0, imgSobel); // X, Y축 연산을 더함
cvNamedWindow("Sobel Filter", 1);
cvShowImage("Sobel Filter", imgSobel);

imgRoberts = roberts(img); // roberts filter 적용
cvNamedWindow("Roberts Filter", 1);
cvShowImage("Roberts Filter", imgRoberts);

cvWaitKey(0); // 키보드 입력을 기다립니다. 
cvReleaseImage(&img); // 이미지에 할당된 리소스 해제
}
}

 Sobel filter를 사용할 때, X축으로 연산한 경우 X축방향의 외곽선이 Y축으로 연산을 한 경우 Y축방향의 외곽선만 추출된것을 볼 수 있습니다. 이 두 연산을 더하게 되면 X,Y 두 방향으로의 외곽선을 추출하게 됩니다.

 Roberts filter는 대각선방향의 외곽선을 추출한 것을 볼 수 있습니다.


 위 알고리즘들은 외곽선이 한 선으로 이어지지 않고 두껍게 나오게 되는데요, 이는 Canny edge detection을 사용해 해결할 수 있습니다.
 구현한 외곽선 추출 알고리즘의 성능 확인은 아래 사이트에서 가능합니다. 사람이 직접 만든 결과와 알고리즘을 통해 얻은 결과를 비교 한 후 성능을 파악하는 것으로, 알고리즘의 성능을 객관적으로 확인해 성능 지표를 얻을 수 있습니다.


3. Corner Detection

 영상처리 및 인식분야에서 코너 정보는 모양이나 추적 등의 분야에 있어서 중요한 기준점이 됩니다. 그 이유는 코너 정보가 영상에서 특징점 이라고 하기에 충분한 성질을 갖고 있기 때문인데요, 좋은 특징점의 조건 중 몇가지는 다음과 같습니다.


 - 물체의 형태나 크기, 위치가 변해도 쉽게 식별이 가능함.

 - 카메라의 시점, 조명이 변해도 영상에서 해당 지점을 쉽게 찾아낼 수 있어야 함.


 이를 만족하는 좋은 특징점인 '코너'에 대한 정의와 기본적인 아이디어를 알아보겠습니다.


그림 출처: Matching with Invariant Features, Lecture Notes 2004


 위 그림에서 네모난 박스는 filter box를 의미하고 있습니다. 이 filter box를 계속해서 움직일 때 어떠한 방향으로도 변화가 없을 경우 이를 'flat'이라고 하고, 한쪽 방향으로의 intensity 변화가 있을때는 'edge'라고 합니다. 또, 모든 방향으로 변화가 있을 경우는 'cornner'라고 볼 수 있는데요, 이렇게 모든 방향으로의 intensity 변화가 있는 곳을 corner라고 합니다. 다르게 본다면 edge와 edge가 만나는 지점이라고도 볼 수 있습니다.

 코너 검출법 중 가장 대표적인 알고리즘은 1988년도에 발표된 Harris Corner Detector입니다. 이에 대한 수식적인 설명과 OpenCV에서 사용하는 방법은 OpenCV docs에 자세하게 나와있기 때문에 하단에 url를 첨부하겠습니다.


http://docs.opencv.org/doc/tutorials/features2d/trackingmotion/harris_detector/harris_detector.html


4. SIFT

그림 출처: Matching with Invariant Features, Lecture Notes 2004


 위에서 언급한 Harris Corner Detector 등 코너 검출법들은 크기와 기울기에 많은 영향을 받습니다. 위 그림처럼 크기가 작을때는 코너라고 인식을 하지만 확대할 경우 엣지가 되는것을 볼 수 있습니다. 이 외에도 특징점 검출 알고리즘들에는 다음과 같은 점들에 대해 문제가 존재합니다.


 ① 강건성(Robustness) : 조명, 크기, 회전, 원근 변화의 불변성

 ② 국부성(Locality) : 잡음과 변화에 강건함

 ③ 독특성(Distinctiveness) : 객체의 커다란 데이터 베이스와 쉽게 매칭

 ④ 다량성(Quantity) : 작은 객체에서도 많은 특징점 검출

 ⑤ 능률성(Efficiency) : 계산적으로 비용이 적고 실시간에 적합함


 이러한 해결해 나온 혁명적인 알고리즘이 SIFT알고리즘 입니다. SIFT는 Scale-invariant feature transform 의 약자로 이름 그대로 크기에 불변한 특징점을 찾는 알고리즘입니다. SIFT 알고리즘에 대한 이론 설명은 매우 길어지기 때문에 생략하도록 하겠습니다.

 SIFT 알고리즘이 발표된 이후에도 계속해서 단점을 보완한 알고리즘이 등장하고 있으며, 속도측면을 향상시킨 SURF(Speeded Up Robust Feature)가 대표적이라고 할 수 있습니다. SURF 알고리즘은 OpenCV에서 지원하고 있습니다. 


 감사합니다.