Do not acquire GIL for rank filters

This commit is contained in:
Johannes Schönberger
2015-05-20 07:26:24 -07:00
parent a7c0b11eda
commit aa38f2485b
6 changed files with 145 additions and 140 deletions
+3 -3
View File
@@ -14,7 +14,7 @@ cdef inline void _kernel_mean(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i
cdef Py_ssize_t bilat_pop = 0
@@ -38,7 +38,7 @@ cdef inline void _kernel_pop(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i
cdef Py_ssize_t bilat_pop = 0
@@ -57,7 +57,7 @@ cdef inline void _kernel_sum(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i
cdef Py_ssize_t bilat_pop = 0
+3 -3
View File
@@ -11,13 +11,13 @@ ctypedef fused dtype_t_out:
double_t
cdef dtype_t _max(dtype_t a, dtype_t b)
cdef dtype_t _min(dtype_t a, dtype_t b)
cdef dtype_t _max(dtype_t a, dtype_t b) nogil
cdef dtype_t _min(dtype_t a, dtype_t b) nogil
cdef void _core(void kernel(dtype_t_out*, Py_ssize_t, Py_ssize_t*, double,
dtype_t, Py_ssize_t, Py_ssize_t, double,
double, Py_ssize_t, Py_ssize_t),
double, Py_ssize_t, Py_ssize_t) nogil,
dtype_t[:, ::1] image,
char[:, ::1] selem,
char[:, ::1] mask,
+107 -105
View File
@@ -9,29 +9,29 @@ cimport numpy as cnp
from libc.stdlib cimport malloc, free
cdef inline dtype_t _max(dtype_t a, dtype_t b):
cdef inline dtype_t _max(dtype_t a, dtype_t b) nogil:
return a if a >= b else b
cdef inline dtype_t _min(dtype_t a, dtype_t b):
cdef inline dtype_t _min(dtype_t a, dtype_t b) nogil:
return a if a <= b else b
cdef inline void histogram_increment(Py_ssize_t* histo, double* pop,
dtype_t value):
dtype_t value) nogil:
histo[value] += 1
pop[0] += 1
cdef inline void histogram_decrement(Py_ssize_t* histo, double* pop,
dtype_t value):
dtype_t value) nogil:
histo[value] -= 1
pop[0] -= 1
cdef inline char is_in_mask(Py_ssize_t rows, Py_ssize_t cols,
Py_ssize_t r, Py_ssize_t c,
char* mask):
char* mask) nogil:
"""Check whether given coordinate is within image and mask is true."""
if r < 0 or r > rows - 1 or c < 0 or c > cols - 1:
return 0
@@ -44,7 +44,7 @@ cdef inline char is_in_mask(Py_ssize_t rows, Py_ssize_t cols,
cdef void _core(void kernel(dtype_t_out*, Py_ssize_t, Py_ssize_t*, double,
dtype_t, Py_ssize_t, Py_ssize_t, double,
double, Py_ssize_t, Py_ssize_t),
double, Py_ssize_t, Py_ssize_t) nogil,
dtype_t[:, ::1] image,
char[:, ::1] selem,
char[:, ::1] mask,
@@ -123,123 +123,125 @@ cdef void _core(void kernel(dtype_t_out*, Py_ssize_t, Py_ssize_t*, double,
t = np.vstack((np.zeros((1, selem.shape[1])), selem))
cdef unsigned char[:, :] t_n = (np.diff(t, axis=0) > 0).view(np.uint8)
for r in range(srows):
for c in range(scols):
if t_e[r, c]:
se_e_r[num_se_e] = r - centre_r
se_e_c[num_se_e] = c - centre_c
num_se_e += 1
if t_w[r, c]:
se_w_r[num_se_w] = r - centre_r
se_w_c[num_se_w] = c - centre_c
num_se_w += 1
if t_n[r, c]:
se_n_r[num_se_n] = r - centre_r
se_n_c[num_se_n] = c - centre_c
num_se_n += 1
if t_s[r, c]:
se_s_r[num_se_s] = r - centre_r
se_s_c[num_se_s] = c - centre_c
num_se_s += 1
with nogil:
for r in range(srows):
for c in range(scols):
rr = r - centre_r
cc = c - centre_c
if selem[r, c]:
for r in range(srows):
for c in range(scols):
if t_e[r, c]:
se_e_r[num_se_e] = r - centre_r
se_e_c[num_se_e] = c - centre_c
num_se_e += 1
if t_w[r, c]:
se_w_r[num_se_w] = r - centre_r
se_w_c[num_se_w] = c - centre_c
num_se_w += 1
if t_n[r, c]:
se_n_r[num_se_n] = r - centre_r
se_n_c[num_se_n] = c - centre_c
num_se_n += 1
if t_s[r, c]:
se_s_r[num_se_s] = r - centre_r
se_s_c[num_se_s] = c - centre_c
num_se_s += 1
for r in range(srows):
for c in range(scols):
rr = r - centre_r
cc = c - centre_c
if selem[r, c]:
if is_in_mask(rows, cols, rr, cc, mask_data):
histogram_increment(histo, &pop, image[rr, cc])
r = 0
c = 0
kernel(&out[r, c, 0], odepth, histo, pop, image[r, c], max_bin, mid_bin,
p0, p1, s0, s1)
# main loop
r = 0
for even_row in range(0, rows, 2):
# ---> west to east
for c in range(1, cols):
for s in range(num_se_e):
rr = r + se_e_r[s]
cc = c + se_e_c[s]
if is_in_mask(rows, cols, rr, cc, mask_data):
histogram_increment(histo, &pop, image[rr, cc])
for s in range(num_se_w):
rr = r + se_w_r[s]
cc = c + se_w_c[s] - 1
if is_in_mask(rows, cols, rr, cc, mask_data):
histogram_decrement(histo, &pop, image[rr, cc])
kernel(&out[r, c, 0], odepth, histo, pop, image[r, c], max_bin,
mid_bin, p0, p1, s0, s1)
r += 1 # pass to the next row
if r >= rows:
break
# ---> north to south
for s in range(num_se_s):
rr = r + se_s_r[s]
cc = c + se_s_c[s]
if is_in_mask(rows, cols, rr, cc, mask_data):
histogram_increment(histo, &pop, image[rr, cc])
r = 0
c = 0
kernel(&out[r, c, 0], odepth, histo, pop, image[r, c], max_bin, mid_bin,
p0, p1, s0, s1)
# main loop
r = 0
for even_row in range(0, rows, 2):
# ---> west to east
for c in range(1, cols):
for s in range(num_se_e):
rr = r + se_e_r[s]
cc = c + se_e_c[s]
if is_in_mask(rows, cols, rr, cc, mask_data):
histogram_increment(histo, &pop, image[rr, cc])
for s in range(num_se_w):
rr = r + se_w_r[s]
cc = c + se_w_c[s] - 1
for s in range(num_se_n):
rr = r + se_n_r[s] - 1
cc = c + se_n_c[s]
if is_in_mask(rows, cols, rr, cc, mask_data):
histogram_decrement(histo, &pop, image[rr, cc])
kernel(&out[r, c, 0], odepth, histo, pop, image[r, c], max_bin,
mid_bin, p0, p1, s0, s1)
r += 1 # pass to the next row
if r >= rows:
break
# ---> east to west
for c in range(cols - 2, -1, -1):
for s in range(num_se_w):
rr = r + se_w_r[s]
cc = c + se_w_c[s]
if is_in_mask(rows, cols, rr, cc, mask_data):
histogram_increment(histo, &pop, image[rr, cc])
# ---> north to south
for s in range(num_se_s):
rr = r + se_s_r[s]
cc = c + se_s_c[s]
if is_in_mask(rows, cols, rr, cc, mask_data):
histogram_increment(histo, &pop, image[rr, cc])
for s in range(num_se_e):
rr = r + se_e_r[s]
cc = c + se_e_c[s] + 1
if is_in_mask(rows, cols, rr, cc, mask_data):
histogram_decrement(histo, &pop, image[rr, cc])
for s in range(num_se_n):
rr = r + se_n_r[s] - 1
cc = c + se_n_c[s]
if is_in_mask(rows, cols, rr, cc, mask_data):
histogram_decrement(histo, &pop, image[rr, cc])
kernel(&out[r, c, 0], odepth, histo, pop, image[r, c], max_bin,
mid_bin, p0, p1, s0, s1)
kernel(&out[r, c, 0], odepth, histo, pop, image[r, c], max_bin,
mid_bin, p0, p1, s0, s1)
r += 1 # pass to the next row
if r >= rows:
break
# ---> east to west
for c in range(cols - 2, -1, -1):
for s in range(num_se_w):
rr = r + se_w_r[s]
cc = c + se_w_c[s]
# ---> north to south
for s in range(num_se_s):
rr = r + se_s_r[s]
cc = c + se_s_c[s]
if is_in_mask(rows, cols, rr, cc, mask_data):
histogram_increment(histo, &pop, image[rr, cc])
for s in range(num_se_e):
rr = r + se_e_r[s]
cc = c + se_e_c[s] + 1
for s in range(num_se_n):
rr = r + se_n_r[s] - 1
cc = c + se_n_c[s]
if is_in_mask(rows, cols, rr, cc, mask_data):
histogram_decrement(histo, &pop, image[rr, cc])
kernel(&out[r, c, 0], odepth, histo, pop, image[r, c], max_bin,
mid_bin, p0, p1, s0, s1)
kernel(&out[r, c, 0], odepth, histo, pop, image[r, c],
max_bin, mid_bin, p0, p1, s0, s1)
r += 1 # pass to the next row
if r >= rows:
break
# ---> north to south
for s in range(num_se_s):
rr = r + se_s_r[s]
cc = c + se_s_c[s]
if is_in_mask(rows, cols, rr, cc, mask_data):
histogram_increment(histo, &pop, image[rr, cc])
for s in range(num_se_n):
rr = r + se_n_r[s] - 1
cc = c + se_n_c[s]
if is_in_mask(rows, cols, rr, cc, mask_data):
histogram_decrement(histo, &pop, image[rr, cc])
kernel(&out[r, c, 0], odepth, histo, pop, image[r, c],
max_bin, mid_bin, p0, p1, s0, s1)
# release memory allocated by malloc
free(se_e_r)
free(se_e_c)
free(se_w_r)
free(se_w_c)
free(se_n_r)
free(se_n_c)
free(se_s_r)
free(se_s_c)
free(histo)
# release memory allocated by malloc
free(se_e_r)
free(se_e_c)
free(se_w_r)
free(se_w_c)
free(se_n_r)
free(se_n_c)
free(se_s_r)
free(se_s_c)
free(histo)
+19 -19
View File
@@ -14,7 +14,7 @@ cdef inline void _kernel_autolevel(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i, imin, imax, delta
@@ -41,7 +41,7 @@ cdef inline void _kernel_bottomhat(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i
@@ -59,7 +59,7 @@ cdef inline void _kernel_equalize(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i
cdef Py_ssize_t sum = 0
@@ -79,7 +79,7 @@ cdef inline void _kernel_gradient(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i, imin, imax
@@ -102,7 +102,7 @@ cdef inline void _kernel_maximum(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i
@@ -120,7 +120,7 @@ cdef inline void _kernel_mean(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i
cdef Py_ssize_t mean = 0
@@ -138,7 +138,7 @@ cdef inline void _kernel_subtract_mean(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i
cdef Py_ssize_t mean = 0
@@ -156,7 +156,7 @@ cdef inline void _kernel_median(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i
cdef double sum = pop / 2.0
@@ -177,7 +177,7 @@ cdef inline void _kernel_minimum(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i
@@ -195,7 +195,7 @@ cdef inline void _kernel_modal(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t hmax = 0, imax = 0
@@ -217,7 +217,7 @@ cdef inline void _kernel_enhance_contrast(dtype_t_out* out,
Py_ssize_t max_bin,
Py_ssize_t mid_bin, double p0,
double p1, Py_ssize_t s0,
Py_ssize_t s1):
Py_ssize_t s1) nogil:
cdef Py_ssize_t i, imin, imax
@@ -243,7 +243,7 @@ cdef inline void _kernel_pop(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
out[0] = <dtype_t_out>pop
@@ -253,7 +253,7 @@ cdef inline void _kernel_sum(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i
cdef Py_ssize_t sum = 0
@@ -271,7 +271,7 @@ cdef inline void _kernel_threshold(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i
cdef Py_ssize_t mean = 0
@@ -289,7 +289,7 @@ cdef inline void _kernel_tophat(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i
@@ -307,7 +307,7 @@ cdef inline void _kernel_noise_filter(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i
cdef Py_ssize_t min_i
@@ -334,7 +334,7 @@ cdef inline void _kernel_entropy(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i
cdef double e, p
@@ -354,7 +354,7 @@ cdef inline void _kernel_otsu(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i
cdef Py_ssize_t max_i
cdef double P, mu1, mu2, q1, new_q1, sigma_b, max_sigma_b
@@ -394,7 +394,7 @@ cdef inline void _kernel_win_hist(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i
cdef Py_ssize_t max_i
cdef double scale
+9 -9
View File
@@ -12,7 +12,7 @@ cdef inline void _kernel_autolevel(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i, imin, imax, sum, delta
@@ -46,7 +46,7 @@ cdef inline void _kernel_gradient(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i, imin, imax, sum, delta
@@ -75,7 +75,7 @@ cdef inline void _kernel_mean(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i, sum, mean, n
@@ -101,7 +101,7 @@ cdef inline void _kernel_sum(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i, sum, sum_g, n
@@ -128,7 +128,7 @@ cdef inline void _kernel_subtract_mean(dtype_t_out* out, Py_ssize_t odepth,
Py_ssize_t max_bin,
Py_ssize_t mid_bin, double p0,
double p1, Py_ssize_t s0,
Py_ssize_t s1):
Py_ssize_t s1) nogil:
cdef Py_ssize_t i, sum, mean, n
@@ -156,7 +156,7 @@ cdef inline void _kernel_enhance_contrast(dtype_t_out* out,
Py_ssize_t max_bin,
Py_ssize_t mid_bin, double p0,
double p1, Py_ssize_t s0,
Py_ssize_t s1):
Py_ssize_t s1) nogil:
cdef Py_ssize_t i, imin, imax, sum, delta
@@ -191,7 +191,7 @@ cdef inline void _kernel_percentile(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i
cdef Py_ssize_t sum = 0
@@ -216,7 +216,7 @@ cdef inline void _kernel_pop(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef Py_ssize_t i, sum, n
@@ -237,7 +237,7 @@ cdef inline void _kernel_threshold(dtype_t_out* out, Py_ssize_t odepth,
double pop, dtype_t g,
Py_ssize_t max_bin, Py_ssize_t mid_bin,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1):
Py_ssize_t s0, Py_ssize_t s1) nogil:
cdef int i
cdef Py_ssize_t sum = 0
+4 -1
View File
@@ -8,6 +8,7 @@ from skimage import data, util, morphology
from skimage.morphology import grey, disk
from skimage.filters import rank
from skimage._shared._warnings import expected_warnings
from skimage._shared.testing import test_parallel
def test_all():
@@ -15,7 +16,9 @@ def test_all():
check_all()
@test_parallel()
def check_all():
np.random.seed(0)
image = np.random.rand(25, 25)
selem = morphology.disk(1)
refs = np.load(os.path.join(skimage.data_dir, "rank_filter_tests.npz"))
@@ -489,7 +492,7 @@ def test_entropy():
assert(np.max(rank.entropy(data, selem)) == 12)
# make sure output is of dtype double
with expected_warnings(['Bitdepth of 11']):
with expected_warnings(['Bitdepth of 11']):
out = rank.entropy(data, np.ones((16, 16), dtype=np.uint8))
assert out.dtype == np.double