소스 뷰어
헤리스 코너 검출¶
- 영상에서 객체를 추척할 때나 영상과 영상을 매칭할 때 일반적으로 사용하는 방법이 중요한 특징 정보를 서로 비교하는 것이다.영상 내에는 에지나 직선과 같은 다양한 특정 정보들이 있다. 그러나 직선 정보는 영상 구조 파악 및 객체 검출에는 도움이 되지만, 영상 매칭에는 큰 도움이 되지 않는다. 도한, 에지는 강도와 방향 정보만 가지므로 영상 매칭을 하기에는 정보가 부족하다.
- 에지나 직선처럼 영상처리에는 중요한 특정 정보로 사용되는 꼭지점 혹은 코너(corner)라 부르는 특징점이 있다
- 이 코너 정보 중에서 영상의 왜곡에도 불편하는 특징을 가진 지점들이 영상 매칭에 유용하게 사용될 수 있다. 대표적인 검출기 중 하나인 헤리스 코너 검출기의 원리에 대해서 설명한다.
import numpy as np, cv2, time
# 문자열 출력 함수 - 그림자 효과
def put_string(frame, text, pt, value=None, color=(120, 200, 90)) :
text = str(text) + str(value)
shade = (pt[0] + 2, pt[1] + 2)
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(frame, text, shade, font, 0.7, (0, 0, 0), 2) # 그림자 효과
cv2.putText(frame, text, pt , font, 0.7, color, 2) # 작성 문자
# 수행시간 체크 함수
stime = 0
def ck_time(mode = 0 , msg = ""):
global stime
if (mode ==0 ):
stime = time.perf_counter()
elif (mode==1):
etime = time.perf_counter()
elapsed = (etime - stime)
print("수행시간 = %.5f sec" % elapsed) # 초 단위 경과 시간
elif (mode == 2):
etime = time.perf_counter()
return (etime - stime)
elif (mode== 3 ):
etime = time.perf_counter()
elapsed = (etime - stime)
print("%s = %.5f sec" %(msg, elapsed)) # 초 단위 경과 시간
def cornerHarris(image, ksize, k):
dx = cv2.Sobel(image, cv2.CV_32F, 1, 0, ksize) # 미분 행렬 - 수평 소벨 마스크
dy = cv2.Sobel(image, cv2.CV_32F, 0, 1, ksize) # 미분 행렬 - 수직 소벨 마스크
a = cv2.GaussianBlur(dx * dx, (5, 5), 0) # 가우시안 블러링 수행
b = cv2.GaussianBlur(dy * dy, (5, 5), 0)
c = cv2.GaussianBlur(dx * dy, (5, 5), 0)
corner = (a * b - c * c) - k * (a + b) ** 2 # 코너 응답 함수 계산 -행렬 연산 적용
return corner
def drawCorner(corner, image, thresh):
cnt = 0
corner = cv2.normalize(corner, 0, 100, cv2.NORM_MINMAX)
corners = []
for i in range(1, corner.shape[0]-1 ):
for j in range(1, corner.shape[1]-1 ):
neighbor = corner[i-1:i+2, j-1:j+2].flatten()
max = np.max(neighbor[1::2])
if thresh < corner[i, j] > max : corners.append((j,i))
for pt in corners:
cv2.circle(image, pt, 3, (0, 230, 0), -1) # 좌표 표시
print("임계값: %2d , 코너 개수: %2d" %(thresh, len(corners)) )
return image
def onCornerHarris(thresh):
img1 = drawCorner(corner1, np.copy(image), thresh)
img2 = drawCorner(corner2, np.copy(image), thresh)
put_string(img1, "USER", (10, 30), "" )
put_string(img2, "OpenCV", (10, 30), "")
dst = cv2.repeat(img1, 1, 2) # 두 개 영상을 하나의 윈도우에 표시
dst[:, img1.shape[1]:, :] = img2
cv2.imshow("harris detect", dst)
image = cv2.imread('img/harris.jpg', cv2.IMREAD_COLOR)
if image is None: raise Exception("영상 파일 읽기 에러")
blockSize = 4 # 이웃 화소 범위
apertureSize = 3 # 소벨 마스크 크기
k = 0.04
thresh = 2 # 코너 응답 임계값
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
corner1 = cornerHarris(gray, apertureSize, k) # 사용자 정의 함수
corner2 = cv2.cornerHarris(gray, blockSize, apertureSize, k) # OpenCV 제공 함수
onCornerHarris(thresh)
cv2.createTrackbar("Threshold", "harris detect", thresh, 20, onCornerHarris)
cv2.waitKey(0)