Python과 OpenCV – 35 : FAST(Features from Accelerated Segment Test)을 이용한 이미지의 특징점 추출

이 글의 원문은 https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_feature2d/py_fast/py_fast.html 입니다.

이미지에서 특징점을 추출해 내는 다양한 방법이 있지만, 그 속도면에서 아쉬움이 있었고 정확도를 희생하는 대신 빠른 속도로 특징점을 추출하는 방법으로 2006년에 FAST가 처음 제안되었습니다. 이 방법은 인공지능의 기계학습에서도 활용된다고 합니다. 이 방법은 특정 화소 인근의 화소값을 16개 뽑고 특정 화소의 화소값이 인근의 16개의 화소값에 임계치값(t)을 더한 값보다 크거나 임계치값을 뺀 값보다 작은 인근화소의 개수에 따라 특징점인지를 결정하는 매우 단순한 방식입니다. 여기에 더욱 속도를 향상시키기 위해 16개의 인근화소가 아닌 4개의 인근화소를 활용한다거나, 특징점이 비슷한 부분에서 너무 많이 추출되는 것을 방지하기 위해 억제(Non-maximal Suppression)하는 등이 절차가 적용되기도 합니다. 다른 방식에 비해 특징점 추출의 정확도를 떨어지지만 실시간에서 활용할 수 있는 속도를 제공하면서 어느 정도의 특징점 추출 방법으로 사용된다고 합니다.

OpneCV에서 이 FAST 특징점 추출에 대한 API 예제는 다음과 같습니다.

import numpy as np
import cv2
from matplotlib import pyplot as plt

filename = './data/butterfly.jpg'
img = cv2.imread(filename,0)

fast = cv2.FastFeatureDetector_create()

kp = fast.detect(img,None)
img2=cv2.drawKeypoints(img,kp,None)

print("Threshold: ", fast.getThreshold())
print("nonmaxSuppression: ", fast.getNonmaxSuppression())
print("neighborhood: ", fast.getType())
print("Total Keypoints with nonmaxSuppression: ", len(kp))

cv2.imshow('img2', img2)

cv2.waitKey()
cv2.destroyAllWindows()

실행결과는 아래와 같습니다.

콘솔에 출력된 결과는 아래와 같은데요.

Threshold:  10
nonmaxSuppression:  True
neighborhood:  2
Total Keypoints with nonmaxSuppression:  4992


인근 픽셀 화소값 비교를 위한 임계치 기본값은 10이고 비슷한 지점에서 너무 많은 특징점이 추출되는 것을 방지하기 위한 nonmaxSuppression가 True로 지정되어 있습니다. 시각적으로 이러한 특징점을 줄이기 위해 임계값을 변경하는 예제는 다음과 같습니다.

import numpy as np
import cv2
from matplotlib import pyplot as plt

filename = './data/butterfly.jpg'
img = cv2.imread(filename,0)

fast = cv2.FastFeatureDetector_create()

fast.setThreshold(150)
#fast.setNonmaxSuppression(False)

kp = fast.detect(img,None)
img2=cv2.drawKeypoints(img,kp,None)

print("Threshold: ", fast.getThreshold())
print("nonmaxSuppression: ", fast.getNonmaxSuppression())
print("neighborhood: ", fast.getType())
print("Total Keypoints with nonmaxSuppression: ", len(kp))

cv2.imshow('img2', img2)

kp = fast.detect(img,None)

cv2.waitKey()
cv2.destroyAllWindows()

결과는 다음과 같습니다.

Python과 OpenCV – 34 : SURF(Speeded-Up Robust Feature)을 이용한 이미지의 특징점 추출

이 글의 원문은 https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_feature2d/py_surf_intro/py_surf_intro.html 입니다.

SURF는 SIFT의 수행 속도를 개선시킨 것으로, 분석에 따르면 대략 3배 정도 빠르다고 합니다.SURF는 이미지가 회전되거나 Blurring 처리가 되었을 때에 사용해도 잘 잘동하지만 밝기가 변경되거나 시점이 변경이 되면 적당하지 않습니다.

OpenCV에서 제공하는 SURF와 관련된 함수를 살펴보겠습니다.

import cv2
import numpy as np

filename = './data/butterfly.jpg'
img = cv2.imread(filename)
gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

surf = cv2.xfeatures2d.SURF_create(50000)

kp, des = surf.detectAndCompute(gray, None)

print(len(kp))

img2 = cv2.drawKeypoints(gray,kp,None,(0,0,255),4)

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

위의 코드에서 이미지의 특징점을 추출하기 위한 SURF 기능을 사용하기 위해 8번 코드에서 SURF 객체를 생성합니다. 생성시 받는 인자는 Hessian 임계값으로 이 값이 작을수록 더 많은 특징점이 추출됩니다. 위 예제에서는 추출될 특징점 개수를 줄이기 위해 50000을 지정했으나 실제에서는 300-500 사이의 값을 지정합니다. 12번 코드에서 추출한 특징점의 개수를 출력하고 특징점을 이미지에 그리기 위해 14번 코드가 실행되었습니다. 결과는 다음과 같습니다.

위의 결과를 보면 특징점의 방향도 같이 표시되고 있는데, 방향이 필요없을 경우 속도 향상을 위해 방향 계산은 하지 않도록 할 수 있으며 아래 예제와 같습니다.

