이 글의 원문은 https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.html 입니다.
먼저 Homography의 정의는 한 평면을 다른 평면에 투영했을 때, 투영된 대응점들 사이에서의 변환 관계라고 합니다. 이를 이미지에서 설명하면, 2개의 이미지가 있다면 첫번째 이미지의 내용을 두번째 이미지에서 포함하고 있는데.. 첫번째 이미지가 두번째 이미지의 어느 위치로 투영 되었는가로 생각할 수 있습니다. 아래는 이 글에서 소개할 예제의 실행 결과입니다.
위의 이미지를 보면, 좌측와 우측에 2개의 이미지가 있습니다. 좌측 이미지는 우측 이미지의 어떤 일정 부분으로 투영되는데.. 바로 우측 이미지에 하얀색으로 표시된 사각형 영역입니다. 이 글은 바로 이 하얀색 사각형 영역을 이미지의 특징점 매칭을 통해 분석하는 글입니다.
이미 앞서 설명했던 이미지의 특징점을 구해 매칭을 했다면, cv2.findHomography()와 cv2.perspectiveTransform() 함수를 사용하여 Homography 분석을 통해 투영된 영역을 찾아낼 수 있습니다.
아래의 코드는 위의 이미지 결과에 대한 예제입니다.
import numpy as np import cv2 from matplotlib import pyplot as plt MIN_MATCH_COUNT = 10 img1 = cv2.imread('./data/harleyQuinnA.jpg',0) # queryImage img2 = cv2.imread('./data/harleyQuinnB.jpg',0) # trainImage # Initiate SIFT detector sift = cv2.xfeatures2d.SIFT_create() # find the keypoints and descriptors with SIFT kp1, des1 = sift.detectAndCompute(img1,None) kp2, des2 = sift.detectAndCompute(img2,None) FLANN_INDEX_KDTREE = 0 index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5) search_params = dict(checks = 50) flann = cv2.FlannBasedMatcher(index_params, search_params) matches = flann.knnMatch(des1,des2,k=2) # store all the good matches as per Lowe's ratio test. good = [] for m,n in matches: if m.distance < 0.3*n.distance: good.append(m) if len(good)>MIN_MATCH_COUNT: src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2) dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2) M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0) matchesMask = mask.ravel().tolist() h,w = img1.shape pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2) dst = cv2.perspectiveTransform(pts,M) img2 = cv2.polylines(img2,[np.int32(dst)],True,255,3, cv2.LINE_AA) else: print("Not enough matches are found - %d/%d" % (len(good),MIN_MATCH_COUNT)) matchesMask = None draw_params = dict(matchColor = (0,255,0), # draw matches in green color singlePointColor = None, matchesMask = matchesMask, # draw only inliers flags = 2) img3 = cv2.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params) plt.imshow(img3, 'gray'),plt.show()
1-31번까지의 코드는 이미지의 특징점을 추출하고 이 중 가장 좋은 특징점을 28번의 if 문을 기준으로 선별합니다. 이렇게 선별된 특징점을 31-45번 코드를 통해 Homography를 분석하여 이미지에 그립니다. 47-54코드는 이렇게 그려진 Homography와 함께 두 이미지 사이의 동일한 특징점에 대한 선을 그려주고 화면에 표시합니다.