feature matching에는 세가지가 있다
Brute -Force Matching with ORB Descriptors
Brute-Force Matching with SiFT Descriptors and Ratio Test
FLANN based Matcher
import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
def display(img,cmap='gray'):
fig = plt.figure(figsize=(12,10))
ax = fig.add_subplot(111)
ax.imshow(img,cmap='gray')
reeses = cv2.imread('../DATA/reeses_puffs.png',0)
display(reeses)
그림을 grayscale화 하는 함수를 display로 정의하고, 흑백화된 씨리얼 사진을 불러온다
cereals = cv2.imread('../DATA/many_cereals.jpg',0)
display(cereals)
일렬로 정돈되지 않은 씨리얼 코너의 흑백사진도 불러온다
1. Brute -Force Matching with ORB Descriptors
orb = cv2.ORB_create()
# find the keypoints and descriptors with ORB
kp1, des1 = orb.detectAndCompute(reeses,None) #매칭을 찾은 곳을 선으로 연결
kp2, des2 = orb.detectAndCompute(cereals,None)
# create BFMatcher object 어디가장 매칭이 제대로 되는지 확인
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
# Match descriptors.어디가장 매칭이 제대로 되는지 확인
matches = bf.match(des1,des2)
# Sort them in the order of their distance.매칭을 찾아서 거리에 따라 분류
matches = sorted(matches, key = lambda x:x.distance)
#distance 함수는 매칭이 얼마나 잘되는지 알려줌, 분류를 디스턴스 함수로
# Draw first 25 matches.
reeses_matches = cv2.drawMatches(reeses,kp1,cereals,kp2,matches[:25],None,flags=2)
#매칭이 265개 있는데 이중 일부인 25개만 일단 가져옴 None은 마스크가 필요 있는지 없는지, flags는 실제로 매칭을 어떻게 그릴건지 정의하는 부분
display(reeses_matches)
아무것도 reese puff를 가리키고 있지 안음. ORB 디스크립터를 활용한 Brute Force는 항상 잘 작동하지 않음.특정 매칭 중 더 정밀한 것이 필요함
2. Brute-Force Matching with SIFT Descriptors and Ratio Test
# Create SIFT Object
sift = cv2.xfeatures2d.SIFT_create()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(reeses,None)
kp2, des2 = sift.detectAndCompute(cereals,None)
# BFMatcher with default params
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1,des2, k=2) #두가지 기술자와 k를 필요로함. 쿼리 세트의 각 기술자의 최상의 k수를 찾아줌
#k=3로 하면 세번째값을 산출해낼 수 있음. 첫번째열이 가장 좋은 값이고, 두번쨰가 가장 좋은 값
# Apply ratio test -> 첫번째 값과 두번째가 가깝다면 전체적으로 볼떄 비슷하게 잘 일치된다는 뜻
good = []
for match1,match2 in matches: #매칭값들은 서로 쌍을 이루고 있음
if match1.distance < 0.75*match2.distance: #첫번째 값의 거리와 두번째 값과의 거리가 75% 이하로 나오면 특정열은 좋은 값을 가지고 있다는 뜻, 적은 비율이 나올 수록 좋은값
good.append([match1])
# cv2.drawMatchesKnn expects list of lists as matches.
sift_matches = cv2.drawMatchesKnn(reeses,kp1,cereals,kp2,good,None,flags=2)
display(sift_matches)
잘 매칭됐고, family size가 다른 제품과도 매칭됨
3. FLANN based Matcher
flann기반 매칭형은 기본적으로 딕셔너리 자료형이고 가장깔끔한 값을 낼 수 있지만 모든 일치점을 다 가져와서 보여줌
# Initiate SIFT detector
sift = cv2.xfeatures2d.SIFT_create()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(reeses,None)
kp2, des2 = sift.detectAndCompute(cereals,None)
# FLANN parameters flann은 근접 지점을 찾은 빠른 라이브러리
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5) #파라미터 많이 이용할 수록 속도 늦어짐
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params,search_params) #인덱스 서치 매개변수
matches = flann.knnMatch(des1,des2,k=2)
good = []
# ratio test
for i,(match1,match2) in enumerate(matches):
if match1.distance < 0.7*match2.distance:
good.append([match1])
flann_matches = cv2.drawMatchesKnn(reeses,kp1,cereals,kp2,good,None,flags=0) #마스크 없고 flags는 0이나 2로하면됨
display(flann_matches)
많이 탐지하긴 했고, 리스 퍼프의 패밀리 사이즈라는 단어까지 다른 씨리얼에서 감지됨
리스 퍼프가 어디있는지 감지함
# Initiate SIFT detector
sift = cv2.xfeatures2d.SIFT_create()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(reeses,None)
kp2, des2 = sift.detectAndCompute(cereals,None)
# FLANN parameters
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params,search_params)
matches = flann.knnMatch(des1,des2,k=2)
# Need to draw only good matches, so create a mask
matchesMask = [[0,0] for i in range(len(matches))] #
# ratio test
for i,(match1,match2) in enumerate(matches):
if match1.distance < 0.7*match2.distance:
matchesMask[i]=[1,0] #(0,0)이 (1,0)으로 바뀜, 일치도 높은 선으로 분류될거임
draw_params = dict(matchColor = (0,255,0), #color of line
singlePointColor = (255,0,0),
matchesMask = matchesMask, #좋은 값을 찾아낸 곳과 한 지점을 얻어낸 곳을 알 수 있음
flags = 0)
flann_matches = cv2.drawMatchesKnn(reeses,kp1,cereals,kp2,matches,None,**draw_params)
#flags 대신 **draw_params 매개변수가 좋은 매칭값이 나온 지점의 색상을 바꾸게 됨
#flags 0을 통해서 실제로 지점을 볼 수 있고 2는 선만 나타나게됨
탐지되는것에 색깔을 넣어서 더 잘보이게함
출처: Udemy X KMOOC OpenCV 및 딥러닝을 이용한 Computer vision 파이썬
'Deep Learning > Computer Vision' 카테고리의 다른 글
얼굴 탐지 (0) | 2023.08.10 |
---|---|
Contour Detection (0) | 2023.08.09 |
그리드 검출 (1) | 2023.08.09 |
엣지 검출 (0) | 2023.08.09 |
코너 검출 (0) | 2023.08.08 |