From 336f0ca26605bb74d60838c3f82c0be7d6e6b410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Sun, 19 Jan 2014 09:38:36 -0500 Subject: [PATCH] Save feature information in attributes for consistency --- doc/examples/plot_brief.py | 16 +++-- doc/examples/plot_censure.py | 14 +++-- doc/examples/plot_orb.py | 15 ++++- skimage/feature/brief.py | 38 +++++------ skimage/feature/censure.py | 18 +++--- skimage/feature/orb.py | 90 +++++++++++++++++---------- skimage/feature/tests/test_brief.py | 14 ++--- skimage/feature/tests/test_censure.py | 20 +++--- skimage/feature/tests/test_orb.py | 54 ++++++++-------- skimage/feature/util.py | 6 ++ 10 files changed, 171 insertions(+), 114 deletions(-) diff --git a/doc/examples/plot_brief.py b/doc/examples/plot_brief.py index e5ffaaf2..2ef473bb 100644 --- a/doc/examples/plot_brief.py +++ b/doc/examples/plot_brief.py @@ -37,13 +37,17 @@ keypoints3 = corner_peaks(corner_harris(img3), min_distance=5) extractor = BRIEF() -descriptors1, mask1 = extractor.extract(img1, keypoints1) -descriptors2, mask2 = extractor.extract(img2, keypoints2) -descriptors3, mask3 = extractor.extract(img3, keypoints3) +extractor.extract(img1, keypoints1) +keypoints1 = keypoints1[extractor.mask_] +descriptors1 = extractor.descriptors_ -keypoints1 = keypoints1[mask1] -keypoints2 = keypoints2[mask2] -keypoints3 = keypoints3[mask3] +extractor.extract(img2, keypoints2) +keypoints2 = keypoints2[extractor.mask_] +descriptors2 = extractor.descriptors_ + +extractor.extract(img3, keypoints3) +keypoints3 = keypoints3[extractor.mask_] +descriptors3 = extractor.descriptors_ matches12 = match_descriptors(descriptors1, descriptors2, cross_check=True) matches13 = match_descriptors(descriptors1, descriptors3, cross_check=True) diff --git a/doc/examples/plot_censure.py b/doc/examples/plot_censure.py index 15cbbd13..06afb8e8 100644 --- a/doc/examples/plot_censure.py +++ b/doc/examples/plot_censure.py @@ -21,21 +21,23 @@ tform = tf.AffineTransform(scale=(1.5, 1.5), rotation=0.5, img2 = tf.warp(img1, tform) detector = CenSurE() -keypoints1, scales1 = detector.detect(img1) -keypoints2, scales2 = detector.detect(img2) fig, ax = plt.subplots(nrows=1, ncols=2) plt.gray() +detector.detect(img1) + ax[0].imshow(img1) ax[0].axis('off') -ax[0].scatter(keypoints1[:, 1], keypoints1[:, 0], 2 ** scales1, - facecolors='none', edgecolors='r') +ax[0].scatter(detector.keypoints_[:, 1], detector.keypoints_[:, 0], + 2 ** detector.scales_, facecolors='none', edgecolors='r') + +detector.detect(img2) ax[1].imshow(img2) ax[1].axis('off') -ax[1].scatter(keypoints2[:, 1], keypoints2[:, 0], 2 ** scales2, - facecolors='none', edgecolors='r') +ax[1].scatter(detector.keypoints_[:, 1], detector.keypoints_[:, 0], + 2 ** detector.scales_, facecolors='none', edgecolors='r') plt.show() diff --git a/doc/examples/plot_orb.py b/doc/examples/plot_orb.py index a3c6bf10..6576fbb7 100644 --- a/doc/examples/plot_orb.py +++ b/doc/examples/plot_orb.py @@ -27,9 +27,18 @@ tform = tf.AffineTransform(scale=(1.3, 1.1), rotation=0.5, img3 = tf.warp(img1, tform) descriptor_extractor = ORB(n_keypoints=200) -keypoints1, descriptors1 = descriptor_extractor.detect_and_extract(img1) -keypoints2, descriptors2 = descriptor_extractor.detect_and_extract(img2) -keypoints3, descriptors3 = descriptor_extractor.detect_and_extract(img3) + +descriptor_extractor.detect_and_extract(img1) +keypoints1 = descriptor_extractor.keypoints_ +descriptors1 = descriptor_extractor.descriptors_ + +descriptor_extractor.detect_and_extract(img2) +keypoints2 = descriptor_extractor.keypoints_ +descriptors2 = descriptor_extractor.descriptors_ + +descriptor_extractor.detect_and_extract(img3) +keypoints3 = descriptor_extractor.keypoints_ +descriptors3 = descriptor_extractor.descriptors_ matches12 = match_descriptors(descriptors1, descriptors2, cross_check=True) matches13 = match_descriptors(descriptors1, descriptors3, cross_check=True) diff --git a/skimage/feature/brief.py b/skimage/feature/brief.py index b7744b4f..b697ec3a 100644 --- a/skimage/feature/brief.py +++ b/skimage/feature/brief.py @@ -74,21 +74,23 @@ class BRIEF(DescriptorExtractor): [0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=int32) >>> keypoints1 = corner_peaks(corner_harris(square1), min_distance=1) >>> keypoints2 = corner_peaks(corner_harris(square2), min_distance=1) - >>> extractor = BRIEF(patch_size=5) - >>> descs1, _ = extractor.extract(square1, keypoints1) - >>> descs2, _ = extractor.extract(square2, keypoints2) - >>> matches = match_descriptors(descs1, descs2) + >>> extractor1 = BRIEF(patch_size=5) + >>> extractor2 = BRIEF(patch_size=5) + >>> extractor1.extract(square1, keypoints1) + >>> extractor2.extract(square2, keypoints2) + >>> matches = match_descriptors(extractor1.descriptors_, + ... extractor2.descriptors_) >>> matches array([[0, 0], [1, 1], [2, 2], [3, 3]]) - >>> keypoints1[matches[:, 0]] + >>> extractor1.keypoints_[matches[:, 0]] array([[2, 2], [2, 5], [5, 2], [5, 5]]) - >>> keypoints2[matches[:, 1]] + >>> extractor2.keypoints_[matches[:, 1]] array([[2, 2], [2, 6], [6, 2], @@ -119,15 +121,15 @@ class BRIEF(DescriptorExtractor): keypoints : (N, 2) array Keypoint coordinates as ``(row, col)``. - Returns - ------- - descriptors : (Q, `descriptor_size`) array of dtype bool + Attributes + ---------- + descriptors_ : (Q, `descriptor_size`) array of dtype bool 2D ndarray of binary descriptors of size `descriptor_size` for Q keypoints after filtering out border keypoints with value at an index ``(i, j)`` either being ``True`` or ``False`` representing the outcome of the intensity comparison for i-th keypoint on j-th decision pixel-pair. It is ``Q == np.sum(mask)``. - mask : (N, ) array of dtype bool + mask_ : (N, ) array of dtype bool Mask indicating whether a keypoint has been filtered out (``False``) or is described in the `descriptors` array (``True``). @@ -163,14 +165,14 @@ class BRIEF(DescriptorExtractor): # Removing keypoints that are within (patch_size / 2) distance from the # image border - mask = _mask_border_keypoints(image.shape, keypoints, patch_size // 2) + self.mask_ = _mask_border_keypoints(image.shape, keypoints, + patch_size // 2) - keypoints = np.array(keypoints[mask, :], dtype=np.intp, order='C', - copy=False) + keypoints = np.array(keypoints[self.mask_, :], dtype=np.intp, + order='C', copy=False) - descriptors = np.zeros((keypoints.shape[0], desc_size), - dtype=bool, order='C') + self.descriptors_ = np.zeros((keypoints.shape[0], desc_size), + dtype=bool, order='C') - _brief_loop(image, descriptors.view(np.uint8), keypoints, pos1, pos2) - - return descriptors, mask + _brief_loop(image, self.descriptors_.view(np.uint8), keypoints, + pos1, pos2) diff --git a/skimage/feature/censure.py b/skimage/feature/censure.py index 991875df..f31c5445 100644 --- a/skimage/feature/censure.py +++ b/skimage/feature/censure.py @@ -157,8 +157,9 @@ class CenSurE(FeatureDetector): >>> from skimage.color import rgb2gray >>> from skimage.feature import CenSurE >>> img = rgb2gray(lena()[100:300, 100:300]) - >>> keypoints, scales = CenSurE().detect(img) - >>> keypoints + >>> censure = CenSurE() + >>> censure.detect(img) + >>> censure.keypoints_ array([[ 71, 148], [ 77, 186], [ 78, 189], @@ -174,7 +175,7 @@ class CenSurE(FeatureDetector): [171, 29], [179, 20], [194, 65]]) - >>> scales + >>> censure.scales_ array([2, 4, 2, 3, 4, 2, 2, 3, 4, 6, 3, 2, 3, 4, 2]) """ @@ -204,8 +205,8 @@ class CenSurE(FeatureDetector): image : 2D ndarray Input image. - Returns - ------- + Attributes + ---------- keypoints : (N, 2) array Keypoint coordinates as ``(row, col)``. scales : (N, ) array @@ -257,7 +258,9 @@ class CenSurE(FeatureDetector): scales = scales + self.min_scale + 1 if self.mode == 'dob': - return keypoints, scales + self.keypoints_ = keypoints + self.scales_ = scales + return cumulative_mask = np.zeros(keypoints.shape[0], dtype=np.bool) @@ -276,4 +279,5 @@ class CenSurE(FeatureDetector): _mask_border_keypoints(image.shape, keypoints, c) & (scales == i)) - return keypoints[cumulative_mask], scales[cumulative_mask] + self.keypoints_ = keypoints[cumulative_mask] + self.scales_ = scales[cumulative_mask] diff --git a/skimage/feature/orb.py b/skimage/feature/orb.py index e7ab22e1..b0010d77 100644 --- a/skimage/feature/orb.py +++ b/skimage/feature/orb.py @@ -69,23 +69,25 @@ class ORB(FeatureDetector, DescriptorExtractor): >>> square = np.random.rand(20, 20) >>> img1[40:60, 40:60] = square >>> img2[53:73, 53:73] = square - >>> detector_extractor = ORB(n_keypoints=5) - >>> keypoints1, descriptors1 = detector_extractor.detect_and_extract(img1) - >>> keypoints2, descriptors2 = detector_extractor.detect_and_extract(img2) - >>> matches = match_descriptors(descriptors1, descriptors2) + >>> detector_extractor1 = ORB(n_keypoints=5) + >>> detector_extractor2 = ORB(n_keypoints=5) + >>> detector_extractor1.detect_and_extract(img1) + >>> detector_extractor2.detect_and_extract(img2) + >>> matches = match_descriptors(detector_extractor1.descriptors_, + ... detector_extractor2.descriptors_) >>> matches array([[0, 0], [1, 1], [2, 2], [3, 3], [4, 4]]) - >>> keypoints1[matches[:, 0]] + >>> detector_extractor1.keypoints_[matches[:, 0]] array([[ 42., 40.], [ 47., 58.], [ 44., 40.], [ 59., 42.], [ 45., 44.]]) - >>> keypoints2[matches[:, 1]] + >>> detector_extractor2.keypoints_[matches[:, 1]] array([[ 55., 53.], [ 60., 71.], [ 57., 53.], @@ -140,15 +142,15 @@ class ORB(FeatureDetector, DescriptorExtractor): image : 2D array Input image. - Returns - ------- - keypoints : (N, 2) array + Attributes + ---------- + keypoints_ : (N, 2) array Keypoint coordinates as ``(row, col)``. - scales : (N, ) array + scales_ : (N, ) array Corresponding scales. - orientations : (N, ) array + orientations_ : (N, ) array Corresponding orientations in radians. - responses : (N, ) array + responses_ : (N, ) array Corresponding Harris corner responses. """ @@ -157,7 +159,7 @@ class ORB(FeatureDetector, DescriptorExtractor): keypoints_list = [] orientations_list = [] - octave_list = [] + scales_list = [] responses_list = [] for octave in range(len(pyramid)): @@ -169,22 +171,27 @@ class ORB(FeatureDetector, DescriptorExtractor): keypoints_list.append(keypoints * self.downscale ** octave) orientations_list.append(orientations) - octave_list.append(self.downscale ** octave + scales_list.append(self.downscale ** octave * np.ones(keypoints.shape[0], dtype=np.intp)) responses_list.append(responses) keypoints = np.vstack(keypoints_list) orientations = np.hstack(orientations_list) - scales = np.hstack(octave_list) + scales = np.hstack(scales_list) responses = np.hstack(responses_list) if keypoints.shape[0] < self.n_keypoints: - return keypoints, scales, orientations, responses + self.keypoints_ = keypoints + self.scales_ = scales + self.orientations_ = orientations + self.responses_ = responses else: # Choose best n_keypoints according to Harris corner response best_indices = responses.argsort()[::-1][:self.n_keypoints] - return (keypoints[best_indices], scales[best_indices], - orientations[best_indices], responses[best_indices]) + self.keypoints_ = keypoints[best_indices] + self.scales_ = scales[best_indices] + self.orientations_ = orientations[best_indices] + self.responses_ = responses[best_indices] def _extract_octave(self, octave_image, keypoints, orientations): mask = _mask_border_keypoints(octave_image.shape, keypoints, @@ -217,15 +224,15 @@ class ORB(FeatureDetector, DescriptorExtractor): orientations : (N, ) array Corresponding orientations in radians. - Returns - ------- - descriptors : (Q, `descriptor_size`) array of dtype bool + Attributes + ---------- + descriptors_ : (Q, `descriptor_size`) array of dtype bool 2D array of binary descriptors of size `descriptor_size` for Q keypoints after filtering out border keypoints with value at an index ``(i, j)`` either being ``True`` or ``False`` representing the outcome of the intensity comparison for i-th keypoint on j-th decision pixel-pair. It is ``Q == np.sum(mask)``. - mask : (N, ) array of dtype bool + mask_ : (N, ) array of dtype bool Mask indicating whether a keypoint has been filtered out (``False``) or is described in the `descriptors` array (``True``). @@ -260,10 +267,8 @@ class ORB(FeatureDetector, DescriptorExtractor): descriptors_list.append(descriptors) mask_list.append(mask) - descriptors = np.vstack(descriptors_list).view(np.bool) - mask = np.hstack(mask_list) - - return descriptors, mask + self.descriptors_ = np.vstack(descriptors_list).view(np.bool) + self.mask_ = np.hstack(mask_list) def detect_and_extract(self, image): """Detect oriented FAST keypoints and extract rBRIEF descriptors. @@ -276,11 +281,17 @@ class ORB(FeatureDetector, DescriptorExtractor): image : 2D array Input image. - Returns - ------- - keypoints : (Q, 2) array + Attributes + ---------- + keypoints_ : (N, 2) array Keypoint coordinates as ``(row, col)``. - descriptors : (Q, `descriptor_size`) array of dtype bool + scales_ : (N, ) array + Corresponding scales. + orientations_ : (N, ) array + Corresponding orientations in radians. + responses_ : (N, ) array + Corresponding Harris corner responses. + descriptors_ : (Q, `descriptor_size`) array of dtype bool 2D array of binary descriptors of size `descriptor_size` for Q keypoints after filtering out border keypoints with value at an index ``(i, j)`` either being ``True`` or ``False`` representing @@ -293,6 +304,8 @@ class ORB(FeatureDetector, DescriptorExtractor): keypoints_list = [] responses_list = [] + scales_list = [] + orientations_list = [] descriptors_list = [] for octave in range(len(pyramid)): @@ -313,15 +326,28 @@ class ORB(FeatureDetector, DescriptorExtractor): keypoints_list.append(keypoints[mask] * self.downscale ** octave) responses_list.append(responses[mask]) + orientations_list.append(orientations[mask]) + scales_list.append(self.downscale ** octave + * np.ones(keypoints.shape[0], dtype=np.intp)) descriptors_list.append(descriptors) keypoints = np.vstack(keypoints_list) responses = np.hstack(responses_list) + scales = np.hstack(scales_list) + orientations = np.hstack(orientations_list) descriptors = np.vstack(descriptors_list).view(np.bool) if keypoints.shape[0] < self.n_keypoints: - return keypoints, descriptors + self.keypoints_ = keypoints + self.scales_ = scales + self.orientations_ = orientations + self.responses_ = responses + self.descriptors_ = descriptors else: # Choose best n_keypoints according to Harris corner response best_indices = responses.argsort()[::-1][:self.n_keypoints] - return keypoints[best_indices], descriptors[best_indices] + self.keypoints_ = keypoints[best_indices] + self.scales_ = scales[best_indices] + self.orientations_ = orientations[best_indices] + self.responses_ = responses[best_indices] + self.descriptors_ = descriptors[best_indices] diff --git a/skimage/feature/tests/test_brief.py b/skimage/feature/tests/test_brief.py index 61cde324..e847c967 100644 --- a/skimage/feature/tests/test_brief.py +++ b/skimage/feature/tests/test_brief.py @@ -21,7 +21,7 @@ def test_normal_mode(): extractor = BRIEF(descriptor_size=8, sigma=2) - descriptors, mask = extractor.extract(img, keypoints[:8]) + extractor.extract(img, keypoints[:8]) expected = np.array([[ True, False, True, False, True, True, False, False], [False, False, False, False, True, False, False, False], @@ -32,7 +32,7 @@ def test_normal_mode(): [False, True, True, True, False, False, True, False], [False, False, False, False, True, False, False, False]], dtype=bool) - assert_array_equal(descriptors, expected) + assert_array_equal(extractor.descriptors_, expected) def test_uniform_mode(): @@ -43,7 +43,7 @@ def test_uniform_mode(): extractor = BRIEF(descriptor_size=8, sigma=2, mode='uniform') - descriptors, mask = extractor.extract(img, keypoints[:8]) + extractor.extract(img, keypoints[:8]) expected = np.array([[ True, False, True, False, False, True, False, False], [False, True, False, False, True, True, True, True], @@ -54,7 +54,7 @@ def test_uniform_mode(): [False, False, True, True, False, False, True, True], [ True, True, False, False, False, False, False, False]], dtype=bool) - assert_array_equal(descriptors, expected) + assert_array_equal(extractor.descriptors_, expected) def test_unsupported_mode(): @@ -66,10 +66,10 @@ def test_border(): keypoints = np.array([[1, 1], [20, 20], [50, 50], [80, 80]]) extractor = BRIEF(patch_size=41) - descs, mask = extractor.extract(img, keypoints) + extractor.extract(img, keypoints) - assert descs.shape[0] == 3 - assert_array_equal(mask, (False, True, True, True)) + assert extractor.descriptors_.shape[0] == 3 + assert_array_equal(extractor.mask_, (False, True, True, True)) if __name__ == '__main__': diff --git a/skimage/feature/tests/test_censure.py b/skimage/feature/tests/test_censure.py index 611604b6..608290d0 100644 --- a/skimage/feature/tests/test_censure.py +++ b/skimage/feature/tests/test_censure.py @@ -28,7 +28,7 @@ def test_keypoints_censure_moon_image_dob(): """Verify the actual Censure keypoints and their corresponding scale with the expected values for DoB filter.""" detector = CenSurE() - keypoints, scales = detector.detect(img) + detector.detect(img) expected_keypoints = np.array([[ 21, 497], [ 36, 46], [119, 350], @@ -40,8 +40,8 @@ def test_keypoints_censure_moon_image_dob(): [467, 260]]) expected_scales = np.array([3, 4, 4, 2, 2, 3, 2, 2, 2]) - assert_array_equal(expected_keypoints, keypoints) - assert_array_equal(expected_scales, scales) + assert_array_equal(expected_keypoints, detector.keypoints_) + assert_array_equal(expected_scales, detector.scales_) def test_keypoints_censure_moon_image_octagon(): @@ -49,7 +49,7 @@ def test_keypoints_censure_moon_image_octagon(): the expected values for Octagon filter.""" detector = CenSurE(mode='octagon') - keypoints, scales = detector.detect(img) + detector.detect(img) expected_keypoints = np.array([[ 21, 496], [ 35, 46], [287, 250], @@ -58,15 +58,15 @@ def test_keypoints_censure_moon_image_octagon(): expected_scales = np.array([3, 4, 2, 2, 2]) - assert_array_equal(expected_keypoints, keypoints) - assert_array_equal(expected_scales, scales) + assert_array_equal(expected_keypoints, detector.keypoints_) + assert_array_equal(expected_scales, detector.scales_) def test_keypoints_censure_moon_image_star(): """Verify the actual Censure keypoints and their corresponding scale with the expected values for STAR filter.""" detector = CenSurE(mode='star') - keypoints, scales = detector.detect(img) + detector.detect(img) expected_keypoints = np.array([[ 21, 497], [ 36, 46], [117, 356], @@ -78,10 +78,10 @@ def test_keypoints_censure_moon_image_star(): [463, 116], [467, 260]]) - expected_scale = np.array([3, 3, 6, 2, 3, 2, 3, 5, 2, 2]) + expected_scales = np.array([3, 3, 6, 2, 3, 2, 3, 5, 2, 2]) - assert_array_equal(expected_keypoints, keypoints) - assert_array_equal(expected_scale, scales) + assert_array_equal(expected_keypoints, detector.keypoints_) + assert_array_equal(expected_scales, detector.scales_) if __name__ == '__main__': diff --git a/skimage/feature/tests/test_orb.py b/skimage/feature/tests/test_orb.py index 9c2a1d6e..9943aeb3 100644 --- a/skimage/feature/tests/test_orb.py +++ b/skimage/feature/tests/test_orb.py @@ -10,7 +10,7 @@ img = rgb2gray(lena()) def test_keypoints_orb_desired_no_of_keypoints(): detector_extractor = ORB(n_keypoints=10, fast_n=12, fast_threshold=0.20) - keypoints, scales, orientations, responses = detector_extractor.detect(img) + detector_extractor.detect(img) exp_rows = np.array([ 435. , 435.6 , 376. , 455. , 434.88, 269. , 375.6 , 310.8 , 413. , 311.04]) @@ -29,22 +29,23 @@ def test_keypoints_orb_desired_no_of_keypoints(): 0.39154173, 0.39084861, 0.39063076, 0.37602487]) - assert_almost_equal(exp_rows, keypoints[:, 0]) - assert_almost_equal(exp_cols, keypoints[:, 1]) - assert_almost_equal(exp_scales, scales) - assert_almost_equal(exp_response, responses) - assert_almost_equal(exp_orientations, np.rad2deg(orientations), 5) + assert_almost_equal(exp_rows, detector_extractor.keypoints_[:, 0]) + assert_almost_equal(exp_cols, detector_extractor.keypoints_[:, 1]) + assert_almost_equal(exp_scales, detector_extractor.scales_) + assert_almost_equal(exp_response, detector_extractor.responses_) + assert_almost_equal(exp_orientations, + np.rad2deg(detector_extractor.orientations_), 5) - keypoints, _ = detector_extractor.detect_and_extract(img) - assert_almost_equal(exp_rows, keypoints[:, 0]) - assert_almost_equal(exp_cols, keypoints[:, 1]) + detector_extractor.detect_and_extract(img) + assert_almost_equal(exp_rows, detector_extractor.keypoints_[:, 0]) + assert_almost_equal(exp_cols, detector_extractor.keypoints_[:, 1]) def test_keypoints_orb_less_than_desired_no_of_keypoints(): img = rgb2gray(lena()) detector_extractor = ORB(n_keypoints=15, fast_n=12, fast_threshold=0.33, downscale=2, n_scales=2) - keypoints, scales, orientations, responses = detector_extractor.detect(img) + detector_extractor.detect(img) exp_rows = np.array([ 67., 247., 269., 413., 435., 230., 264., 330., 372.]) @@ -61,15 +62,16 @@ def test_keypoints_orb_less_than_desired_no_of_keypoints(): 0.39063076, 0.96770745, 0.04935129, 0.21431068, 0.15826555, 0.42403573]) - assert_almost_equal(exp_rows, keypoints[:, 0]) - assert_almost_equal(exp_cols, keypoints[:, 1]) - assert_almost_equal(exp_scales, scales) - assert_almost_equal(exp_response, responses) - assert_almost_equal(exp_orientations, np.rad2deg(orientations), 5) + assert_almost_equal(exp_rows, detector_extractor.keypoints_[:, 0]) + assert_almost_equal(exp_cols, detector_extractor.keypoints_[:, 1]) + assert_almost_equal(exp_scales, detector_extractor.scales_) + assert_almost_equal(exp_response, detector_extractor.responses_) + assert_almost_equal(exp_orientations, + np.rad2deg(detector_extractor.orientations_), 5) - keypoints, _ = detector_extractor.detect_and_extract(img) - assert_almost_equal(exp_rows, keypoints[:, 0]) - assert_almost_equal(exp_cols, keypoints[:, 1]) + detector_extractor.detect_and_extract(img) + assert_almost_equal(exp_rows, detector_extractor.keypoints_[:, 0]) + assert_almost_equal(exp_cols, detector_extractor.keypoints_[:, 1]) def test_descriptor_orb(): @@ -96,14 +98,16 @@ def test_descriptor_orb(): [False, True, False, False, True, False, False, False, True, True], [ True, False, True, False, False, False, True, True, False, False]], dtype=bool) - keypoints1, scales1, orientations1, responses1 \ - = detector_extractor.detect(img) - descriptors1, mask1 \ - = detector_extractor.extract(img, keypoints1, scales1, orientations1) - assert_array_equal(exp_descriptors, descriptors1[100:120, 10:20]) + detector_extractor.detect(img) + detector_extractor.extract(img, detector_extractor.keypoints_, + detector_extractor.scales_, + detector_extractor.orientations_) + assert_array_equal(exp_descriptors, + detector_extractor.descriptors_[100:120, 10:20]) - keypoints2, descriptors2 = detector_extractor.detect_and_extract(img) - assert_array_equal(exp_descriptors, descriptors2[100:120, 10:20]) + detector_extractor.detect_and_extract(img) + assert_array_equal(exp_descriptors, + detector_extractor.descriptors_[100:120, 10:20]) if __name__ == '__main__': diff --git a/skimage/feature/util.py b/skimage/feature/util.py index b5faa565..8ee2baf8 100644 --- a/skimage/feature/util.py +++ b/skimage/feature/util.py @@ -5,6 +5,9 @@ from skimage.util import img_as_float class FeatureDetector(object): + def __init__(self): + self.keypoints_ = np.array([]) + def detect(self, image): """Detect keypoints in image. @@ -19,6 +22,9 @@ class FeatureDetector(object): class DescriptorExtractor(object): + def __init__(self): + self.descriptors_ = np.array([]) + def extract(self, image, keypoints): """Extract feature descriptors in image for given keypoints.