Python/파이썬 OpenCV 공부

[파이썬 OpenCV] 두 영상의 특징점 매칭과 매칭 결과 그리기 - cv2.BFMatcher_create, cv2.DescriptorMatcher, cv2.drawMatches

AI 꿈나무 2020. 10. 17. 15:10
반응형

 두 영상에서 검출한 특징점을 서로 매칭하는 방법을 공부해보겠습니다.

특징점 매칭 - Feature point matching

 특징점 매칭은 두 영상에서 추출한 특징점 기술자를 비교하여 서로 유사한 기술자를 찾는 작업입니다.

 

 

 왼쪽은 4개의 기술자, 오른쪽은 3개의 기술자를 계산했습니다.

 가장 비슷한 것을 찾으므로 4개의 점은 다 매칭이 될 것입니다.

 위 그림에서 #3이 잘못 매칭된 것을 확인할 수 있는데 알고리즘은 가장 거리가 짧은 곳을 찾아서 매칭을 하기 때문에 매칭이 되었습니다.

 이처럼 잘못 연결된 매칭을 걸러내는 작업을 해야합니다.

 

[특징 벡터 유사도 측정 방법]

 

(1) 실수 특징 벡터 : L2 노름(L2 norm) 사용

(2) 이진 특징 벡터 : 해밍 거리(hamming distance) 사용

 

1. OpenCV 특징점 매칭 클래스

 

 match는 가장 비슷한거 1개를 매칭

 knnMatch는 비슷한거 k개를 매칭

 radiusMatch는 반경을 정해두고 반경에 들어오는 비슷한 것을 다 매칭. 갯수는 미지수

 

 실제로 사용할 때는 match, knnMatch, radiusMatch를 상속받은 cv2.BFMatcher or cv2.FlannBasedMatcher를 이용해야 합니다.

 

 cv2.BFMatcher는 BF방법, 전수조사를 합니다.

 특징점이 많으면 시간이 오래 걸립니다.

 

 cv2.FlannBasedMatcher는 특징점이 너무 많은 경우 근사화를 하여 조사하는 방법입니다.

 완전히 최솟값에 매칭을 못할 가능성이 있지만 속도가 빠릅니다.

 내부적으로 KD트리를 이용합니다.

 

 막상 실행해보면 둘의 속도차이는 얼마 없습니다.

 

 반환값은 Dmatch객체를 반환합니다.

 Dmatch는 4개의 멤버를 갖고 있습니다.

 

(1) queryIdx : 1번 이미지의 특징점 번호입니다.

(2) trainIdx : 2번 이미지의 특징점 번호입니다.

(3) imgidx : 두 영상이 아닌 여러 개의 영상을 이용할 때 이 값을 이용합니다.

(4) distance : 매칭될 때의 최소 거리값이 저장됩니다.

 

2. 특징점 매칭 알고리즘 객체 생성 - cv2.BFMatcher_create

cv2.BFMatcher_create(, normType=None, crossCheck=None) -> retval

• normType: 특징점 기술자 거리 계산 방식 지정. 기본값은 cv2.NORM_L2.

 

• crossCheck: 이 값이 True이면 양방향 매칭 결과가 같은 경우만 반환함. 기본값은 False.

 주의할 점은 실수 기술자, 이진 기술자를 쓰는 알고리즘을 구분하여 normType인자를 지정해줘야 합니다.

 

 crossCheck가 True면 좀 더 정확한 형태의 매칭을 할 수 있지만 시간이 소요됍니다. 기본값을 이용해도 됩니다.

 

3. 특징점 검출 알고리즘 객체 생성 - cv2.DescriptorMatcher.match, cv2.DescriptorMatcher.knnmatch

cv2.DescriptorMatcher.match(queryDescriptors, trainDescriptors, mask=None) -> matches

• queryDescriptors: (기준 영상 특징점) 질의 기술자 행렬

• trainDescriptors: (대상 영상 특징점) 학습 기술자 행렬

• mask: 매칭 진행 여부를 지정하는 행렬 마스크.

