특징을 나타내는 값을 매칭하기 위해서는 회전이나 크기 등에 영향이 없어야 하며, 이를 위해서는 feature descriptor(특징 디스크립터)가 필요하다. 특징 디스크립터는 keypoint의 주변의 밝기나 색상 등의 정보를 표현한 것으로, keypoint의 주변 픽셀을 일정한 크기로 나눈 후 각 영역에 대한 pixel의 그래디언트를 계산한 것이 된다. 특징 디스크립터를 활용한 검출기의 종류는 다음과 같다.

ORB(Oriented FAST and Roteted BRIEF) FAST 코너 검출기와 BRIEF의 회전이 고려되도록 한 것
SIFT(Scale Invariant Feature Transform) 크기 변화에 관계없이 특징 검출이 이루어지도록 한 것
SURF(Speed Up Robust Features) SIFT의 처리 속도를 개선한 것

 

1. ORB

ORB에서 BRIEF(Binary Robust Independent Elementary features)는 특징 디스크립터를 검출하지 않고 binary 문자열을 구하는 역할을 한다. 단, OpenCV 4.2.0 버전에서는 SIFT와 SURF가 지원되지 않는다. 

 

pip install opencv-python==3.4.2.16
pip install opencv-contrib-python==3.4.2.16

SIFT와 SURF를 사용하려면 커맨드 창에서 위와 같이 OpenCV 버전 다운그레이드를 통해서 실행할 수는 있으나 작업 환경 유지를 위해 이 글에서는 ORB를 중심으로만 다룬다. ORB로 keypoint를 검출하는 방법은 아래와 같다.

import cv2
import numpy as np

img = cv2.imread('weapon/search/vector.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# ORB 생성
orb = cv2.ORB_create(50)

# keypoint 검출 및 descriptor 계산
keypoint, descriptor = orb.detectAndCompute(img, None)

# keypoint 표시
draw = cv2.drawKeypoints(img, keypoint, None, flags = cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

cv2.imshow('ORB', draw)
cv2.waitKey()
cv2.destroyAllWindows()

ORB 검출기를 생성하는 cv2.ORB_create()는 [최대 검출 특징 수, 이미지 피라미드 비율, 이미지 피라미드 계층, 제외할 테두리 크기, 이미지 피라미드 최초 계층, 임의의 좌표 생성 수, keypoint 검출 방식, descriptor 패치 크기, FAST에 사용할 임계값]을 인자로 사용한다. default 값으로는 다음과 같이 설정된다.

최대 검출 특징 수 500
이미지 피라미드 비율 1.2
이미지 피라미드 계층 8
제외할 테두리 크기 31
이미지 피라미드 최초 계층 0
임의의 좌표 생성 수 2
 keypoint 검출 방식 cv2.ORB_HARRIS_SCORE
descriptor 패치 크기 31
FAST에 사용할 임계값 20

이미지 피라미드란 다음을 의미한다. 일반적으로는 일정한 크기의 이미지로 작업을 수행하지만, 이미지의 크기를 확대하거나 축소하면서 해상도가 다른 이미지를 만들어서 분석하는 경우도 발생한다. 이 때, 이렇게 생성된 이미지 집합을 이미지 피라미드라 한다. 또한, cv2.ORB_create()를 사용할 때는 제외할 테두리 크기와 descriptor 패치 크기는 같은 값을 설정해야 한다. keypoint 검출 방식의 경우 cv2.ORB_FAST_SCORE로 바꿔서 속도를 높일수는 있지만 좋지 못한 결과를 얻을 수도 있으니 주의해야 한다.

 

2. BFmatcher

BRMacther(Brute-Force matcher)는 매칭의 기준이 되는 디스크립터와 매칭의 대상이 되는 디스크립터에 대해 하나씩 매칭하는 것으로 cv2.BFMatcher를 사용한다.

import cv2
import numpy as np

img1 = cv2.imread('lion.jpg')
img2 = cv2.imread('image.jpg')
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)


orb = cv2.ORB_create(50)

keypoint1, descriptor1 = orb.detectAndCompute(gray1, None)
keypoint2, descriptor2 = orb.detectAndCompute(gray2, None)

# BFmatcher 생성 및 계산
matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck = True)
match = matcher.match(descriptor1, descriptor2)

draw = cv2.drawMatches(img1, keypoint1, img2, keypoint2, match, None, flags = cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS)

cv2.imshow('BFMatcher & ORB', draw)
cv2.waitKey()
cv2.destroyAllWindows()

cv2.BFMatcher는 [거리 측정 방법, 상호 매칭 반영 여부]가 인자로 사용되며, 거리 측정 방법의 종류는 다음과 같다.

cv2.NORM_L1 
cv2.NORM_L2(default)
cv2.NORM_L2SQR
cv2.NORM_HAMMING
cv2.NORM_HAMMING2

상호 매칭 반영 여부는 default로 False가 설정되며, ORB의 경우 NORM_HAMMING을 주로 사용한다. 상호 매칭 반영 여부를 True로 지정하면 2가지의 디스크립터 모두에서 매칭이 성립하는 것만 반영된다는 장점을 얻지만 속도가 느려진다는 단점도 갖는다.

728x90
반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 라이프코리아트위터 공유하기
  • shared
  • 카카오스토리 공유하기