반응형
Corner Detect(코너 검출)
▶ 특징 (Feature)
- 영상으로부터 추출한 유용한 정보
- 밝기 평균, 히스토그램, 에지, 코너
- 전역 특징, 지역 특징
▶ 코너 검출 방법
- 에지 방향이 급격히 변하는 부분
- 꼭지점, 튀어나온 부분.
- 코너는 다른 지역 특징에 비해 분별력이 높고 영상 전체에 분포
코너점 검출
▶ cv2.preCornerDetect(src, ksize)
- dst의 local optima 값으로 검출
- 미분 연산자의 의한 에지 방향 이용
▶ cv2.preCornerEigenValsAndVecs(src, blackSize, ksize)
- src : input
- blocksize : 이웃 윈도우 크기
- ksize : sobel filter mask
- 영상 내 각 이웃의 covariance matrix M의 eigenvalue, eigenvector를 계산하여 코너 검출eigenvalue λ1,λ2λ1,λ2가 모두 작은 값: 평평한 영역에 있는 점
- eigenvalue λ1,λ2λ1,λ2 둘 중 하나는 크고 하나는 작은 값: 에지
- eigenvalue λ1,λ2λ1,λ2 두 값이 모두 큰 값: 코너
▶ findLocalMaxima()
- 지격 극대값의 좌표를 points 배열에 검출하여 반환.
- 결국 코너점 검출하는 방식을 사용하면 하나의 point가 출력되는 것이 아니라 코너점 Point에서 주변의 point까지 전부 출력하는 것을 알 수 있다.
- 즉, 특정 크기의 지역내의 극대점을 하나로서 표현함으로써 코너점을 하나로 만들기 위한 Method.
▶ 계산 순서
- LocalMaxima를 dilate로서 계산
- LocalMaxima를 erode로서 계산
- LocalMaxima2는 LocalMinima보다 큰 값으로 계산
- LocalMaxima & LocalMinima2를 통하여 최대값 계산
- x,y 위치를 바꿔서 반환
해리스 코너 검출
1988년 해리스(C. Harris)가 개발한 코너 검출 방법은 코너 점 구분을 위한 기본적인 아이디어를 수학적으로 잘 정의하였다는 점에서 큰 의미가 있음. (Harris88)
코너 검출 연구는 1970년대 후반 부터 활발하게 진행.
영상의 특정 위치(x,y) 에서 Δx와 Δy만큼 떨어진 픽셀과의 밝기 차이를 다음 수식으로 표현.
w(x, y) : 균일한 값 도는 가우시안 형태의 가중치를 갖는 윈도우
E(Δx, Δy) 함수가 모든 방향으로 값이 크게 나타난다면 점(x, y)는 코너라고 간주 할 수 있음.
해리스는 수학적 기법을 적용하여 코너 응답 함수 R을 유도함.
- K : 보통 0.01~0.06
- R이 0보다 충분히 큰 양수 : 코너
- R이 0에 가까운 실수 : 평탄한 영역
- R이 0보다 작은 음수 : 에지
FAST 코너 검출 방법
- 16개의 주변 픽셀과 밝기를 비교하여 코너 여부 판별
- p점 주변 1번부터 16번 픽셀과의 밝기 비교
- 주변 16개의 픽셀 중에서 점 p보다 충분히 밝거나 또는 충분히 어두운 픽셀이 9개 이상 연속으로 존재하면 코너로 정의 (원 논문은 12개)
다른 코너 탐지 보다 몇배 더 빠른 성능.
노이즈에 견고하지 못하며 Threshold에 결과 의존.
▶ FAST 코너 검출 방법
- cv2.FastFeatureDetector
- detect
- setNonmaxSuppression
- cv2.drawKeypoints
체스 보드 코너점 검출
▶ cv2.findChessboardCorners(img, patternSize, corners, flags]])
체스보드 패턴 코너점 검출
카메라 캘리브레이션에 자주 사용되는 체스보드 패턴 검출
- image : input(chessboard)
- patternSize : 체스보드 안의 한 칸 column, row size
- corners : output
- flag : 0이거나 다양한 값의 조합이 될 수 있음
▶ cv2.drawChessboardCorners(img, patternSize, corners, patternWasFound)
- 검출된 코너점 배열
- corners를 8비트 컬러 image에 표시
- image : Destination lmage
- patternSize : number of inner corners per a chessboard row and colummn
- corner : 검출한 코너점
- patternWasFound : Pattern을 검출하였나 안 하였나 판단하는 Flag
▶ cv2.findCirclesGrid(image, patternSize, centers, flags)
원형태의 격자에서 원의 중심점을 검출한다.
cornor¶
cv2.preCornerDetect()
In [20]:
import cv2
import matplotlib.pyplot as plt
import numpy as np
src = cv2.imread('./image/CornerTest.jpg')
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
res = cv2.preCornerDetect(gray, ksize=3)
_, res2 = cv2.threshold(np.abs(res), 0.1, 0, cv2.THRESH_TOZERO)
points = np.argwhere(res2 > 0)
for x,y in points:
cv2.circle(src, (y, x), 5, (0,0,255), 2)
plt.style.use("grayscale")
plt.figure(figsize=(15,15)) #width, height
ax1 = plt.subplot(1,2,1)
ax2 = plt.subplot(1,2,2)
ax1.imshow(src)
ax2.imshow(gray)
ax1.axis('off')
ax2.axis('off')
ax1.set_title("")
ax2.set_title("")
cv2.imshow('src', src)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.waitKey(1)
Out[20]:
-1
findLocalMaxima()¶
자동화 함수
In [18]:
def findLocalMaxima(src):
kernel = cv2.getStructuringElement(shape=cv2.MORPH_RECT, ksize=(11,11))
dilate = cv2.dilate(src, kernel)
localMax = (src == dilate)
erode = cv2.erode(src, kernel)
localMax2 = (src > erode)
localMax &= localMax2
points = np.argwhere(localMax == True)
points[:, [0, 1]] = points[:, [1, 0]]
return points
In [66]:
src = cv2.imread('./image/CornerTest.jpg')
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
res = cv2.preCornerDetect(gray, ksize=3)
_, res2 = cv2.threshold(np.abs(res), 0.1, 0, cv2.THRESH_TOZERO)
points = findLocalMaxima(res2)
print(np.unique(res2))
dst = src.copy()
for x, y in points:
r = np.random.randint(0, 255)
g = np.random.randint(0, 255)
b = np.random.randint(0, 255)
cv2.circle(dst, (x, y), 4, (b, g, r), 2) # corners 이용 작은 원 그리기
plt.style.use("grayscale")
plt.figure(figsize=(15,15)) #width, height
ax1 = plt.subplot(1,2,1)
ax2 = plt.subplot(1,2,2)
ax1.imshow(src)
ax2.imshow(dst)
ax1.axis('off')
ax2.axis('off')
ax1.set_title("")
ax2.set_title("")
# cv2.imshow('src', gray)
# cv2.imshow('res2', res2)
# cv2.imshow('dst', dst)
# cv2.waitKey()
# cv2.destroyAllWindows()
# cv2.waitKey(1)
[0. 0.18627355 0.18651575 0.1867647 0.1872549 0.18749999
0.18774031 0.18946366 1.1191252 1.1220559 1.1227951 1.125 ]
Out[66]:
Text(0.5, 1.0, '')
cornerMinEigenVal()¶
In [64]:
import cv2
import matplotlib.pyplot as plt
import numpy as np
src = cv2.imread('./image/CornerTest.jpg')
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
# eigen value를 구하여 임계값 보다 큰 값 반환(코너 값)
eigen = cv2.cornerMinEigenVal(gray, blockSize=5)
print('eigen.shape=',eigen.shape)
# eigen 밝기값 분포 확인 eigen이 특정값을 초과하는 좌표 구하기
corners = np.argwhere(eigen > 0.2)
corners[:, [0,1]] = corners[:,[1,0]]
print('len(corners)=',len(corners))
#원본 영상 카피하여 위의 좌표를 빨간색 점으로 출력
dst = src.copy()
for x,y in corners :
cv2.circle(dst, (x,y), 3, (0,0,255), 2)
plt.figure(figsize=(10,10))
imgae1=plt.subplot(1,2,1)
imgae1.set_title('Original')
plt.axis('off')
plt.imshow(src, cmap="gray")
imgae2=plt.subplot(1,2,2)
imgae2.set_title('CornerTest')
plt.axis('off')
plt.imshow(dst, cmap="gray")
plt.show()
# cv2.imshow('dst', dst)
# cv2.waitKey()
# cv2.destroyAllWindows()
# cv2.waitKey(1)
eigen.shape= (512, 512)
len(corners)= 8
In [63]:
src = cv2.imread('./image/lena.jpg')
src2 = cv2.cvtColor(src, cv2.COLOR_BGR2RGB)
gray = cv2.cvtColor(src2, cv2.COLOR_RGB2GRAY)
eigen = cv2.cornerMinEigenVal(gray,blockSize=5)
print('eigen.shape=',eigen.shape)
print(np.unique(eigen))
T = 0.01
corners = np.argwhere(eigen > T)
corners[:,[0,1]] = corners[:,[1,0]]
print('len(corners)=',len(corners))
dst = src2.copy()
for x,y, in corners:
cv2.circle(dst,(x,y),3,(0,0,255),1)
plt.figure(figsize=(10,10))
imgae1=plt.subplot(1,2,1)
imgae1.set_title('Original')
plt.axis('off')
plt.imshow(src2, cmap="gray")
imgae2=plt.subplot(1,2,2)
imgae2.set_title('CornerTest')
plt.axis('off')
plt.imshow(dst, cmap="gray")
plt.show()
eigen.shape= (512, 512)
[5.0092785e-07 5.7663419e-07 6.7404653e-07 ... 4.6648271e-02 4.6998546e-02
5.6870822e-02]
len(corners)= 1541
cornerHarris()¶
In [15]:
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv2.imread('./image/CornerTest.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
dst = cv2.cornerHarris(gray,10,3,0.04)
img[dst > 0.02 * dst.max()] = [0,0,255]
plt.style.use("grayscale")
plt.figure(figsize=(15,15)) #width, height
ax1 = plt.subplot(1,2,1)
ax2 = plt.subplot(1,2,2)
ax1.imshow(gray)
ax2.imshow(img)
ax1.axis('off')
ax2.axis('off')
ax1.set_title("src")
ax2.set_title("dst")
Out[15]:
Text(0.5, 1.0, 'dst')
In [19]:
src = cv2.imread('./image/CornerTest.jpg')
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
res = cv2.cornerHarris(gray, blockSize=5, ksize=3, k=0.01) # 해리스에서 지정하는 k 상수
ret, res2 = cv2.threshold(np.abs(res), 0.005, 0, cv2.THRESH_TOZERO) # 임계값 0.02 기준, res 절대값 낮으면 0, 높으면 원래 값
corners = findLocalMaxima(res2) # 위 함수에 적용, 로컬 맥시마 위치 저장
print('corners =', corners) # 코너 좌표 출력
dst = src.copy()
for x, y in corners:
cv2.circle(dst, (x, y), 3, (0, 0, 255), 2)
cv2.imshow('cornerHarris', dst)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.waitKey(1)
corners = [[109 127]
[264 127]
[267 167]
[386 170]
[109 268]
[167 271]
[170 374]
[386 374]]
Out[19]:
-1
FAST 코너 검출 방법¶
In [53]:
import cv2
import matplotlib.pyplot as plt
import numpy as np
src = cv2.imread('./image/seaport.jpeg')
# gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
src = cv2.cvtColor(src, cv2.COLOR_BGR2RGB)
gray = cv2.cvtColor(src, cv2.COLOR_RGB2GRAY)
T = 50
fast = cv2.FastFeatureDetector_create(T)
fast.setNonmaxSuppression(0)
kp = fast.detect(src, None)
dst = src.copy()
cv2.drawKeypoints(src, kp, dst, (255,0,0))
plt.style.use("grayscale")
plt.figure(figsize=(15,15)) #width, height
ax1 = plt.subplot(1,2,1)
ax2 = plt.subplot(1,2,2)
ax1.imshow(src)
ax2.imshow(dst)
ax1.axis('off')
ax2.axis('off')
ax1.set_title("src")
ax2.set_title("dst")
# cv2.imshow('cornerHarris', dst)
# cv2.waitKey()
# cv2.destroyAllWindows()
# cv2.waitKey(1)
Out[53]:
Text(0.5, 1.0, 'dst')
In [75]:
import cv2
import matplotlib.pyplot as plt
import numpy as np
# findChessboardCorners with ChessBoard.jpg
src = cv2.imread('./image/chessBoard.jpg')
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
patternSize = (6, 3) # 가로 6개 세로 3개
found, corners = cv2.findChessboardCorners(gray, patternSize)
print('corners.shape =', corners.shape)
dst = src.copy()
cv2.drawChessboardCorners(dst, patternSize, corners, found)
plt.style.use("grayscale")
plt.figure(figsize=(10,10)) #width, height
ax1 = plt.subplot(2,1,1)
ax2 = plt.subplot(2,1,2)
ax1.imshow(src)
ax2.imshow(dst)
ax1.axis('off')
ax2.axis('off')
ax1.set_title("src")
ax2.set_title("dst")
# cv2.imshow('Chessboard', dst)
# cv2.waitKey()
# cv2.destroyAllWindows()
# cv2.waitKey(1)
corners.shape = (18, 1, 2)
Out[75]:
Text(0.5, 1.0, 'dst')
findCirclesGrid()¶
In [76]:
import cv2
import matplotlib.pyplot as plt
import numpy as np
# findChessboardCorners with ChessBoard.jpg
src = cv2.imread('./image/circleGrid.jpg')
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
patternSize = (6, 4)
found, corners = cv2.findCirclesGrid(gray, patternSize)
print('corners.shape =', corners.shape)
dst = src.copy()
cv2.drawChessboardCorners(dst, patternSize, corners, found)
plt.style.use("grayscale")
plt.figure(figsize=(10,10)) #width, height
ax1 = plt.subplot(2,1,1)
ax2 = plt.subplot(2,1,2)
ax1.imshow(src)
ax2.imshow(dst)
ax1.axis('off')
ax2.axis('off')
ax1.set_title("src")
ax2.set_title("dst")
# cv2.imshow('Chessboard', dst)
# cv2.waitKey()
# cv2.destroyAllWindows()
# cv2.waitKey(1)
corners.shape = (24, 1, 2)
libpng warning: bKGD: invalid
Out[76]:
Text(0.5, 1.0, 'dst')
반응형
'Python' 카테고리의 다른 글
[Python] openCV : Moments (0) | 2022.11.17 |
---|---|
[Python] openCV : Hough Transformation (0) | 2022.11.17 |
[Python] openCV : Canny Edge Detection (0) | 2022.11.17 |
[Python] openCV : Labeling (0) | 2022.11.17 |
[Python] openCV : Morphology (0) | 2022.11.17 |