-
Feature MatchingRobotics/Open CV python 2019. 7. 24. 15:51
Feature Matching
Goal
- 어떻게 features를 한 이미지에서 다른 이미지로 matching 시키는 지 알아볼 것입니다.
- 여기서 Brute-Force matcher 와 FLANN Matcher 를 open cv 에서 사용할 것입니다.
Basics of Brute-Force Matcher
Brute-Force matcher는 간단합니다. 첫 번째 세트에서 한 feature의 descriptor를 가져 와서 일부 거리 계산을 사용하여 두 번째 세트의 다른 모든 피쳐와 일치시킵니다. 그리고 가장 가까운 것이 반환됩니다.
BF matcher의 경우 먼저 cv2.BFMatcher ()를 사용하여 BFMatcher 객체를 만들어야합니다. 두 개의 선택적 매개 변수가 필요합니다. 첫 번째는 normType입니다. 사용할 거리 측정을 지정합니다. 기본적으로 cv2.NORM_L2입니다. SIFT, SURF 등 (cv2.NORM_L1도 거기에 있다)에 좋다. ORB, BRIEF, BRISK 등과 같은 binary string 기반 descriptors의 경우, Hamming distance를 측정으로 사용하는 cv2.NORM_HAMMING이 사용되어야한다. ORB가 VTA_K == 3 또는 4를 사용하는 경우, cv2.NORM_HAMMING2를 사용해야합니다.
두 번째 매개 변수는 boolean variable 인 crossCheck이며 기본적으로 false입니다. 참인 경우, Matcher는 세트 A의 i 번째 설명자가 세트 B의 j 번째 설명자를 최상의 match로 가지도록 하는 값 (i, j)을 갖는 match 만 리턴합니다. (반대도 마찬가지입니다). 즉, 두 세트의 두 features 이 서로 match되야합니다. 일관된 결과를 제공하며 D.Lowe가 SIFT 논문에서 제안한 ratio test의 좋은 대안입니다.
일단 그것이 생성되면, 중요한 두 가지 메소드는 BFMatcher.match ()와 BFMatcher.knnMatch ()입니다. 첫 번째는 가장 match하는 것을 반환합니다. 두 번째 방법은 k가 사용자에 의해 지정된 k 개의 최상의 일치를 반환합니다. 추가 작업이 필요할 때 유용 할 수 있습니다.
우리가 cv2.drawKeypoints ()를 사용하여 키포인트를 그리는 것처럼, cv2.drawMatches ()는 우리가 일치하는 것을 그리는 데 도움이됩니다. 두 개의 이미지를 가로로 쌓고 첫 번째 이미지에서 두 번째 이미지까지 선을 그려 가장 잘 맞는 이미지를 보여줍니다. k 개의 가장 일치하는 것을 끌어 오는 cv2.drawMatchesKnn도 있습니다. k = 2 인 경우 각 키포인트에 대해 두 개의 일치 행을 그립니다. 따라서 선택적으로 그리려면 mask를 전달해야합니다.
SURF와 ORB 각각에 대해 하나의 예제를 보도록하겠습니다. 둘 다 다른 거리 측정을 사용합니다.
Brute-Force Matching with ORB Descriptors
여기서는 두 이미지간에 피쳐를 일치시키는 방법에 대한 간단한 예를 살펴 보겠습니다. 이 경우 queryImage 및 trainImage가 있습니다. 특징 매칭을 사용하여 trainImage에서 queryImage를 찾으려고합니다. (이미지는 /samples/c/box.png 및 /samples/c/box_in_scene.png 입니다.))
SIFT descriptors를 사용하여 features을 일치시킵니다. 이제 이미지로드, descriptors 찾기 등으로 시작합시다.
import numpy as np import cv2 from matplotlib import pyplot as plt img1 = cv2.imread('box.png',0) # queryImage img2 = cv2.imread('box_in_scene.png',0) # trainImage # Initiate SIFT detector orb = cv2.ORB() # find the keypoints and descriptors with SIFT kp1, des1 = orb.detectAndCompute(img1,None) kp2, des2 = orb.detectAndCompute(img2,None)
다음으로 cv2.NORM_HAMMING (ORB를 사용하고 있으므로)을 사용한 거리 측정 으로 BFMatcher 객체를 만들고 crossCheck를 사용하면 더 나은 결과를 얻을 수 있습니다. 그런 다음 Matcher.match () 메서드를 사용하여 두 이미지에서 최상의 일치를 얻습니다. 우리는 거리들을 오름차순으로 정렬하여 최상의 결과 (낮은 거리)가 제일 앞쪽으로 오게 됩니다.. 그런 다음 처음 10 개의 일치 항목 만 표시합니다 (가시성을 위해, 해당 항목을 원하는만큼 늘릴 수 있습니다.).
# 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) # Draw first 10 matches. img3 = cv2.drawMatches(img1,kp1,img2,kp2,matches[:10], flags=2) plt.imshow(img3),plt.show()
다음은 얻은 결과입니다.
What is this Matcher Object?
matches 의 결과=bf.match(des1,des2)푸른선이 DMatch objects의 list 입니다. 이 DMatch object 는 다음의 attributes 를 가지고 있습니다. :
- DMatch.distance- descriptors 간의 거리. 낮을수록 좋습니다.
- DMatch.trainIdx- train descriptors 중 descriptor Index
- DMatch.queryIdx- query descriptors 중 descriptorIndex
- DMatch.imgIdx- train image 의 index
Brute-Force Matching with SIFT Descriptors and Ratio Test
이번에는 BFMatcher.knnMatch ()를 사용하여 k 개의 가장 match하는 항목을 가져옵니다. 이 예제에서 우리는 그의 paper에서 D.Lowe가 설명한 비율 테스트를 적용 할 수 있도록 k = 2를 취할 것입니다.
import numpy as np import cv2 from matplotlib import pyplot as plt img1 = cv2.imread('box.png',0) # queryImage img2 = cv2.imread('box_in_scene.png',0) # trainImage # Initiate SIFT detector sift = cv2.SIFT() # find the keypoints and descriptors with SIFT kp1, des1 = sift.detectAndCompute(img1,None) kp2, des2 = sift.detectAndCompute(img2,None) # BFMatcher with default params bf = cv2.BFMatcher() matches = bf.knnMatch(des1,des2, k=2) # Apply ratio test good = [] for m,n in matches: if m.distance < 0.75*n.distance: good.append([m]) # cv2.drawMatchesKnn expects list of lists as matches. img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,flags=2) plt.imshow(img3),plt.show()
결과는 아래와 같습니다.
FLANN based Matcher
FLANN은 Approximate Nearest Neighbors의 Fast Library를 나타냅니다. 대규모 데이터 세트 및 고차원features에서 nearest neighbor search 을 위해 최적화 된 알고리즘 모음이 포함되어 있습니다. 대규모 데이터 세트의 경우 BFMatcher보다 더 빠르게 작동합니다. FLANN 기반 matcher로 두 번째 예제를 보게 될 것입니다.
FLANN 기반 매처의 경우 사용할 알고리즘, 관련 매개 변수 등을 지정하는 두 개의 사전을 전달해야합니다. 먼저 IndexParams입니다. 다양한 알고리즘에 대해 전달할 정보는 FLANN 문서에 설명되어 있습니다. 요약하면 SIFT, SURF 등과 같은 알고리즘의 경우 다음을 전달할 수 있습니다.
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
ORB를 사용하는 동안 다음을 전달할 수 있습니다. 주석 값은 문서별로 권장되지만 경우에 따라 필요한 결과를 제공하지 않습니다. 다른 값은 잘 작동했습니다.
index_params= dict(algorithm = FLANN_INDEX_LSH, table_number = 6, # 12 key_size = 12, # 20 multi_probe_level = 1) #2
두 번째 사전은 SearchParams입니다. 인덱스의 트리를 재귀 적으로 탐색해야하는 횟수를 지정합니다. 값이 높을수록 정확도가 높아지지만 시간이 더 많이 소요됩니다. 값을 변경하려면 search_params = dict (checks = 100)를 전달하십시오.
이러한 정보를 통해 이제 우리는 잘 할 수 있습니다.
import numpy as np import cv2 from matplotlib import pyplot as plt img1 = cv2.imread('box.png',0) # queryImage img2 = cv2.imread('box_in_scene.png',0) # trainImage # Initiate SIFT detector sift = cv2.SIFT() # find the keypoints and descriptors with SIFT kp1, des1 = sift.detectAndCompute(img1,None) kp2, des2 = sift.detectAndCompute(img2,None) # FLANN parameters FLANN_INDEX_KDTREE = 0 index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5) search_params = dict(checks=50) # or pass empty dictionary 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 xrange(len(matches))] # ratio test as per Lowe's paper for i,(m,n) in enumerate(matches): if m.distance < 0.7*n.distance: matchesMask[i]=[1,0] draw_params = dict(matchColor = (0,255,0), singlePointColor = (255,0,0), matchesMask = matchesMask, flags = 0) img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,**draw_params) plt.imshow(img3,),plt.show()
결과는 아래와 같았습니다.
'Robotics > Open CV python' 카테고리의 다른 글
Feature Matching + Homography to find Objects (0) 2019.07.24 ORB (Oriented FAST and Rotated BRIEF) (0) 2019.07.24 BRIEF (Binary Robust Independent Elementary Features) (0) 2019.07.24 FAST Algorithm for Corner Detection (0) 2019.07.23 SURF (0) 2019.07.22