diff --git a/skimage/feature/corner_cy.pyx b/skimage/feature/corner_cy.pyx index cef104e0..4f5c32c6 100644 --- a/skimage/feature/corner_cy.pyx +++ b/skimage/feature/corner_cy.pyx @@ -5,7 +5,7 @@ import numpy as np cimport numpy as cnp from libc.float cimport DBL_MAX -from libc.math cimport atan2 +from libc.math cimport atan2, fabs from ..util import img_as_float, pad from ..color import rgb2grey @@ -67,27 +67,30 @@ def corner_moravec(image, Py_ssize_t window_size=1): cdef double msum, min_msum cdef Py_ssize_t r, c, br, bc, mr, mc, a, b - for r in range(2 * window_size, rows - 2 * window_size): - for c in range(2 * window_size, cols - 2 * window_size): - min_msum = DBL_MAX - for br in range(r - window_size, r + window_size + 1): - for bc in range(c - window_size, c + window_size + 1): - if br != r and bc != c: - msum = 0 - for mr in range(- window_size, window_size + 1): - for mc in range(- window_size, window_size + 1): - msum += (cimage[r + mr, c + mc] - - cimage[br + mr, bc + mc]) ** 2 - min_msum = min(msum, min_msum) - out[r, c] = min_msum + with nogil: + for r in range(2 * window_size, rows - 2 * window_size): + for c in range(2 * window_size, cols - 2 * window_size): + min_msum = DBL_MAX + for br in range(r - window_size, r + window_size + 1): + for bc in range(c - window_size, c + window_size + 1): + if br != r and bc != c: + msum = 0 + for mr in range(- window_size, window_size + 1): + for mc in range(- window_size, window_size + 1): + msum += (cimage[r + mr, c + mc] + - cimage[br + mr, bc + mc]) ** 2 + min_msum = min(msum, min_msum) + + out[r, c] = min_msum return np.asarray(out) cdef inline double _corner_fast_response(double curr_pixel, double* circle_intensities, - signed char* bins, signed char state, char n): + signed char* bins, signed char state, + char n) nogil: cdef char consecutive_count = 0 cdef double curr_response cdef Py_ssize_t l, m @@ -97,7 +100,7 @@ cdef inline double _corner_fast_response(double curr_pixel, if consecutive_count == n: curr_response = 0 for m in range(16): - curr_response += abs(circle_intensities[m] - curr_pixel) + curr_response += fabs(circle_intensities[m] - curr_pixel) return curr_response else: consecutive_count = 0 @@ -124,49 +127,50 @@ def _corner_fast(double[:, ::1] image, signed char n, double threshold): cdef double curr_response - for i in range(3, rows - 3): - for j in range(3, cols - 3): + with nogil: + for i in range(3, rows - 3): + for j in range(3, cols - 3): - curr_pixel = image[i, j] - lower_threshold = curr_pixel - threshold - upper_threshold = curr_pixel + threshold + curr_pixel = image[i, j] + lower_threshold = curr_pixel - threshold + upper_threshold = curr_pixel + threshold - for k in range(16): - circle_intensities[k] = image[i + rp[k], j + cp[k]] - if circle_intensities[k] > upper_threshold: - # Brighter pixel - bins[k] = 'b' - elif circle_intensities[k] < lower_threshold: - # Darker pixel - bins[k] = 'd' - else: - # Similar pixel - bins[k] = 's' + for k in range(16): + circle_intensities[k] = image[i + rp[k], j + cp[k]] + if circle_intensities[k] > upper_threshold: + # Brighter pixel + bins[k] = 'b' + elif circle_intensities[k] < lower_threshold: + # Darker pixel + bins[k] = 'd' + else: + # Similar pixel + bins[k] = 's' - # High speed test for n >= 12 - if n >= 12: - speed_sum_b = 0 - speed_sum_d = 0 - for k in range(0, 16, 4): - if bins[k] == 'b': - speed_sum_b += 1 - elif bins[k] == 'd': - speed_sum_d += 1 - if speed_sum_d < 3 and speed_sum_b < 3: - continue + # High speed test for n >= 12 + if n >= 12: + speed_sum_b = 0 + speed_sum_d = 0 + for k in range(0, 16, 4): + if bins[k] == 'b': + speed_sum_b += 1 + elif bins[k] == 'd': + speed_sum_d += 1 + if speed_sum_d < 3 and speed_sum_b < 3: + continue - # Test for bright pixels - curr_response = \ - _corner_fast_response(curr_pixel, circle_intensities, - bins, 'b', n) - - # Test for dark pixels - if curr_response == 0: + # Test for bright pixels curr_response = \ _corner_fast_response(curr_pixel, circle_intensities, - bins, 'd', n) + bins, 'b', n) - corner_response[i, j] = curr_response + # Test for dark pixels + if curr_response == 0: + curr_response = \ + _corner_fast_response(curr_pixel, circle_intensities, + bins, 'd', n) + + corner_response[i, j] = curr_response return np.asarray(corner_response) @@ -254,22 +258,23 @@ def corner_orientations(image, Py_ssize_t[:, :] corners, mask): cdef double curr_pixel cdef double m01, m10, m01_tmp - for i in range(corners.shape[0]): - r0 = corners[i, 0] - c0 = corners[i, 1] + with nogil: + for i in range(corners.shape[0]): + r0 = corners[i, 0] + c0 = corners[i, 1] - m01 = 0 - m10 = 0 + m01 = 0 + m10 = 0 - for r in range(mrows): - m01_tmp = 0 - for c in range(mcols): - if cmask[r, c]: - curr_pixel = cimage[r0 + r, c0 + c] - m10 += curr_pixel * (c - mcols2) - m01_tmp += curr_pixel - m01 += m01_tmp * (r - mrows2) + for r in range(mrows): + m01_tmp = 0 + for c in range(mcols): + if cmask[r, c]: + curr_pixel = cimage[r0 + r, c0 + c] + m10 += curr_pixel * (c - mcols2) + m01_tmp += curr_pixel + m01 += m01_tmp * (r - mrows2) - orientations[i] = atan2(m01, m10) + orientations[i] = atan2(m01, m10) return np.asarray(orientations) diff --git a/skimage/feature/tests/test_corner.py b/skimage/feature/tests/test_corner.py index a9f5bb91..aa7e1409 100644 --- a/skimage/feature/tests/test_corner.py +++ b/skimage/feature/tests/test_corner.py @@ -6,6 +6,7 @@ from skimage import data from skimage import img_as_float from skimage.color import rgb2gray from skimage.morphology import octagon +from skimage._shared.testing import test_parallel from skimage.feature import (corner_moravec, corner_harris, corner_shi_tomasi, corner_subpix, peak_local_max, corner_peaks, @@ -99,6 +100,7 @@ def test_hessian_matrix_det(): assert_almost_equal(det, 0, decimal = 3) +@test_parallel() def test_square_image(): im = np.zeros((50, 50)).astype(float) im[:25, :25] = 1. @@ -280,6 +282,7 @@ def test_corner_fast_image_unsupported_error(): assert_raises(ValueError, corner_fast, img) +@test_parallel() def test_corner_fast_lena(): img = rgb2gray(data.astronaut()) expected = np.array([[101, 198], @@ -335,6 +338,7 @@ def test_corner_orientations_even_shape_error(): np.asarray([[7, 7]]), np.ones((4, 4))) +@test_parallel() def test_corner_orientations_lena(): img = rgb2gray(data.lena()) corners = corner_peaks(corner_fast(img, 11, 0.35))