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



2015년 10월 7일 수요일

matlab] Canny Edge Detection Method

 컴퓨터 비전에 사용되는 Canny Edge에 설명해 보겠다. Canny Edge란 사진에서 물체와 물체의 경계가 되는 선을 찾는 것이다. 막상 생각해보면 어렵겠지만 한번 이해 한다면 그렇게 어렵게 느껴지지 않을 것이다. (흑백 사진을 기준으로 한다.)

 첫번째로 사진의 x축 gradient(경사도, 가중치)와 y축 gradient를 구한다. 구하는 방법은 gradient를 구할 필터를 하나 만들고 그것을 한픽셀 한픽셀씩 convolution하면 되는 것이다. 다시 말해 필터를 만들어 반복문을 통하여 한픽셀 한픽셀씩 픽셀의 gradient를 구하면 되는 것이다. 예를 들어 설명하자면 [-2 -1 0 1 2] 라는 1*5행렬의 필터를 만든다. 그리고 어떤 x,y의 픽셀에 저 필터를 대입하면 x,y의 값에는 0이 곱해지고 주위의 한픽셀씩에는 -1과 1이 2픽셀 옆에는 -2와 2의 값이 곱해진다음 0을 곱한 x,y를 포함한 5개의 숫자를 더한 값이 새로운 배열의 값이 된다. 이 방식을 이용해 원래 사진과 같은 크기의 배열을 만들어 낼 수 있다. y축은 저것을 5*1배열의 필터를 만들어 반복하면 된다. (저 필터의 크기나 값은 이 방식을 이해한다면 원하는 대로 바꿀 수 있다.)

 처음에는 이게 어떤 의미인지 헷갈릴 수 있다. 만약 사진의 평평한 부분 흰도화지에 저 필터를 적용 한다고 생각해보자. 자신의 좌우나 세로의 주변 값은 모두 동일할 것이다. 그럼 동일한 값에 -2와 -1을 곱하고 1과 2를 곱해서 다 더한 값은 0이나 0에 가까운 숫자가 나올 것이다. 필터를 사용하다가 흰색부분을 지나서 검은색지역으로 넘어 간다고 생각해보자. 그러면 그 경계가 되는 부분에서  [흰색] [검출 대상 픽셀] [검정] 처럼 흰색과 검정 중간 경계에서 저 gradient 필터를 적용한다면 [-2*255] [-1*255] [0] [1*0] [2*0]라는 값을 얻을 수있다. 저것을 다 더한다면 -765라는 큰 값을 얻을 수 있게 된다. (gradient에서 +와 -는 중요하지 않다. 나중에 검출할 때 부호에 상관없이 값의 크기만 얻기 위해서 한번 제곱을 해 준다.)
그리고 다시 검은색 지점을 지나칠때는 흰색과 동일하게 0에 가까운 값만을 얻을 것이다.

그럼 이제 전체적으로 gradient를 구한 값을 생각해보자. 밝기나 색이 바뀌는 부분(우리가 생각하는 Edge)에서는 +나 -로 큰 값이 저장 되어있고 나머지는 0에 가까운 수가 되어 있을 것이다. 이것은 x축필터로 한번 y축 필터로 한번씩 해서 x의 gradient와 y의 gradient를 구할 수 있다. 여기까지 이해가 안된다면 과정을 다시 생각해 보는 것도 좋은 것이다. 지금의 gradient의 개념이 앞으로 나올 개념들의 기초가 될 것이다.

위에서 구한 x축과 y축의 gradient 값을 각각 제곱해서 더 해준 값에 루트를 씌운다. 그렇게 해서 전체적인 gradient값을 구한 후 또 하나 필요한 건 각 픽셀의 기울기이다. 각 픽셀에 gradient가 존재 한다면 필요한 것이 기울기이다. 값이 존재한다면 선이 존재한다는 말이 되는 것이고 그렇다면 세로로 이어진 선인지 가로로 이어진 선인지 대각선인지를 판단할 수 있어야 한다. x축 gradient는 가로축방향만 가지는 값이고 y축 gradient값은 세로축 방향만을 가지는 값이다.  기울기를 구하는 것은 atan(y/x)이다. 이것으로 구한 값을 이용해 방향성을 알 수 있다.

