|
| 1 | +import os |
| 2 | +import cv2 |
| 3 | +import time |
| 4 | +import imutils |
| 5 | +import numpy as np |
| 6 | +sift = cv2.xfeatures2d.SIFT_create() |
| 7 | + |
| 8 | + |
| 9 | +def parse_sift_output(target_path): |
| 10 | + """ |
| 11 | + Return: |
| 12 | + kp: keypoint of hessian affine descriptor. location, orientation etc... OpenCV KeyPoint format. |
| 13 | + des: 128d uint8 np array |
| 14 | + """ |
| 15 | + |
| 16 | + # print(os.listdir("./sample")) |
| 17 | + kp = [] |
| 18 | + des = [] |
| 19 | + with open(target_path, "r") as f: |
| 20 | + lines = list(map(lambda x: x.strip(), f.readlines())) |
| 21 | + num_descriptor = int(lines[1]) |
| 22 | + lines = lines[2:] |
| 23 | + for i in range(num_descriptor): |
| 24 | + # print(i, lines[i]) |
| 25 | + val = lines[i].split(" ") |
| 26 | + x = float(val[0]) |
| 27 | + y = float(val[1]) |
| 28 | + a = float(val[2]) |
| 29 | + b = float(val[3]) |
| 30 | + c = float(val[4]) |
| 31 | + # TODO: generate ellipse shaped key point |
| 32 | + # Refer: https://math.stackexchange.com/questions/1447730/drawing-ellipse-from-eigenvalue-eigenvector |
| 33 | + # Refer: http://www.robots.ox.ac.uk/~vgg/research/affine/det_eval_files/display_features.m |
| 34 | + # Refer: http://www.robots.ox.ac.uk/~vgg/research/affine/detectors.html |
| 35 | + key_point = cv2.KeyPoint(x, y, 1) |
| 36 | + sift_descriptor = np.array(list(map(lambda x: int(x), val[5:])), dtype=np.uint8) |
| 37 | + kp.append(key_point) |
| 38 | + des.append(sift_descriptor) |
| 39 | + |
| 40 | + |
| 41 | + return kp, np.array(des) |
| 42 | + |
| 43 | + |
| 44 | +def resize(img): |
| 45 | + h, w, _ = img.shape |
| 46 | + if w > 500: |
| 47 | + img = imutils.resize(img, width=500) |
| 48 | + img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) |
| 49 | + return img |
| 50 | + |
| 51 | +def hessian_sift_extractor(path1, path2): |
| 52 | + os.system('./hesaff_c++/hesaff {}'.format(path1)) |
| 53 | + os.system('./hesaff_c++/hesaff {}'.format(path2)) |
| 54 | + |
| 55 | + kp1, des1 = parse_sift_output(path1 + '.hesaff.sift') |
| 56 | + kp2, des2 = parse_sift_output(path2 + '.hesaff.sift') |
| 57 | + des1 = des1.astype('float32') |
| 58 | + des2 = des2.astype('float32') |
| 59 | + return kp1, des1, kp2, des2 |
| 60 | + |
| 61 | +def sift_extractor(img1, img2): |
| 62 | + kp1, des1 = sift.detectAndCompute(img1, None) |
| 63 | + kp2, des2 = sift.detectAndCompute(img2, None) |
| 64 | + return kp1, des1, kp2, des2 |
| 65 | + |
| 66 | + |
| 67 | +def show_match(path1, path2): |
| 68 | + |
| 69 | + img1 = cv2.imread(path1, 1) |
| 70 | + img2 = cv2.imread(path2, 1) |
| 71 | + img1_gray = resize(img1.copy()) |
| 72 | + img2_gray = resize(img2.copy()) |
| 73 | + |
| 74 | + kp1, des1, kp2, des2 = hessian_sift_extractor(path1, path2) |
| 75 | + # kp1, des1, kp2, des2 = sift_extractor(img1_gray, img2_gray) |
| 76 | + |
| 77 | + #### FLANN |
| 78 | + FLANN_INDEX_KDTREE = 0 |
| 79 | + index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5) |
| 80 | + search_params = dict(checks = 50) #指定递归次数 |
| 81 | + |
| 82 | + begin = time.time() |
| 83 | + flann = cv2.FlannBasedMatcher(index_params, search_params) |
| 84 | + matches = flann.knnMatch(des1, des2, k=2) |
| 85 | + |
| 86 | + # Need to draw only good matches, so create a mask |
| 87 | + matchesMask = [[0, 0] for i in range(len(matches))] |
| 88 | + |
| 89 | + |
| 90 | + del_same = [] |
| 91 | + mat = 0 |
| 92 | + for i, (m, n) in enumerate(matches): |
| 93 | + # ratio test as per Lowe's paper |
| 94 | + if m.distance < 0.6 * n.distance: |
| 95 | + mat += 1 |
| 96 | + matchesMask[i] = [1, 0] |
| 97 | + del_same.append(m.trainIdx) |
| 98 | + count = len(set(del_same)) |
| 99 | + print('匹配耗时:{:.5f}, 匹配到的点个数:{}'.format(time.time() - begin, count)) |
| 100 | + |
| 101 | + |
| 102 | + |
| 103 | + |
| 104 | + draw_params = dict(matchColor = (0, 255, 0), |
| 105 | + singlePointColor = (255, 0, 0), |
| 106 | + matchesMask = matchesMask, |
| 107 | + flags = 0) |
| 108 | + img3 = cv2.drawMatchesKnn(img1_gray, kp1, img2_gray, kp2, matches, None, **draw_params) |
| 109 | + # img3 = cv2.drawKeypoints(img1, kp1, img1,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) #画出特征点,并显示为红色圆圈 |
| 110 | + |
| 111 | + cv2.namedWindow('img',cv2.WINDOW_AUTOSIZE) |
| 112 | + cv2.imshow('img',img3) |
| 113 | + cv2.waitKey(0) |
| 114 | + cv2.destroyAllWindows() |
| 115 | + # cv2.imwrite('test.jpg', img3) |
| 116 | + |
| 117 | + |
| 118 | +if __name__ == '__main__': |
| 119 | + |
| 120 | + path1 = './test_pics/1.jpg' |
| 121 | + path2 = './test_pics/2.jpg' |
| 122 | + show_match(path1, path2) |
0 commit comments