반응형
1. 올바른 매칭점 찾기
(1) match() 함수
- match()함수는 모든 디스크립터를 하나하나 비교하여 매칭점을 찾고,
- 가장 작은 거리 값과 큰 거리값의 상위 몇 퍼센트만 골라서 올바른 매칭점을 찾게 된다.
: 모든 디스크립터를 하나하나 비교하여 매칭점을 찾는다
: 가장 작은 거리 값과 큰 거리 값의 상위 몇 퍼센트만 골라서 올바른 매칭점을 찾을 수 있음
인자를 3개를 기본으로 넣어주면 되는데, 구간 시작점, 구간 끝점, 구간 내 숫자 개수 3가지를 순서대로 채워주시면 됩니다. 예를 들어 1과 10 사이를 숫자 100개(끝점 포함)로 채운 예시를 보도록 하겠습니다.
import cv2
import numpy as np
img1 = cv2.imread('img/taekwonv1.jpg')
img2 = cv2.imread('img/figures.jpg')
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# 1) ORB로 서술자 추출
detector = cv2.ORB_create()
kp1, desc1 = detector.detectAndCompute(gray1, None)
kp2, desc2 = detector.detectAndCompute(gray2, None)
# 2) BF-Hamming으로 매칭
matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = matcher.match(desc1, desc2)
# 3) 매칭 결과를 거리기준 오름차순으로 정렬
matches = sorted(matches, key=lambda x:x.distance)
# 4) 최소 거리 값과 최대 거리 값 확보
min_dist, max_dist = matches[0].distance, matches[-1].distance
# 5) 최소 거리의 15% 지점을 임계점으로 설정
ratio = 0.2
good_thresh = (max_dist - min_dist) * ratio + min_dist
# 6) 임계점 보다 작은 매칭점만 좋은 매칭점으로 분류
good_matches = [m for m in matches if m.distance < good_thresh]
print('matches:%d/%d, min:%.2f, max:%.2f, thresh:%.2f' \
%(len(good_matches),len(matches), min_dist, max_dist, good_thresh))
# 7) 좋은 매칭점만 그리기
res = cv2.drawMatches(img1, kp1, img2, kp2, good_matches, None, \
flags=cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS)
# 8) 결과 출력
cv2.imshow('Good Match', res)
cv2.waitKey()
cv2.destroyAllWindows()

(2) knnMatch() 함수
- 디스크립터 당 k개의 최근접 이웃 매칭점을 가까운 순서대로 반환하는 것으로,
- k개의 최근접 이웃 거리 중 거리가 가까운 것은 좋은 매칭점이고, 거리가 먼 것은 좋지 못한 매칭점일 가능성이 높다.
- 최 근접 이웃 중 거리가 가까운 것 위주로 골라내게 되면 좋은 매칭점을 찾을 수 있음
# knnMatch 함수로부터 올바른 매칭점 찾기
import cv2, numpy as np
img1 = cv2.imread('img/taekwonv1.jpg')
img2 = cv2.imread('img/figures.jpg')
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# 1) ORB로 서술자 추출
detector = cv2.ORB_create()
kp1, desc1 = detector.detectAndCompute(gray1, None)
kp2, desc2 = detector.detectAndCompute(gray2, None)
# 2) BF-Hamming 생성
matcher = cv2.BFMatcher(cv2.NORM_HAMMING2)
# 3) knnMatch, k=2
matches = matcher.knnMatch(desc1, desc2, 2)
# 4) 첫번재 이웃의 거리가 두 번째 이웃 거리의 75% 이내인 것만 추출
ratio = 0.75
good_matches = [first for first,second in matches \
if first.distance < second.distance * ratio]
print('matches:%d/%d' %(len(good_matches),len(matches)))
# 5) 좋은 매칭만 그리기
res = cv2.drawMatches(img1, kp1, img2, kp2, good_matches, None, \
flags=cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS)
# 결과 출력
cv2.imshow('Matching', res)
cv2.waitKey()
cv2.destroyAllWindows()

- 최근접 이웃 중 거리가 가까운 것 중 75%만 고름
반응형