import cv2
import numpy as np

filename = './data/butterfly.jpg'
img = cv2.imread(filename)
gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

surf = cv2.xfeatures2d.SURF_create(50000)

surf.setUpright(True)
kp, des = surf.detectAndCompute(gray, None)

print(len(kp))

img2 = cv2.drawKeypoints(gray,kp,None,(0,0,255),4)

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

10번 코드를 통해 방향은 항상 위쪽 방향으로 간주하라고 지정합니다. 결과는 아래와 같습니다.

Python과 OpenCV – 33 : SIFT(Scale-Invariant Feature Transform)을 이용한 이미지의 특징점 추출

이 글의 원문은 https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.html 입니다.

이전 글에서는 이미지의 특징점을 Corner로 간주하였습니다. 이미지를 회전해도 귀퉁이(Corner)은 여전이 귀퉁이입니다. 그러나 만약 이미지의 크기를 늘렸을때는 어떨까요? 아래의 그림을 보면..

왼쪽의 이미지에서 초록색 사각형 안의 형상은 Corner입니다. 그러니 이 이미지를 확대하고 동일한 크기의 초록색 사각형 안의 형상은 더 이상 Corner라고 보기 어렵습니다. 즉, 이전 장에서 살펴본 이미지의 특징점으로써 Corner를 대상으로 했던 방법은 이미지의 확대에서 적용하기 어렵습니다. 이처럼 이미지의 회전뿐만 아니라 이미지의 크기가 변경될때에도 이미지의 특징점을 추출해 낼 수 있는 방법이 바로 SIFT 입니다.

SIFT는 다음처럼 총 4 단계의 절차를 통해 이미지의 특징점을 추출하고 추출한 특징점을 통해 매칭을 수행 합니다.

OpenCV는 SIFT를 구현하여 바로 활용할 수 있도록 함수를 제공하는데, 아래의 예제를 살펴보면..

import cv2
import numpy as np

filename = './data/home.jpg'
img = cv2.imread(filename)
gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

sift = cv2.xfeatures2d.SIFT_create()
kp = sift.detect(gray,None)

img=cv2.drawKeypoints(gray,kp,None,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

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

위의 결과는 다음과 같습니다.

상당이 많은 특징점이 추출되었는데, 추출한 특징점은 11번의 코드에서 cv2.drawKeypoints 함수를 통해 그릴 수 있습니다. 그려진 특징점 각각에는 특징점의 위치, 특징점의 영향 범위에 대한 반경, 그리고 회전시 특징점을 식별할 수 있는 각도값으로써의 특징점 방향을 알 수 있습니다.

특징점으로써의 keypoint를 추출했다면, 이제 이 keypoint를 가지고 각 keypoint의 식별자(Descriptor)를 계산합니다. 2가지 방식이 있는데.. 먼저 앞의 예제처럼 먼저 키포인트를 얻고 난뒤, 이 키포인트를 가지고 식별자를 계산하는 sift.coomput() 함수를 사용하는 방법, 예를 들어 kp, des = sift.compute(gray, kp) 와 같이 실행할 수 있습니다. 그리고 앞선 예제처럼 keypoint를 먼저 추출하지 않고 keypoint의 계산과 동시에 기술자도 함께 계산할 수 있는 sift.detectAndConput() 함수가 있는데, 아래의 예처럼 함수를 호출할 수 있습니다.

sift = cv2.SIFT()
kp, des = sift.detectAndCompute(gray,None)

키포인트와 식별자를 얻었다면, 이 키포인트와 식별자를 조합하여 특징점을 사용하여 서로 다른 이미지 사이의 동일한 위치를 식별할 수 있습니다. 이는 다른 글에서 살펴 보겠습니다.

Python과 OpenCV – 32 : Shi-Tomasi Corner Detection

이 글의 원문은 https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_feature2d/py_shi_tomasi/py_shi_tomasi.html 입니다.

Shi-Tomasi Corner Detection는 Harris Corner Detector를 기본으로 개선을 통해 좀더 정확한 Corner를 추출해 내는 알고리즘으로 cv2.goodFeaturesToTrack 함수로 구현되어 있습니다. 이에 대한 예제는 아래와 같습니다.

import numpy as np
import cv2
from matplotlib import pyplot as plt

filename = './data/blox.jpg'
img = cv2.imread(filename)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

corners = cv2.goodFeaturesToTrack(gray,30,0.01,10)
corners = np.int0(corners)

for i in corners:
    x,y = i.ravel()
    cv2.circle(img,(x,y),3,255,-1)

plt.imshow(img),plt.show()

cv2.goodFeaturesToTrack 함수는 4개의 인자를 받는데, 첫번째는 특징점인 Corner를 추출할 입력 이미지로 1채널인 Grayscale 이미지를 받습니다. 두번째는 추출할 특징점의 개수이고 세번째는 특징점으로써의 최소 품질인데 품질의 범위는 0-1 사이값입니다. 이 최소 품질보다 낮으면 특징점으로써 버려집니다. 그리고 마지막 인자는 최소 거리로써 얻어진 특징점에서 이 최소 거리 이내의 특징점은 버려집니다. 아래는 위 예제의 결과입니다.