-0.4142< atan(y/x) <= 0.4142 가로방향
0.4142< atan(y/x) < 2.4142 2시와 7시방향을 가로지르는 직선 방향의 대각
|atan(y/x)| >= 2.4142 는 세로방향
-2.4142 < atan(y/x) <= -0.4142 10시와 5시 방향의 대각

이것으로 각 픽셀의 방향성을 알 수 있다. 이제 각 픽셀의 방향성을 검토하면서 그 방향성 둘중 한군데에서 자기 자신보다 큰 값을 가지는 픽셀이 있다면 자기 자신을 0으로 만든다.
이렇게 전체적으로 반복해 나간다면 남아 있는것은 그 방향에서 제일 큰 값을 가지는 픽셀만 남아있을 수 있게 되는 것이다.

2015년 10월 5일 월요일

matlab] 매트랩 함수 사용 정리



ans = imread('img.jpg');
이미지를 읽어 들어와 그 픽셀 값을 변수에 저장한다 컬러 이미지의 경우 3차원 배열 R,G,B
흑백이미지의 경우 x,y값만 가지는 2차원 배열이 생성된다.

imshow(ans);
figure, imshow(ans);
배열 변수의 값을 출력하여 사용자에게 보여준다. 그래프나 사진작업을 이용할때 이용하면 좋다. figure를 사용하면 사진을 여러개 띄울 수 있다.

A .* B  A ./ B ....
A배열과 B배열의 각각의 요소끼리 곱한다. 매트랩에서 기본적으로 행렬연산을 제공하지만 이건 단순 곱을 할 수 있다. 같은 방법으로 나누기도 가능하다

ans = sum(A);
A의 모든 변수를 더해준다.  2차원 배열의 경우 각 행을 첫번째 열에 다 더하기 때문에 ans = sum(sum(A))를 하면 모든 값을 더한 수 하나만 나온다. 


ans = fspecial('gaussian', [7 7], 2);
매트랩에서 제공하는 필터를 만들어서 제공해준다. gaussian말고 다른 함수가 있지만 잘 모르겠다.

ans = filter2(filter, img);
 반복문을사용할 필요 없이 filter를 img에 적용 시킬 수 있다. filter의 사이즈는 사용자가 자유롭게 설정할 수 있다.

What is Gaussian Filter, Mean Filter and Median Filter?

Gaussian FilterMean Filter 그리고 Median Filter는 모두 사진의 노이즈를 제거해서 좀 더 매끄러운 사진을 만들 수 있게 해준다. 각각은 필터안에 들어가는 값과 방식의 차이가 있지만 방법은 동일하다고 볼 수 있다. 먼저 제일 간단한 개념을 보면 사진의 각 픽셀의 값을 재정의 하게 되는데 재정의의 필요한 픽셀은 주변픽셀의 값에 영향을 받아서 정한 다는 것이다. Mean Filter에서 3x3filter size의 경우 자신을 제외한 자기를 둘러싸고 있는 8개의 픽셀과 자기 자신을 포함한 총 9개의 픽셀을 다 더한 후 9로 나누어 준 평균으로 재정의 함으로써 전체적으로 부드러운 이미지를 얻어 낼 수 있다. 방식을 유지한 채 한 픽셀 한 픽셀을 이동하여 전체적으로 필터로 픽셀 값을 얻어낸다. Median Filter의 경우는 중간 값을 이용하여 값을 재정의한다. 자신과 주변에 둘러싼 픽셀을 정렬하여 가장 중간에 오는 값으로 픽셀 값을 정한다. Gaussian Filter는 필터에 가우시안 분포를 이용하여 필터의 값을 정하게 된다. 정하는 식은 필터의 정 중앙은 좌표 0,0으로 취급한다. 아래의 식을 사용하여 필터의 값을 정한 후 그 필터를 한픽셀 한픽셀씩 지나가면서 값을 재정의 한다.
시그마 필터의 사이즈와 시그마 값을 입력받아서 실행하게 되어진다. 시그마가 높을수록 사진이 전체적으로 좀더 뭉개진다.
filter size의 크기는 변할 수 있으며 정사각형의 홀수개의 크기를 가진다.
 

