Do not acquire GIL for corner detectors

This commit is contained in:
Johannes Schönberger
2015-05-20 07:45:04 -07:00
parent c52c7f4bfb
commit a489b85b22
2 changed files with 75 additions and 66 deletions
+71 -66
View File
@@ -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)
+4
View File
@@ -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))