2 minute read


Harris corner dectecion

기본원리

  • 한 pixel을 중심으로 두고 작은 window를 설정, 이 window를 x축으로 u만큼, y축으로 v만큼 이동

  • 그 다음 윈도우 내의 pixel값의 차이의 제곱 합을 구한다.

    -> 얼마나 변했을 지를 계산, coner값 이라면 차이가 클 것이다!

    -> E값이 크면 coner라고 판단

    image

    • E 값이 크려면 중간이 커야 한다. => M이라고 부르자

    image

  • 이 행렬 M을 고유값 분해하면 2개의 고유벡터image와 이에 상응하는 고유벡터를 얻을수 있다.

  • image 가 둘다 크면 M은 큰 값을 가지게 되고 coner라고 판단할수 있다.

  • 둘중 하나만 큰 경우에는 edge라고 볼수있다.

image

Harris corner detection

  • Sobel filter 적용
    • 𝐼𝑥, 𝐼𝑦를 추출
  • 𝐼𝑥 2 , 𝐼𝑦 2 , 𝐼𝑥𝐼𝑦 구하기

  • 𝐼𝑥 2 , 𝐼𝑦 2 , 𝐼𝑥𝐼𝑦 에 Gaussian filter 적용

  • M 완성

  • det 𝑀, trace 𝑀 구하기 > 코너 판별

  • 근처의 코너가 많은 경우 코너 수 줄이기

결과 코드

import cv2
import numpy as np
from library.filtering import my_filtering

def find_local_maxima(src,ksize):
    (h,w) = src.shape
    pad_img = np.zeros((h+ksize,w+ksize))
    pad_img[ksize//2:h+ksize//2,ksize//2:w+ksize//2] = src
    dst = np.zeros((h,w))

    for row in range(h):
        for col in range(w):
            max_val = np.max(pad_img[row:row+ksize,col:col+ksize])
            if max_val == 0:
                continue
            if src[row,col] ==max_val:
                dst[row,col] = src[row,col]

    return dst
def get_my_sobel():
    sobel_x = np.dot(np.array([[1],[2],[1]]),np.array([[-1,0,1]]))
    sobel_y = np.dot(np.array([[-1],[0],[1]]),np.array([[1,2,1]]))
    return sobel_x,sobel_y

def my_get_Gaussian_filter(fshape,sigma=1):
    (f_h,f_w) = fshape
    y,x = np.mgrid[-(f_h//2):(f_h//2)+1,-(f_w//2):(f_w//2)+1]
    filter_gaus = 1/(2*np.pi*sigma**2) * np.exp(-((x**2 + y**2 )/(2*sigma**2)))
    #mask의 총 합  = 1
    filter_gaus/= np.sum(filter_gaus)
    return filter_gaus

def GaussianFiltering(src,fshape=(3,3),sigma=1):
    gaus = my_get_Gaussian_filter(fshape,sigma)
    dst = my_filtering(src,gaus)
    return dst
def calc_derivatives(src):
    # Todo
    #3x3 sobel필터를 사용해서 Ix Iy 구하기
    # : param src : 입력이미지 (흑백)
    # : return : Ix,Iy
    sobel_x, sobel_y = get_my_sobel()
    Ix = my_filtering(src, sobel_x, 'repetition')
    Iy = my_filtering(src, sobel_y, 'repetition')
    return Ix,Iy

def HarrisDetector(src,gaus_filter_size=3,gaus_sigma=1,alpha=0.04,threshold_rate=0.01):
    (h,w) = src.shape
    #calculate Ix,Iy
    Ix,Iy = calc_derivatives(src)

    #Todo : IxIx,IyIy,IxIy 구하기
    IxIx = np.square(Ix)    # IxIx = Ix*Ix
    IyIy = np.square(Iy)
    IxIy = Ix*Iy

    # Todo : 가우시안 필터 적용하기
    G_IxIx =GaussianFiltering(IxIx,(gaus_filter_size,gaus_filter_size),gaus_sigma)
    G_IyIy =GaussianFiltering(IyIy,(gaus_filter_size,gaus_filter_size),gaus_sigma)
    G_IxIy =GaussianFiltering(IxIy,(gaus_filter_size,gaus_filter_size),gaus_sigma)

    # Todo : har 구하기 교수님 이론 67p참고
    # har = detM -a* traceM**2= g(x)g(y)-g(xy)**2
    har = G_IxIx*G_IyIy - G_IxIy**2 - alpha*(G_IxIx+G_IyIy)**2  #맞나..?

    # 0~1사이의 값으로 변경 후 0~255로 변경 -> 결과가 잘 나왔는지 확인하기 위해서
    G_dst_har_Norm = ((har - np.min(har)) / np.max(har - np.min(har)) * 255 + 0.5).astype(np.uint8)
    cv2.imshow('G_dst_har_Norm', G_dst_har_Norm)

    #thresholding
    har[har<threshold_rate * np.max(har)]=0

    G_dst_har_thresh_Norm = ((har - np.min(har)) / np.max(har - np.min(har)) * 255 + 0.5).astype(np.uint8)
    cv2.imshow('G_dst_har_thresh_Norm', G_dst_har_thresh_Norm)

    dst = find_local_maxima(har,21)

    return dst

def main():
    src = cv2.imread('../image/zebra.png')
    harris_img = src.copy()
    gray = cv2.cvtColor(src, cv2.COLOR_BGRA2GRAY).astype(np.float32)/255.
    cv2.imshow('original', src)

    dst = HarrisDetector(gray,gaus_filter_size=3,gaus_sigma=1,alpha=0.04)
    #calculate Ix, Iy , 먼저 0-1값으로 바꿔준호 0-255의 값으로 바꾸어주었다.

    # dst = cv2.cornerHarris(gray, 3, 3, 0.04)
    dst = cv2.dilate(dst, None)
    interest_points = np.zeros((dst.shape[0], dst.shape[1], 3))
    interest_points[dst != 0] = [0, 0, 255]
    harris_img[dst != 0] = [0, 0, 255]
    cv2.imshow('interest_points', interest_points)
    cv2.imshow('harris_img', harris_img)

    cv2.waitKey()
    cv2.destroyAllWindows()

if __name__=='__main__':
    main()

Tags:

Categories:

Updated: