2015년 10월 19일 월요일

Computer Vision] Harris Corner Detector

 영상처리에서 Corner를 찾는 일은 매우 중요하다. 사진이 변형 되어졌을 때 변하지 않는 corner를 찾는 것이 사진을 비교하거나 처리함에 있어 간단하고 편리하기 때문이다. Edge같은 경우는 사진이 회전하였을때 어떤 Edge이 같은지를 판단하기가 힘든데 corner같은 경우는 쉽다.

 해리스코너의 원리는 사진에서 어느 한 지점의 윈도우에서 세로와 가로 대각선으로 움직였을 때의 변화량 값을 측정하여 그곳이 코너인지 아닌지를 판단하는 것이다.  만약 픽셀의 위치가 Edge였을 경우를 생각해보자 아래의 그림의 경우 y축으로 위아래로 한픽셀씩 움직이면 변화량의 차이는 거의 없을 것이다. 하지만 x축으로 좌우로 움직이면 변화량은 있을 것이다. 윈도우를 상하 좌우 대각으로 움직였을 때 한쪽 방향이 변화량의 거의 없다면 그곳은 Edge로 판단한다. flat 즉, 평평한 곳일 경우는 어느 방향으로 해도 변화량의 차이가 없을 것이다. 마지막으로 corner를 생각해보면 상하 좌우 대각어느 방향으로 움직여도 변화량이 강하게 보이기 때문에 그곳을 corner로 판단할 수 있다.
 자세한 수학적인 이론과 방법은 생략하기로 하고 실제로 matlab에서 Harris Corner를 찾는 방법을 설명하겠다.(모르는 것을 설명하면 더 큰 혼란을 줄 수 있을것 같다.) 지금 설명하는 방법은 완벽한 정답이 아니니 경계하고 전체적인 틀로써 봐주면 좋을 것 같다.
 먼저 제일 먼저 해야 할 것은 x축 gradient와 y축 gradient이다. Canny Edge에서 했던 것과 동일하게 각각 5*1 행렬과 1*5행렬을 만들어 이미지 전체를 convolution하여 얻은 값이다. 이렇게 하면 각각 sample image와 같은 크기의 x축 gradient 행렬과 y축 gradient행렬이 만들어 질 것이다. 각 gradient값은 x축과 y축으로 이동하였을 때의 차이 값을 나타내는데 +일수도 있고 -일 수도 있다.  x축은 x축끼리 y축은 y축 끼리 제곱한 것을 각각 Ix2와 Iy2로 표현하겠다. 그리고 x축과 y축 을 서로 곱한것은 Ixy로 한다. (여기서 x축과 y축은 각 gradient를 말하는 것이다) Ix2과 Iy2그리고 Ixy에 가우시안 필터를 적용한 것을 다시 Sx2와 Sy2그리고 Sxy로 하겠다. corner를 찾는 것에 있어서 이 Sx2, Sy2 그리고 Sxy를 구하는 것이 중요하다. 각 행렬이 의미하는 것은  Sx2와 Sy2는 말그대로 각 x축과 y축에 대한 gradient 값이라면 Sxy는 대각성분으로 볼 수 있다. 이 성분을 가지고 corner를 찾는다. 아래의 그림을 보면서 설명을 이어 나가겠다.
