Python/파이썬 OpenCV 공부

[파이썬 OpenCV] 영상의 특징점 검출과 특징점 그리기 - KAZE, AKAZE, ORB - cv2.Feature2D.detect, cv2.drawKeypoints

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

1. Harris, GFTT, FAST 코너 검출 방법의 문제점

 이전 포스팅에서 공부했던 Harris, GFTT, FAST 코너 검출 방법은 이동, 회전 변화에 강인하지만 크기 변환에 취약하다는 단점이 있습니다.

 

 

 확대된 영상에서 작은 사각형으로 코너를 찾으려하면 기존의 코너가 에지처럼 보이게 됩니다.

 이 경우에 다양한 크기 관점에서 특징점을 검출하는 것이 필요합니다.

 입력 영상을 줄이거나 박스를 키우거나 해야 합니다.

 즉, 코너를 찾을 때 오리지널 사이즈만 보는것이 아니라 다양항 크기도 고려를 해서 코너 형태를 찾는 것이 고유한 특징을 찾는데에 적합합니다.

 

2. 특징점 검출

 고유한 특징을 나타내는 점들을 집합한 것을 특징점(feature point) or 키포인트(keypoint) or 관심점(interest point) 라고 합니다.

 

 특징점 주변의 부분 영상을 짤라서 특징점에 대한 특징을 기술하는 방법기술자(descriptor) or 특징 벡터(feature vector)이라고 합니다.

 

 두 개의 영상이 같은지 다른지 판별하기 위해 매칭을 할 때 특징점을 활용합니다.

 

3. 크기 불변 특징점 검출 방법

 SIFT, KAZE, AKAZE, ORB 등 다양한 특징점 검출 방법에서 스케일 스페이스(scale-space), 이미지 피라미드(image pyramid)를 구성하여 크기 불변 특징점을 검출합니다.

 

 스케일 스페이스(Scale Space)는 리사이즈와 가우시안 블러링을 여러번 하는 방법입니다.

 가우시안 블러링을 통해 초점이 안맞는 가상의 영상을 만들어 완전한 코너는 아니지만 반복적으로 검출될 수 있는 점들을 검출하는 형태로 구현합니다. 대표적인게 SHIFT 입니다.

 

4. OpenCV 특징점 검출 클래스 - Feature2D 클래스와 파생 클래스

 OpenCV에서 여러가지 특징점 검출 방법이 구현되어 있습니다.

 

 

 Feature2D 클래스에 자식 클래스 형태로 구현되어 있습니다.

 Feature2D 클래스에 선언된 detect(), compute(), detectAndCompute() 함수는 자식 클래스에서도 이용할 수 있습니다.

 

 SHIFT와 SURF는 특허가 걸려있어 상업적으로 이용할 때는 특허료를 내야합니다.

 하지만 SHIFT는 특허가 만료되서 4.4버전부터 사용이 가능합니다.

 

 위 그림에 나와있는 방법들은 특징점 검출, 특징점 기술, 둘 다 가능한 알고리즘 3종류로 구분할 수 있습니다.

 특징점을 기술할 수 없는 알고리즘에 특징점 기술 함수를 사용하면 프로그램이 종료될 수 있습니다.

 

 여기에 나와있는 방법 이외에도 OpenCV에서 제공하는 다양한 몇십가지 방법이 있습니다.

 

 KAZE, AKAZE, ORB가 유명하므로 예제 코드에서 세 가지 방법만 구현해보겠습니다.

 

5. 특징점 검출 알고리즘 객체 생성 - cv2.방법_create

 특징점 검출을 위해서는 각 클래스를 생성해야 합니다.

 

cv2.KAZE_create(, ...) -> retval

cv2.AKAZE_create(, ...) -> retval

cv2.ORB_create(, ...) -> retval

cv2.xfeatures2d.SIFT_create(, ...) -> retval

• retval: 각 특징점 검출 알고리즘 객체

• 참고사항
  ▪ 각각의 알고리즘은 고유한 파라미터를 인자로 받을 수 있음
  ▪ 대부분의 인자는 기본값을 가지고 있으므로 함수 인자 없이 호출 가능

 retval는 각각의 알고리즘에 대한 클래스 객체를 반환해줍니다.

 이 클래스 객체에 detect 함수를 호출하면 특징점 고유한 알고리즘을 이용해서 검출합니다.

  

