(생략했지만)
이전까지는 해리스 같은 코너 검출기들을 살펴보았습니다. 이들은 회전 불변으로, 이미지가 회전이 된다해도 같은 코너점을 찾을수가 있겠습니다. 하지만 크기변화에선 어떨까요?
이미지가 크기가 조정되면 코너가 더이상 코너가 안될수도 있습니다. 예를들자면 아래의 그림을 한번 살펴보세요. 왼쪽 그림에서 코너는 작은 윈도우에 들어갔지만, 줌해서 커진경우에는 여러 부분들을 찾을수가 있겠습니다.
그래서 해리스 코너는 크기 변화에 불변하지 않다고 얘기 합니다.
2004년 D.Lowe는 새로운 알고리즘으로 크기에 불변한 특징 변환 이라고 하는 SIFT 알고리즘을 제안하였습니다. 여기서 크기 불변 키포인트로 이미지 특징이라는 논문에서 키포인트를 추출하고, 기술자를 계산하는 방법에 대해서 소개하고 있습니다.
SIFT 알고리즘에대해서 4단계로 나누어 설명해보겠습니다.
1. 크기 공간 극점 검출 Scale-space Etrema Detection
위 그림을 보시면 다른 스케일의 키포인트를 검출할때 같은 크기의 윈도우를 사용할수가 없는걸 봤었습니다. 작은 코너라면 괜찬겠죠. 하지만ㄴ 큰 코너를 구한다면 큰 윈도우가 필요할겁니다.
이것떄문에 크기 공간 필터가 사용됩니다. 이를 위해서 다양한 분산 값 omega을 가진 이미지의 LoG Laplacian of Gaussian을 구해보겠습니다. LoG는 방울 검출기 처럼 동작을할건데 omega의 값 변화에 따라 다양한 크기의 blob을 검출하게 될겁니다.
여기서 omega는 스케일 파라미터로 사용되어, 위 영상에서 omega가 작은 가우시안 커널을 사용한다면 작은 코너들을 찾아낼것이고, 큰 omega값을 가진 가우시안 커널을 사용시 큰 코너들을 찾아낼 겁니다.
이렇게 해서 다양한 스케일에 대해 지역 극대점을 찾아내고, 이들을 (x, y, omega)값의 목록으로 정리하겠습니다. 이 값의 의미는 omega 스케일의 공간에서 (x, y)에서 키포인트를 의미합니다.
하지만 LoG는 계산하기에는 비용이커 SIFT 알고리즘은 DoG Differeence of Gaussian을 사용하게되는데 이는 LoG를 근사시킨거라고 할수 있겠습니다. DoG 필터는 두개의 다른 omega로 블러링한 가우시안 영상의 차이로 얻을수가 있겠습니다. 이 방법은 가우시안 피라미드에서 다른 옥타브를 가진것끼리 차 연산을해서 얻을수가 있겠습니다.
그래서 DoG를 구하면, 크기와 공간에 대해서 지역 특징들을 찾을겁니다. 어느 이미지에서 한 픽셀들은 주위의 8개 이웃과 비교할거고, 또 이전 스캐일의 9픽셀과 비교하겠습니다. 이 픽셀이 지역적으로 극점이라면, (잠재적인 키포인트라 판단하고) 해당 스케일에서 최적인 키포인트가 되겠습니다. 이에 대한 그림은 아래와 같습니다.
이 논문에서는 4개의 옥타브와 5개의 스케일 레벨이 주어지고, 초기값으로 omega = 1.6, k = root(2)를 줄때 최적의 결과를 얻을수 있다고 합니다.
2. 키포인트 위치 추정 keypoint localization
잠재적 키포인트의 위치를 찾아내었다면, 실제 결과를 얻기 위해 재정의 하겠습니다. 극점의 정확한 위치를 얻기 위해 스케일 공간에 대해 테일러 전개를 사용할건데, 이 극점에서의 강도가 임계값 0.03(논문에서)보다 작다면 극점이 아닌것으로 판단합니다. 여기서 사용하는 임계치를 contrastTrheshold라 부릅니다.
DoG는 에지에서 강한 응답을 보이는데, 그래서 에지를 제거하여야 합니다. 해리스 코너에서 본것과 비슷한 컨샙을 사용할건데, 2 x 2 해시안 행렬을 사용해서 곡률을 계산하겠습니다
. 해리스 코너 검출기에서 에지의 경우 고유값은 다른것보다 크다는 사실을 알고 있으므로, 이를 간단한 함수로 사용할수 있는데, 이 비율이 임계치보다 크면 그 잠재적 키포인트는 제거하겠습니다. 이렇게 하여 차이가 적은 키포인트와 에지들을 제거하여 강인한 점들만 남게 됩니다.
3. 방향 할당 orientation assingment
각각의 키포인트에는 이미지 회전에 강인할수 있도록 방향이 배정됩니다. 키포인트 주위에 있는 이웃점들은 스케일에 의존하고, 그라디언트 크기와 방향은 이 공간에서 계산할수 있겠습니다. 360도 방향을 다루기위해 36개의 이진 값을 가진 방향 히스토그램을 만들겠습니다.
이 히스토그램은 가우시안 크기와 가우시안 가중치 원형 윈도우(oemga는 1.5인)으로 가중화 될건데, 히스토그램의 가장 높은 지점이나 80%이상인 지점을 방향으로 계산하겠습니다. 이를 통해 같은 크기위 위치를 가졌으나 다른 방향인 키포인트가 만들어지겠습니다. 이 개념이 추후 매치하는데 사용되겠습니다.
4. 키포인트 기술자 keypoint descriptor
이제 키포인트 기술자를 만들어보겠습니다. 키포인트 주위에 16 x 16크기의 이웃점들을 사용할건데 이들을 4 x4 크기의 16개 작은 블록으로 나누겠습니다. 각각의 작은 블록들을 8 이진 방향 히스토그램으로 만들겠습니다. 총 128개의 이진 값들을 얻겠습니다. 이렇게 얻은 벡터를 기포인트 기술자라고 부르겠습니다. 키포인트 기술자를 사용해서 조명 변화나 회전에 강인해질수 있겠습니다.
5. 키포인트 매칭
두 영상 사이의 키포인트를 주위의 최근접 이웃들을 확인해서 매치시킬수가 있겠습니다. 하지만 어떤 경우에는 가장 가까운것보다 두번째것들이 가장 가까울수가 있는데요. 이 경우에는 노이즈나 다른 이유로 발생할수도 있겠습니다. 이 경우에는 두번째 최근접 거리에 대한 최근접 거리의 비율이 필요하겠습니다. 0.8보다 크면 이들은 제거되어 90% 오탐을 제거하는 반면에 5%의 정탐만을 제거한다고 합니다.
import cv2
import numpy as np
img = cv2.imread('./res/home.jpg')
gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
sift = cv2.SIFT_create()
kp = sift.detect(gray,None)
#img=cv2.drawKeypoints(gray,kp, img)
img=cv.drawKeypoints(gray,kp,img,flags=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow("img",img)
cv2.waitKey(0)
cv2.destroyAllWindows()
- 위 코드에서 kp는 키포인트들의 목록이고, des는 키포인트의 배열로
(kepyoint 개수) x128 형태가 된다고 한다.
sift.detect()에서 죽으니 대신 결과 캡처해서 올린다.
=> 보니까 기존의 opencv-python 튜토리얼은 이전 버전 기준이라 죽었었다.
opencv 4.4.0 기준 현재 수정한 코드를 사용하면 잘 동작된다.
'로봇 > 영상' 카테고리의 다른 글
opencv-python 튜토리얼 - 23. FAST (0) | 2020.08.15 |
---|---|
opencv-python 튜토리얼 - 22. SURF (0) | 2020.08.15 |
opencv-python 튜토리얼 - 20. 피처 이해하기 (0) | 2020.08.15 |
opencv-python 튜토리얼 - 중간 정리 (0) | 2020.08.15 |
opencv-python 튜토리얼 - 19. 워터셰드 알고리즘으로 영상 분할 (0) | 2020.08.15 |