diff --git a/doc/examples/plot_brief.py b/doc/examples/plot_brief.py index e01d431a..47c9ad5f 100644 --- a/doc/examples/plot_brief.py +++ b/doc/examples/plot_brief.py @@ -34,16 +34,16 @@ keypoints3 = corner_peaks(corner_harris(img3), min_distance=5) extractor = BRIEF() extractor.extract(img1, keypoints1) -keypoints1 = keypoints1[extractor.mask_] -descriptors1 = extractor.descriptors_ +keypoints1 = keypoints1[extractor.mask] +descriptors1 = extractor.descriptors extractor.extract(img2, keypoints2) -keypoints2 = keypoints2[extractor.mask_] -descriptors2 = extractor.descriptors_ +keypoints2 = keypoints2[extractor.mask] +descriptors2 = extractor.descriptors extractor.extract(img3, keypoints3) -keypoints3 = keypoints3[extractor.mask_] -descriptors3 = extractor.descriptors_ +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 06afb8e8..41f20496 100644 --- a/doc/examples/plot_censure.py +++ b/doc/examples/plot_censure.py @@ -30,14 +30,14 @@ detector.detect(img1) ax[0].imshow(img1) ax[0].axis('off') -ax[0].scatter(detector.keypoints_[:, 1], detector.keypoints_[:, 0], - 2 ** detector.scales_, 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(detector.keypoints_[:, 1], detector.keypoints_[:, 0], - 2 ** detector.scales_, 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/skimage/feature/brief.py b/skimage/feature/brief.py index 3421156b..d1626f17 100644 --- a/skimage/feature/brief.py +++ b/skimage/feature/brief.py @@ -44,6 +44,18 @@ class BRIEF(DescriptorExtractor): to alleviate noise sensitivity, which is strongly recommended to obtain discriminative and good descriptors. + 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 indicating whether a keypoint has been filtered out + (``False``) or is described in the `descriptors` array (``True``). + Examples -------- >>> from skimage.feature import (corner_harris, corner_peaks, BRIEF, @@ -76,9 +88,9 @@ class BRIEF(DescriptorExtractor): >>> keypoints2 = corner_peaks(corner_harris(square2), min_distance=1) >>> extractor = BRIEF(patch_size=5) >>> extractor.extract(square1, keypoints1) - >>> descriptors1 = extractor.descriptors_ + >>> descriptors1 = extractor.descriptors >>> extractor.extract(square2, keypoints2) - >>> descriptors2 = extractor.descriptors_ + >>> descriptors2 = extractor.descriptors >>> matches = match_descriptors(descriptors1, descriptors2) >>> matches array([[0, 0], @@ -111,6 +123,9 @@ class BRIEF(DescriptorExtractor): self.sigma = sigma self.sample_seed = sample_seed + self.descriptors = None + self.mask = None + def extract(self, image, keypoints): """Extract BRIEF binary descriptors for given keypoints in image. @@ -121,18 +136,6 @@ class BRIEF(DescriptorExtractor): keypoints : (N, 2) array Keypoint coordinates as ``(row, col)``. - 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 indicating whether a keypoint has been filtered out - (``False``) or is described in the `descriptors` array (``True``). - """ np.random.seed(self.sample_seed) @@ -165,14 +168,14 @@ class BRIEF(DescriptorExtractor): # Removing keypoints that are within (patch_size / 2) distance from the # image border - self.mask_ = _mask_border_keypoints(image.shape, keypoints, + self.mask = _mask_border_keypoints(image.shape, keypoints, patch_size // 2) - keypoints = np.array(keypoints[self.mask_, :], dtype=np.intp, + keypoints = np.array(keypoints[self.mask, :], dtype=np.intp, order='C', copy=False) - self.descriptors_ = np.zeros((keypoints.shape[0], desc_size), + self.descriptors = np.zeros((keypoints.shape[0], desc_size), dtype=bool, order='C') - _brief_loop(image, self.descriptors_.view(np.uint8), keypoints, + _brief_loop(image, self.descriptors.view(np.uint8), keypoints, pos1, pos2) diff --git a/skimage/feature/censure.py b/skimage/feature/censure.py index f31c5445..c111bc0f 100644 --- a/skimage/feature/censure.py +++ b/skimage/feature/censure.py @@ -139,6 +139,13 @@ class CenSurE(FeatureDetector): Threshold for rejecting interest points which have ratio of principal curvatures greater than this value. + Attributes + ---------- + keypoints : (N, 2) array + Keypoint coordinates as ``(row, col)``. + scales : (N, ) array + Corresponding scales. + References ---------- .. [1] Motilal Agrawal, Kurt Konolige and Morten Rufus Blas @@ -159,7 +166,7 @@ class CenSurE(FeatureDetector): >>> img = rgb2gray(lena()[100:300, 100:300]) >>> censure = CenSurE() >>> censure.detect(img) - >>> censure.keypoints_ + >>> censure.keypoints array([[ 71, 148], [ 77, 186], [ 78, 189], @@ -175,7 +182,7 @@ class CenSurE(FeatureDetector): [171, 29], [179, 20], [194, 65]]) - >>> censure.scales_ + >>> censure.scales array([2, 4, 2, 3, 4, 2, 2, 3, 4, 6, 3, 2, 3, 4, 2]) """ @@ -197,6 +204,9 @@ class CenSurE(FeatureDetector): self.non_max_threshold = non_max_threshold self.line_threshold = line_threshold + self.keypoints = None + self.scales = None + def detect(self, image): """Detect CenSurE keypoints along with the corresponding scale. @@ -205,13 +215,6 @@ class CenSurE(FeatureDetector): image : 2D ndarray Input image. - Attributes - ---------- - keypoints : (N, 2) array - Keypoint coordinates as ``(row, col)``. - scales : (N, ) array - Corresponding scales. - """ # (1) First we generate the required scales on the input grayscale @@ -258,8 +261,8 @@ class CenSurE(FeatureDetector): scales = scales + self.min_scale + 1 if self.mode == 'dob': - self.keypoints_ = keypoints - self.scales_ = scales + self.keypoints = keypoints + self.scales = scales return cumulative_mask = np.zeros(keypoints.shape[0], dtype=np.bool) @@ -279,5 +282,5 @@ class CenSurE(FeatureDetector): _mask_border_keypoints(image.shape, keypoints, c) & (scales == i)) - self.keypoints_ = keypoints[cumulative_mask] - self.scales_ = 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 b0010d77..fa24c59f 100644 --- a/skimage/feature/orb.py +++ b/skimage/feature/orb.py @@ -54,6 +54,23 @@ class ORB(FeatureDetector, DescriptorExtractor): Maximum number of scales from the bottom of the image pyramid to extract the features from. + Attributes + ---------- + keypoints : (N, 2) array + Keypoint coordinates as ``(row, col)``. + 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 + the outcome of the intensity comparison for i-th keypoint on j-th + decision pixel-pair. It is ``Q == np.sum(mask)``. + References ---------- .. [1] Ethan Rublee, Vincent Rabaud, Kurt Konolige and Gary Bradski @@ -73,21 +90,21 @@ class ORB(FeatureDetector, DescriptorExtractor): >>> 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 = match_descriptors(detector_extractor1.descriptors, + ... detector_extractor2.descriptors) >>> matches array([[0, 0], [1, 1], [2, 2], [3, 3], [4, 4]]) - >>> detector_extractor1.keypoints_[matches[:, 0]] + >>> detector_extractor1.keypoints[matches[:, 0]] array([[ 42., 40.], [ 47., 58.], [ 44., 40.], [ 59., 42.], [ 45., 44.]]) - >>> detector_extractor2.keypoints_[matches[:, 1]] + >>> detector_extractor2.keypoints[matches[:, 1]] array([[ 55., 53.], [ 60., 71.], [ 57., 53.], @@ -106,6 +123,12 @@ class ORB(FeatureDetector, DescriptorExtractor): self.fast_threshold = fast_threshold self.harris_k = harris_k + self.keypoints = None + self.scales = None + self.responses = None + self.orientations = None + self.descriptors = None + def _build_pyramid(self, image): image = _prepare_grayscale_input_2D(image) return list(pyramid_gaussian(image, self.n_scales - 1, self.downscale)) @@ -142,17 +165,6 @@ class ORB(FeatureDetector, DescriptorExtractor): image : 2D array Input image. - Attributes - ---------- - keypoints_ : (N, 2) array - Keypoint coordinates as ``(row, col)``. - scales_ : (N, ) array - Corresponding scales. - orientations_ : (N, ) array - Corresponding orientations in radians. - responses_ : (N, ) array - Corresponding Harris corner responses. - """ pyramid = self._build_pyramid(image) @@ -181,17 +193,17 @@ class ORB(FeatureDetector, DescriptorExtractor): responses = np.hstack(responses_list) if keypoints.shape[0] < self.n_keypoints: - self.keypoints_ = keypoints - self.scales_ = scales - self.orientations_ = orientations - self.responses_ = 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] - self.keypoints_ = keypoints[best_indices] - self.scales_ = scales[best_indices] - self.orientations_ = orientations[best_indices] - self.responses_ = 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, @@ -224,18 +236,6 @@ class ORB(FeatureDetector, DescriptorExtractor): orientations : (N, ) array Corresponding orientations in radians. - 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 indicating whether a keypoint has been filtered out - (``False``) or is described in the `descriptors` array (``True``). - """ pyramid = self._build_pyramid(image) @@ -267,7 +267,7 @@ class ORB(FeatureDetector, DescriptorExtractor): descriptors_list.append(descriptors) mask_list.append(mask) - self.descriptors_ = np.vstack(descriptors_list).view(np.bool) + self.descriptors = np.vstack(descriptors_list).view(np.bool) self.mask_ = np.hstack(mask_list) def detect_and_extract(self, image): @@ -281,23 +281,6 @@ class ORB(FeatureDetector, DescriptorExtractor): image : 2D array Input image. - Attributes - ---------- - keypoints_ : (N, 2) array - Keypoint coordinates as ``(row, col)``. - 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 - the outcome of the intensity comparison for i-th keypoint on j-th - decision pixel-pair. It is ``Q == np.sum(mask)``. - """ pyramid = self._build_pyramid(image) @@ -338,16 +321,16 @@ class ORB(FeatureDetector, DescriptorExtractor): descriptors = np.vstack(descriptors_list).view(np.bool) if keypoints.shape[0] < self.n_keypoints: - self.keypoints_ = keypoints - self.scales_ = scales - self.orientations_ = orientations - self.responses_ = responses - self.descriptors_ = 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] - 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] + 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 e847c967..554301b2 100644 --- a/skimage/feature/tests/test_brief.py +++ b/skimage/feature/tests/test_brief.py @@ -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(extractor.descriptors_, expected) + assert_array_equal(extractor.descriptors, expected) def test_uniform_mode(): @@ -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(extractor.descriptors_, expected) + assert_array_equal(extractor.descriptors, expected) def test_unsupported_mode(): @@ -68,8 +68,8 @@ def test_border(): extractor = BRIEF(patch_size=41) extractor.extract(img, keypoints) - assert extractor.descriptors_.shape[0] == 3 - assert_array_equal(extractor.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 608290d0..05348d43 100644 --- a/skimage/feature/tests/test_censure.py +++ b/skimage/feature/tests/test_censure.py @@ -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, detector.keypoints_) - assert_array_equal(expected_scales, detector.scales_) + assert_array_equal(expected_keypoints, detector.keypoints) + assert_array_equal(expected_scales, detector.scales) def test_keypoints_censure_moon_image_octagon(): @@ -58,8 +58,8 @@ def test_keypoints_censure_moon_image_octagon(): expected_scales = np.array([3, 4, 2, 2, 2]) - assert_array_equal(expected_keypoints, detector.keypoints_) - assert_array_equal(expected_scales, detector.scales_) + assert_array_equal(expected_keypoints, detector.keypoints) + assert_array_equal(expected_scales, detector.scales) def test_keypoints_censure_moon_image_star(): @@ -80,8 +80,8 @@ def test_keypoints_censure_moon_image_star(): expected_scales = np.array([3, 3, 6, 2, 3, 2, 3, 5, 2, 2]) - assert_array_equal(expected_keypoints, detector.keypoints_) - assert_array_equal(expected_scales, detector.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 9943aeb3..30394d07 100644 --- a/skimage/feature/tests/test_orb.py +++ b/skimage/feature/tests/test_orb.py @@ -29,16 +29,16 @@ def test_keypoints_orb_desired_no_of_keypoints(): 0.39154173, 0.39084861, 0.39063076, 0.37602487]) - 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_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) + np.rad2deg(detector_extractor.orientations), 5) detector_extractor.detect_and_extract(img) - assert_almost_equal(exp_rows, detector_extractor.keypoints_[:, 0]) - assert_almost_equal(exp_cols, detector_extractor.keypoints_[:, 1]) + 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(): @@ -62,16 +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, 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_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) + np.rad2deg(detector_extractor.orientations), 5) detector_extractor.detect_and_extract(img) - assert_almost_equal(exp_rows, detector_extractor.keypoints_[:, 0]) - assert_almost_equal(exp_cols, detector_extractor.keypoints_[:, 1]) + assert_almost_equal(exp_rows, detector_extractor.keypoints[:, 0]) + assert_almost_equal(exp_cols, detector_extractor.keypoints[:, 1]) def test_descriptor_orb(): @@ -99,15 +99,15 @@ def test_descriptor_orb(): [ True, False, True, False, False, False, True, True, False, False]], dtype=bool) detector_extractor.detect(img) - detector_extractor.extract(img, detector_extractor.keypoints_, - detector_extractor.scales_, - detector_extractor.orientations_) + 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]) + detector_extractor.descriptors[100:120, 10:20]) detector_extractor.detect_and_extract(img) assert_array_equal(exp_descriptors, - detector_extractor.descriptors_[100:120, 10:20]) + detector_extractor.descriptors[100:120, 10:20]) if __name__ == '__main__':