6. 특징점 검출 함수 - cv2.Feature2D.detect

cv2.Feature2D.detect(image, mask=None) -> keypoints

• image: 입력 영상

• mask: 마스크 영상

• keypoints: 검출된 특징점 정보. cv2.KeyPoint 객체의 리스트.

 리턴 값은 키포인트와 키포인트 객체의 리스트로 반환합니다.

 

 키포인트 클래스는 pt, size, angle 3가지 변수를 갖고 있습니다.

 이것 말고 더 갖고 있지만 주로 기억해야 할 것은 저 3개입니다.

 

 pt는 float 형태로 x,y 좌표를 저장합니다.

 size는 특징점을 검출할 때 어느정도 주변 크기를 가지고 특징점을 검출했는지에 대한 정보

 angle은 부분 영상의 주된 방향 변수입니다. 알고리즘에 따라서 angle을 계산해주는 것이 있고 안해주는 것이 있습니다.

 

 특징점을 검출하고 나서 특징점 주변 영상을 기술하는 기술자, 특징 벡터를 계산할 때 방향에 대한 보정을 합니다.

 주된 방향 성분을 계산해서 주된 방향 성분만큼 보정해서 특징 벡터를 계산하는데 그때 사용할 부분 영상의 주된 방향 성분이 angle입니다.

 

7. 검출된 특징점 그리기 함수 - cv2.drawKeypoints

 Keypoints 를 검출하고나서 어느 위치에 존재하는지 확인하기 위해 그려볼 수 있습니다.

 

cv2.drawKeypoints(image, keypoints, outImage, color=None, flags=None) -> outImage

• image: 입력 영상

• keypoints: 검출된 특징점 정보. cv2.KeyPoint 객체의 리스트.

• outImage: 출력 영상

• color: 특징점 표현 색상. 기본값은 (-1, -1, -1, -1)이며, 이 경우 임의의 색상으로 표현.

• flags: 특징점 표현 방법.
 (1) cv2.DRAW_MATCHES_FLAGS_DEFAULT : 특정한 위치만을 표현하는 작은 크기의 원
 (2) cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS : 특징점의 크기와 방향을 반영한 원

 cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS는 키포인트에 있는 사이즈나 앵글에 들어있는 변수를 고려해서 다양항 크기로 그려지고 방향 성분까지 직선을 이용해서 표현합니다. flags 플래그 2번째를 이용하는 것이 키포인트를 분석하는 데에 유용합니다.

 

8. 특징점 검출 예제 - KAZE, AKAZE, ORB

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

 

KAZE, AKAZE, ORB 세 가지 방법을 구현하겠습니다.

 KAZE는 방향성분은 표현이 안됩니다.

 

 AKAZE는 내부적으로 FAST 코너 검출을 적용하고, 이미지 피라미드 각각의 영상에서 코너를 검출하여 코너들이 중첩되어 동심원이 많이 보입니다. 또한 방향 성분을 표현합니다.

 

 ORB는 속도가 가장 빠릅니다.

 

# 영상 불러오기
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() # 카제를 빠르게, accelateKaze, 방향선분 표현
# feature = cv2.ORB_create() # 가장 빠르지만 성능이 떨어짐

# 특징점 검출
kp1 = feature.detect(src1)
kp2 = feature.detect(src2)

# 검출된 특징점 갯수 파악
print('# of kp1:', len(kp1))
print('# of kp2:', len(kp2))

# 검출된 특징점 출력 영상 생성
dst1 = cv2.drawKeypoints(src1, kp1, None, 
						 flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
dst2 = cv2.drawKeypoints(src2, kp2, None,
                         flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

# 영상 출력
cv2.imshow('dst1', dst1)
cv2.imshow('dst2', dst2)
cv2.waitKey()
cv2.destroyAllWindows()

 

1. KAZE

 

 

2. AKAZE

 

 

3. ORB

 

 

 ORB에서 동심원이 많이 보이는 이유는 내부적으로 이미지 피라미드를 적용하고 각각의 영상에 FAST 코너 검출을 이용하기 때문입니다. 가장 빠르지만 성능이 떨어집니다.

 


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

docs.opencv.org/4.3.0/db/d27/tutorial_py_table_of_contents_feature2d.html

반응형