diff --git a/skimage/feature/corner.py b/skimage/feature/corner.py index 12c2ea89..8a7944e6 100644 --- a/skimage/feature/corner.py +++ b/skimage/feature/corner.py @@ -53,8 +53,9 @@ def _compute_auto_correlation(image, sigma): """ - if image.ndim == 3: - image = img_as_float(rgb2grey(image)) + image = np.squeeze(image) + if image.ndim != 2: + raise ValueError("Only 2-D gray-scale images supported.") imx, imy = _compute_derivatives(image) @@ -567,8 +568,8 @@ def corner_fast(image, n=12, threshold=0.15): Returns ------- - corners : (N, 2) ndarray - Location i.e. (row, col) of extracted FAST corners. + response : ndarray + FAST corner response image. References ---------- @@ -578,6 +579,31 @@ def corner_fast(image, n=12, threshold=0.15): .. [2] Wikipedia, "Features from accelerated segment test", https://en.wikipedia.org/wiki/Features_from_accelerated_segment_test + Examples + -------- + >>> import numpy as np + >>> from skimage.feature import corner_fast, corner_peaks + >>> square = np.zeros((12, 12)) + >>> square[3:9, 3:9] = 1 + >>> square + array([[ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], + [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], + [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], + [ 0., 0., 0., 1., 1., 1., 1., 1., 1., 0., 0., 0.], + [ 0., 0., 0., 1., 1., 1., 1., 1., 1., 0., 0., 0.], + [ 0., 0., 0., 1., 1., 1., 1., 1., 1., 0., 0., 0.], + [ 0., 0., 0., 1., 1., 1., 1., 1., 1., 0., 0., 0.], + [ 0., 0., 0., 1., 1., 1., 1., 1., 1., 0., 0., 0.], + [ 0., 0., 0., 1., 1., 1., 1., 1., 1., 0., 0., 0.], + [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], + [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], + [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]]) + >>> corner_peaks(corner_fast(square, 9), min_distance=1) + array([[3, 3], + [3, 8], + [8, 3], + [8, 8]]) + """ image = np.squeeze(image) if image.ndim != 2: @@ -585,4 +611,5 @@ def corner_fast(image, n=12, threshold=0.15): image = img_as_float(image) image = np.ascontiguousarray(image) - return _corner_fast(image, n, threshold) + response = _corner_fast(image, n, threshold) + return response diff --git a/skimage/feature/corner_cy.pyx b/skimage/feature/corner_cy.pyx index 2f916d4d..66908472 100644 --- a/skimage/feature/corner_cy.pyx +++ b/skimage/feature/corner_cy.pyx @@ -168,7 +168,9 @@ def _corner_fast(double[:, ::1] image, char n, double threshold): def corner_fast_orientation(image, Py_ssize_t[:, :] fast_corners): - """Compute the orientation of FAST corners using the first order central + """Compute the orientation of FAST corners. + + The orientation of corners is computed using the first order central moment i.e. the center of mass approach. The corner orientation is the angle of the vector from the keypoint to the intensity centroid calculated using first order central moment. @@ -199,7 +201,7 @@ def corner_fast_orientation(image, Py_ssize_t[:, :] fast_corners): if image.ndim != 2: raise ValueError("Only 2-D gray-scale images supported.") - cdef double[:, :] cimage = np.ascontiguousarray(img_as_float(image)) + cdef double[:, :] cimage = img_as_float(image) # Essentially skimage.morphology.octagon(3, 2) cdef char[:, ::1] circular_mask = np.array([[0, 0, 1, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 0], @@ -210,34 +212,23 @@ def corner_fast_orientation(image, Py_ssize_t[:, :] fast_corners): [0, 0, 1, 1, 1, 0, 0]], dtype=np.uint8) cdef Py_ssize_t n_fast_corners = fast_corners.shape[0] - cdef Py_ssize_t i, r, c, x_top, y_left - cdef double[:, ::1] kp_circular_patch, mu + cdef Py_ssize_t i, r, c, y_top, x_left cdef double[:] kp_orientation = np.zeros(fast_corners.shape[0], dtype=np.double) cdef double m00, m01, m10 for i in range(n_fast_corners): - x_top = fast_corners[i, 0] - 3 - y_left = fast_corners[i, 1] - 3 + y_top = fast_corners[i, 0] - 3 + x_left = fast_corners[i, 1] - 3 m00 = 0 m01 = 0 m10 = 0 - #kp_circular_patch = np.ascontiguousarray(image[x - 3:x + 4, y - 3:y + 4]) - #mu = np.zeros((2, 2), dtype=np.double) for r in range(7): for c in range(7): if circular_mask[r, c]: - m00 += cimage[x_top + r, y_left + c] - - for r in range(7): - for c in range(7): - if circular_mask[r, c]: - m01 += cimage[x_top + r, y_left + c] * (c - 3) - - for r in range(7): - for c in range(7): - if circular_mask[r, c]: - m10 += cimage[x_top + r, y_left + c] * (r - 3) + m00 += cimage[y_top + r, x_left + c] + m01 += cimage[y_top + r, x_left + c] * (c - 3) + m10 += cimage[y_top + r, x_left + c] * (r - 3) kp_orientation[i] = atan2(m10 / m00, m01 / m00) diff --git a/skimage/feature/tests/test_corner.py b/skimage/feature/tests/test_corner.py index 1a520ceb..b0abcaed 100644 --- a/skimage/feature/tests/test_corner.py +++ b/skimage/feature/tests/test_corner.py @@ -125,7 +125,7 @@ def test_num_peaks(): peak_local_max returns exactly the right amount of peaks. Test is run on Lena in order to produce a sufficient number of corners""" - lena_corners = corner_harris(data.lena()) + lena_corners = corner_harris(rgb2gray(data.lena())) for i in range(20): n = np.random.random_integers(20)