What are the spherical aberration, chromatic aberration and vignetting?

물체나 장면이 보인다는 것은 반사된 빛이 렌즈를 통하여 한점에 상이 맺혀야 제대로 보일 수 있다. spherical aberration이란 구면 수차라고 말할 수 있다. 구면 수차는 반사된 평행한 광선이 렌즈를 통하여 한점에 맺혀야 하는데 그렇지 않고 맺히는 위치가 앞뒤에서 어긋나 버리는 현상을 말한다. 렌즈의 주변부와 중심부가 굴절율이 다르기 때문에 일어난다. 이 구면 수차를 줄이는 방법은 비구면 렌즈의 사용과 조리개를 중심한 좌우 대칭 렌즈의 구조, 조리개를 좁혀서 활영 한다면 나아 질 수 있다. chromaic aberration는 색수차라고 불리어 진다.파장에 따른 굴절률의 차이에 의해 생기는 수차이다. 긴 파장의 빛일수록 렌즈를 통과한 뒤에 다른 빛보다 초점이 렌즈에서 먼 쪽으로 맺히기 때문에 일어나는 현상으로, 광학기기에 사용하는 렌즈를 만들 때에는 이를 보정하기 위해 여러 개의 렌즈를 결합한다. vignetting이란 사진의 외곽이나 모서리가 어둡게 나오는 현상이다. 렌즈 주변부의 광량 저하로 촬영된 사진의 외곽 부분이 어두워지는 현상이며, 촬영시 최대한 조리개를 줄이게 되면 비네팅 현상을 줄일 수 있다. 조리개를 줄여 줌으로써 주변부와 중심부의 광량을 어느정도 맞출 수 있기 때문이다.

Please explain perspective, weak-perspective and orthographic projections.

사람의 눈은 사물이나 장면을 볼 때, 가까이 있는 것은 크게 보이고 멀이 있는 것은 작게 보인다. 우리가 입체적인 사물을 볼 때 우리가 보는 방향에 따라 모양이 달라 보인다. 입체적인 정육면체를 생각해 보자. 정면에서 봤을때는 정사각형이지만 옆에서 보거나 위에서 볼 때는 정육면체의 각이 직각을 이루지 않고 평행사변형이나 사다리꼴과 같은 모습을 볼 수 있게 된다. 이것은 우리가 입체적인 사물이나 장면을 보았을때 이러한 현상이 나타나게 되는데 이것의 원인은 가까이 있는 것은 크게 보이고 멀리 있는 것은 작게 보이는 원근감 때문에 생기는 것이다. 이 때 우리가 생각해야 하는 것은 어떤 규칙에 의해서 그렇게 보이는 지 알아야 하는 것이다. 사물이나 장면은 우리의 눈높이에 따라 직선을 그으면 소실점이라는 선이 생긴다. 혹시 전철이 다니는 선로 위에 서본 적이 있다면 평행한 두 선로를 따라 시선을 움직이다 보면 저 멀리 두 선로가 만나는 듯이 보인 적이 있을 것이다. 원근에 따라 두 선로가 한점에 모이게 되는 현상이 일어나는데 이것을 vanishing point(소실점) 이라고 한다.
projection이란 이러한 3차원의 object를 화면에 표현하기 위해 2D평면으로 투영하는 것을 projection이라고 하는데 perspective projection이란 이러한 원근의 원리를 이용하여 가까운 것을 크게 멀리있는 것을 작게 그리고 vanishing point를 고려해서 projection을 하는 것을 말한다. 반대로 orthographic projection은 원근에서 중요한 역할을 하는 vanishing point를 고려하지 않고 투영하는 방식이다. 입체적인 사물을 보았을 때 그대로의 모습을 projection 하는 것이다. vanishing point를 고려하지 않아 그로 인해 생기는 왜곡된 모습이 아닌 원래 모습 그대로를 알 수 있다. weak-perspective projectionorthographic projectionsperspective projection의 중간 이라고 볼 수 있다. 원리는 orthographic projection의 원리를 사용하지만 vanishing point를 구현 하기도 하는데 이는 정확한 값에 의한 것이 아니라 근사치를 이용해 구현 되어 진다.