본문 바로가기
OpenCV/OpenCV-Chapter

CH09 OpenCV-Python SIFT, KAZE, AKAZE, ORB..

by kiimy 2021. 12. 25.
728x90

Harris, GFTT, FAST 코너의 문제점

• 이동, 회전 변환에 강인

• 크기 변환에 취약

그림1, 그림2, 그림3

작은 사각형 가지고 Corner를 찾을려하니 그림2처럼 Edge처럼 보임
그래서 사각형을 키우거나 Image를 resize하는 다양항 크기의 형태도 고려해야함

• 특징점(feature point) ≈ 키포인트(keypoint) ≈ 관심점(interest point)

= 다양한 크기의 형태를 고려한 점들

 

• 기술자(descriptor) ≈ 특징 벡터(feature vector)

= 특징점 주변에 부분영상을 잘라서 그 특징점에 대한 특징을 기술하는 방법

 

크기 불변 특징점 검출 방법

SIFT, KAZE, AKAZE, ORB 등 다양한 특징점 검출 방법에서 스케일 스페이스(scale-space),

이미지 피라미드(image pyramid)를 구성하여 크기 불변 특징점을 검출

scale-space = resize, gaussian영상의 세트를 만드는 것

기술자(descriptor)

 행 개수: 특징점 개수

 열 개수: 특징점 기술자 알고리즘에 의해 정의됨

 실수 기술자: numpy.float32 / 이진 기술자: numpy.uint8

한 행 = (32/ 8) * 64 byte

실수 기술자( KAZE, SIFT, SURF ) 

- 주로 특징점 부근 부분 영상의 방향 히스토그램을 사용(HOG)

- 두 개의 특징벡터가 같은지 다른지 판단하는 용도로 사용(= 유클리디안 L2 Norm)

= 유클리디안을 사용하여 유사도 판단

이진 기술자( AKAZE, ORB )

- 밝기의 차이값으로 이진수로 잘 표현한 것

- 두 개의 특징벡터를 나열하고(이진수 나열) 이 이진수 중에 두개 bit가 서로 다른게 몇개 있나

  Counting하는 방식(= Hamming distance 해밍거리)

= 해밍 거리(Hamming distance)를 사용하여 유사도를 판단

    (e.g.) d1 = 1011101, d2 = 1001001 인 경우 해밍 거리는 2.

부분영상에서 특징점을 가정

이진 기술
특징점을 가정하고 부분영상을 잘라내서 1, 2, 3 각 위치에 밝기를 비교
1 > 2 == 1 
2 < 3 == 0 
1 > 3 == 1

OpenCV 특징점 검출 클래스

'''
sift = cv2.xfeatures2d.SIFT_create() 좋음
'''
# 특징점 알고리즘 객체 생성 (KAZE, AKAZE, ORB 등)

feature = cv2.KAZE_create() # 방향 성분 x( 0도 )
feature = cv2.AKAZE_create() # 방향 성분 o
feature = cv2.ORB_create() # 상당히 빠름
cv2.ORB_create(1000) 검출할 특징점 개수, default = 500

feature ==> cv2.Feature2D
            detect(), compute(), detectAndCompute()

############################################################################

keypoints= cv2.KeyPoint객체의 리스트
pt, size, angle
pt = x좌표, y좌표 (float)
size= 특징점을 검출할 때 어느정도 주변의 크기로 검출 했냐
angle = 특징점을 검출하고나서 그 특징점 주변영상을(기술자) 계산할때
        방향에 대한 주된 방향성분을 계산해서 그 주된 방향성분만큼 보정한다.
        그리고 특징벡터를 계산, 즉 부분영상의 주된 방향
# src2 = 기울어진 영상
src1 = cv2.imread('ch09\\images\\graf1.png', cv2.IMREAD_GRAYSCALE)
src2 = cv2.imread('ch09\\images\\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() # 방향 성분 x( 0도 )
#feature = cv2.AKAZE_create() # 방향 성분 o
#feature = cv2.ORB_create() # 상당히 빠름

# 특징점 검출 및 기술자 계산
kp1 = feature.detect(src1)

# 특징점 기술자 계산 함수
_, desc1 = feature.compute(src1, kp1)
'''
-> keypoints, descriptors
'''

# 특징점 검출 및 기술자 계산(detect, compute)
# 이 두가 지가 모두 가능한 class를 사용해야해(Fastfeaturedetector?? = detection만 됨)
# kp1, desc2 = feature.detectAndCompute(src1, None)
kp2, desc2 = feature.detectAndCompute(src2, None)

print('desc1.shape:', desc1.shape) # column의 갯수는 무조건 동일()
print('desc1.dtype:', desc1.dtype)
print('desc2.shape:', desc2.shape)
print('desc2.dtype:', desc2.dtype)

# 검출된 특징점 출력 영상 생성
# for loop 굳이 안돌리고 drawKeypoints 사용
dst1 = cv2.drawKeypoints(src1, kp1, None, 
                        flags= cv2.DRAW_MATCHES_FLAGS_DEFAULT)
dst2 = cv2.drawKeypoints(src2, kp2, None, 
                        flags= cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
'''
cv2.DRAW_MATCHES_FLAGS_DEFAULT
= 특징점 위치만을 표현하는 작은 크기의 원

DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS
= 특징점의 크기와 방향을 반영한 원
'''

cv2.imshow('src1', src1)
cv2.imshow('src2', src2)
cv2.imshow('dst1', dst1)
cv2.imshow('dst2', dst2)
cv2.waitKey()

DRAW_MATCHES_FLAGS_DEFAULT / DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS
AKAZE를 사용해도 성능 충분

 

728x90

댓글