데이터분석/Vision Recognition

② 파이썬 - 컴퓨터 비전 프로그래밍 (Local Image Descriptor) (1)

늘근이 2015. 10. 3. 17:46

본 글은 Programming Computer Vision with Python (Jan Erik Solem) 을 그대로 따라간거임.



코너검출

코너검출은 이미지의 특징점을 잡아내는데 있어 대표적인 방법이다. 물론 사진의 코너만 검출하고 거기서 끝이나면 그만큼 허무한것도 없겠지만, 코너를 잡아내어 이미지를 비교하거나 얼굴등의 윤곽선을 잡아낼수 있다. 뭐 이런느낌 아닐까?


출처 : http://www.learncomputervision.com/articles/programming/opencv-corner-detection-with-c/


원리는 간단하다. 어떤 한 지점에서 동서남북으로 픽셀을 검사해봤을때 

1) 변화가 있으면 코너이고, 

2) 변화가 있기는 한데 같은 방향에서의 변화가 없으면 코너는 아니고 그냥 경계면이다.

3) 변화가 많이 없으면 그냥 아무것도 아니다.


먼저 코너 검출을 위해 픽셀마다 다음의 식으로 경계 픽셀과의 값들이 많이 차이나는 정도에 대해 점수를 줘볼수있다.

그렇다면 도대체 이 식은 무엇을 뜻한단 말인가?

그렇다면 도대체 저 세모는 무엇을 뜻한단 말인가?


그렇다면 저 대문자 I는 무엇을 뜻한단 말인가? 이미지에서의 변화량이다. 


위의 사진은, (1) 원본, (2) 추출한 변화량(x) 표시 (3) 추출한 변화량(y) 표시 (4) 두개를 제곱해서 더한후 나눈 값을 표현


즉, 변화량에 대한 것을 시각화 한것이다. 거슬러 저런식으로 코너에서의 변화량을 표시하는데 이를 수치화 한 함수는 다음과 같다.


from PIL import Image
from numpy import *
from pylab import *
from scipy.ndimage import filters


def compute_harris_response(im,sigma=3):
	# 시그마 만큼의 derivatives를 추출 
	imx = zeros(im.shape)
	filters.gaussian_filter(im, (sigma,sigma), (0,1), imx)
	imy = zeros(im.shape)
	filters.gaussian_filter(im, (sigma,sigma), (1,0), imy)
	
	# 해리스 행렬의 값들을 구한다.
	Wxx = filters.gaussian_filter(imx*imx,sigma)
	Wxy = filters.gaussian_filter(imx*imy,sigma)
	Wyy = filters.gaussian_filter(imy*imy,sigma)
	
	# det와 trace는 여기서 다음과 같이 계산이 된다. 
	Wdet = Wxx*Wyy - Wxy**2
	Wtr = Wxx + Wyy
	return Wdet / Wtr
	


수치화한 이 값이 리턴되는데 Wdet / Wtr 은 맨 위에서 보았던 판단값으로 작용한다.

이제, 충분한 역치값 ( threshold) 과의 비교를 통해 이값보다 작으면 코너라고 판단할수있다.


from PIL import Image
from numpy import *
from pylab import *
from scipy.ndimage import filters


def get_harris_points(target_harris,min_dist=10,threshold=0.1):
	# find top corner candidates above a threshold
	corner_threshold = target_harris.max() * threshold
	harrisim_t = (target_harris > corner_threshold) * 1
	
	# get coordinates of candidates
	coords = array(harrisim_t.nonzero()).T
	
	# ...and their values
	candidate_values = [target_harris[c[0],c[1]] for c in coords]
	
	# sort candidates
	index = argsort(candidate_values)
	
	# store allowed point locations in array
	allowed_locations = zeros(target_harris.shape)
	allowed_locations[min_dist:-min_dist,min_dist:-min_dist] = 1
	
	# select the best points taking min_distance into account
	filtered_coords = []
	for i in index:
		if allowed_locations[coords[i,0],coords[i,1]] == 1:
			filtered_coords.append(coords[i])
			allowed_locations[(coords[i,0]-min_dist):(coords[i,0]+min_dist),
			(coords[i,1]-min_dist):(coords[i,1]+min_dist)] = 0
			
	return filtered_coords
	
def plot_harris_points(image,filtered_coords):
	
	figure()
	gray()
	imshow(image)
	plot([p[1] for p in filtered_coords],[p[0] for p in filtered_coords],'*')
	axis('off')
	show()

im = array(Image.open('image.PNG').convert('L'))
harris_calc_result = compute_harris_response(im)
filtered_coords = get_harris_points(harris_calc_result,6)
plot_harris_points(im, filtered_coords)



별로 그다지 잘 된다고 하기에는 좀 그렇다. 한번 다른 이미지를 넣어보겠다.



별로 성능은 구리지만, Threshold의 조정을 통해 조금 더 많은 코너를 디텍트 할수 있을것이다.


솔직히 이해도가 낮으니 이해하기 헉헉대기 바쁘다. 만약에라도 보는 분들은, 밑의 자료들 꼭 참조하시길


참고자료


영상 특징점 추출방법

http://darkpgmr.tistory.com/131

https://en.wikipedia.org/wiki/Corner_detection

딥러닝 

http://liv3rt4s.tistory.com/

http://deview.kr/2014/session?seq=26