mirror of
https://github.com/wassname/scikit-image.git
synced 2026-08-11 11:25:30 +08:00
Do not acquire GIL for corner detectors
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
cimport numpy as cnp
|
cimport numpy as cnp
|
||||||
from libc.float cimport DBL_MAX
|
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 ..util import img_as_float, pad
|
||||||
from ..color import rgb2grey
|
from ..color import rgb2grey
|
||||||
@@ -67,27 +67,30 @@ def corner_moravec(image, Py_ssize_t window_size=1):
|
|||||||
|
|
||||||
cdef double msum, min_msum
|
cdef double msum, min_msum
|
||||||
cdef Py_ssize_t r, c, br, bc, mr, mc, a, b
|
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)
|
return np.asarray(out)
|
||||||
|
|
||||||
|
|
||||||
cdef inline double _corner_fast_response(double curr_pixel,
|
cdef inline double _corner_fast_response(double curr_pixel,
|
||||||
double* circle_intensities,
|
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 char consecutive_count = 0
|
||||||
cdef double curr_response
|
cdef double curr_response
|
||||||
cdef Py_ssize_t l, m
|
cdef Py_ssize_t l, m
|
||||||
@@ -97,7 +100,7 @@ cdef inline double _corner_fast_response(double curr_pixel,
|
|||||||
if consecutive_count == n:
|
if consecutive_count == n:
|
||||||
curr_response = 0
|
curr_response = 0
|
||||||
for m in range(16):
|
for m in range(16):
|
||||||
curr_response += abs(circle_intensities[m] - curr_pixel)
|
curr_response += fabs(circle_intensities[m] - curr_pixel)
|
||||||
return curr_response
|
return curr_response
|
||||||
else:
|
else:
|
||||||
consecutive_count = 0
|
consecutive_count = 0
|
||||||
@@ -124,49 +127,50 @@ def _corner_fast(double[:, ::1] image, signed char n, double threshold):
|
|||||||
|
|
||||||
cdef double curr_response
|
cdef double curr_response
|
||||||
|
|
||||||
for i in range(3, rows - 3):
|
with nogil:
|
||||||
for j in range(3, cols - 3):
|
for i in range(3, rows - 3):
|
||||||
|
for j in range(3, cols - 3):
|
||||||
|
|
||||||
curr_pixel = image[i, j]
|
curr_pixel = image[i, j]
|
||||||
lower_threshold = curr_pixel - threshold
|
lower_threshold = curr_pixel - threshold
|
||||||
upper_threshold = curr_pixel + threshold
|
upper_threshold = curr_pixel + threshold
|
||||||
|
|
||||||
for k in range(16):
|
for k in range(16):
|
||||||
circle_intensities[k] = image[i + rp[k], j + cp[k]]
|
circle_intensities[k] = image[i + rp[k], j + cp[k]]
|
||||||
if circle_intensities[k] > upper_threshold:
|
if circle_intensities[k] > upper_threshold:
|
||||||
# Brighter pixel
|
# Brighter pixel
|
||||||
bins[k] = 'b'
|
bins[k] = 'b'
|
||||||
elif circle_intensities[k] < lower_threshold:
|
elif circle_intensities[k] < lower_threshold:
|
||||||
# Darker pixel
|
# Darker pixel
|
||||||
bins[k] = 'd'
|
bins[k] = 'd'
|
||||||
else:
|
else:
|
||||||
# Similar pixel
|
# Similar pixel
|
||||||
bins[k] = 's'
|
bins[k] = 's'
|
||||||
|
|
||||||
# High speed test for n >= 12
|
# High speed test for n >= 12
|
||||||
if n >= 12:
|
if n >= 12:
|
||||||
speed_sum_b = 0
|
speed_sum_b = 0
|
||||||
speed_sum_d = 0
|
speed_sum_d = 0
|
||||||
for k in range(0, 16, 4):
|
for k in range(0, 16, 4):
|
||||||
if bins[k] == 'b':
|
if bins[k] == 'b':
|
||||||
speed_sum_b += 1
|
speed_sum_b += 1
|
||||||
elif bins[k] == 'd':
|
elif bins[k] == 'd':
|
||||||
speed_sum_d += 1
|
speed_sum_d += 1
|
||||||
if speed_sum_d < 3 and speed_sum_b < 3:
|
if speed_sum_d < 3 and speed_sum_b < 3:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Test for bright pixels
|
# Test for bright pixels
|
||||||
curr_response = \
|
|
||||||
_corner_fast_response(curr_pixel, circle_intensities,
|
|
||||||
bins, 'b', n)
|
|
||||||
|
|
||||||
# Test for dark pixels
|
|
||||||
if curr_response == 0:
|
|
||||||
curr_response = \
|
curr_response = \
|
||||||
_corner_fast_response(curr_pixel, circle_intensities,
|
_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)
|
return np.asarray(corner_response)
|
||||||
|
|
||||||
@@ -254,22 +258,23 @@ def corner_orientations(image, Py_ssize_t[:, :] corners, mask):
|
|||||||
cdef double curr_pixel
|
cdef double curr_pixel
|
||||||
cdef double m01, m10, m01_tmp
|
cdef double m01, m10, m01_tmp
|
||||||
|
|
||||||
for i in range(corners.shape[0]):
|
with nogil:
|
||||||
r0 = corners[i, 0]
|
for i in range(corners.shape[0]):
|
||||||
c0 = corners[i, 1]
|
r0 = corners[i, 0]
|
||||||
|
c0 = corners[i, 1]
|
||||||
|
|
||||||
m01 = 0
|
m01 = 0
|
||||||
m10 = 0
|
m10 = 0
|
||||||
|
|
||||||
for r in range(mrows):
|
for r in range(mrows):
|
||||||
m01_tmp = 0
|
m01_tmp = 0
|
||||||
for c in range(mcols):
|
for c in range(mcols):
|
||||||
if cmask[r, c]:
|
if cmask[r, c]:
|
||||||
curr_pixel = cimage[r0 + r, c0 + c]
|
curr_pixel = cimage[r0 + r, c0 + c]
|
||||||
m10 += curr_pixel * (c - mcols2)
|
m10 += curr_pixel * (c - mcols2)
|
||||||
m01_tmp += curr_pixel
|
m01_tmp += curr_pixel
|
||||||
m01 += m01_tmp * (r - mrows2)
|
m01 += m01_tmp * (r - mrows2)
|
||||||
|
|
||||||
orientations[i] = atan2(m01, m10)
|
orientations[i] = atan2(m01, m10)
|
||||||
|
|
||||||
return np.asarray(orientations)
|
return np.asarray(orientations)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from skimage import data
|
|||||||
from skimage import img_as_float
|
from skimage import img_as_float
|
||||||
from skimage.color import rgb2gray
|
from skimage.color import rgb2gray
|
||||||
from skimage.morphology import octagon
|
from skimage.morphology import octagon
|
||||||
|
from skimage._shared.testing import test_parallel
|
||||||
|
|
||||||
from skimage.feature import (corner_moravec, corner_harris, corner_shi_tomasi,
|
from skimage.feature import (corner_moravec, corner_harris, corner_shi_tomasi,
|
||||||
corner_subpix, peak_local_max, corner_peaks,
|
corner_subpix, peak_local_max, corner_peaks,
|
||||||
@@ -99,6 +100,7 @@ def test_hessian_matrix_det():
|
|||||||
assert_almost_equal(det, 0, decimal = 3)
|
assert_almost_equal(det, 0, decimal = 3)
|
||||||
|
|
||||||
|
|
||||||
|
@test_parallel()
|
||||||
def test_square_image():
|
def test_square_image():
|
||||||
im = np.zeros((50, 50)).astype(float)
|
im = np.zeros((50, 50)).astype(float)
|
||||||
im[:25, :25] = 1.
|
im[:25, :25] = 1.
|
||||||
@@ -280,6 +282,7 @@ def test_corner_fast_image_unsupported_error():
|
|||||||
assert_raises(ValueError, corner_fast, img)
|
assert_raises(ValueError, corner_fast, img)
|
||||||
|
|
||||||
|
|
||||||
|
@test_parallel()
|
||||||
def test_corner_fast_lena():
|
def test_corner_fast_lena():
|
||||||
img = rgb2gray(data.astronaut())
|
img = rgb2gray(data.astronaut())
|
||||||
expected = np.array([[101, 198],
|
expected = np.array([[101, 198],
|
||||||
@@ -335,6 +338,7 @@ def test_corner_orientations_even_shape_error():
|
|||||||
np.asarray([[7, 7]]), np.ones((4, 4)))
|
np.asarray([[7, 7]]), np.ones((4, 4)))
|
||||||
|
|
||||||
|
|
||||||
|
@test_parallel()
|
||||||
def test_corner_orientations_lena():
|
def test_corner_orientations_lena():
|
||||||
img = rgb2gray(data.lena())
|
img = rgb2gray(data.lena())
|
||||||
corners = corner_peaks(corner_fast(img, 11, 0.35))
|
corners = corner_peaks(corner_fast(img, 11, 0.35))
|
||||||
|
|||||||
Reference in New Issue
Block a user