Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- 가상환경
- Matplotlib
- 파이썬
- 코딩테스트
- queue
- Algorithm
- aws jupyter notebook
- dataframe
- pandas
- 알고리즘 스터디
- 노마드코딩
- 정보처리기사 c언어
- 선그래프
- 알고리즘스터디
- 데이터시각화
- javascript
- Selenium
- MySQL
- Stack
- openCV
- 프로그래머스
- programmers
- 자료구조
- Join
- 백준
- type hint
- 알고리즘
- python
- NumPy
- String Method
Archives
- Today
- Total
조금씩 꾸준히 완성을 향해
[OpenCV/Python] 코너 검출 - 해리스(Harris), FAST, preCornerDetect, preCornerEigenValsAndVecs 본문
Python/OpenCV
[OpenCV/Python] 코너 검출 - 해리스(Harris), FAST, preCornerDetect, preCornerEigenValsAndVecs
all_sound 2022. 11. 18. 17:35코너 검출
- 특징(feature)
- 영상으로부터 추출한 유용한 정보
- global feature & local feature
- 코너 검출 방법
- 엣지 방향이 급격히 변하는 부분
- 꼭지점, 튀어나온 부분
- 코너는 다른 지역 특징에 비해 분별력이 높고 영상 전체에 분포
# 코너점 검출
- 미분 연산자에 의한 엣지 방향 이용
- cv2.preCornerDetect(src, ksize)
- dst의 local optima 값으로 검출
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import cv2
src = cv2.imread('./CornerTest.jpg') # 컬러로 이미지 가져오기
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) # gray 컬러로 변경
res = cv2.preCornerDetect(gray, ksize=3)
ret, res2 = cv2.threshold(np.abs(res), 0.1, 0, cv2.THRESH_TOZERO) # 임계값 0.1 보다 낮으면 블랙(0)으로, 높으면 원래값
points = np.argwhere(res2 > 0) # 0이 아닌 값들의 위치 저장 => 코너일 가능성이 있는 점들
points.shape
# (24, 2)
# points 점들을 중심으로 작은 원 그리기
dst = src.copy()
for y, x 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), radius=4, color=(r,g,b), thickness=2)
cv2.imshow('src', dst)
cv2.waitKey()
cv2.destroyAllWindows()
# 24개의 원 생성 -> 실제 코너점(8개) 보다 많음
- 침식과 팽창을 이용한 corner 찾기 방법
kernel = cv2.getStructuringElement(shape=cv2.MORPH_RECT, ksize=(11,11))
dilate = cv2.dilate(src, kernel)
erode = cv2.erode(src, kernel)
plt.figure(figsize=(12, 6))
ax1 = plt.subplot(1, 3, 1)
ax2 = plt.subplot(1, 3, 2)
ax3 = plt.subplot(1, 3, 3)
ax1.imshow(src)
ax2.imshow(dilate)
ax3.imshow(erode)
def findLocalMaxima(src):
kernel = cv2.getStructuringElement(shape=cv2.MORPH_RECT, ksize=(11,11))
dilate = cv2.dilate(src, kernel) # dilate => 최대픽셀이 팽창
localMax = (src == dilate) # 원본에서 최대픽셀값인 값 찾기
erode = cv2.erode(src, kernel) # erode => 최소픽셀값 침식
localMax2 = (src > erode) # 원본에서 최소픽셀값보다 큰 픽셀값 찾기
localMax &= localMax2 # &= AND연산
points = np.argwhere(localMax == True) # localMax 좌표 저장
points[:, [0, 1]] = points[:, [1, 0]] # x, y축 위치 변경
return points
points = findLocalMaxima(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) # 코너점에 원 그리기
cv2.imshow('src', gray)
cv2.imshow('res2', res2)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()
- cv2.preCornerEigenValsAndVecs(srx, blockSize, ksize)
- ksize = 이웃 윈도우 크기
- ksize sobel mask
- 영상 내 각 이웃의 covariance matrix M의 eigenvalue, eigenvector를 계산하여 코너 검출
src = cv2.imread('./CornerTest.jpg') # 컬러로 이미지 가져오기
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) # gray 컬러로 변경
# 아이겐밸류 구해서 임계값보다 큰 값 반환(이 값이 코너)
eigen = cv2.cornerMinEigenVal(gray, blockSize=5)
#eigen 밝기값 분포 확인, eigen이 특정값을 초과하는 좌표 구하기
corners = np.argwhere(eigen > 0.2)
corners[:, [0, 1]] = corners[:, [1,0]]
corners.shape
# (8, 2)
#원본 영상 카피하여 위의 좌표를 빨간색 점으로 출력
dst = src.copy()
for x, y in corners:
cv2.circle(dst, (x, y), 4, (0, 0, 255), 2)
cv2.imshow('gray', gray)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()
# lena로 실습
src = cv2.imread('./lena.jpg')
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
eigen = cv2.cornerMinEigenVal(gray, blockSize=5)
eigen.max()
0.056870822
T = 0.008
corners = np.argwhere(eigen > T)
corners[:, [0, 1]] = corners[:, [1,0]]
corners.shape
# (2489, 2)
dst = src.copy()
for x, y in corners:
cv2.circle(dst, (x, y), 4, (0, 0, 255), 1)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()
# 해리스 코너 검출 방법
- 영상 내부 작은 영역이 모든 방향에 대해 변화가 큰 경우 코너로 규정
- 코너 응답 함수 R을 반환 -> R(x,y)가 충분히 크면 코너로 구분
▶ cv2.cornerHarris(src, blockSize, ksize, k, dst=None, borderType=None)
- src: 입력 단일채널 8비트 또는 실수형 영상
- blockSize: 코너 응답 함수 계산에서 고려할 이웃 픽셀 크기. 보통 2~5.
- ksize: (미분을 위한) 소벨 연산자를 위한 커널 크기. 보통 3.
- k: 해리스 코너 검출 상수 (보통 0.04~0.06)
- dst: 해리스 코너 응답 계수. src와 같은 크기의 행렬(numpy.ndarray). dtype=numpy.float32.
- borderType: 가장자리 픽셀 확장 방식. 기본값은 cv2.BORDER_DEFAULT.
# 사각형
src = cv2.imread('./CornerTest.jpg.')
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
# cornerHarris 함수
res = cv2.cornerHarris(gray, blockSize=5, ksize=3, k=0.01)
_, res2 = cv2.threshold(np.abs(res), 0.06, 0, cv2.THRESH_TOZERO) #임계값 0.06보다 낮으면 블랙(0), 높으면 원래값
corners= np.argwhere(res2 > 0) # res2가 0이 아닌 좌표 출력
corners.shape # 좌표 개수 확인
# (8, 2)
for y, x in corners: #원을 그려 좌표 표시
cv2.circle(src, (x, y), radius=4, color=(0,0,255), thickness=3)
cv2.imshow('src', src)
cv2.waitKey()
cv2.destroyAllWindows()
# findLocalMaxima 함수 사용
src = cv2.imread('./CornerTest.jpg.')
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
# cornerHarris 함수
res = cv2.cornerHarris(gray, blockSize=5, ksize=3, k=0.01) # 해리스에서 지정하는 k 상수
ret, res2 = cv2.threshold(np.abs(res), 0.06, 0, cv2.THRESH_TOZERO) # res 절대값이 임계값 0.02 보다 낮으면 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()
# dasol 이미지
src = cv2.imread('./dasol.jpg')
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
res = cv2.cornerHarris(gray, blockSize=5, ksize=3, k=0.01)
_, res2 = cv2.threshold(np.abs(res), 0.0009, 0, cv2.THRESH_TOZERO)
corners= np.argwhere(res2 > 0)
for y, x in corners:
cv2.circle(src, (x, y), radius=5, color=(0,0,255), thickness=1)
cv2.imshow('src', src)
cv2.waitKey()
cv2.destroyAllWindows()
# FAST 코너 검출 방법
- 주변 16개 픽셀 값 크기를 분석
- 기준 픽셀(p)보다 충분히 밝거나 또는 충분히 어두운 픽셀이 n개 연속으로 나타나면 코너로 인식(n은 보통 9)
▶ cv2.FastFeatureDetector_create(, threshold=None, nonmaxSuppression=None, type=None)
- threshold: 중심 픽셀 값과 주변 픽셀 값과의 차이 임계값. 기본값은 10. 30~60 적절
- nonmaxSuppression: 비최대 억제 수행 여부. 기본값은 True.
- type: 코너 검출 방법. 기본값은 cv2.FAST_FEATURE_DETECTOR_TYPE_9_16.
- retval: FastFeatureDetector 객체
src = cv2.imread('./CornerTest.jpg.')
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
fast = cv2.FastFeatureDetector_create(30)
fast.setNonmaxSuppression(0) # off
kp = fast.detect(gray, None)
dst = src.copy()
cv2.drawKeypoints(src, kp, dst, (0, 0, 255))
cv2.imshow('fast', dst)
cv2.waitKey()
cv2.destroyAllWindows()
# lena
src = cv2.imread('./lena.jpg')
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
# fast.setNonmaxSuppression(0) # on
fast = cv2.FastFeatureDetector_create(40)
kp = fast.detect(gray, None)
dst = src.copy()
cv2.drawKeypoints(src, kp, dst, (0, 0, 255))
cv2.imshow('fast', dst)
cv2.waitKey()
cv2.destroyAllWindows()