728x90

이번 시간에는

 

하나의 이미지가 주어질때 다른것과 어떻게 특징을 매치시키는지 배워봅시다.

 

또, 브루트포스 매처와 플란 매처를 사용해 봅시다.

 

 

 

브루트 포스 매처의 기본 basic of brute-force matcher

 

 브루트 포스 매처는 단순합니다. 첫 집합에서 하나의 특징 기술자를 주어지면 거리 계산 방법으로 두번째 집합에 존재하는 모든 특징들과 매치시켜봅니다. 그리고 가장 가까운것을 반환해줘요.

 

 BF 매처에서는 처음 BF매처를 생성시키고 (cv2.BFMatcher())) 여기서 2개의 옵션 파라미터를 줄수 있습니다. 첫번째 옵션은 거리 측정 방법을 명시해주는데 넘어가고, 두번쨰 파라미터는 교차 검증을 하는것으로 기본적으로 false로 되어있습니다.

 

  매처에서는 A 집합에서 i번째 기술자와 B 집합에서 j번째 기술자가 서로 잘맞는지 매치 결과를 반환해주는데, 같은 집합에 대해 두 특징을 한다면 서로 잘 될거고 일관된 결과를 보여줄겁니다.

 

  일단 매처가 만들어지고 나면, 두 중요한 방법으로 BFMatcher.match()와 BFMatcher.knnMatch()가 있습니다. 첫번째는 최적의 매치를 반환하고, 두번째는 사용자가 지정한 k개만큼의 최적의 매치를 반환해줍니다. 하고싶은 데로 하시면 되겠습니다.

 

 그 다음 키포인트를 그리기 위해서 cv2.keypoints()를 사용했지만 cv2.drawMatches()를 사용해서 매치를 그릴수가 있겠습니다. 이걸 사용하면 두 이미지가 평행하게 놓여지고, 첫번쨰 이미지에서 두번째 이미지로 최적의 매치를 하는 선을 그려줄겁니다. k개의 최적 매치에 대해서 cv2.drawMatchsKnn도 사용할수 있겠습니다.

 

 이제 SURF와 OR의 예시를 한번 보겠습니다

 

 

 

 

 

 

ORB 기술자를 이용한 브루트포스 매칭

 

 두 이미지 사이 피처를 매칭시키는 간단한 예시를 보겠습니다. 이 경우에서 쿼리 이미지와 훈련 이미지가 있는데요. 피처 매칭을 사용해서 트레이닝 이미지에 쿼리 이미지가 어디있는지 찾겠습니다.

 

 우선 시프트 기술자를 사용해서 피처를 매치시켜보겠씁니다. 여기서 이미지를 읽고 기술자를 찾겠습니다.

 

 

 다음으로 할일은 BFMatcher 객체를 생성해서 거리는 cv2.NORM_HAMMING그리고, 더나은 결과를 얻도록 crossCheck를 해줍시다.

 

 10개를 찾아 띄워주면 아래의 결과를 얻을수 있겠습니다.

 

import numpy as np
import cv2
from matplotlib import pyplot as plt

img1 = cv2.imread('./res/box.png',0)          # queryImage
img2 = cv2.imread('./res/box_in_scene.png',0) # trainImage
img3 = img1
# Initiate SIFT detector
orb = cv2.ORB_create()

# find the keypoints and descriptors with SIFT
kp1, des1 = orb.detectAndCompute(img1,None)
kp2, des2 = orb.detectAndCompute(img2,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)

# Draw first 10 matches.
img3 = cv2.drawMatches(img1,kp1,img2,kp2,matches[:10], img3,flags=2)

plt.imshow(img3),plt.show()

 

 

 

 

 

플란 기반 매처 FLANN based Matcher

 

 FLANN은 Fast Library for Approximate Nearest Neighbors를 말하며, 크고 고차원 데이터에서 고속 최근접 탐색을 위해 최적화된 알고리즘들의 집합을 가지고 있습니다. 많은 데이터셋에서 BFMatcher보다 더 빠르게 동작하므로 이번에는 플란 기반 매처를 사용해보겠습니다.

 

 

 플란 기반 매처를 사용하려면, 어떤 알고리즘을 사용할지 명시하는 딕셔너리 두개가 필요합니다. 첫번째는 인덱스 파라미터로 FLANN 문서에 자세히 설명되어있습니다. 

 

import numpy as np
import cv2
from matplotlib import pyplot as plt

img1 = cv2.imread('./res/box.png',0)          # queryImage
img2 = cv2.imread('./res/box_in_scene.png',0) # trainImage

# Initiate SIFT detector
sift = cv2.SIFT_create()

# 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 range(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()

 

 

300x250

+ Recent posts