그림을 보면서 설명을 이어나가도록 하겠다. 먼저 식에 대한 설명을 하자면 H(x,y)란 2x2행렬이 보일 것이다. corner를 구하는 것에 있어서 determine이란 개념을 사용하는데 determine이란 간단하게 설명하자면 A = {a b; c d}라는 2x2의 행렬이 있을 때 ad-bc이다.
(역행렬구하는 공식과 사용하는데 자세한 설명은 찾아보면 쉽게 찾아 낼 수 있을 것이다.)
k는 경험적으로 0.04-0.06을 택하고 있다. 그리고 Trace(H)란 대각의 합으로 위의 A행렬에서 a+d를 말하는 것이다. 이 식에서 중요한 최종 목표는 각 행열에 해당하는 R값을 구하는 것이다.  우리는 원하는 각 픽셀의 Sx2, Sy2, Sxy값을 모두 가지고 있다. 잊 대입하여 그 픽셀에 해당하는 R값을 구할 수 있을 것이다.  그렇게 구한 R행렬에서 주변 값들중에 최대값인 것만을 남기고 그 값을 기준으로 몇 %까지의 수를 화면에 표시할 것인지를 정하여야 한다. 이렇게 정한 기준에 따라 코너의 개수가 달라질 수 있다.

 이제 Sx2와 Sy2 그리고 Sxy에 대한 이야기를 좀더 해보겠다. 각 x와 y의 gradient라 하였는데 머리속으로 상상하면서 따라와보자. gradient의 값이 있을때는 언제일까. gradient의 값이 없을 때는 언제일까. 가로로된 직선위에서의 x축 gradient는 어떻게 될까. 만약 가로로된 직선이 있다면 x축 gradient는 0에 가까울 것이다. 반대로 세로로 된 직선 위에 픽셀의 y축 gradient는 0에 가까울 것이다. det(H)를 생각해보자 Sx2*Sy2-Sxy^2 이다. 여기서 Sx나 Sy 둘중 하나의 값이 0에 가깝다면 Det값은 어떻게 정해질까. 그렇게 된다면 R값을 정함에 있어서 -값이 나올 것이다. 반대로 corner를 생각해보자. x축 gradient와 y축 gradient가 높을 것으로 예상되지 않는지. 

 지금 여기서 내가 설명한 것은 정말 수학적인 지식이 필요하지 않은 Harris Corner Detector를 의식의 흐름처럼 그냥 간단하게 설명한 것이다. 흔히 말하는 '가라'식의 표현이라서 이 글을 읽고 전체적인 흐름만 이해한다고 생각하면 된다. 정말 수학적으로 어떤식으로 인해 유도되는것은 중요하지만 처음부터 그런것을 맞닥뜨리게 되면 혼란스러울 것이다. 전체적인 흐름을 알고 수학적인 식이나 원리를 보게 된다면 이해하기가 더 편할수도 있을 것이다. 마지막으로 한가지 말하고 싶은 것은 이것이 정답이 아닐 수도 있다는 것이다. 더 다양한 시점에서 공부하길 바란다.




harrisco('lena_N.jpg', 0.008);

function [ output_args ] = harrisco( img_name, num )
%HARRISCO Summary of this function goes here
%   Detailed explanation goes here
gau = fspecial('gaussian', [7 7], 2);
fx = [-2 -1 0 1 2];
fy = [-2; -1; 0; 1; 2];
img = imread(img_name);
%img = rgb2gray(img);

[h w] = size(img);

lx = filter2(fx, img);
ly = filter2(fy, img);
lx2 = lx.*lx;
ly2 = ly.*ly;
lxy = lx.*ly;

Sx2 = filter2(gau, lx2);
Sy2 = filter2(gau, ly2);
Sxy = filter2(gau, lxy);
H = [Sx2 Sxy; Sxy Sy2];

for i=1:h
    for j=1:w
        R(i,j) = (Sx2(i,j)*Sy2(i,j)-Sxy(i,j)*Sxy(i,j)) - 0.04*((Sx2(i,j)+Sy2(i,j))^2);
    end
end


m = max(max(R));

for i=2:h-1
    for j=2:w-1
        if(m * num < R(i,j))
        
            if R(i-1,j) > R(i,j) || R(i+1,j) > R(i,j) || R(i,j-1) > R(i,j) || R(i,j+1) > R(i,j) || R(i+1,j+1) > R(i,j) || R(i-1,j+1) > R(i,j) || R(i+1,j-1) > R(i,j) || R(i-1,j-1) > R(i,j)
                result(i,j) = 0;
            else
                result(i,j) = 1;
            end         
        else
           reslut(i,j) = 0;
        end
        
    end
end

[posc, posr] = find(result == 1);

imshow(img)
hold on;
plot(posr,posc, 'r+');
end



댓글 없음:

댓글 쓰기