def get_inliers(loc1, desc1, loc2, desc2): n_feat1, n_feat2 = loc1.shape[0], loc2.shape[0] # from scipy.spatial import cKDTree KD_THRESH = 0.8 d1_tree = cKDTree(desc1) distances, indices = d1_tree.query(desc2, distance_upper_bound=KD_THRESH) loc2_to_use = np.array( [loc2[i, ] for i in range(n_feat2) if indices[i] != n_feat1]) loc1_to_use = np.array( [loc1[indices[i], ] for i in range(n_feat2) if indices[i] != n_feat1]) np.random.seed(114514) # from skimage.measure import ransac as _ransac # from skimage.transform import AffineTransform model_robust, inliers = _ransac((loc1_to_use, loc2_to_use), AffineTransform, min_samples=3, residual_threshold=20, max_trials=1000) return sum(inliers)
def get_ransac_inlier(kp1, kp2, des1, des2, is_binary_descriptor=False, matcher_method="FLANN", verification_method="opencv_ransac_6dof", min_samples=3, residual_threshold=5.0, max_trials=1000): """ Args: verification_method: "opencv_ransac_6dof", "scikit", "fsm_5dof" """ des1 = sift_to_rootsift(des1) des2 = sift_to_rootsift(des2) matches = get_matches(des1, des2, matcher_method, is_binary_descriptor=False) if len(matches) < 5: # print("not enough matches: {}".format(len(matches))) return [] # Perform geometric verification using RANSAC. if verification_method == "opencv_ransac_6dof": src_pts = np.float32([cv2.KeyPoint(kp1[m.queryIdx][0], kp1[m.queryIdx][1], 1).pt for m in matches ]).reshape(-1,1,2) dst_pts = np.float32([cv2.KeyPoint(kp2[m.trainIdx][0], kp2[m.trainIdx][1], 1).pt for m in matches ]).reshape(-1,1,2) M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, residual_threshold) matchesMask = mask.ravel().tolist() inlier_idxs = np.nonzero(matchesMask)[0] elif verification_method == "scikit": locations_1_to_use = [] locations_2_to_use = [] for match in matches: locations_1_to_use.append((kp1[match.queryIdx].pt[1], kp1[match.queryIdx].pt[0])) # (row, col) locations_2_to_use.append((kp2[match.trainIdx].pt[1], kp2[match.trainIdx].pt[0])) locations_1_to_use = np.array(locations_1_to_use) locations_2_to_use = np.array(locations_2_to_use) _, inliers = _ransac( (locations_1_to_use, locations_2_to_use), AffineTransform, min_samples=min_samples, residual_threshold=residual_threshold, max_trials=max_trials) inlier_idxs = np.nonzero(inliers)[0] elif verification_method == "fsm_5dof": affine_matches = [] # TODO: handle multi match. # when one key points matches multiple key points. check data structure for this and fsm. for match_idx, m in enumerate(matches): am = AffineMatch(m.queryIdx, kp1[m.queryIdx]) feature2 = FeatureGeometryAffine() feature2.feature_id_ = m.trainIdx feature2.setPosition(kp2[m.trainIdx][0], kp2[m.trainIdx][1]) feature2.a_ = kp2[m.trainIdx][2] feature2.b_ = kp2[m.trainIdx][3] feature2.c_ = kp2[m.trainIdx][4] am.features2.append(feature2) am.word_ids.append(m.trainIdx) # pass dummy word_id. We may don't use value for FSM. affine_matches.append(am) # TODO: check do we need sort by size of features2 (smaller first) for matches. for FSM # print("num matches:", len(affine_matches)) match_list = affine_matches match_obj_list = [] for m in affine_matches: match_obj_list.append(m.get_object()) transform, inliers = fsmmatcher.perform_spatial_verification(match_obj_list) # print("transform from SFM:", transform) # print("num inliers from SFM:", len(inliers)) inlier_idxs = [] for match_idx, feature_idx in inliers: inlier_idxs.append(match_idx) else: raise Exception() inlier_match = [] for idx in inlier_idxs: inlier_match.append(matches[idx]) # print("num kp1: {}, kp2: {}, match: {}, inlier: {}".format(len(kp1), len(kp2), len(matches), len(inlier_match))) return inlier_match
def ransac(img1, img2, detector, descriptor_extractor, is_binary_descriptor, match_method, description): # find the keypoints and descriptors kp1 = detector.detect(img1, None) kp1, des1 = descriptor_extractor.compute(img1, kp1) print(len(kp1)) kp2 = detector.detect(img2, None) kp2, des2 = descriptor_extractor.compute(img2, kp2) print(len(kp2)) matches = get_matches(des1, des2, 'BRUTE_FORCE', is_binary_descriptor=is_binary_descriptor) matches = matches[:100] print(len(matches)) print("------------------------------------------------------------") # # Draw matches. flag: cv2.DrawMatchesFlags.DRAW_RICH_KEYPOINTS 4 # matching_img = cv2.drawMatches(img1, kp1, img2, kp2, matches, None, flags=0) # matching_img = cv2.cvtColor(matching_img, cv2.COLOR_BGR2RGB); # plt.figure(figsize=(16, 12)) # plt.imshow(matching_img) # plt.show() locations_1_to_use = [] locations_2_to_use = [] for match in matches: locations_1_to_use.append((kp1[match.queryIdx].pt[1], kp1[match.queryIdx].pt[0])) # (row, col) locations_2_to_use.append( (kp2[match.trainIdx].pt[1], kp2[match.trainIdx].pt[0])) locations_1_to_use = np.array(locations_1_to_use) locations_2_to_use = np.array(locations_2_to_use) # Perform geometric verification using RANSAC. model_robust, inliers = _ransac((locations_1_to_use, locations_2_to_use), AffineTransform, min_samples=5, residual_threshold=1, max_trials=1000) T, mask = cv2.findHomography(locations_1_to_use, locations_2_to_use, cv2.RANSAC, ransacReprojThreshold=3.0) #print (T) inlier_idxs = np.nonzero(inliers)[0] inlier_match = [] for idx in inlier_idxs: inlier_match.append(matches[idx]) # Does ransac consider size and orientation of keypoints? ransac_img = cv2.drawMatches(img1, kp1, img2, kp2, inlier_match, None, flags=0) if inliers is None: score = 0 else: score = len(inliers) return ransac_img, score
def get_ransac_inlier(kp1, kp2, des1, des2, is_binary_descriptor=False, matcher_method="FLANN", min_samples=3, residual_threshold=5, max_trials=1000): """ """ des1 = sift_to_rootsift(des1) des2 = sift_to_rootsift(des2) matches = get_matches(des1, des2, matcher_method, is_binary_descriptor=False) if len(matches) < 5: # print("not enough matches: {}".format(len(matches))) return [] # Perform geometric verification using RANSAC. # ransac_lib = "scikit" ransac_lib = "opencv" if ransac_lib == "opencv": src_pts = np.float32([kp1[m.queryIdx].pt for m in matches]).reshape(-1, 1, 2) dst_pts = np.float32([kp2[m.trainIdx].pt for m in matches]).reshape(-1, 1, 2) M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) matchesMask = mask.ravel().tolist() # print(matchesMask) inlier_idxs = np.nonzero(matchesMask)[0] elif ransac_lib == "scikit": locations_1_to_use = [] locations_2_to_use = [] for match in matches: locations_1_to_use.append( (kp1[match.queryIdx].pt[1], kp1[match.queryIdx].pt[0])) # (row, col) locations_2_to_use.append( (kp2[match.trainIdx].pt[1], kp2[match.trainIdx].pt[0])) locations_1_to_use = np.array(locations_1_to_use) locations_2_to_use = np.array(locations_2_to_use) _, inliers = _ransac((locations_1_to_use, locations_2_to_use), AffineTransform, min_samples=min_samples, residual_threshold=residual_threshold, max_trials=max_trials) inlier_idxs = np.nonzero(inliers)[0] inlier_match = [] for idx in inlier_idxs: inlier_match.append(matches[idx]) print("num kp1: {}, kp2: {}, match: {}, inlier: {}".format( len(kp1), len(kp2), len(matches), len(inlier_match))) return inlier_match