코너점(Corner) 검출 - preCornerDetect
2018, Aug 01
- Reference : Python으로 배우는 OpenCV 프로그래밍
- Code : https://github.com/gaussian37/Vision/tree/master/OpenCV/corner%20detection
** 오늘 하루도 즐거운 하루 되길 바라며, 도움이 되셨다면 광고 한번 클릭 부탁 드립니다. 꾸벅 ^^ **
OpenCV를 이용하여 영상에서의 코너점을 검출하는 방법에 대하여 알아보도록 하겠습니다.
코너점
은 단일 채널의 입력 영상의 미분 연산자에 의한 에지 방향
을 이용하여 검출 합니다.
코너점 검출 함수
코너점을 검출할 수 있는 OpenCV의 대표적인 6가지 방법중에 preCornerDetect
에 대하여 알아보도록 하겠습니다.
코너 검출에는 다음 이미지를 사용하겠습니다.
- dst = cv2.preCornerDetect(src, ksize)
- 코드 : 링크
- 코너 검출 방법 : local maxima, minima
- 영상 src에서 코너점 검출을 위한 특징맵 dst를 Sobel 미분 연산자를 이용하여 계산
- ksize는 Sobel 연산자의 마스크 크기
- 코너점은 dst에서 local maxima/minima 에서 검출
- 이 때, \(dst(x, y) = I^{2}_{x}I_{yy} + I^{2}_{y}I_{xx} - 2I_{x}I_{y}I_{xy}\)
\(I_{x} = \frac{\partial I(x,y)}{\partial x}\)
\(I_{y} = \frac{\partial I(x,y)}{\partial y}\)
\(I_{xx} = \frac{\partial^{2} I(x,y)}{\partial^{2} x}\)
\(I_{yy} = \frac{\partial^{2} I(x,y)}{\partial^{2} x}\)
\(I_{xy} = \frac{\partial^{2} I(x,y)}{\partial x \partial y}\)
코드는 아래와 같습니다.
import argparse
import cv2
import numpy as np
# findLocalMaxima()는 src에서 Morphology 연산(팽창 & 침식)으로
# Local maxia의 좌표를 points 배열에 검출하여 반환함
def findLocalMaxima(src):
kernel= cv2.getStructuringElement(shape = cv2.MORPH_RECT, ksize = (11,11))
# cv2.dilate()로 src에서 rectKernel의 이웃에서 최댓값을 dilate에 계산
# kernel = None을 사용하면 기본적으로 3 x 3 커널이 사용됩니다.
dilate = cv2.dilate(src, kernel)
# src == dilate 연산으로 src에서 local maxima 위치를 localMax 배열에 계산합니다.
localMax = (src == dilate)
# cv2.erode()로 src에서 rectKernel의 이웃에서 최솟값을 erode에 계산합니다.
erode = cv2.erode(src, kernel) # local min if kernel = None, 3x3
# src > erode로 최솟값보다 큰 위치를 localMax2에 계산합니다.
localMax2 = src > erode
# & 연산으로 local maxima 위치를 계산
localMax &= localMax2
# 행,열 순서로 localMax 위치를 찾습니다.
points = np.argwhere(localMax == True)
# 좌표 순서를 열(x), 행(y)으로 변경 합니다.
points[:,[0,1]] = points[:,[1,0]] # switch x, y
return points
# argument parser를 구성해 주고 입력 받은 argument는 parse 합니다.
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="Path to the image")
args = vars(ap.parse_args())
src = cv2.imread(args["image"])
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
# grayscale의 gray에서 cv2.preCornerDetect()로 res를 계산합니다.
res = cv2.preCornerDetect(gray, ksize = 3)
# 극대값만을 찾기 위해서 np.abs(res)인 절대값 배열에서
pointprocessing
# res에서 임계값보다 작은 값을 제거 합니다.
# findLocalMaxima() 함수를 통해 res2에서
# 지역 극값의 좌표를 코너점으로 찾아 corners에 저장합니다.
ret, res2 = cv2.threshold(np.abs(res), 0.1, 0, cv2.THRESH_TOZERO)
# corner를 저장합니다.
corners = findLocalMaxima(res2)
print('corners.shape=', corners.shape)
# src를 dst에 복사하고, 코너점 배열 corners의 각 코너점 좌표에 cv2.circle()로
# dst에 반지름 5, 빨간색 원을 그립니다.
dst = src.copy()
for x, y in corners:
cv2.circle(dst, (x, y), 5,(0, 0, 255), 2)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()
도움이 되셨으면 광고 한번 클릭이 저에게 큰 도움이 됩니다. 꾸벅.