diff --git a/doc/examples/plot_brief.py b/doc/examples/plot_brief.py index 526c4acd..b4e7d8cd 100644 --- a/doc/examples/plot_brief.py +++ b/doc/examples/plot_brief.py @@ -45,16 +45,17 @@ keypoints1 = keypoints1[mask1] keypoints2 = keypoints2[mask2] keypoints3 = keypoints3[mask3] +matches12 = match_descriptors(descriptors1, descriptors2, cross_check=True) +matches13 = match_descriptors(descriptors1, descriptors3, cross_check=True) + fig, ax = plt.subplots(nrows=2, ncols=1) plt.gray() -idxs1, idxs2 = match_descriptors(descriptors1, descriptors2, cross_check=True) -plot_matches(ax[0], img1, img2, keypoints1, keypoints2, idxs1, idxs2) +plot_matches(ax[0], img1, img2, keypoints1, keypoints2, matches12) ax[0].axis('off') -idxs1, idxs3 = match_descriptors(descriptors1, descriptors3, cross_check=True) -plot_matches(ax[1], img1, img3, keypoints1, keypoints3, idxs1, idxs3) +plot_matches(ax[1], img1, img3, keypoints1, keypoints3, matches13) ax[1].axis('off') plt.show() diff --git a/doc/examples/plot_orb.py b/doc/examples/plot_orb.py index 534c4634..a3c6bf10 100644 --- a/doc/examples/plot_orb.py +++ b/doc/examples/plot_orb.py @@ -31,18 +31,17 @@ keypoints1, descriptors1 = descriptor_extractor.detect_and_extract(img1) keypoints2, descriptors2 = descriptor_extractor.detect_and_extract(img2) keypoints3, descriptors3 = descriptor_extractor.detect_and_extract(img3) +matches12 = match_descriptors(descriptors1, descriptors2, cross_check=True) +matches13 = match_descriptors(descriptors1, descriptors3, cross_check=True) + fig, ax = plt.subplots(nrows=2, ncols=1) plt.gray() -idxs1, idxs2 = match_descriptors(descriptors1, descriptors2, cross_check=True) -plot_matches(ax[0], img1, img2, keypoints1, keypoints2, - idxs1, idxs2) +plot_matches(ax[0], img1, img2, keypoints1, keypoints2, matches12) ax[0].axis('off') -idxs1, idxs3 = match_descriptors(descriptors1, descriptors3, cross_check=True) -plot_matches(ax[1], img1, img3, keypoints1, keypoints3, - idxs1, idxs3) +plot_matches(ax[1], img1, img3, keypoints1, keypoints3, matches13) ax[1].axis('off') plt.show() diff --git a/skimage/feature/brief.py b/skimage/feature/brief.py index cac7f347..45c9fa11 100644 --- a/skimage/feature/brief.py +++ b/skimage/feature/brief.py @@ -77,15 +77,18 @@ class BRIEF(DescriptorExtractor): >>> extractor = BRIEF(patch_size=5) >>> descs1, _ = extractor.extract(square1, keypoints1) >>> descs2, _ = extractor.extract(square2, keypoints2) - >>> idxs1, idxs2 = match_descriptors(descs1, descs2) - >>> idxs1, idxs2 - (array([0, 1, 2, 3]), array([0, 1, 2, 3])) - >>> keypoints1[idxs1] + >>> matches = match_descriptors(descs1, descs2) + >>> matches + array([[0, 0], + [1, 1], + [2, 2], + [3, 3]]) + >>> keypoints1[matches[:, 0]] array([[2, 2], [2, 5], [5, 2], [5, 5]]) - >>> keypoints2[idxs2] + >>> keypoints2[matches[:, 1]] array([[2, 2], [2, 6], [6, 2], diff --git a/skimage/feature/match.py b/skimage/feature/match.py index c6f23f6b..ccd8c035 100644 --- a/skimage/feature/match.py +++ b/skimage/feature/match.py @@ -35,10 +35,10 @@ def match_descriptors(descriptors1, descriptors2, metric=None, p=2, Returns ------- - indices1 : (Q, ) array - Indices of corresponding matches for first set of descriptors. - indices2 : (Q, ) array - Indices of corresponding matches for second set of descriptors. + matches : (Q, 2) array + Indices of corresponding matches in first and second set of + descriptors, where ``matches[:, 0]`` denote the indices in the first + and ``matches[:, 1]`` the indices in the second set of descriptors. """ @@ -62,4 +62,4 @@ def match_descriptors(descriptors1, descriptors2, metric=None, p=2, indices1 = indices1[mask] indices2 = indices2[mask] - return indices1, indices2 + return np.column_stack((indices1, indices2)) diff --git a/skimage/feature/orb.py b/skimage/feature/orb.py index 7512054a..a743962b 100644 --- a/skimage/feature/orb.py +++ b/skimage/feature/orb.py @@ -72,16 +72,20 @@ class ORB(FeatureDetector, DescriptorExtractor): >>> detector_extractor = ORB(n_keypoints=5) >>> keypoints1, descriptors1 = detector_extractor.detect_and_extract(img1) >>> keypoints2, descriptors2 = detector_extractor.detect_and_extract(img2) - >>> idxs1, idxs2 = match_descriptors(descriptors1, descriptors2) - >>> idxs1, idxs2 - (array([0, 1, 2, 3, 4]), array([0, 1, 2, 3, 4])) - >>> keypoints1[idxs1] + >>> matches = match_descriptors(descriptors1, descriptors2) + >>> matches + array([[0, 0], + [1, 1], + [2, 2], + [3, 3], + [4, 4]]) + >>> keypoints1[matches[:, 0]] array([[ 42., 40.], [ 47., 58.], [ 44., 40.], [ 59., 42.], [ 45., 44.]]) - >>> keypoints2[idxs2] + >>> keypoints2[matches[:, 1]] array([[ 55., 53.], [ 60., 71.], [ 57., 53.], diff --git a/skimage/feature/tests/test_match.py b/skimage/feature/tests/test_match.py index a028b585..e8b7c1ad 100644 --- a/skimage/feature/tests/test_match.py +++ b/skimage/feature/tests/test_match.py @@ -9,21 +9,20 @@ from skimage.feature import (BRIEF, match_descriptors, def test_binary_descriptors_unequal_descriptor_sizes_error(): """Sizes of descriptors of keypoints to be matched should be equal.""" - des1 = np.array([[True, True, False, True], + descs1 = np.array([[True, True, False, True], [False, True, False, True]]) - des2 = np.array([[True, False, False, True, False], + descs2 = np.array([[True, False, False, True, False], [False, True, True, True, False]]) - assert_raises(ValueError, match_descriptors, des1, des2) + assert_raises(ValueError, match_descriptors, descs1, descs2) def test_binary_descriptors(): - des1 = np.array([[True, True, False, True, True], + descs1 = np.array([[True, True, False, True, True], [False, True, False, True, True]]) - des2 = np.array([[True, False, False, True, False], + descs2 = np.array([[True, False, False, True, False], [False, False, True, True, True]]) - indices1, indices2 = match_descriptors(des1, des2) - assert_equal(indices1, [0, 1]) - assert_equal(indices2, [0, 1]) + matches = match_descriptors(descs1, descs2) + assert_equal(matches, [[0, 0], [1, 1]]) def test_binary_descriptors_lena_rotation_crosscheck_false(): @@ -45,19 +44,19 @@ def test_binary_descriptors_lena_rotation_crosscheck_false(): descriptors2, mask2 = descriptor.extract(rotated_img, keypoints2) keypoints2 = keypoints1[mask2] - m1, m2 = match_descriptors(descriptors1, descriptors2, threshold=0.13, + matches = match_descriptors(descriptors1, descriptors2, threshold=0.13, cross_check=False) - expected_mask1 = np.array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46]) - expected_mask2 = np.array([33, 0, 35, 7, 1, 35, 3, 2, 3, 6, 4, 9, - 11, 10, 28, 7, 8, 5, 31, 14, 13, 15, 21, 16, - 16, 13, 17, 18, 19, 21, 22, 23, 0, 24, 1, 24, - 23, 0, 26, 27, 25, 34, 28, 14, 29, 30, 21]) - assert_equal(m1, expected_mask1) - assert_equal(m2, expected_mask2) + exp_matches1 = np.array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46]) + exp_matches2 = np.array([33, 0, 35, 7, 1, 35, 3, 2, 3, 6, 4, 9, + 11, 10, 28, 7, 8, 5, 31, 14, 13, 15, 21, 16, + 16, 13, 17, 18, 19, 21, 22, 23, 0, 24, 1, 24, + 23, 0, 26, 27, 25, 34, 28, 14, 29, 30, 21]) + assert_equal(matches[:, 0], exp_matches1) + assert_equal(matches[:, 1], exp_matches2) def test_binary_descriptors_lena_rotation_crosscheck_true(): @@ -79,17 +78,17 @@ def test_binary_descriptors_lena_rotation_crosscheck_true(): descriptors2, mask2 = descriptor.extract(rotated_img, keypoints2) keypoints2 = keypoints1[mask2] - m1, m2 = match_descriptors(descriptors1, descriptors2, threshold=0.13, + matches = match_descriptors(descriptors1, descriptors2, threshold=0.13, cross_check=True) - expected_mask1 = np.array([ 0, 1, 2, 4, 6, 7, 9, 10, 11, 12, 13, 15, + exp_matches1 = np.array([ 0, 1, 2, 4, 6, 7, 9, 10, 11, 12, 13, 15, 16, 17, 19, 20, 21, 24, 26, 27, 28, 29, 30, 35, 36, 38, 39, 40, 42, 44, 45]) - expected_mask2 = np.array([33, 0, 35, 1, 3, 2, 6, 4, 9, 11, 10, 7, + exp_matches2 = np.array([33, 0, 35, 1, 3, 2, 6, 4, 9, 11, 10, 7, 8, 5, 14, 13, 15, 16, 17, 18, 19, 21, 22, 24, 23, 26, 27, 25, 28, 29, 30]) - assert_equal(m1, expected_mask1) - assert_equal(m2, expected_mask2) + assert_equal(matches[:, 0], exp_matches1) + assert_equal(matches[:, 1], exp_matches2) if __name__ == '__main__': diff --git a/skimage/feature/tests/test_util.py b/skimage/feature/tests/test_util.py index 31ca826a..2b601b94 100644 --- a/skimage/feature/tests/test_util.py +++ b/skimage/feature/tests/test_util.py @@ -54,16 +54,17 @@ def test_plot_matches(): keypoints2 = 10 * np.random.rand(10, 2) idxs1 = np.random.randint(10, size=10) idxs2 = np.random.randint(10, size=10) + matches = np.column_stack((idxs1, idxs2)) for shape1, shape2 in shapes: img1 = np.zeros(shape1) img2 = np.zeros(shape2) - plot_matches(ax, img1, img2, keypoints1, keypoints2, idxs1, idxs2) - plot_matches(ax, img1, img2, keypoints1, keypoints2, idxs1, idxs2, + plot_matches(ax, img1, img2, keypoints1, keypoints2, matches) + plot_matches(ax, img1, img2, keypoints1, keypoints2, matches, only_matches=True) - plot_matches(ax, img1, img2, keypoints1, keypoints2, idxs1, idxs2, + plot_matches(ax, img1, img2, keypoints1, keypoints2, matches, keypoints_color='r') - plot_matches(ax, img1, img2, keypoints1, keypoints2, idxs1, idxs2, + plot_matches(ax, img1, img2, keypoints1, keypoints2, matches, matches_color='r') diff --git a/skimage/feature/util.py b/skimage/feature/util.py index 6d824ef3..c3970766 100644 --- a/skimage/feature/util.py +++ b/skimage/feature/util.py @@ -33,9 +33,8 @@ class DescriptorExtractor(object): raise NotImplementedError() -def plot_matches(ax, image1, image2, keypoints1, keypoints2, - indices1, indices2, keypoints_color='k', matches_color=None, - only_matches=False): +def plot_matches(ax, image1, image2, keypoints1, keypoints2, matches, + keypoints_color='k', matches_color=None, only_matches=False): """Plot matched features. Parameters @@ -50,10 +49,10 @@ def plot_matches(ax, image1, image2, keypoints1, keypoints2, First keypoint coordinates as ``(row, col)``. keypoints2 : (K2, 2) array Second keypoint coordinates as ``(row, col)``. - indices1 : (Q, ) array - Indices of corresponding matches for first set of keypoints. - indices2 : (Q, ) array - Indices of corresponding matches for second set of keypoints. + matches : (Q, 2) array + Indices of corresponding matches in first and second set of + descriptors, where ``matches[:, 0]`` denote the indices in the first + and ``matches[:, 1]`` the indices in the second set of descriptors. keypoints_color : matplotlib color Color for keypoint locations. matches_color : matplotlib color @@ -67,9 +66,6 @@ def plot_matches(ax, image1, image2, keypoints1, keypoints2, image1 = img_as_float(image1) image2 = img_as_float(image2) - indices1 = np.squeeze(indices1) - indices2 = np.squeeze(indices2) - new_shape1 = list(image1.shape) new_shape2 = list(image2.shape) @@ -106,9 +102,9 @@ def plot_matches(ax, image1, image2, keypoints1, keypoints2, ax.imshow(image) ax.axis((0, 2 * offset[1], offset[0], 0)) - for i in range(len(indices1)): - idx1 = indices1[i] - idx2 = indices2[i] + for i in range(matches.shape[0]): + idx1 = matches[i, 0] + idx2 = matches[i, 1] if matches_color is None: color = np.random.rand(3, 1)