From 4a14a217b951c7c83b9c12f07dec52efc1dd42fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Fri, 9 Nov 2012 19:39:30 +0100 Subject: [PATCH] Improve overall code style --- skimage/filter/rank/_core16.pxd | 23 +- skimage/filter/rank/_core16.pyx | 125 ++--- skimage/filter/rank/_core8.pxd | 27 +- skimage/filter/rank/_core8.pyx | 154 +++--- skimage/filter/rank/_crank16.pyx | 46 +- skimage/filter/rank/_crank16_bilateral.pyx | 6 +- skimage/filter/rank/_crank16_percentiles.pyx | 64 +-- skimage/filter/rank/_crank8.pyx | 65 +-- skimage/filter/rank/_crank8_percentiles.pyx | 36 +- skimage/filter/rank/bilateral_rank.pyx | 135 +++--- skimage/filter/rank/percentile_rank.pyx | 361 ++++++++------ skimage/filter/rank/rank.pyx | 475 +++++++++++-------- 12 files changed, 812 insertions(+), 705 deletions(-) diff --git a/skimage/filter/rank/_core16.pxd b/skimage/filter/rank/_core16.pxd index 9590e277..b236d982 100644 --- a/skimage/filter/rank/_core16.pxd +++ b/skimage/filter/rank/_core16.pxd @@ -1,18 +1,17 @@ cimport numpy as np -#--------------------------------------------------------------------------- -# 16 bit core kernel receives extra information about data bitdepth -#--------------------------------------------------------------------------- -# generic cdef functions cdef int int_max(int a, int b) cdef int int_min(int a, int b) -cdef _core16( - np.uint16_t kernel(Py_ssize_t * , float, np.uint16_t, Py_ssize_t, Py_ssize_t, Py_ssize_t, float, float, Py_ssize_t, Py_ssize_t), - np.ndarray[np.uint16_t, ndim=2] image, - np.ndarray[np.uint8_t, ndim=2] selem, - np.ndarray[np.uint8_t, ndim=2] mask, - np.ndarray[np.uint16_t, ndim=2] out, - char shift_x, char shift_y, Py_ssize_t bitdepth, - float p0, float p1, Py_ssize_t s0, Py_ssize_t s1) + +# 16 bit core kernel receives extra information about data bitdepth +cdef void _core16(np.uint16_t kernel(Py_ssize_t *, float, np.uint16_t, + Py_ssize_t, Py_ssize_t, Py_ssize_t, float, + float, Py_ssize_t, Py_ssize_t), + np.ndarray[np.uint16_t, ndim=2] image, + np.ndarray[np.uint8_t, ndim=2] selem, + np.ndarray[np.uint8_t, ndim=2] mask, + np.ndarray[np.uint16_t, ndim=2] out, + char shift_x, char shift_y, Py_ssize_t bitdepth, + float p0, float p1, Py_ssize_t s0, Py_ssize_t s1) diff --git a/skimage/filter/rank/_core16.pyx b/skimage/filter/rank/_core16.pyx index 4829792b..671a92fc 100644 --- a/skimage/filter/rank/_core16.pyx +++ b/skimage/filter/rank/_core16.pyx @@ -6,50 +6,40 @@ import numpy as np cimport numpy as np from libc.stdlib cimport malloc, free +from _core8 cimport is_in_mask -#--------------------------------------------------------------------------- -# 16 bit core kernel receives extra information about data bitdepth -#--------------------------------------------------------------------------- -# generic cdef functions cdef inline int int_max(int a, int b): return a if a >= b else b + + cdef inline int int_min(int a, int b): return a if a <= b else b -cdef inline void histogram_increment(Py_ssize_t * histo, float * pop, np.uint16_t value): + +cdef inline void histogram_increment(Py_ssize_t * histo, float * pop, + np.uint16_t value): histo[value] += 1 pop[0] += 1. -cdef inline void histogram_decrement(Py_ssize_t * histo, float * pop, np.uint16_t value): + +cdef inline void histogram_decrement(Py_ssize_t * histo, float * pop, + np.uint16_t value): histo[value] -= 1 pop[0] -= 1. -cdef inline np.uint8_t is_in_mask(Py_ssize_t rows, Py_ssize_t cols, Py_ssize_t r, Py_ssize_t c, np.uint8_t * mask): - """ returns 1 if given(r,c) coordinate are within the image frame ([0-rows],[0-cols]) and - inside the given mask - returns 0 otherwise - """ - if r < 0 or r > rows - 1 or c < 0 or c > cols - 1: - return 0 - else: - if mask[r * cols + c]: - return 1 - else: - return 0 - -cdef inline _core16( - np.uint16_t kernel(Py_ssize_t *, float, np.uint16_t, Py_ssize_t, Py_ssize_t, Py_ssize_t, float, float, Py_ssize_t, Py_ssize_t), - np.ndarray[np.uint16_t, ndim=2] image, - np.ndarray[np.uint8_t, ndim=2] selem, - np.ndarray[np.uint8_t, ndim=2] mask, - np.ndarray[np.uint16_t, ndim=2] out, - char shift_x, char shift_y, Py_ssize_t bitdepth, - float p0, float p1, Py_ssize_t s0, Py_ssize_t s1): - """ Main loop, this function computes the histogram for each image point - - data is uint8 - - result is uint8 casted +cdef void _core16(np.uint16_t kernel(Py_ssize_t *, float, np.uint16_t, + Py_ssize_t, Py_ssize_t, Py_ssize_t, float, + float, Py_ssize_t, Py_ssize_t), + np.ndarray[np.uint16_t, ndim=2] image, + np.ndarray[np.uint8_t, ndim=2] selem, + np.ndarray[np.uint8_t, ndim=2] mask, + np.ndarray[np.uint16_t, ndim=2] out, + char shift_x, char shift_y, Py_ssize_t bitdepth, + float p0, float p1, Py_ssize_t s0, Py_ssize_t s1): + """Compute histogram for each pixel neighborhood, apply kernel function and + use kernel function return value for output image. """ cdef Py_ssize_t rows = image.shape[0] @@ -71,35 +61,20 @@ cdef inline _core16( midbin_list = [0, 0, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] #set maxbin and midbin - cdef Py_ssize_t maxbin = maxbin_list[bitdepth], midbin = midbin_list[bitdepth] + cdef Py_ssize_t maxbin = maxbin_list[bitdepth] + cdef Py_ssize_t midbin = midbin_list[bitdepth] assert (image < maxbin).all() - image = np.ascontiguousarray(image) - - if mask is None: - mask = np.ones((rows, cols), dtype=np.uint8) - else: - mask = np.ascontiguousarray(mask) - - if image is out: - raise NotImplementedError("Cannot perform rank operation in place.") - - if out is None: - out = np.zeros((rows, cols), dtype=np.uint16) - else: - out = np.ascontiguousarray(out) - - mask = np.ascontiguousarray(mask) - # define pointers to the data - cdef np.uint16_t * out_data = out.data - cdef np.uint16_t * image_data = image.data - cdef np.uint8_t * mask_data = mask.data + cdef np.uint16_t * out_data = out.data + cdef np.uint16_t * image_data = image.data + cdef np.uint8_t * mask_data = mask.data # define local variable types cdef Py_ssize_t r, c, rr, cc, s, value, local_max, i, even_row - cdef float pop # number of pixels actually inside the neighborhood (float) + # number of pixels actually inside the neighborhood (float) + cdef float pop # allocate memory with malloc cdef Py_ssize_t max_se = srows * scols @@ -108,24 +83,22 @@ cdef inline _core16( cdef Py_ssize_t num_se_n, num_se_s, num_se_e, num_se_w # the current local histogram distribution - cdef Py_ssize_t * histo = malloc(maxbin * sizeof(Py_ssize_t)) + cdef Py_ssize_t * histo = malloc(maxbin * sizeof(Py_ssize_t)) - # these lists contain the relative pixel row and column for each of the 4 attack borders - # east, west, north and south - # e.g. se_e_r lists the rows of the east structuring element border - - cdef Py_ssize_t * se_e_r = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t * se_e_c = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t * se_w_r = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t * se_w_c = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t * se_n_r = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t * se_n_c = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t * se_s_r = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t * se_s_c = malloc(max_se * sizeof(Py_ssize_t)) + # these lists contain the relative pixel row and column for each of the 4 + # attack borders east, west, north and south e.g. se_e_r lists the rows of + # the east structuring element border + cdef Py_ssize_t * se_e_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_e_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_w_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_w_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_n_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_n_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_s_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_s_c = malloc(max_se * sizeof(Py_ssize_t)) # build attack and release borders # by using difference along axis - t = np.hstack((selem, np.zeros((selem.shape[0], 1)))) t_e = np.diff(t, axis=1) == -1 @@ -171,7 +144,7 @@ cdef inline _core16( cc = c - centre_c if selem[r, c]: if is_in_mask(rows, cols, rr, cc, mask_data): - histogram_increment(histo, & pop, image_data[rr * cols + cc]) + histogram_increment(histo, &pop, image_data[rr * cols + cc]) r = 0 c = 0 @@ -189,13 +162,13 @@ cdef inline _core16( 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_data[rr * cols + cc]) + histogram_increment(histo, &pop, image_data[rr * cols + 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_data[rr * cols + cc]) + histogram_decrement(histo, &pop, image_data[rr * cols + cc]) # kernel ------------------------------------------- out_data[r * cols + c] = kernel( @@ -212,13 +185,13 @@ cdef inline _core16( 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_data[rr * cols + cc]) + histogram_increment(histo, &pop, image_data[rr * cols + 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_data[rr * cols + cc]) + histogram_decrement(histo, &pop, image_data[rr * cols + cc]) # kernel ------------------------------------------- out_data[r * cols + c] = kernel(histo, pop, image_data[r * cols + c], @@ -231,13 +204,13 @@ cdef inline _core16( 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_data[rr * cols + cc]) + histogram_increment(histo, &pop, image_data[rr * cols + 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_data[rr * cols + cc]) + histogram_decrement(histo, &pop, image_data[rr * cols + cc]) # kernel ------------------------------------------- out_data[r * cols + c] = kernel( @@ -254,13 +227,13 @@ cdef inline _core16( 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_data[rr * cols + cc]) + histogram_increment(histo, &pop, image_data[rr * cols + 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_data[rr * cols + cc]) + histogram_decrement(histo, &pop, image_data[rr * cols + cc]) # kernel ------------------------------------------- out_data[r * cols + c] = kernel(histo, pop, image_data[r * cols + c], @@ -279,5 +252,3 @@ cdef inline _core16( free(se_s_c) free(histo) - - return out diff --git a/skimage/filter/rank/_core8.pxd b/skimage/filter/rank/_core8.pxd index 9f898faa..d724c417 100644 --- a/skimage/filter/rank/_core8.pxd +++ b/skimage/filter/rank/_core8.pxd @@ -1,17 +1,22 @@ cimport numpy as np -# generic cdef functions + cdef np.uint8_t uint8_max(np.uint8_t a, np.uint8_t b) cdef np.uint8_t uint8_min(np.uint8_t a, np.uint8_t b) -#--------------------------------------------------------------------------- -# 8 bit core kernel receives extra information about data inferior and superior percentiles -#--------------------------------------------------------------------------- -cdef _core8( - np.uint8_t kernel(Py_ssize_t *, float, np.uint8_t, float, float, Py_ssize_t, Py_ssize_t), - np.ndarray[np.uint8_t, ndim=2] image, - np.ndarray[np.uint8_t, ndim=2] selem, - np.ndarray[np.uint8_t, ndim=2] mask, - np.ndarray[np.uint8_t, ndim=2] out, - char shift_x, char shift_y, float p0, float p1, Py_ssize_t s0, Py_ssize_t s1) +cdef np.uint8_t is_in_mask(Py_ssize_t rows, Py_ssize_t cols, + Py_ssize_t r, Py_ssize_t c, + np.uint8_t * mask) + + +# 8 bit core kernel receives extra information about data inferior and superior +# percentiles +cdef void _core8(np.uint8_t kernel(Py_ssize_t *, float, np.uint8_t, float, + float, Py_ssize_t, Py_ssize_t), + np.ndarray[np.uint8_t, ndim=2] image, + np.ndarray[np.uint8_t, ndim=2] selem, + np.ndarray[np.uint8_t, ndim=2] mask, + np.ndarray[np.uint8_t, ndim=2] out, + char shift_x, char shift_y, float p0, float p1, + Py_ssize_t s0, Py_ssize_t s1) diff --git a/skimage/filter/rank/_core8.pyx b/skimage/filter/rank/_core8.pyx index 9955a1e1..17e5f64e 100644 --- a/skimage/filter/rank/_core8.pyx +++ b/skimage/filter/rank/_core8.pyx @@ -7,30 +7,31 @@ import numpy as np cimport numpy as np from libc.stdlib cimport malloc, free -# generic cdef functions + cdef inline np.uint8_t uint8_max(np.uint8_t a, np.uint8_t b): return a if a >= b else b + + cdef inline np.uint8_t uint8_min(np.uint8_t a, np.uint8_t b): return a if a <= b else b -#--------------------------------------------------------------------------- -# 8 bit core kernel -#--------------------------------------------------------------------------- - -cdef inline void histogram_increment(Py_ssize_t * histo, float * pop, np.uint8_t value): +cdef inline void histogram_increment(Py_ssize_t * histo, float * pop, + np.uint8_t value): histo[value] += 1 pop[0] += 1. -cdef inline void histogram_decrement(Py_ssize_t * histo, float * pop, np.uint8_t value): + +cdef inline void histogram_decrement(Py_ssize_t * histo, float * pop, + np.uint8_t value): histo[value] -= 1 pop[0] -= 1. -cdef inline np.uint8_t is_in_mask(Py_ssize_t rows, Py_ssize_t cols, Py_ssize_t r, Py_ssize_t c, np.uint8_t * mask): - """ returns 1 if given(r,c) coordinate are within the image frame ([0-rows],[0-cols]) and - inside the given mask - returns 0 otherwise - """ + +cdef inline np.uint8_t is_in_mask(Py_ssize_t rows, Py_ssize_t cols, + Py_ssize_t r, Py_ssize_t c, + np.uint8_t * mask): + """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 else: @@ -39,16 +40,17 @@ cdef inline np.uint8_t is_in_mask(Py_ssize_t rows, Py_ssize_t cols, Py_ssize_t r else: return 0 -cdef inline _core8( - np.uint8_t kernel(Py_ssize_t * , float, np.uint8_t, float, float, Py_ssize_t, Py_ssize_t), - np.ndarray[np.uint8_t, ndim=2] image, - np.ndarray[np.uint8_t, ndim=2] selem, - np.ndarray[np.uint8_t, ndim=2] mask, - np.ndarray[np.uint8_t, ndim=2] out, - char shift_x, char shift_y, float p0, float p1, Py_ssize_t s0, Py_ssize_t s1): - """ Main loop, this function computes the histogram for each image point - - data is uint8 - - result is uint8 casted + +cdef void _core8(np.uint8_t kernel(Py_ssize_t *, float, np.uint8_t, float, + float, Py_ssize_t, Py_ssize_t), + np.ndarray[np.uint8_t, ndim=2] image, + np.ndarray[np.uint8_t, ndim=2] selem, + np.ndarray[np.uint8_t, ndim=2] mask, + np.ndarray[np.uint8_t, ndim=2] out, + char shift_x, char shift_y, float p0, float p1, + Py_ssize_t s0, Py_ssize_t s1): + """Compute histogram for each pixel neighborhood, apply kernel function and + use kernel function return value for output image. """ cdef Py_ssize_t rows = image.shape[0] @@ -65,28 +67,11 @@ cdef inline _core8( assert centre_r < srows assert centre_c < scols - image = np.ascontiguousarray(image) - - if mask is None: - mask = np.ones((rows, cols), dtype=np.uint8) - else: - mask = np.ascontiguousarray(mask) - - if image is out: - raise NotImplementedError("Cannot perform rank operation in place.") - - if out is None: - out = np.zeros((rows, cols), dtype=np.uint8) - else: - out = np.ascontiguousarray(out) - - mask = np.ascontiguousarray(mask) - # define pointers to the data - cdef np.uint8_t * out_data = out.data - cdef np.uint8_t * image_data = image.data - cdef np.uint8_t * mask_data = mask.data + cdef np.uint8_t * out_data = out.data + cdef np.uint8_t * image_data = image.data + cdef np.uint8_t * mask_data = mask.data # define local variable types cdef Py_ssize_t r, c, rr, cc, s, value, local_max, i, even_row @@ -101,24 +86,22 @@ cdef inline _core8( cdef Py_ssize_t num_se_n, num_se_s, num_se_e, num_se_w # the current local histogram distribution - cdef Py_ssize_t * histo = malloc(256 * sizeof(Py_ssize_t)) + cdef Py_ssize_t * histo = malloc(256 * sizeof(Py_ssize_t)) - # these lists contain the relative pixel row and column for each of the 4 attack borders - # east, west, north and south - # e.g. se_e_r lists the rows of the east structuring element border - - cdef Py_ssize_t * se_e_r = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t * se_e_c = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t * se_w_r = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t * se_w_c = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t * se_n_r = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t * se_n_c = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t * se_s_r = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t * se_s_c = malloc(max_se * sizeof(Py_ssize_t)) + # these lists contain the relative pixel row and column for each of the 4 + # attack borders east, west, north and south e.g. se_e_r lists the rows of + # the east structuring element border + cdef Py_ssize_t * se_e_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_e_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_w_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_w_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_n_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_n_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_s_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_s_c = malloc(max_se * sizeof(Py_ssize_t)) # build attack and release borders # by using difference along axis - t = np.hstack((selem, np.zeros((selem.shape[0], 1)))) t_e = np.diff(t, axis=1) == -1 @@ -152,7 +135,8 @@ cdef inline _core8( se_s_c[num_se_s] = c - centre_c num_se_s += 1 - # initial population and histogram (kernel is centered on the first row and column) + # initial population and histogram (kernel is centered on the first row and + # column) for i in range(256): histo[i] = 0 @@ -164,14 +148,14 @@ cdef inline _core8( cc = c - centre_c if selem[r, c]: if is_in_mask(rows, cols, rr, cc, mask_data): - histogram_increment(histo, & pop, image_data[rr * cols + cc]) + histogram_increment(histo, &pop, image_data[rr * cols + cc]) r = 0 c = 0 - # kernel -------------------------------------------------------------------- - out_data[r * cols + c] = kernel(histo, pop, image_data[r * cols + - c], p0, p1, s0, s1) - # kernel -------------------------------------------------------------------- + # kernel ------------------------------------------------------------------- + out_data[r * cols + c] = kernel(histo, pop, image_data[r * cols + c], + p0, p1, s0, s1) + # kernel ------------------------------------------------------------------- # main loop r = 0 @@ -182,18 +166,18 @@ cdef inline _core8( 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_data[rr * cols + cc]) + histogram_increment(histo, &pop, image_data[rr * cols + 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_data[rr * cols + cc]) + histogram_decrement(histo, &pop, image_data[rr * cols + cc]) - # kernel -------------------------------------------------------------------- - out_data[r * cols + c] = kernel( - histo, pop, image_data[r * cols + c], p0, p1, s0, s1) - # kernel -------------------------------------------------------------------- + # kernel ----------------------------------------------------------- + out_data[r * cols + c] = \ + kernel(histo, pop, image_data[r * cols + c], p0, p1, s0, s1) + # kernel ----------------------------------------------------------- r += 1 # pass to the next row if r >= rows: @@ -204,18 +188,18 @@ cdef inline _core8( 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_data[rr * cols + cc]) + histogram_increment(histo, &pop, image_data[rr * cols + 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_data[rr * cols + cc]) + histogram_decrement(histo, &pop, image_data[rr * cols + cc]) - # kernel -------------------------------------------------------------------- - out_data[r * cols + c] = kernel(histo, pop, image_data[r * - cols + c], p0, p1, s0, s1) - # kernel -------------------------------------------------------------------- + # kernel --------------------------------------------------------------- + out_data[r * cols + c] = kernel(histo, pop, image_data[r * cols + c], + p0, p1, s0, s1) + # kernel --------------------------------------------------------------- # ---> east to west for c in range(cols - 2, -1, -1): @@ -223,18 +207,18 @@ cdef inline _core8( 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_data[rr * cols + cc]) + histogram_increment(histo, &pop, image_data[rr * cols + 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_data[rr * cols + cc]) + histogram_decrement(histo, &pop, image_data[rr * cols + cc]) - # kernel -------------------------------------------------------------------- + # kernel ----------------------------------------------------------- out_data[r * cols + c] = kernel( histo, pop, image_data[r * cols + c], p0, p1, s0, s1) - # kernel -------------------------------------------------------------------- + # kernel ----------------------------------------------------------- r += 1 # pass to the next row if r >= rows: @@ -245,18 +229,18 @@ cdef inline _core8( 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_data[rr * cols + cc]) + histogram_increment(histo, &pop, image_data[rr * cols + 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_data[rr * cols + cc]) + histogram_decrement(histo, &pop, image_data[rr * cols + cc]) - # kernel -------------------------------------------------------------------- - out_data[r * cols + c] = kernel(histo, pop, image_data[r * - cols + c], p0, p1, s0, s1) - # kernel -------------------------------------------------------------------- + # kernel --------------------------------------------------------------- + out_data[r * cols + c] = kernel(histo, pop, image_data[r * cols + c], + p0, p1, s0, s1) + # kernel --------------------------------------------------------------- # release memory allocated by malloc @@ -270,5 +254,3 @@ cdef inline _core8( free(se_s_c) free(histo) - - return out diff --git a/skimage/filter/rank/_crank16.pyx b/skimage/filter/rank/_crank16.pyx index 73e8e0bd..ab5b6015 100644 --- a/skimage/filter/rank/_crank16.pyx +++ b/skimage/filter/rank/_crank16.pyx @@ -240,6 +240,7 @@ cdef inline np.uint16_t kernel_entropy( return < np.uint16_t > e*1000 + # ----------------------------------------------------------------- # python wrappers # ----------------------------------------------------------------- @@ -250,7 +251,8 @@ def autolevel(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - return _core16(kernel_autolevel, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_autolevel, image, selem, mask, out, shift_x, shift_y, + bitdepth, 0, 0, 0, 0) def bottomhat(np.ndarray[np.uint16_t, ndim=2] image, @@ -258,7 +260,8 @@ def bottomhat(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - return _core16(kernel_bottomhat, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_bottomhat, image, selem, mask, out, shift_x, shift_y, + bitdepth, 0, 0, 0, 0) def equalize(np.ndarray[np.uint16_t, ndim=2] image, @@ -266,7 +269,8 @@ def equalize(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - return _core16(kernel_equalize, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_equalize, image, selem, mask, out, shift_x, shift_y, + bitdepth, 0, 0, 0, 0) def gradient(np.ndarray[np.uint16_t, ndim=2] image, @@ -274,7 +278,8 @@ def gradient(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - return _core16(kernel_gradient, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_gradient, image, selem, mask, out, shift_x, shift_y, + bitdepth, 0, 0, 0, 0) def maximum(np.ndarray[np.uint16_t, ndim=2] image, @@ -282,7 +287,8 @@ def maximum(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - return _core16(kernel_maximum, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_maximum, image, selem, mask, out, shift_x, shift_y, + bitdepth, 0, 0, 0, 0) def mean(np.ndarray[np.uint16_t, ndim=2] image, @@ -290,7 +296,8 @@ def mean(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - return _core16(kernel_mean, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_mean, image, selem, mask, out, shift_x, shift_y, + bitdepth, 0, 0, 0, 0) def meansubstraction(np.ndarray[np.uint16_t, ndim=2] image, @@ -298,7 +305,8 @@ def meansubstraction(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - return _core16(kernel_meansubstraction, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_meansubstraction, image, selem, mask, out, shift_x, shift_y, + bitdepth, 0, 0, 0, 0) def median(np.ndarray[np.uint16_t, ndim=2] image, @@ -306,7 +314,8 @@ def median(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - return _core16(kernel_median, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_median, image, selem, mask, out, shift_x, shift_y, + bitdepth, 0, 0, 0, 0) def minimum(np.ndarray[np.uint16_t, ndim=2] image, @@ -314,7 +323,8 @@ def minimum(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - return _core16(kernel_minimum, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_minimum, image, selem, mask, out, shift_x, shift_y, + bitdepth, 0, 0, 0, 0) def morph_contr_enh(np.ndarray[np.uint16_t, ndim=2] image, @@ -322,7 +332,8 @@ def morph_contr_enh(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - return _core16(kernel_morph_contr_enh, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_morph_contr_enh, image, selem, mask, out, shift_x, shift_y, + bitdepth, 0, 0, 0, 0) def modal(np.ndarray[np.uint16_t, ndim=2] image, @@ -330,7 +341,8 @@ def modal(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - return _core16(kernel_modal, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_modal, image, selem, mask, out, shift_x, shift_y, + bitdepth, 0, 0, 0, 0) def pop(np.ndarray[np.uint16_t, ndim=2] image, @@ -338,7 +350,8 @@ def pop(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - return _core16(kernel_pop, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_pop, image, selem, mask, out, shift_x, shift_y, + bitdepth, 0, 0, 0, 0) def threshold(np.ndarray[np.uint16_t, ndim=2] image, @@ -346,7 +359,8 @@ def threshold(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - return _core16(kernel_threshold, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_threshold, image, selem, mask, out, shift_x, shift_y, + bitdepth, 0, 0, 0, 0) def tophat(np.ndarray[np.uint16_t, ndim=2] image, @@ -354,11 +368,13 @@ def tophat(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - return _core16(kernel_tophat, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_tophat, image, selem, mask, out, shift_x, shift_y, + bitdepth, 0, 0, 0, 0) def entropy(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - return _core16(kernel_entropy, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_entropy, image, selem, mask, out, shift_x, shift_y, + bitdepth, 0, 0, 0, 0) diff --git a/skimage/filter/rank/_crank16_bilateral.pyx b/skimage/filter/rank/_crank16_bilateral.pyx index c013b779..cf68115e 100644 --- a/skimage/filter/rank/_crank16_bilateral.pyx +++ b/skimage/filter/rank/_crank16_bilateral.pyx @@ -59,7 +59,8 @@ def mean(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8, int s0=1, int s1=1): """average gray level (clipped on uint8) """ - return _core16(kernel_mean, image, selem, mask, out, shift_x, shift_y, bitdepth, 0., 0., s0, s1) + _core16(kernel_mean, image, selem, mask, out, shift_x, shift_y, + bitdepth, 0., 0., s0, s1) def pop(np.ndarray[np.uint16_t, ndim=2] image, @@ -69,4 +70,5 @@ def pop(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8, int s0=1, int s1=1): """returns the number of actual pixels of the structuring element inside the mask """ - return _core16(kernel_pop, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, s0, s1) + _core16(kernel_pop, image, selem, mask, out, shift_x, shift_y, + bitdepth, .0, .0, s0, s1) diff --git a/skimage/filter/rank/_crank16_percentiles.pyx b/skimage/filter/rank/_crank16_percentiles.pyx index 0d37b77c..3b50c86c 100644 --- a/skimage/filter/rank/_crank16_percentiles.pyx +++ b/skimage/filter/rank/_crank16_percentiles.pyx @@ -205,93 +205,93 @@ def autolevel(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, - char shift_x=0, char shift_y=0, int bitdepth=8, float p0=0., float p1=0.): + char shift_x=0, char shift_y=0, int bitdepth=8, + float p0=0., float p1=0.): """bottom hat """ - return _core16( - kernel_autolevel, image, selem, mask, out, shift_x, shift_y, bitdepth, p0, p1, - < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_autolevel, image, selem, mask, out, shift_x, shift_y, + bitdepth, p0, p1, 0, 0) def gradient(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, - char shift_x=0, char shift_y=0, int bitdepth=8, float p0=0., float p1=0.): + char shift_x=0, char shift_y=0, int bitdepth=8, + float p0=0., float p1=0.): """return p0,p1 percentile gradient """ - return _core16( - kernel_gradient, image, selem, mask, out, shift_x, shift_y, bitdepth, p0, p1, < Py_ssize_t > 0, - < Py_ssize_t > 0) + _core16(kernel_gradient, image, selem, mask, out, shift_x, shift_y, + bitdepth, p0, p1, 0, 0) def mean(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, - char shift_x=0, char shift_y=0, int bitdepth=8, float p0=0., float p1=0.): + char shift_x=0, char shift_y=0, int bitdepth=8, + float p0=0., float p1=0.): """return mean between [p0 and p1] percentiles """ - return _core16( - kernel_mean, image, selem, mask, out, shift_x, shift_y, bitdepth, p0, p1, < Py_ssize_t > 0, - < Py_ssize_t > 0) + _core16(kernel_mean, image, selem, mask, out, shift_x, shift_y, + bitdepth, p0, p1, 0, 0) def mean_substraction(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, - char shift_x=0, char shift_y=0, int bitdepth=8, float p0=0., float p1=0.): + char shift_x=0, char shift_y=0, int bitdepth=8, + float p0=0., float p1=0.): """return original - mean between [p0 and p1] percentiles *.5 +127 """ - return _core16( - kernel_mean_substraction, image, selem, mask, out, shift_x, shift_y, bitdepth, p0, p1, - < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_mean_substraction, image, selem, mask, out, shift_x, shift_y, + bitdepth, p0, p1, 0, 0) def morph_contr_enh(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, - char shift_x=0, char shift_y=0, int bitdepth=8, float p0=0., float p1=0.): + char shift_x=0, char shift_y=0, int bitdepth=8, + float p0=0., float p1=0.): """reforce contrast using percentiles """ - return _core16( - kernel_morph_contr_enh, image, selem, mask, out, shift_x, shift_y, bitdepth, p0, p1, - < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_morph_contr_enh, image, selem, mask, out, shift_x, shift_y, + bitdepth, p0, p1, 0, 0) def percentile(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, - char shift_x=0, char shift_y=0, int bitdepth=8, float p0=0., float p1=0.): + char shift_x=0, char shift_y=0, int bitdepth=8, + float p0=0., float p1=0.): """return p0 percentile """ - return _core16( - kernel_percentile, image, selem, mask, out, shift_x, shift_y, bitdepth, p0, p1, - < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_percentile, image, selem, mask, out, shift_x, shift_y, + bitdepth, p0, p1, 0, 0) def pop(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, - char shift_x=0, char shift_y=0, int bitdepth=8, float p0=0., float p1=0.): + char shift_x=0, char shift_y=0, int bitdepth=8, + float p0=0., float p1=0.): """return nb of pixels between [p0 and p1] """ - return _core16( - kernel_pop, image, selem, mask, out, shift_x, shift_y, bitdepth, p0, p1, - < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_pop, image, selem, mask, out, shift_x, shift_y, + bitdepth, p0, p1, 0, 0) def threshold(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, - char shift_x=0, char shift_y=0, int bitdepth=8, float p0=0., float p1=0.): + char shift_x=0, char shift_y=0, int bitdepth=8, + float p0=0., float p1=0.): """return (maxbin-1) if g > percentile p0 """ - return _core16( - kernel_threshold, image, selem, mask, out, shift_x, shift_y, bitdepth, p0, p1, - < Py_ssize_t > 0, < Py_ssize_t > 0) + _core16(kernel_threshold, image, selem, mask, out, shift_x, shift_y, + bitdepth, p0, p1, 0, 0) diff --git a/skimage/filter/rank/_crank8.pyx b/skimage/filter/rank/_crank8.pyx index 4efd2bb0..5b2cba01 100644 --- a/skimage/filter/rank/_crank8.pyx +++ b/skimage/filter/rank/_crank8.pyx @@ -315,9 +315,8 @@ def autolevel(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - return _core8( - kernel_autolevel, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, - < Py_ssize_t > 0) + _core8(kernel_autolevel, image, selem, mask, out, shift_x, shift_y, + 0, 0, 0, 0) def bottomhat(np.ndarray[np.uint8_t, ndim=2] image, @@ -325,9 +324,8 @@ def bottomhat(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - return _core8( - kernel_bottomhat, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, - < Py_ssize_t > 0) + _core8(kernel_bottomhat, image, selem, mask, out, shift_x, shift_y, + 0, 0, 0, 0) def equalize(np.ndarray[np.uint8_t, ndim=2] image, @@ -335,9 +333,8 @@ def equalize(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - return _core8( - kernel_equalize, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, - < Py_ssize_t > 0) + _core8(kernel_equalize, image, selem, mask, out, shift_x, shift_y, + 0, 0, 0, 0) def gradient(np.ndarray[np.uint8_t, ndim=2] image, @@ -345,9 +342,8 @@ def gradient(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - return _core8( - kernel_gradient, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, - < Py_ssize_t > 0) + _core8(kernel_gradient, image, selem, mask, out, shift_x, shift_y, + 0, 0, 0, 0) def maximum(np.ndarray[np.uint8_t, ndim=2] image, @@ -355,7 +351,8 @@ def maximum(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - return _core8(kernel_maximum, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core8(kernel_maximum, image, selem, mask, out, shift_x, shift_y, + 0, 0, 0, 0) def mean(np.ndarray[np.uint8_t, ndim=2] image, @@ -363,7 +360,8 @@ def mean(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - return _core8(kernel_mean, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core8(kernel_mean, image, selem, mask, out, shift_x, shift_y, + 0, 0, 0, 0) def meansubstraction(np.ndarray[np.uint8_t, ndim=2] image, @@ -371,9 +369,8 @@ def meansubstraction(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - return _core8( - kernel_meansubstraction, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, - < Py_ssize_t > 0) + _core8(kernel_meansubstraction, image, selem, mask, out, shift_x, shift_y, + 0, 0, 0, 0) def median(np.ndarray[np.uint8_t, ndim=2] image, @@ -381,7 +378,8 @@ def median(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - return _core8(kernel_median, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core8(kernel_median, image, selem, mask, out, shift_x, shift_y, + 0, 0, 0, 0) def minimum(np.ndarray[np.uint8_t, ndim=2] image, @@ -389,7 +387,8 @@ def minimum(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - return _core8(kernel_minimum, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core8(kernel_minimum, image, selem, mask, out, shift_x, shift_y, + 0, 0, 0, 0) def morph_contr_enh(np.ndarray[np.uint8_t, ndim=2] image, @@ -397,9 +396,8 @@ def morph_contr_enh(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - return _core8( - kernel_morph_contr_enh, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, - < Py_ssize_t > 0) + _core8(kernel_morph_contr_enh, image, selem, mask, out, shift_x, shift_y, + 0, 0, 0, 0) def modal(np.ndarray[np.uint8_t, ndim=2] image, @@ -407,7 +405,8 @@ def modal(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - return _core8(kernel_modal, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core8(kernel_modal, image, selem, mask, out, shift_x, shift_y, + 0, 0, 0, 0) def pop(np.ndarray[np.uint8_t, ndim=2] image, @@ -415,7 +414,8 @@ def pop(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - return _core8(kernel_pop, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core8(kernel_pop, image, selem, mask, out, shift_x, shift_y, + 0, 0, 0, 0) def threshold(np.ndarray[np.uint8_t, ndim=2] image, @@ -423,9 +423,8 @@ def threshold(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - return _core8( - kernel_threshold, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, - < Py_ssize_t > 0) + _core8(kernel_threshold, image, selem, mask, out, shift_x, shift_y, 0, 0, + 0, 0) def tophat(np.ndarray[np.uint8_t, ndim=2] image, @@ -433,7 +432,8 @@ def tophat(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - return _core8(kernel_tophat, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core8(kernel_tophat, image, selem, mask, out, shift_x, shift_y, + 0, 0, 0, 0) def noise_filter(np.ndarray[np.uint8_t, ndim=2] image, @@ -441,18 +441,21 @@ def noise_filter(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - return _core8(kernel_noise_filter, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core8(kernel_noise_filter, image, selem, mask, out, shift_x, shift_y, + 0, 0, 0, 0) def entropy(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - return _core8(kernel_entropy, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core8(kernel_entropy, image, selem, mask, out, shift_x, shift_y, + 0, 0, 0, 0) def otsu(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - return _core8(kernel_otsu, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core8(kernel_otsu, image, selem, mask, out, shift_x, shift_y, + 0, 0, 0, 0) diff --git a/skimage/filter/rank/_crank8_percentiles.pyx b/skimage/filter/rank/_crank8_percentiles.pyx index 618a6452..636295fd 100644 --- a/skimage/filter/rank/_crank8_percentiles.pyx +++ b/skimage/filter/rank/_crank8_percentiles.pyx @@ -201,9 +201,8 @@ def autolevel(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0, float p0=0., float p1=0.): """autolevel """ - return _core8( - kernel_autolevel, image, selem, mask, out, shift_x, shift_y, p0, p1, < Py_ssize_t > 0, - < Py_ssize_t > 0) + _core8(kernel_autolevel, image, selem, mask, out, shift_x, shift_y, p0, p1, + 0, 0) def gradient(np.ndarray[np.uint8_t, ndim=2] image, @@ -213,9 +212,8 @@ def gradient(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0, float p0=0., float p1=0.): """return p0,p1 percentile gradient """ - return _core8( - kernel_gradient, image, selem, mask, out, shift_x, shift_y, p0, p1, < Py_ssize_t > 0, - < Py_ssize_t > 0) + _core8(kernel_gradient, image, selem, mask, out, shift_x, shift_y, p0, p1, + 0, 0) def mean(np.ndarray[np.uint8_t, ndim=2] image, @@ -225,7 +223,8 @@ def mean(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0, float p0=0., float p1=0.): """return mean between [p0 and p1] percentiles """ - return _core8(kernel_mean, image, selem, mask, out, shift_x, shift_y, p0, p1, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core8(kernel_mean, image, selem, mask, out, shift_x, shift_y, p0, p1, + 0, 0) def mean_substraction(np.ndarray[np.uint8_t, ndim=2] image, @@ -235,9 +234,8 @@ def mean_substraction(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0, float p0=0., float p1=0.): """return original - mean between [p0 and p1] percentiles *.5 +127 """ - return _core8( - kernel_mean_substraction, image, selem, mask, out, shift_x, shift_y, p0, p1, < Py_ssize_t > 0, - < Py_ssize_t > 0) + _core8(kernel_mean_substraction, image, selem, mask, out, shift_x, shift_y, + p0, p1, 0, 0) def morph_contr_enh(np.ndarray[np.uint8_t, ndim=2] image, @@ -247,9 +245,8 @@ def morph_contr_enh(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0, float p0=0., float p1=0.): """reforce contrast using percentiles """ - return _core8( - kernel_morph_contr_enh, image, selem, mask, out, shift_x, shift_y, p0, p1, < Py_ssize_t > 0, - < Py_ssize_t > 0) + _core8(kernel_morph_contr_enh, image, selem, mask, out, shift_x, shift_y, + p0, p1, 0, 0) def percentile(np.ndarray[np.uint8_t, ndim=2] image, @@ -259,9 +256,8 @@ def percentile(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0, float p0=0., float p1=0.): """return p0 percentile """ - return _core8( - kernel_percentile, image, selem, mask, out, shift_x, shift_y, p0, p1, < Py_ssize_t > 0, - < Py_ssize_t > 0) + _core8(kernel_percentile, image, selem, mask, out, shift_x, shift_y, + p0, p1, 0, 0) def pop(np.ndarray[np.uint8_t, ndim=2] image, @@ -271,7 +267,8 @@ def pop(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0, float p0=0., float p1=0.): """return nb of pixels between [p0 and p1] """ - return _core8(kernel_pop, image, selem, mask, out, shift_x, shift_y, p0, p1, < Py_ssize_t > 0, < Py_ssize_t > 0) + _core8(kernel_pop, image, selem, mask, out, shift_x, shift_y, p0, p1, + 0, 0) def threshold(np.ndarray[np.uint8_t, ndim=2] image, @@ -281,6 +278,5 @@ def threshold(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0, float p0=0., float p1=0.): """return 255 if g > percentile p0 """ - return _core8( - kernel_threshold, image, selem, mask, out, shift_x, shift_y, p0, p1, < Py_ssize_t > 0, - < Py_ssize_t > 0) + _core8(kernel_threshold, image, selem, mask, out, shift_x, shift_y, p0, p1, + 0, 0) diff --git a/skimage/filter/rank/bilateral_rank.pyx b/skimage/filter/rank/bilateral_rank.pyx index f181735b..39afa71a 100644 --- a/skimage/filter/rank/bilateral_rank.pyx +++ b/skimage/filter/rank/bilateral_rank.pyx @@ -1,31 +1,31 @@ -"""bilateral_rank.py - approximate bilateral rankfilter for local (custom kernel) mean +"""Approximate bilateral rankfilter for local (custom kernel) mean. -The local histogram is computed using a sliding window similar to the method described in +The local histogram is computed using a sliding window similar to the method +described in: -Reference: Huang, T. ,Yang, G. ; Tang, G.. "A fast two-dimensional median filtering algorithm", -IEEE Transactions on Acoustics, Speech and Signal Processing, Feb 1979. Volume: 27 , Issue: 1, Page(s): 13 - 18. +Reference: Huang, T. ,Yang, G. ; Tang, G.. "A fast two-dimensional median +filtering algorithm", IEEE Transactions on Acoustics, Speech and Signal +Processing, Feb 1979. Volume: 27 , Issue: 1, Page(s): 13 - 18. -input image can be 8 bit or 16 bit with a value < 4096 (i.e. 12 bit), -8 bit images are casted in 16 bit -the number of histogram bins is determined from the maximum value present in the image +Input image can be 8 bit or 16 bit with a value < 4096 (i.e. 12 bit), 8 bit +images are casted in 16 bit the number of histogram bins is determined from the +maximum value present in the image. The pixel neighborhood is defined by: * the given structuring element - * an interval [g-s0,g+s1] in gray level around g the processed pixel gray level -The kernel is flat (i.e. each pixel belonging to the neighborhood contributes equally) +The kernel is flat (i.e. each pixel belonging to the neighborhood contributes +equally). -result image is 16 bit with respect to the input image +Result image is 16 bit with respect to the input image. """ -from skimage import img_as_ubyte - import numpy as np +from skimage import img_as_ubyte from skimage.filter.rank import _crank16_bilateral - from skimage.filter.rank.generic import find_bitdepth @@ -34,52 +34,74 @@ __all__ = ['bilateral_mean', 'bilateral_pop'] def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y, s0, s1): selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - image = image.astype(np.uint16) - elif image.dtype == np.uint16: - pass + image = np.ascontiguousarray(image) + + if mask is None: + mask = np.ones(image.shape, dtype=np.uint8) else: - raise TypeError("only uint8 and uint16 image supported!") - bitdepth = find_bitdepth(image) - if bitdepth > 11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return func16( - image, selem, shift_x=shift_x, shift_y=shift_y, mask=mask, bitdepth=bitdepth + 1, out=out, - s0=s0, s1=s1) + mask = np.ascontiguousarray(mask) + mask = img_as_ubyte(mask) + if image is out: + raise NotImplementedError("Cannot perform rank operation in place.") + + mask = np.ascontiguousarray(mask) + if image.dtype == np.uint8: + if func8 is None: + raise TypeError("Not implemented for uint8 image.") + if out is None: + out = np.zeros(image.shape, dtype=np.uint8) + func8(image, selem, shift_x=shift_x, shift_y=shift_y, + mask=mask, out=out, s0=s0, s1=s1) + elif image.dtype == np.uint16: + if func16 is None: + raise TypeError("Not implemented for uint16 image.") + if out is None: + out = np.zeros(image.shape, dtype=np.uint16) + bitdepth = find_bitdepth(image) + if bitdepth > 11: + raise ValueError("Only uint16 <4096 image (12bit) supported.") + func16(image, selem, shift_x=shift_x, shift_y=shift_y, mask=mask, + bitdepth=bitdepth + 1, out=out, s0=s0, s1=s1) + else: + raise TypeError("Only uint8 and uint16 image supported.") + + return out -def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False, s0=10, s1=10): +def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, + shift_y=False, s0=10, s1=10): """Apply a flat kernel bilateral filter. This is an edge-preserving and noise reducing denoising filter. It averages pixels based on their spatial closeness and radiometric similarity. - Spatial closeness is measured by considering only the local pixel neighborhood given by a - structuring element (selem). + Spatial closeness is measured by considering only the local pixel + neighborhood given by a structuring element (selem). - Radiometric similarity is defined by the gray level interval [g-s0,g+s1] where g is the current pixel gray level. - Only pixels belonging to the structuring element AND having a gray level inside this interval are averaged. - Return greyscale local bilateral_mean of an image. + Radiometric similarity is defined by the gray level interval [g-s0,g+s1] + where g is the current pixel gray level. Only pixels belonging to the + structuring element AND having a gray level inside this interval are + averaged. Return greyscale local bilateral_mean of an image. Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, as the + algorithm uses max. 12bit histogram, an exception will be raised if + image has a value > 4095 selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). s0, s1 : int - define the [s0,s1] interval to be considered for computing the value. + define the [s0, s1] interval to be considered for computing the value. Returns ------- @@ -108,32 +130,35 @@ def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal >>> bilat_ima = bilateral_mean(ima, disk(20), s0=10,s1=10) """ - return _apply( - None, _crank16_bilateral.mean, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, - s0=s0, s1=s1) + return _apply(None, _crank16_bilateral.mean, image, selem, out=out, + mask=mask, shift_x=shift_x, shift_y=shift_y, s0=s0, s1=s1) -def bilateral_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=False, s0=10, s1=10): - """Return the number (population) of pixels actually inside the bilateral neighborhood, - i.e. being inside the structuring element AND having a gray level inside the interval [g-s0,g+s1]. +def bilateral_pop(image, selem, out=None, mask=None, shift_x=False, + shift_y=False, s0=10, s1=10): + """Return the number (population) of pixels actually inside the bilateral + neighborhood, i.e. being inside the structuring element AND having a gray + level inside the interval [g-s0, g+s1]. Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, as the + algorithm uses max. 12bit histogram, an exception will be raised if + image has a value > 4095 selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). s0, s1 : int - define the [s0,s1] interval to be considered for computing the value. + define the [s0, s1] interval to be considered for computing the value. Returns ------- @@ -159,7 +184,5 @@ def bilateral_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fals """ - return _apply( - None, _crank16_bilateral.pop, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, - s0=s0, s1=s1) - + return _apply(None, _crank16_bilateral.pop, image, selem, out=out, + mask=mask, shift_x=shift_x, shift_y=shift_y, s0=s0, s1=s1) diff --git a/skimage/filter/rank/percentile_rank.pyx b/skimage/filter/rank/percentile_rank.pyx index 1bd89eb8..c5a5a594 100644 --- a/skimage/filter/rank/percentile_rank.pyx +++ b/skimage/filter/rank/percentile_rank.pyx @@ -1,337 +1,390 @@ -"""percentile_rank.py - inferior and superior ranks, provided by the user, are passed to the kernel function -to provide a softer version of the rank filters. E.g. percentile_autolevel will stretch image levels between -percentile [p0,p1] instead of using [min,max]. It means that isolate bright or dark pixels will not produce halos. +"""Inferior and superior ranks, provided by the user, are passed to the kernel +function to provide a softer version of the rank filters. E.g. +percentile_autolevel will stretch image levels between percentile [p0, p1] +instead of using [min,max]. It means that isolate bright or dark pixels will not +produce halos. -The local histogram is computed using a sliding window similar to the method described in +The local histogram is computed using a sliding window similar to the method +described in: -Reference: Huang, T. ,Yang, G. ; Tang, G.. "A fast two-dimensional median filtering algorithm", -IEEE Transactions on Acoustics, Speech and Signal Processing, Feb 1979. Volume: 27 , Issue: 1, Page(s): 13 - 18. +Reference: Huang, T. ,Yang, G. ; Tang, G.. "A fast two-dimensional median +filtering algorithm", IEEE Transactions on Acoustics, Speech and Signal +Processing, Feb 1979. Volume: 27 , Issue: 1, Page(s): 13 - 18. -input image can be 8 bit or 16 bit with a value < 4096 (i.e. 12 bit), -for 16 bit input images, the number of histogram bins is determined from the maximum value present in the image +Input image can be 8 bit or 16 bit with a value < 4096 (i.e. 12 bit), for 16 bit +input images, the number of histogram bins is determined from the maximum value +present in the image. -result image is 8 or 16 bit with respect to the input image +Result image is 8 or 16 bit with respect to the input image. """ -from skimage import img_as_ubyte import numpy as np - +from skimage import img_as_ubyte from skimage.filter.rank.generic import find_bitdepth from skimage.filter.rank import _crank16_percentiles, _crank8_percentiles + __all__ = ['percentile_autolevel', 'percentile_gradient', 'percentile_mean', 'percentile_mean_substraction', - 'percentile_morph_contr_enh', 'percentile', 'percentile_pop', 'percentile_threshold'] + 'percentile_morph_contr_enh', 'percentile', 'percentile_pop', + 'percentile_threshold'] def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y, p0, p1): selem = img_as_ubyte(selem) - if mask is not None: + image = np.ascontiguousarray(image) + + if mask is None: + mask = np.ones(image.shape, dtype=np.uint8) + else: + mask = np.ascontiguousarray(mask) mask = img_as_ubyte(mask) + if image is out: + raise NotImplementedError("Cannot perform rank operation in place.") + + mask = np.ascontiguousarray(mask) if image.dtype == np.uint8: - return func8(image, selem, shift_x=shift_x, shift_y=shift_y, mask=mask, out=out, p0=p0, p1=p1) + if func8 is None: + raise TypeError("Not implemented for uint8 image.") + if out is None: + out = np.zeros(image.shape, dtype=np.uint8) + func8(image, selem, shift_x=shift_x, shift_y=shift_y, + mask=mask, out=out, p0=p0, p1=p1) elif image.dtype == np.uint16: + if func16 is None: + raise TypeError("Not implemented for uint16 image.") + if out is None: + out = np.zeros(image.shape, dtype=np.uint16) bitdepth = find_bitdepth(image) if bitdepth > 11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return func16( - image, selem, shift_x=shift_x, shift_y=shift_y, mask=mask, bitdepth=bitdepth + 1, out=out, - p0=p0, p1=p1) + raise ValueError("Only uint16 <4096 image (12bit) supported.") + func16(image, selem, shift_x=shift_x, shift_y=shift_y, mask=mask, + bitdepth=bitdepth + 1, out=out, p0=p0, p1=p1) else: - raise TypeError("only uint8 and uint16 image supported!") + raise TypeError("Only uint8 and uint16 image supported.") + + return out -def percentile_autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): +def percentile_autolevel(image, selem, out=None, mask=None, shift_x=False, + shift_y=False, p0=.0, p1=1.): """Return greyscale local autolevel of an image. - Autolevel is computed on the given structuring element. Only levels between percentiles [p0,p1] ,are used. + Autolevel is computed on the given structuring element. Only levels between + percentiles [p0, p1] are used. Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, as the + algorithm uses max. 12bit histogram, an exception will be raised if + image has a value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). - p0, p1 : float in [0.,...,1.] - define the [p0,p1] percentile interval to be considered for computing the value. + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). + p0, p1 : float in [0, ..., 1] + Define the [p0, p1] percentile interval to be considered for computing + the value. Returns ------- - local autolevel : uint8 array or uint16 array depending on input image + local autolevel : uint8 array or uint16 The result of the local autolevel. - """ - return _apply( - _crank8_percentiles.autolevel, _crank16_percentiles.autolevel, image, selem, out=out, mask=mask, - shift_x=shift_x, shift_y=shift_y, p0=p0, p1=p1) + return _apply(_crank8_percentiles.autolevel, _crank16_percentiles.autolevel, + image, selem, out=out, mask=mask, shift_x=shift_x, + shift_y=shift_y, p0=p0, p1=p1) -def percentile_gradient(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): +def percentile_gradient(image, selem, out=None, mask=None, shift_x=False, + shift_y=False, p0=.0, p1=1.): """Return greyscale local percentile_gradient of an image. - percentile_gradient is computed on the given structuring element. Only levels between percentiles [p0,p1] ,are used. + percentile_gradient is computed on the given structuring element. Only + levels between percentiles [p0, p1] are used. Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, as the + algorithm uses max. 12bit histogram, an exception will be raised if + image has a value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). - p0, p1 : float in [0.,...,1.] - define the [p0,p1] percentile interval to be considered for computing the value. + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). + p0, p1 : float in [0, ..., 1] + Define the [p0, p1] percentile interval to be considered for computing + the value. Returns ------- - local percentile_gradient : uint8 array or uint16 array depending on input image + local percentile_gradient : uint8 array or uint16 The result of the local percentile_gradient. - - """ - return _apply( - _crank8_percentiles.gradient, _crank16_percentiles.gradient, image, selem, out=out, mask=mask, - shift_x=shift_x, shift_y=shift_y, p0=p0, p1=p1) + return _apply(_crank8_percentiles.gradient, _crank16_percentiles.gradient, + image, selem, out=out, mask=mask, shift_x=shift_x, + shift_y=shift_y, p0=p0, p1=p1) -def percentile_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): +def percentile_mean(image, selem, out=None, mask=None, shift_x=False, + shift_y=False, p0=.0, p1=1.): """Return greyscale local mean of an image. - Mean is computed on the given structuring element. Only levels between percentiles [p0,p1] ,are used. + Mean is computed on the given structuring element. Only levels between + percentiles [p0, p1] are used. Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, as the + algorithm uses max. 12bit histogram, an exception will be raised if + image has a value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). - p0, p1 : float in [0.,...,1.] - define the [p0,p1] percentile interval to be considered for computing the value. + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). + p0, p1 : float in [0, ..., 1] + Define the [p0, p1] percentile interval to be considered for computing + the value. Returns ------- - local mean : uint8 array or uint16 array depending on input image + local mean : uint8 array or uint16 The result of the local mean. - """ - return _apply( - _crank8_percentiles.mean, _crank16_percentiles.mean, image, selem, out=out, mask=mask, - shift_x=shift_x, shift_y=shift_y, p0=p0, p1=p1) + return _apply(_crank8_percentiles.mean, _crank16_percentiles.mean, + image, selem, out=out, mask=mask, shift_x=shift_x, + shift_y=shift_y, p0=p0, p1=p1) -def percentile_mean_substraction(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): +def percentile_mean_substraction(image, selem, out=None, mask=None, + shift_x=False, shift_y=False, p0=.0, p1=1.): """Return greyscale local mean_substraction of an image. - mean_substraction is computed on the given structuring element. Only levels between percentiles [p0,p1] ,are used. + mean_substraction is computed on the given structuring element. Only levels + between percentiles [p0, p1] are used. Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, as the + algorithm uses max. 12bit histogram, an exception will be raised if + image has a value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). - p0, p1 : float in [0.,...,1.] - define the [p0,p1] percentile interval to be considered for computing the value. + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). + p0, p1 : float in [0, ..., 1] + Define the [p0, p1] percentile interval to be considered for computing + the value. Returns ------- - local mean_substraction : uint8 array or uint16 array depending on input image + local mean_substraction : uint8 array or uint16 The result of the local mean_substraction. - - """ - return _apply( - _crank8_percentiles.mean_substraction, _crank16_percentiles.mean_substraction, image, selem, out=out, - mask=mask, shift_x=shift_x, shift_y=shift_y, p0=p0, p1=p1) + return _apply(_crank8_percentiles.mean_substraction, + _crank16_percentiles.mean_substraction, + image, selem, out=out, mask=mask, shift_x=shift_x, + shift_y=shift_y, p0=p0, p1=p1) -def percentile_morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): +def percentile_morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, + shift_y=False, p0=.0, p1=1.): """Return greyscale local morph_contr_enh of an image. - morph_contr_enh is computed on the given structuring element. Only levels between percentiles [p0,p1] ,are used. + morph_contr_enh is computed on the given structuring element. Only levels + between percentiles [p0, p1] are used. Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, as the + algorithm uses max. 12bit histogram, an exception will be raised if + image has a value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). - p0, p1 : float in [0.,...,1.] - define the [p0,p1] percentile interval to be considered for computing the value. + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). + p0, p1 : float in [0, ..., 1] + Define the [p0, p1] percentile interval to be considered for computing + the value. Returns ------- - local morph_contr_enh : uint8 array or uint16 array depending on input image + local morph_contr_enh : uint8 array or uint16 The result of the local morph_contr_enh. - - """ - return _apply( - _crank8_percentiles.morph_contr_enh, _crank16_percentiles.morph_contr_enh, image, selem, out=out, - mask=mask, shift_x=shift_x, shift_y=shift_y, p0=p0, p1=p1) + return _apply(_crank8_percentiles.morph_contr_enh, + _crank16_percentiles.morph_contr_enh, + image, selem, out=out, mask=mask, shift_x=shift_x, + shift_y=shift_y, p0=p0, p1=p1) -def percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): +def percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, + p0=.0, p1=1.): """Return greyscale local percentile of an image. - percentile is computed on the given structuring element. Only levels between percentiles [p0,p1] ,are used. + percentile is computed on the given structuring element. Only levels between + percentiles [p0, p1] are used. Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, as the + algorithm uses max. 12bit histogram, an exception will be raised if + image has a value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). - p0, p1 : float in [0.,...,1.] - define the [p0,p1] percentile interval to be considered for computing the value. + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). + p0, p1 : float in [0, ..., 1] + Define the [p0, p1] percentile interval to be considered for computing + the value. Returns ------- - local percentile : uint8 array or uint16 array depending on input image + local percentile : uint8 array or uint16 The result of the local percentile. - - """ - return _apply( - _crank8_percentiles.percentile, _crank16_percentiles.percentile, image, selem, out=out, mask=mask, - shift_x=shift_x, shift_y=shift_y, p0=p0, p1=p1) + return _apply(_crank8_percentiles.percentile, + _crank16_percentiles.percentile, + image, selem, out=out, mask=mask, shift_x=shift_x, + shift_y=shift_y, p0=p0, p1=p1) -def percentile_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): +def percentile_pop(image, selem, out=None, mask=None, shift_x=False, + shift_y=False, p0=.0, p1=1.): """Return greyscale local pop of an image. - pop is computed on the given structuring element. Only levels between percentiles [p0,p1] ,are used. + pop is computed on the given structuring element. Only levels between + percentiles [p0, p1] are used. Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, as the + algorithm uses max. 12bit histogram, an exception will be raised if + image has a value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). - p0, p1 : float in [0.,...,1.] - define the [p0,p1] percentile interval to be considered for computing the value. + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). + p0, p1 : float in [0, ..., 1] + Define the [p0, p1] percentile interval to be considered for computing + the value. Returns ------- - local pop : uint8 array or uint16 array depending on input image + local pop : uint8 array or uint16 The result of the local pop. - - """ - return _apply( - _crank8_percentiles.pop, _crank16_percentiles.pop, image, selem, out=out, mask=mask, shift_x=shift_x, - shift_y=shift_y, p0=p0, p1=p1) + return _apply(_crank8_percentiles.pop, _crank16_percentiles.pop, + image, selem, out=out, mask=mask, shift_x=shift_x, + shift_y=shift_y, p0=p0, p1=p1) -def percentile_threshold(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): +def percentile_threshold(image, selem, out=None, mask=None, shift_x=False, + shift_y=False, p0=.0, p1=1.): """Return greyscale local threshold of an image. - threshold is computed on the given structuring element. Only levels between percentiles [p0,p1] ,are used. + threshold is computed on the given structuring element. Only levels between + percentiles [p0, p1] are used. Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, as the + algorithm uses max. 12bit histogram, an exception will be raised if + image has a value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). - p0, p1 : float in [0.,...,1.] - define the [p0,p1] percentile interval to be considered for computing the value. + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). + p0, p1 : float in [0, ..., 1] + Define the [p0, p1] percentile interval to be considered for computing + the value. Returns ------- - local threshold : uint8 array or uint16 array depending on input image + local threshold : uint8 array or uint16 The result of the local threshold. - """ - return _apply( - _crank8_percentiles.threshold, _crank16_percentiles.threshold, image, selem, out=out, mask=mask, - shift_x=shift_x, shift_y=shift_y, p0=p0, p1=p1) - - + return _apply(_crank8_percentiles.threshold, _crank16_percentiles.threshold, + image, selem, out=out, mask=mask, shift_x=shift_x, + shift_y=shift_y, p0=p0, p1=p1) diff --git a/skimage/filter/rank/rank.pyx b/skimage/filter/rank/rank.pyx index 6a35920b..8ac98f81 100644 --- a/skimage/filter/rank/rank.pyx +++ b/skimage/filter/rank/rank.pyx @@ -1,44 +1,63 @@ -"""rank.py - rankfilter for local (custom kernel) maximum, minimum, median, mean, auto-level, equalization, etc +"""The local histogram is computed using a sliding window similar to the method +described in: -The local histogram is computed using a sliding window similar to the method described in +Reference: Huang, T. ,Yang, G. ; Tang, G.. "A fast two-dimensional median +filtering algorithm", IEEE Transactions on Acoustics, Speech and Signal +Processing, Feb 1979. Volume: 27 , Issue: 1, Page(s): 13 - 18. -Reference: Huang, T. ,Yang, G. ; Tang, G.. "A fast two-dimensional median filtering algorithm", -IEEE Transactions on Acoustics, Speech and Signal Processing, Feb 1979. Volume: 27 , Issue: 1, Page(s): 13 - 18. +Input image can be 8 bit or 16 bit with a value < 4096 (i.e. 12 bit), for 16 bit +input images, the number of histogram bins is determined from the maximum value +present in the image. -input image can be 8 bit or 16 bit with a value < 4096 (i.e. 12 bit), -for 16 bit input images, the number of histogram bins is determined from the maximum value present in the image - -result image is 8 or 16 bit with respect to the input image +Result image is 8 or 16 bit with respect to the input image. """ -from skimage import img_as_ubyte import numpy as np +from skimage import img_as_ubyte from skimage.filter.rank import _crank8, _crank16 - from skimage.filter.rank.generic import find_bitdepth -__all__ = ['autolevel', 'bottomhat', 'equalize', 'gradient', 'maximum', 'mean', 'meansubstraction', 'median', 'minimum', - 'modal', 'morph_contr_enh', 'pop', 'threshold', 'tophat','noise_filter','entropy','otsu'] + +__all__ = ['autolevel', 'bottomhat', 'equalize', 'gradient', 'maximum', 'mean', + 'meansubstraction', 'median', 'minimum', 'modal', 'morph_contr_enh', + 'pop', 'threshold', 'tophat','noise_filter','entropy','otsu'] def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y): selem = img_as_ubyte(selem) - if mask is not None: + image = np.ascontiguousarray(image) + + if mask is None: + mask = np.ones(image.shape, dtype=np.uint8) + else: + mask = np.ascontiguousarray(mask) mask = img_as_ubyte(mask) + if image is out: + raise NotImplementedError("Cannot perform rank operation in place.") + + mask = np.ascontiguousarray(mask) if image.dtype == np.uint8: if func8 is None: - raise TypeError("not implemented for uint8 image") - return func8(image, selem, shift_x=shift_x, shift_y=shift_y, mask=mask, out=out) + raise TypeError("Not implemented for uint8 image.") + if out is None: + out = np.zeros(image.shape, dtype=np.uint8) + func8(image, selem, shift_x=shift_x, shift_y=shift_y, + mask=mask, out=out) elif image.dtype == np.uint16: if func16 is None: - raise TypeError("not implemented for uint16 image") + raise TypeError("Not implemented for uint16 image.") + if out is None: + out = np.zeros(image.shape, dtype=np.uint16) bitdepth = find_bitdepth(image) if bitdepth > 11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return func16(image, selem, shift_x=shift_x, shift_y=shift_y, mask=mask, bitdepth=bitdepth + 1, out=out) + raise ValueError("Only uint16 <4096 image (12bit) supported.") + func16(image, selem, shift_x=shift_x, shift_y=shift_y, mask=mask, + bitdepth=bitdepth + 1, out=out) else: - raise TypeError("only uint8 and uint16 image supported!") + raise TypeError("Only uint8 and uint16 image supported.") + + return out def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): @@ -47,18 +66,20 @@ def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, the algorithm + uses max. 12bit histogram, an exception will be raised if image has a + value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). Returns ------- @@ -77,9 +98,8 @@ def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """ - return _apply( - _crank8.autolevel, _crank16.autolevel, image, selem, out=out, mask=mask, shift_x=shift_x, - shift_y=shift_y) + return _apply(_crank8.autolevel, _crank16.autolevel, image, selem, out=out, + mask=mask, shift_x=shift_x, shift_y=shift_y) def bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): @@ -88,30 +108,30 @@ def bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, the algorithm + uses max. 12bit histogram, an exception will be raised if image has a + value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). Returns ------- local bottomhat : uint8 array or uint16 array depending on input image The result of the local bottomhat. - """ - return _apply( - _crank8.bottomhat, _crank16.bottomhat, image, selem, out=out, mask=mask, shift_x=shift_x, - shift_y=shift_y) + return _apply(_crank8.bottomhat, _crank16.bottomhat, image, selem, out=out, + mask=mask, shift_x=shift_x, shift_y=shift_y) def equalize(image, selem, out=None, mask=None, shift_x=False, shift_y=False): @@ -120,18 +140,20 @@ def equalize(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, the algorithm + uses max. 12bit histogram, an exception will be raised if image has a + value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). Returns ------- @@ -147,32 +169,35 @@ def equalize(image, selem, out=None, mask=None, shift_x=False, shift_y=False): >>> ima = data.camera() >>> # Local equalization >>> equ = equalize(ima, disk(20)) + """ - return _apply( - _crank8.equalize, _crank16.equalize, image, selem, out=out, mask=mask, shift_x=shift_x, - shift_y=shift_y) + return _apply(_crank8.equalize, _crank16.equalize, image, selem, out=out, + mask=mask, shift_x=shift_x, shift_y=shift_y) def gradient(image, selem, out=None, mask=None, shift_x=False, shift_y=False): - """Return greyscale local gradient of an image (i.e. local maximum - local minimum). + """Return greyscale local gradient of an image (i.e. local maximum - local + minimum). Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, the algorithm + uses max. 12bit histogram, an exception will be raised if image has a + value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). Returns ------- @@ -181,9 +206,8 @@ def gradient(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """ - return _apply( - _crank8.gradient, _crank16.gradient, image, selem, out=out, mask=mask, shift_x=shift_x, - shift_y=shift_y) + return _apply(_crank8.gradient, _crank16.gradient, image, selem, out=out, + mask=mask, shift_x=shift_x, shift_y=shift_y) def maximum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): @@ -193,18 +217,20 @@ def maximum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, the algorithm + uses max. 12bit histogram, an exception will be raised if image has a + value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). Returns ------- @@ -213,17 +239,18 @@ def maximum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): See also -------- - skimage.morphology.dilation() + skimage.morphology.dilation Note ---- * input image can be 8 bit or 16 bit with a value < 4096 (i.e. 12 bit) - - * the lower algorithm complexity makes the rank.maximum() more efficient for larger images and structuring elements + * the lower algorithm complexity makes the rank.maximum() more efficient for + larger images and structuring elements """ - return _apply(_crank8.maximum, _crank16.maximum, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) + return _apply(_crank8.maximum, _crank16.maximum, image, selem, out=out, + mask=mask, shift_x=shift_x, shift_y=shift_y) def mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False): @@ -232,18 +259,20 @@ def mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, the algorithm + uses max. 12bit histogram, an exception will be raised if image has a + value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). Returns ------- @@ -259,63 +288,66 @@ def mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False): >>> ima = data.camera() >>> # Local mean >>> avg = mean(ima, disk(20)) + """ - return _apply(_crank8.mean, _crank16.mean, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) + return _apply(_crank8.mean, _crank16.mean, image, selem, out=out, + mask=mask, shift_x=shift_x, shift_y=shift_y) -def meansubstraction(image, selem, out=None, mask=None, shift_x=False, shift_y=False): +def meansubstraction(image, selem, out=None, mask=None, shift_x=False, + shift_y=False): """Return image substracted from its local mean. Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, the algorithm + uses max. 12bit histogram, an exception will be raised if image has a + value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). Returns ------- out : uint8 array or uint16 array (same as input image) The result of the local meansubstraction. - - """ - return _apply( - _crank8.meansubstraction, _crank16.meansubstraction, image, selem, out=out, mask=mask, - shift_x=shift_x, shift_y=shift_y) + return _apply(_crank8.meansubstraction, _crank16.meansubstraction, image, + selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) def median(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Return greyscale local median of an image. - Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, the algorithm + uses max. 12bit histogram, an exception will be raised if image has a + value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). Returns ------- @@ -331,9 +363,11 @@ def median(image, selem, out=None, mask=None, shift_x=False, shift_y=False): >>> ima = data.camera() >>> # Local mean >>> avg = median(ima, disk(20)) + """ - return _apply(_crank8.median, _crank16.median, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) + return _apply(_crank8.median, _crank16.median, image, selem, out=out, + mask=mask, shift_x=shift_x, shift_y=shift_y) def minimum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): @@ -342,18 +376,20 @@ def minimum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, the algorithm + uses max. 12bit histogram, an exception will be raised if image has a + value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). Returns ------- @@ -362,17 +398,18 @@ def minimum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): See also -------- - skimage.morphology.erosion() + skimage.morphology.erosion Note ---- * input image can be 8 bit or 16 bit with a value < 4096 (i.e. 12 bit) - - * the lower algorithm complexity makes the rank.minimum() more efficient for larger images and structuring elements + * the lower algorithm complexity makes the rank.minimum() more efficient + for larger images and structuring elements """ - return _apply(_crank8.minimum, _crank16.minimum, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) + return _apply(_crank8.minimum, _crank16.minimum, image, selem, out=out, + mask=mask, shift_x=shift_x, shift_y=shift_y) def modal(image, selem, out=None, mask=None, shift_x=False, shift_y=False): @@ -381,49 +418,55 @@ def modal(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, the algorithm + uses max. 12bit histogram, an exception will be raised if image has a + value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). Returns ------- out : uint8 array or uint16 array (same as input image) The local modal. - """ - return _apply(_crank8.modal, _crank16.modal, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) + return _apply(_crank8.modal, _crank16.modal, image, selem, out=out, + mask=mask, shift_x=shift_x, shift_y=shift_y) -def morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, shift_y=False): - """Enhance an image replacing each pixel by the local maximum if pixel graylevel is closest to maximimum - than local minimum OR local minimum otherwise. +def morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, + shift_y=False): + """Enhance an image replacing each pixel by the local maximum if pixel + graylevel is closest to maximimum than local minimum OR local minimum + otherwise. Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, the algorithm + uses max. 12bit histogram, an exception will be raised if image has a + value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). Returns ------- @@ -439,31 +482,34 @@ def morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa >>> ima = data.camera() >>> # Local mean >>> avg = morph_contr_enh(ima, disk(20)) + """ - return _apply( - _crank8.morph_contr_enh, _crank16.morph_contr_enh, image, selem, out=out, mask=mask, shift_x=shift_x, - shift_y=shift_y) + return _apply(_crank8.morph_contr_enh, _crank16.morph_contr_enh, image, + selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) def pop(image, selem, out=None, mask=None, shift_x=False, shift_y=False): - """Return the number (population) of pixels actually inside the neighborhood. + """Return the number (population) of pixels actually inside the + neighborhood. Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, the algorithm + uses max. 12bit histogram, an exception will be raised if image has a + value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). Returns ------- @@ -487,10 +533,10 @@ def pop(image, selem, out=None, mask=None, shift_x=False, shift_y=False): [6, 9, 9, 9, 6], [4, 6, 6, 6, 4]], dtype=uint8) - """ - return _apply(_crank8.pop, _crank16.pop, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) + return _apply(_crank8.pop, _crank16.pop, image, selem, out=out, + mask=mask, shift_x=shift_x, shift_y=shift_y) def threshold(image, selem, out=None, mask=None, shift_x=False, shift_y=False): @@ -499,18 +545,20 @@ def threshold(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, the algorithm + uses max. 12bit histogram, an exception will be raised if image has a + value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). Returns ------- @@ -534,12 +582,10 @@ def threshold(image, selem, out=None, mask=None, shift_x=False, shift_y=False): [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]], dtype=uint8) - """ - return _apply( - _crank8.threshold, _crank16.threshold, image, selem, out=out, mask=mask, shift_x=shift_x, - shift_y=shift_y) + return _apply(_crank8.threshold, _crank16.threshold, image, selem, out=out, + mask=mask, shift_x=shift_x, shift_y=shift_y) def tophat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): @@ -548,18 +594,20 @@ def tophat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, the algorithm + uses max. 12bit histogram, an exception will be raised if image has a + value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). Returns ------- @@ -568,32 +616,35 @@ def tophat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """ - return _apply(_crank8.tophat, _crank16.tophat, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) + return _apply(_crank8.tophat, _crank16.tophat, image, selem, out=out, + mask=mask, shift_x=shift_x, shift_y=shift_y) -def noise_filter(image, selem, out=None, mask=None, shift_x=False, shift_y=False): +def noise_filter(image, selem, out=None, mask=None, shift_x=False, + shift_y=False): """Returns the noise feature as described in [Hashimoto12]_ Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, the algorithm + uses max. 12bit histogram, an exception will be raised if image has a + value > 4095. selem : ndarray - The neighborhood expressed as a 2-D array of 1's and 0's. Central element is removed during the filtering. + The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). - Reference + References ---------- - - .. [Hashimoto12] N. Hashimoto et al. Referenceless image quality evaluation for whole slide imaging. J Pathol Inform 2012;3:9. - + .. [Hashimoto12] N. Hashimoto et al. Referenceless image quality evaluation + for whole slide imaging. J Pathol Inform 2012;3:9. Returns ------- @@ -601,6 +652,7 @@ def noise_filter(image, selem, out=None, mask=None, shift_x=False, shift_y=False The image noise . """ + # ensure that the central pixel in the structuring element is empty centre_r = int(selem.shape[0] / 2) + shift_y centre_c = int(selem.shape[1] / 2) + shift_x @@ -608,41 +660,43 @@ def noise_filter(image, selem, out=None, mask=None, shift_x=False, shift_y=False selem_cpy = selem.copy() selem_cpy[centre_r,centre_c] = 0 - return _apply(_crank8.noise_filter, None, image, selem_cpy, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) + return _apply(_crank8.noise_filter, None, image, selem_cpy, out=out, + mask=mask, shift_x=shift_x, shift_y=shift_y) def entropy(image, selem, out=None, mask=None, shift_x=False, shift_y=False): - """Returns the entropy [wiki_entropy]_ computed locally. Entropy is computed using base 2 logarithm i.e. - the filter returns the minimum number of bits needed to encode local greylevel distribution. - - References - ---------- - .. [wiki_entropy] http://en.wikipedia.org/wiki/Entropy_(information_theory) + """Returns the entropy [wiki_entropy]_ computed locally. Entropy is computed + using base 2 logarithm i.e. the filter returns the minimum number of + bits needed to encode local greylevel distribution. Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, the algorithm + uses max. 12bit histogram, an exception will be raised if image has a + value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). Returns ------- out : uint8 array or uint16 array (same as input image) entropy x10 (uint8 images) and entropy x1000 (uint16 images) + References + ---------- + .. [wiki_entropy] http://en.wikipedia.org/wiki/Entropy_(information_theory) Examples -------- - >>> # Local entropy >>> from skimage import data >>> from skimage.filter.rank import entropy @@ -650,46 +704,48 @@ def entropy(image, selem, out=None, mask=None, shift_x=False, shift_y=False): >>> # defining a 8- and a 16-bit test images >>> a8 = data.camera() >>> a16 = data.camera().astype(np.uint16)*4 - >>> ent8 = entropy(a8,disk(5)) # pixel value contain 10x the local entropy - >>> ent16 = entropy(a16,disk(5)) # pixel value contain 1000x the local entropy + >>> # pixel values contain 10x the local entropy + >>> ent8 = entropy(a8,disk(5)) + >>> # pixel values contain 1000x the local entropy + >>> ent16 = entropy(a16,disk(5)) """ - return _apply(_crank8.entropy, _crank16.entropy, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) + return _apply(_crank8.entropy, _crank16.entropy, image, selem, out=out, + mask=mask, shift_x=shift_x, shift_y=shift_y) def otsu(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Returns the image threshold using a the Otsu [otsu]_ locally . - References - ---------- - - .. [otsu] http://en.wikipedia.org/wiki/Otsu's_method - Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, - an exception will be raised if image has a value > 4095 + Image array (uint8 array or uint16). If image is uint16, the algorithm + uses max. 12bit histogram, an exception will be raised if image has a + value > 4095. selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) - Mask array that defines (>0) area of the image included in the local neighborhood. - If None, the complete image is used (default). - shift_x, shift_y : (int) - Offset added to the structuring element center point. - Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Mask array that defines (>0) area of the image included in the local + neighborhood. If None, the complete image is used (default). + shift_x, shift_y : int + Offset added to the structuring element center point. Shift is bounded + to the structuring element sizes (center must be inside the given + structuring element). Returns ------- out : uint8 array or uint16 array (same as input image) threshold image + References + ---------- + .. [otsu] http://en.wikipedia.org/wiki/Otsu's_method Examples -------- - >>> # Local entropy >>> from skimage import data >>> from skimage.filter.rank import otsu @@ -700,4 +756,5 @@ def otsu(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """ - return _apply(_crank8.otsu, None, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) \ No newline at end of file + return _apply(_crank8.otsu, None, image, selem, out=out, + mask=mask, shift_x=shift_x, shift_y=shift_y)