특징 매칭

qkdk·2024년 8월 21일

openCV

목록 보기
6/15
post-thumbnail

특징 매칭을 활용하면 1차 이미지와 2차 이미지가 완전히 동일할 필요 없다.

KeyPoint & Descriptor

KeyPoint와 Descriptor는 특징(Feature) Point 사용되는

  • KeyPoint

    • 이미지 내의 특정한 점이나 위치를 나타냄
    • 이미지 내의 위치 정보만 가지고 있음
  • Descriptor

    • KeyPoint 주변의 이미지를 설명하는 특징 벡터.
    • Descriptor는 주변의 이미지를 특징 벡터로 변환하여, 서로 다른 이미지간 비교를 가능하게 함

Brute Force Matcing With ORB Descriptor

ORB ( Oriented FAST and Rotated BRIEF )

  • FAST 알고리즘

    • KeyPoint를 탐지
    • 픽셀 주변의 임계값을 적용, 어두운 픽셀, 밝은 필셀, 유사한 픽셀로 분류
  • BRIEF 알고리즘

    • Descriptor를 생성하는데 사용
    • Key Point 에 대한 이진 벡터를 만들어 내는데 사용
    • 회전에 민감하다는 점 존재
  • ORB

    • FAST가 코너 뿐만 아니라 엣지도 검출하는 문제로 인해 ORB에서는 Harris 코너 검출 알고리즘을 같이 활용해서 KeyPoint 탐지
    • KeyPoint 주변 그라디언트 방향 계산해 방향 벡터 생성, BREIF 알고리즘에 회전 불변성을 갖도록 보완

# Example
orb = cv2.ORB_create()
kp1, des1 = orb.detectAndCompute(resses, None)
kp2, des2 = orb.detectAndCompute(resses, None)

bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck = True)

matches = bf.match(des1, des2)

matches = sorted(matches, key=lambda x:x.distance)

detectAndCompute를 사용해 KeyPoint와 Descriptor를 생성하고, matcher의 match 매소드를 사용해 유사도 분석

유사도는 이미지 벡터간의 거리로 계산 되기 때문에, distance가 작을수록 유사한 특징

성능이 생각보다 좋지 않다...

Brute-Force Matching With SIFT Descriptors and Ratio Test

SIFT 알고리즘

  • feature 추출에 있어서 성능은 좋으나 시간이 오래걸림
  • 한꺼번에 KeyPoint와 Descriptor추출

동작과정

  1. Scale-space extreama Detection
    Scale - Space 만들기
    이미지의 크기를 늘리고 여러 이미지를 만들고, Gaussina 필터를 적용해 점점 bluring 시킨 이미지들을 만든다.
    총 20개의 이미지 생성
    DoG (Differnece of Gaussian)
    Gaussian 필터를 이용해 bluring 시킨 이미지에서 인접한 이미지를 빼서 만든값
    SIFT알고리즘에서는 16(20 - 4)개의 이미지 생성

    Scale이 중요한 이유 : 스케일-불변 특징 (Scale-Invariant Features)
    같은 이미지라도 크기가 커지면, 특정 범위에 대한 기울기가 달라지기 때문에, Edge와 Corner와 같은 특성들이 달라짐
    여러 Scale에서도 검출되는 Feature(Edge, Corner,...)가 신뢰성 높은 Feature라 볼수있다.

  2. keypoint localization

    • 나쁜 Keypoint 제거
      • 코너가 아닌 엣지에 있는경우
      • 임계점(treshold) 보다 낮은 경우
  3. Oriented Assignment

  4. Keypoint Descriptor Generation

# SIFT Descriptors
kp1, des1 = sift.detectAndCompute(reeses, None)
kp2, des2 = sift.detectAndCompute(reeses, None)

bf = cv2.BFMatcher()
matches = bf.knnMatch(des1, des2, k=2)


# Ratio Test
good = []
for match, match2 in matches:
	if match1.distance < 0.75 * match2.distance:
    	good.append([match1])
        
sift_matches = cv2.drawMatchesKnn(reeses,kp1,cereals,kp2,good,None,flags=2)
  • knnMatch
    • 일치하는 특징 여러개를 리턴

ORB와 비교했을때 더 좋은 성능을 확인할수 있다.

FLANN BASED MATCHER

FLANN

  • Fast Library for Approximate Nearest Neighbors
  • Brute Force기반 Matcher에 비해 빠르다.
  • K-D Tree, kMeans 와 같은 자료구조를 사용해 대용량 대이터에서 더욱 빠른 속도를 가질 수 있다.
  • 모든 데이터를 탐색하는 것이 아닌, 이웃하는 데이터 끼리 탐색을 진행하기 때문에, 결과가 BF에 비해 부정확할 수 있다.
# Example
sift = cv2.xfeatures2d.SIFT_create()

kp1, des1 = sift.detectAndCompute(reeses,None)
kp2, des2 = sift.detectAndCompute(cereals,None)

# FLANN
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(check = 50)

flann = cv2.FlannBasedMatcher(index_params, search_params)

# ---- 나머지는 SIFT와 동일 ----

cv2.FlannBasedMatcher - index_params

  • dict 형태
  • algorithm
    • 0: Linear (브루트 포스 방식)
    • 1: KD-Tree
    • 2: KMeans
    • 6: LSH (Locality Sensitive Hashing)
  • trees: KD-Tree를 사용할 때 트리의 수를 지정합니다.
    ...

cv2.FlannBasedMatcher - search_params

  • dict 형태
  • checks
    • 검색할 후보 수
    • 많을 수록 성능 🔺 속도 🔻
profile
qkdk

0개의 댓글