• matches: 매칭 결과. cv2.DMatch 객체의 리스트.

 querryDescriptors : 1번 영상에서 계산한 기술자

 trainDescriptors : 2번 영상에서 계산한 기술자

 matches의 행의 크기는 querryIdx의 행 크기와 같습니다. 

 

cv2.DescriptorMatcher.knnmatch(queryDescriptors, trainDescriptors, k, mask=None, compactResult=None) -> matches

• queryDescriptors: (기준 영상 특징점) 질의 기술자 행렬

• trainDescriptors: (대상 영상 특징점) 학습 기술자 행렬

• k: 질의 기술자에 대해 검출할 매칭 개수

• mask: 매칭 수행 여부를 지정하는 행렬 마스크

• compactResult: mask가 None이 아닐 때 사용되는 파라미터. 기본값은 False이며, 이 경우 결과 matches는 기준 영상 특징점과 같은 크기를 가짐.

• matches: 매칭 결과. cv2.DMatch 객체의 리스트의 리스트

 knnmatch는 가장 유사한 특징점 두 새개를 결과로 받습니다.

 k값을 지정할 수 있습니다.

 

4. 특징점 매칭 결과 영상 생성 - cv2.drawMatches

cv2.drawMatches(img1, keypoints1, img2, keypoints2, matches1to2, outImg, matchColor=None, singlePointColor=None, matchesMask=None, flags=None) -> outImg

• img1, keypoints1: 기준 영상과 기준 영상에서 추출한 특징점 정보

• img2, keypoints2: 대상 영상과 대상 영상에서 추출한 특징점 정보

• matches1to2: 매칭 정보. cv2.DMatch의 리스트.

• outImg: 출력 영상 (None)

• matchColor: 매칭된 특징점과 직선 색상, 랜덤한 색상

• singlePointColor: 매칭되지 않은 특징점 색상

• matchesMask: 매칭 정보를 선택하여 그릴 때 사용할 마스크

• flags: 매칭 정보 그리기 방법. 기본값은 cv2.DRAW_MATCHES_FLAGS_DEFAULT.

 img1, keypoints1, img2, keypoints2, matches1to2, outImg 까지 지정하고 나머지 인자는 기본값을 이용해도 됩니다.

 

5. 특징점 매칭 예제

예제 코드 출처 :  황선규 박사님 github홈페이지 sunkyoo.github.io/opencv4cvml/

 

# 영상 불러오기
src1 = cv2.imread('graf1.png', cv2.IMREAD_GRAYSCALE)
src2 = cv2.imread('graf3.png', cv2.IMREAD_GRAYSCALE)

if src1 is None or src2 is None:
    print('Image load failed!')
    sys.exit()
    
# 특징점 알고리즘 객체 생성 (KAZE, AKAZE, ORB 등)
feature = cv2.KAZE_create()
#feature = cv2.AKAZE_create()
#feature = cv2.ORB_create()

# 특징점 검출 및 기술자 계산
kp1, desc1 = feature.detectAndCompute(src1, None)
kp2, desc2 = feature.detectAndCompute(src2, None)

# 특징점 매칭
matcher = cv2.BFMatcher_create()
#matcher = cv2.BFMatcher_create(cv2.NORM_HAMMING) # 이진 기술자를 사용하는 알고리즘
matches = matcher.match(desc1, desc2)

print('# of kp1:', len(kp1))
print('# of kp2:', len(kp2))
print('# of matches:', len(matches))

# 특징점 매칭 결과 영상 생성
dst = cv2.drawMatches(src1, kp1, src2, kp2, matches, None)

cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()

 

특징점 매칭

 

 결과가 너무 복잡해서 매칭이 잘 된건지 확인하기가 어렵습니다.

 더 좋은 매칭 결과를 얻기 위해서는 1번 이미지에서 검출된 특징점들이 2번 이미지에서 무조건 1개를 찾는다는 처리를 해줘야 합니다.

 이처럼 좋은 매칭 결과를 선별하는 방법은 다음 포스팅에서 공부해보도록 하겠습니다. 

 


OpenCV 튜토리얼과 황선규 박사님의 'OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝' 을 공부하면서 정리해 보았습니다.

docs.opencv.org/4.3.0/dc/dc3/tutorial_py_matcher.html

반응형