mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-25 13:30:51 +08:00
@@ -29,8 +29,3 @@ this path to your PYTHONPATH variable and compiling the extensions:
|
||||
License
|
||||
-------
|
||||
Please read LICENSE.txt in this directory.
|
||||
|
||||
Contact
|
||||
-------
|
||||
Stefan van der Walt <stefan at sun.ac.za>
|
||||
|
||||
@@ -1,35 +1,32 @@
|
||||
To use this to build your Cython file use the commandline options:
|
||||
|
||||
.. sourcecode:: text
|
||||
|
||||
$ python setup.py build_ext --inplace
|
||||
|
||||
|
||||
**To do**
|
||||
To do
|
||||
-----
|
||||
|
||||
* add simple examples, adapt documentation on existing examples
|
||||
|
||||
* add/check existing doc
|
||||
|
||||
* adapting tests for each type of filter
|
||||
|
||||
**General remarks**
|
||||
General remarks
|
||||
---------------
|
||||
|
||||
Basically these filters compute local histogram for each pixel. Histogram is build using a moving window in
|
||||
order to limit redundant computation. The path followed by the moving window is given hereunder
|
||||
Basically these filters compute local histogram for each pixel. Histogram is
|
||||
build using a moving window in order to limit redundant computation. The path
|
||||
followed by the moving window is given hereunder
|
||||
|
||||
...-----------------------\
|
||||
/--------------------------/
|
||||
\-------------------------- ...
|
||||
|
||||
A comparison is proposed with cmorph.dilate algorithm to show how computation costs evolve with respect to image size or
|
||||
structuring element size. This implementation gives better results for large structuring elements.
|
||||
A comparison is proposed with cmorph.dilate algorithm to show how computation
|
||||
costs evolve with respect to image size or structuring element size. This
|
||||
implementation gives better results for large structuring elements.
|
||||
|
||||
A local histogram is update at each pixel by introducing pixel entering the structuring element border and
|
||||
by removing those leaving it. The histogram size is 8bit (256 bins) for 8 bit images and 2 to 12 bit (up to 4096 bins)
|
||||
for 16bit image depending on the image maximum value. Image with pixels higher than 4095 raise a ValueError.
|
||||
|
||||
The filter is applied up to the image border, the neighboorhood used is adjusted accordingly. The user may provide
|
||||
a mask image (same size as input image) where non zero value are the part of the image participating the the
|
||||
histogram computation. By default all the image is filtered.
|
||||
A local histogram is update at each pixel by introducing pixel entering the
|
||||
structuring element border and by removing those leaving it. The histogram size
|
||||
is 8bit (256 bins) for 8 bit images and 2 to 12 bit (up to 4096 bins) for 16bit
|
||||
image depending on the image maximum value. Image with pixels higher than 4095
|
||||
raise a ValueError.
|
||||
|
||||
The filter is applied up to the image border, the neighboorhood used is adjusted
|
||||
accordingly. The user may provide a mask image (same size as input image) where
|
||||
non zero value are the part of the image participating the the histogram
|
||||
computation. By default all the image is filtered.
|
||||
|
||||
@@ -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) except *
|
||||
|
||||
@@ -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.
|
||||
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
|
||||
pop[0] -= 1
|
||||
|
||||
|
||||
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) except *:
|
||||
"""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]
|
||||
@@ -70,36 +60,21 @@ cdef inline _core16(
|
||||
maxbin_list = [0, 0, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096]
|
||||
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]
|
||||
# set maxbin and midbin
|
||||
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 = <np.uint16_t * >out.data
|
||||
cdef np.uint16_t * image_data = <np.uint16_t * >image.data
|
||||
cdef np.uint8_t * mask_data = <np.uint8_t * >mask.data
|
||||
cdef np.uint16_t * out_data = <np.uint16_t*>out.data
|
||||
cdef np.uint16_t * image_data = <np.uint16_t*>image.data
|
||||
cdef np.uint8_t * mask_data = <np.uint8_t*>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 = <Py_ssize_t * >malloc(maxbin * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * histo = <Py_ssize_t*>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 = <Py_ssize_t * >malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_e_c = <Py_ssize_t * >malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_w_r = <Py_ssize_t * >malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_w_c = <Py_ssize_t * >malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_n_r = <Py_ssize_t * >malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_n_c = <Py_ssize_t * >malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_s_r = <Py_ssize_t * >malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_s_c = <Py_ssize_t * >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 = <Py_ssize_t*>malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_e_c = <Py_ssize_t*>malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_w_r = <Py_ssize_t*>malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_w_c = <Py_ssize_t*>malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_n_r = <Py_ssize_t*>malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_n_c = <Py_ssize_t*>malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_s_r = <Py_ssize_t*>malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_s_c = <Py_ssize_t*>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
|
||||
|
||||
@@ -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) except *
|
||||
|
||||
@@ -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.
|
||||
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.
|
||||
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) except *:
|
||||
"""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 = <np.uint8_t * >out.data
|
||||
cdef np.uint8_t * image_data = <np.uint8_t * >image.data
|
||||
cdef np.uint8_t * mask_data = <np.uint8_t * >mask.data
|
||||
cdef np.uint8_t * out_data = <np.uint8_t*>out.data
|
||||
cdef np.uint8_t * image_data = <np.uint8_t*>image.data
|
||||
cdef np.uint8_t * mask_data = <np.uint8_t*>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 = <Py_ssize_t * >malloc(256 * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * histo = <Py_ssize_t*>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 = <Py_ssize_t * >malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_e_c = <Py_ssize_t * >malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_w_r = <Py_ssize_t * >malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_w_c = <Py_ssize_t * >malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_n_r = <Py_ssize_t * >malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_n_c = <Py_ssize_t * >malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_s_r = <Py_ssize_t * >malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_s_c = <Py_ssize_t * >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 = <Py_ssize_t*>malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_e_c = <Py_ssize_t*>malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_w_r = <Py_ssize_t*>malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_w_c = <Py_ssize_t*>malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_n_r = <Py_ssize_t*>malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_n_c = <Py_ssize_t*>malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_s_r = <Py_ssize_t*>malloc(max_se * sizeof(Py_ssize_t))
|
||||
cdef Py_ssize_t * se_s_c = <Py_ssize_t*>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
|
||||
|
||||
+153
-104
@@ -6,18 +6,19 @@
|
||||
import numpy as np
|
||||
cimport numpy as np
|
||||
from libc.math cimport log2
|
||||
|
||||
# import main loop
|
||||
from skimage.filter.rank._core16 cimport _core16
|
||||
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# kernels uint16 take extra parameter for defining the bitdepth
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
cdef inline np.uint16_t kernel_autolevel(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g,
|
||||
Py_ssize_t bitdepth, Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint16_t kernel_autolevel(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef Py_ssize_t i, imin, imax, delta
|
||||
|
||||
if pop:
|
||||
@@ -31,27 +32,30 @@ cdef inline np.uint16_t kernel_autolevel(
|
||||
break
|
||||
delta = imax - imin
|
||||
if delta > 0:
|
||||
return < np.uint16_t > (1. * (maxbin - 1) * (g - imin) / delta)
|
||||
return <np.uint16_t>(1. * (maxbin - 1) * (g - imin) / delta)
|
||||
else:
|
||||
return < np.uint16_t > (imax - imin)
|
||||
return <np.uint16_t>(imax - imin)
|
||||
|
||||
cdef inline np.uint16_t kernel_bottomhat(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g,
|
||||
Py_ssize_t bitdepth, Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint16_t kernel_bottomhat(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef Py_ssize_t i
|
||||
|
||||
for i in range(maxbin):
|
||||
if histo[i]:
|
||||
break
|
||||
|
||||
return < np.uint16_t > (g - i)
|
||||
return <np.uint16_t>(g - i)
|
||||
|
||||
|
||||
cdef inline np.uint16_t kernel_equalize(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g,
|
||||
Py_ssize_t bitdepth, Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef inline np.uint16_t kernel_equalize(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef Py_ssize_t i
|
||||
cdef float sum = 0.
|
||||
|
||||
@@ -61,14 +65,16 @@ cdef inline np.uint16_t kernel_equalize(
|
||||
if i >= g:
|
||||
break
|
||||
|
||||
return < np.uint16_t > (((maxbin - 1) * sum) / pop)
|
||||
return <np.uint16_t>(((maxbin - 1) * sum) / pop)
|
||||
else:
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
cdef inline np.uint16_t kernel_gradient(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g,
|
||||
Py_ssize_t bitdepth, Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint16_t kernel_gradient(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef Py_ssize_t i, imin, imax
|
||||
|
||||
if pop:
|
||||
@@ -80,55 +86,66 @@ cdef inline np.uint16_t kernel_gradient(
|
||||
if histo[i]:
|
||||
imin = i
|
||||
break
|
||||
return < np.uint16_t > (imax - imin)
|
||||
return <np.uint16_t>(imax - imin)
|
||||
else:
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
cdef inline np.uint16_t kernel_maximum(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g,
|
||||
Py_ssize_t bitdepth, Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint16_t kernel_maximum(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef Py_ssize_t i
|
||||
|
||||
if pop:
|
||||
for i in range(maxbin - 1, -1, -1):
|
||||
if histo[i]:
|
||||
return < np.uint16_t > (i)
|
||||
return <np.uint16_t>(i)
|
||||
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
cdef inline np.uint16_t kernel_mean(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g,
|
||||
Py_ssize_t bitdepth, Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint16_t kernel_mean(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef Py_ssize_t i
|
||||
cdef float mean = 0.
|
||||
|
||||
if pop:
|
||||
for i in range(maxbin):
|
||||
mean += histo[i] * i
|
||||
return < np.uint16_t > (mean / pop)
|
||||
return <np.uint16_t>(mean / pop)
|
||||
else:
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
cdef inline np.uint16_t kernel_meansubstraction(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g,
|
||||
Py_ssize_t bitdepth, Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint16_t kernel_meansubstraction(Py_ssize_t * histo,
|
||||
float pop,
|
||||
np.uint16_t g,
|
||||
Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin,
|
||||
Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef Py_ssize_t i
|
||||
cdef float mean = 0.
|
||||
|
||||
if pop:
|
||||
for i in range(maxbin):
|
||||
mean += histo[i] * i
|
||||
return < np.uint16_t > ((g - mean / pop) / 2. + (midbin - 1))
|
||||
return <np.uint16_t>((g - mean / pop) / 2. + (midbin - 1))
|
||||
else:
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
cdef inline np.uint16_t kernel_median(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g,
|
||||
Py_ssize_t bitdepth, Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint16_t kernel_median(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef Py_ssize_t i
|
||||
cdef float sum = pop / 2.0
|
||||
|
||||
@@ -137,27 +154,31 @@ cdef inline np.uint16_t kernel_median(
|
||||
if histo[i]:
|
||||
sum -= histo[i]
|
||||
if sum < 0:
|
||||
return < np.uint16_t > (i)
|
||||
return <np.uint16_t>(i)
|
||||
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
cdef inline np.uint16_t kernel_minimum(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g,
|
||||
Py_ssize_t bitdepth, Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint16_t kernel_minimum(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef Py_ssize_t i
|
||||
|
||||
if pop:
|
||||
for i in range(maxbin):
|
||||
if histo[i]:
|
||||
return < np.uint16_t > (i)
|
||||
return <np.uint16_t>(i)
|
||||
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
cdef inline np.uint16_t kernel_modal(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g,
|
||||
Py_ssize_t bitdepth, Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint16_t kernel_modal(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef Py_ssize_t hmax = 0, imax = 0
|
||||
|
||||
if pop:
|
||||
@@ -165,14 +186,19 @@ cdef inline np.uint16_t kernel_modal(
|
||||
if histo[i] > hmax:
|
||||
hmax = histo[i]
|
||||
imax = i
|
||||
return < np.uint16_t > (imax)
|
||||
return <np.uint16_t>(imax)
|
||||
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
cdef inline np.uint16_t kernel_morph_contr_enh(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g,
|
||||
Py_ssize_t bitdepth, Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint16_t kernel_morph_contr_enh(Py_ssize_t * histo,
|
||||
float pop,
|
||||
np.uint16_t g,
|
||||
Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin,
|
||||
Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef Py_ssize_t i, imin, imax
|
||||
|
||||
if pop:
|
||||
@@ -185,49 +211,56 @@ cdef inline np.uint16_t kernel_morph_contr_enh(
|
||||
imin = i
|
||||
break
|
||||
if imax - g < g - imin:
|
||||
return < np.uint16_t > (imax)
|
||||
return <np.uint16_t>(imax)
|
||||
else:
|
||||
return < np.uint16_t > (imin)
|
||||
return <np.uint16_t>(imin)
|
||||
else:
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
cdef inline np.uint16_t kernel_pop(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g,
|
||||
Py_ssize_t bitdepth, Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
return < np.uint16_t > (pop)
|
||||
|
||||
cdef inline np.uint16_t kernel_threshold(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g,
|
||||
Py_ssize_t bitdepth, Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef inline np.uint16_t kernel_pop(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
return <np.uint16_t>(pop)
|
||||
|
||||
|
||||
cdef inline np.uint16_t kernel_threshold(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef Py_ssize_t i
|
||||
cdef float mean = 0.
|
||||
|
||||
if pop:
|
||||
for i in range(maxbin):
|
||||
mean += histo[i] * i
|
||||
return < np.uint16_t > (g > (mean / pop))
|
||||
return <np.uint16_t>(g > (mean / pop))
|
||||
else:
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
cdef inline np.uint16_t kernel_tophat(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g,
|
||||
Py_ssize_t bitdepth, Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint16_t kernel_tophat(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef Py_ssize_t i
|
||||
|
||||
for i in range(maxbin - 1, -1, -1):
|
||||
if histo[i]:
|
||||
break
|
||||
|
||||
return < np.uint16_t > (i - g)
|
||||
return <np.uint16_t>(i - g)
|
||||
|
||||
|
||||
cdef inline np.uint16_t kernel_entropy(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g,
|
||||
Py_ssize_t bitdepth, Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef inline np.uint16_t kernel_entropy(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef Py_ssize_t i
|
||||
cdef float e,p
|
||||
|
||||
@@ -238,7 +271,8 @@ cdef inline np.uint16_t kernel_entropy(
|
||||
if p>0:
|
||||
e -= p*log2(p)
|
||||
|
||||
return < np.uint16_t > e*1000
|
||||
return <np.uint16_t>e*1000
|
||||
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# python wrappers
|
||||
@@ -250,7 +284,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def bottomhat(np.ndarray[np.uint16_t, ndim=2] image,
|
||||
@@ -258,7 +293,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def equalize(np.ndarray[np.uint16_t, ndim=2] image,
|
||||
@@ -266,7 +302,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def gradient(np.ndarray[np.uint16_t, ndim=2] image,
|
||||
@@ -274,7 +311,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def maximum(np.ndarray[np.uint16_t, ndim=2] image,
|
||||
@@ -282,7 +320,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def mean(np.ndarray[np.uint16_t, ndim=2] image,
|
||||
@@ -290,7 +329,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def meansubstraction(np.ndarray[np.uint16_t, ndim=2] image,
|
||||
@@ -298,7 +338,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def median(np.ndarray[np.uint16_t, ndim=2] image,
|
||||
@@ -306,7 +347,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def minimum(np.ndarray[np.uint16_t, ndim=2] image,
|
||||
@@ -314,7 +356,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def morph_contr_enh(np.ndarray[np.uint16_t, ndim=2] image,
|
||||
@@ -322,7 +365,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def modal(np.ndarray[np.uint16_t, ndim=2] image,
|
||||
@@ -330,7 +374,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def pop(np.ndarray[np.uint16_t, ndim=2] image,
|
||||
@@ -338,7 +383,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def threshold(np.ndarray[np.uint16_t, ndim=2] image,
|
||||
@@ -346,7 +392,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def tophat(np.ndarray[np.uint16_t, ndim=2] image,
|
||||
@@ -354,11 +401,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, <Py_ssize_t>0, <Py_ssize_t>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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
@@ -5,18 +5,19 @@
|
||||
|
||||
import numpy as np
|
||||
cimport numpy as np
|
||||
|
||||
# import main loop
|
||||
from skimage.filter.rank._core16 cimport _core16
|
||||
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# kernels uint16 take extra parameter for defining the bitdepth
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
|
||||
cdef inline np.uint16_t kernel_mean(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin, float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef inline np.uint16_t kernel_mean(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef int i, bilat_pop = 0
|
||||
cdef float mean = 0.
|
||||
@@ -27,16 +28,18 @@ cdef inline np.uint16_t kernel_mean(
|
||||
bilat_pop += histo[i]
|
||||
mean += histo[i] * i
|
||||
if bilat_pop:
|
||||
return < np.uint16_t > (mean / bilat_pop)
|
||||
return <np.uint16_t>(mean / bilat_pop)
|
||||
else:
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
else:
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
|
||||
cdef inline np.uint16_t kernel_pop(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g, Py_ssize_t bitdepth, Py_ssize_t maxbin,
|
||||
Py_ssize_t midbin, float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef inline np.uint16_t kernel_pop(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef int i, bilat_pop = 0
|
||||
|
||||
@@ -44,14 +47,16 @@ cdef inline np.uint16_t kernel_pop(
|
||||
for i in range(maxbin):
|
||||
if (g > (i - s0)) and (g < (i + s1)):
|
||||
bilat_pop += histo[i]
|
||||
return < np.uint16_t > (bilat_pop)
|
||||
return <np.uint16_t>(bilat_pop)
|
||||
else:
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# python wrappers
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
|
||||
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,
|
||||
@@ -59,7 +64,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,
|
||||
@@ -67,6 +73,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, int bitdepth=8, int s0=1, int s1=1):
|
||||
"""returns the number of actual pixels of the structuring element inside the mask
|
||||
"""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)
|
||||
|
||||
@@ -5,17 +5,19 @@
|
||||
|
||||
import numpy as np
|
||||
cimport numpy as np
|
||||
|
||||
# import main loop
|
||||
from skimage.filter.rank._core16 cimport _core16, int_min, int_max
|
||||
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# kernels uint16 (SOFT version using percentiles)
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
cdef inline np.uint16_t kernel_autolevel(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin, float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint16_t kernel_autolevel(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef int i, imin, imax, sum, delta
|
||||
|
||||
@@ -36,16 +38,19 @@ cdef inline np.uint16_t kernel_autolevel(
|
||||
|
||||
delta = imax - imin
|
||||
if delta > 0:
|
||||
return < np.uint16_t > (1.0 * (maxbin - 1) * (int_min(int_max(imin, g), imax) - imin) / delta)
|
||||
return <np.uint16_t>(1.0 * (maxbin - 1) \
|
||||
* (int_min(int_max(imin, g), imax) - imin) / delta)
|
||||
else:
|
||||
return < np.uint16_t > (imax - imin)
|
||||
return <np.uint16_t>(imax - imin)
|
||||
else:
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
|
||||
cdef inline np.uint16_t kernel_gradient(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin, float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef inline np.uint16_t kernel_gradient(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef int i, imin, imax, sum, delta
|
||||
|
||||
@@ -64,14 +69,16 @@ cdef inline np.uint16_t kernel_gradient(
|
||||
imax = i
|
||||
break
|
||||
|
||||
return < np.uint16_t > (imax - imin)
|
||||
return <np.uint16_t>(imax - imin)
|
||||
else:
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
|
||||
cdef inline np.uint16_t kernel_mean(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin, float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef inline np.uint16_t kernel_mean(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef int i, sum, mean, n
|
||||
|
||||
@@ -86,15 +93,21 @@ cdef inline np.uint16_t kernel_mean(
|
||||
mean += histo[i] * i
|
||||
|
||||
if n > 0:
|
||||
return < np.uint16_t > (1.0 * mean / n)
|
||||
return <np.uint16_t>(1.0 * mean / n)
|
||||
else:
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
else:
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
cdef inline np.uint16_t kernel_mean_substraction(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin, float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint16_t kernel_mean_substraction(Py_ssize_t * histo,
|
||||
float pop,
|
||||
np.uint16_t g,
|
||||
Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin,
|
||||
Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef int i, sum, mean, n
|
||||
|
||||
@@ -108,15 +121,21 @@ cdef inline np.uint16_t kernel_mean_substraction(
|
||||
n += histo[i]
|
||||
mean += histo[i] * i
|
||||
if n > 0:
|
||||
return < np.uint16_t > ((g - (mean / n)) * .5 + midbin)
|
||||
return <np.uint16_t>((g - (mean / n)) * .5 + midbin)
|
||||
else:
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
else:
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
cdef inline np.uint16_t kernel_morph_contr_enh(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin, float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint16_t kernel_morph_contr_enh(Py_ssize_t * histo,
|
||||
float pop,
|
||||
np.uint16_t g,
|
||||
Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin,
|
||||
Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef int i, imin, imax, sum, delta
|
||||
|
||||
@@ -135,19 +154,22 @@ cdef inline np.uint16_t kernel_morph_contr_enh(
|
||||
imax = i
|
||||
break
|
||||
if g > imax:
|
||||
return < np.uint16_t > imax
|
||||
return <np.uint16_t>imax
|
||||
if g < imin:
|
||||
return < np.uint16_t > imin
|
||||
return <np.uint16_t>imin
|
||||
if imax - g < g - imin:
|
||||
return < np.uint16_t > imax
|
||||
return <np.uint16_t>imax
|
||||
else:
|
||||
return < np.uint16_t > imin
|
||||
return <np.uint16_t>imin
|
||||
else:
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
cdef inline np.uint16_t kernel_percentile(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin, float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint16_t kernel_percentile(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef int i
|
||||
cdef float sum = 0.
|
||||
@@ -158,13 +180,16 @@ cdef inline np.uint16_t kernel_percentile(
|
||||
if sum >= p0 * pop:
|
||||
break
|
||||
|
||||
return < np.uint16_t > (i)
|
||||
return <np.uint16_t>(i)
|
||||
else:
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
cdef inline np.uint16_t kernel_pop(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin, float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint16_t kernel_pop(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef int i, sum, n
|
||||
|
||||
@@ -175,13 +200,16 @@ cdef inline np.uint16_t kernel_pop(
|
||||
sum += histo[i]
|
||||
if (sum >= p0 * pop) and (sum <= p1 * pop):
|
||||
n += histo[i]
|
||||
return < np.uint16_t > (n)
|
||||
return <np.uint16_t>(n)
|
||||
else:
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
cdef inline np.uint16_t kernel_threshold(
|
||||
Py_ssize_t * histo, float pop, np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin, float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint16_t kernel_threshold(Py_ssize_t * histo, float pop,
|
||||
np.uint16_t g, Py_ssize_t bitdepth,
|
||||
Py_ssize_t maxbin, Py_ssize_t midbin,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef int i
|
||||
cdef float sum = 0.
|
||||
@@ -192,9 +220,10 @@ cdef inline np.uint16_t kernel_threshold(
|
||||
if sum >= p0 * pop:
|
||||
break
|
||||
|
||||
return < np.uint16_t > ((maxbin - 1) * (g >= i))
|
||||
return <np.uint16_t>((maxbin - 1) * (g >= i))
|
||||
else:
|
||||
return < np.uint16_t > (0)
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# python wrappers
|
||||
@@ -205,93 +234,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, <Py_ssize_t>0, <Py_ssize_t>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, <Py_ssize_t>0, <Py_ssize_t>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, <Py_ssize_t>0, <Py_ssize_t>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, <Py_ssize_t>0, <Py_ssize_t>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, <Py_ssize_t>0, <Py_ssize_t>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, <Py_ssize_t>0, <Py_ssize_t>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, <Py_ssize_t>0, <Py_ssize_t>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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
+150
-132
@@ -5,19 +5,18 @@
|
||||
|
||||
import numpy as np
|
||||
cimport numpy as np
|
||||
|
||||
from libc.math cimport log2
|
||||
|
||||
# import main loop
|
||||
from skimage.filter.rank._core8 cimport _core8
|
||||
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# kernels uint8
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
cdef inline np.uint8_t kernel_autolevel(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_autolevel(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef Py_ssize_t i, imin, imax, delta
|
||||
|
||||
@@ -32,15 +31,16 @@ cdef inline np.uint8_t kernel_autolevel(
|
||||
break
|
||||
delta = imax - imin
|
||||
if delta > 0:
|
||||
return < np.uint8_t > (255. * (g - imin) / delta)
|
||||
return <np.uint8_t>(255. * (g - imin) / delta)
|
||||
else:
|
||||
return < np.uint8_t > (imax - imin)
|
||||
return <np.uint8_t>(imax - imin)
|
||||
else:
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
cdef inline np.uint8_t kernel_bottomhat(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_bottomhat(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef Py_ssize_t i
|
||||
|
||||
@@ -48,12 +48,12 @@ cdef inline np.uint8_t kernel_bottomhat(
|
||||
if histo[i]:
|
||||
break
|
||||
|
||||
return < np.uint8_t > (g - i)
|
||||
return <np.uint8_t>(g - i)
|
||||
|
||||
|
||||
cdef inline np.uint8_t kernel_equalize(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef inline np.uint8_t kernel_equalize(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef Py_ssize_t i
|
||||
cdef float sum = 0.
|
||||
@@ -64,13 +64,14 @@ cdef inline np.uint8_t kernel_equalize(
|
||||
if i >= g:
|
||||
break
|
||||
|
||||
return < np.uint8_t > ((255 * sum) / pop)
|
||||
return <np.uint8_t>((255 * sum) / pop)
|
||||
else:
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
cdef inline np.uint8_t kernel_gradient(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1, Py_ssize_t s0,
|
||||
Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_gradient(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef Py_ssize_t i, imin, imax
|
||||
|
||||
@@ -83,26 +84,28 @@ cdef inline np.uint8_t kernel_gradient(
|
||||
if histo[i]:
|
||||
imin = i
|
||||
break
|
||||
return < np.uint8_t > (imax - imin)
|
||||
return <np.uint8_t>(imax - imin)
|
||||
else:
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
cdef inline np.uint8_t kernel_maximum(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1, Py_ssize_t s0,
|
||||
Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_maximum(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef Py_ssize_t i
|
||||
|
||||
if pop:
|
||||
for i in range(255, -1, -1):
|
||||
if histo[i]:
|
||||
return < np.uint8_t > (i)
|
||||
return <np.uint8_t>(i)
|
||||
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
cdef inline np.uint8_t kernel_mean(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1, Py_ssize_t s0,
|
||||
Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_mean(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef Py_ssize_t i
|
||||
cdef float mean = 0.
|
||||
@@ -110,13 +113,14 @@ cdef inline np.uint8_t kernel_mean(
|
||||
if pop:
|
||||
for i in range(256):
|
||||
mean += histo[i] * i
|
||||
return < np.uint8_t > (mean / pop)
|
||||
return <np.uint8_t>(mean / pop)
|
||||
else:
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
cdef inline np.uint8_t kernel_meansubstraction(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_meansubstraction(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef Py_ssize_t i
|
||||
cdef float mean = 0.
|
||||
@@ -124,13 +128,14 @@ cdef inline np.uint8_t kernel_meansubstraction(
|
||||
if pop:
|
||||
for i in range(256):
|
||||
mean += histo[i] * i
|
||||
return < np.uint8_t > ((g - mean / pop) / 2. + 127)
|
||||
return <np.uint8_t>((g - mean / pop) / 2. + 127)
|
||||
else:
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
cdef inline np.uint8_t kernel_median(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1, Py_ssize_t s0,
|
||||
Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_median(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef Py_ssize_t i
|
||||
cdef float sum = pop / 2.0
|
||||
@@ -140,25 +145,28 @@ cdef inline np.uint8_t kernel_median(
|
||||
if histo[i]:
|
||||
sum -= histo[i]
|
||||
if sum < 0:
|
||||
return < np.uint8_t > (i)
|
||||
return <np.uint8_t>(i)
|
||||
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
cdef inline np.uint8_t kernel_minimum(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1, Py_ssize_t s0,
|
||||
Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_minimum(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef Py_ssize_t i
|
||||
|
||||
if pop:
|
||||
for i in range(256):
|
||||
if histo[i]:
|
||||
return < np.uint8_t > (i)
|
||||
return <np.uint8_t>(i)
|
||||
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
cdef inline np.uint8_t kernel_modal(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1, Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_modal(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef Py_ssize_t hmax = 0, imax = 0
|
||||
|
||||
@@ -167,13 +175,14 @@ cdef inline np.uint8_t kernel_modal(
|
||||
if histo[i] > hmax:
|
||||
hmax = histo[i]
|
||||
imax = i
|
||||
return < np.uint8_t > (imax)
|
||||
return <np.uint8_t>(imax)
|
||||
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
cdef inline np.uint8_t kernel_morph_contr_enh(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_morph_contr_enh(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef Py_ssize_t i, imin, imax
|
||||
|
||||
@@ -187,21 +196,23 @@ cdef inline np.uint8_t kernel_morph_contr_enh(
|
||||
imin = i
|
||||
break
|
||||
if imax - g < g - imin:
|
||||
return < np.uint8_t > (imax)
|
||||
return <np.uint8_t>(imax)
|
||||
else:
|
||||
return < np.uint8_t > (imin)
|
||||
return <np.uint8_t>(imin)
|
||||
else:
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
cdef inline np.uint8_t kernel_pop(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1, Py_ssize_t s0,
|
||||
Py_ssize_t s1):
|
||||
|
||||
return < np.uint8_t > (pop)
|
||||
cdef inline np.uint8_t kernel_pop(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_threshold(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1, Py_ssize_t s0,
|
||||
Py_ssize_t s1):
|
||||
return <np.uint8_t>(pop)
|
||||
|
||||
|
||||
cdef inline np.uint8_t kernel_threshold(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef Py_ssize_t i
|
||||
cdef float mean = 0.
|
||||
@@ -209,13 +220,14 @@ cdef inline np.uint8_t kernel_threshold(
|
||||
if pop:
|
||||
for i in range(256):
|
||||
mean += histo[i] * i
|
||||
return < np.uint8_t > (g > (mean / pop))
|
||||
return <np.uint8_t>(g > (mean / pop))
|
||||
else:
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
cdef inline np.uint8_t kernel_tophat(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1, Py_ssize_t s0,
|
||||
Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_tophat(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef Py_ssize_t i
|
||||
|
||||
@@ -223,64 +235,64 @@ cdef inline np.uint8_t kernel_tophat(
|
||||
if histo[i]:
|
||||
break
|
||||
|
||||
return < np.uint8_t > (i - g)
|
||||
return <np.uint8_t>(i - g)
|
||||
|
||||
cdef inline np.uint8_t kernel_noise_filter(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1, Py_ssize_t s0,
|
||||
Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_noise_filter(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef Py_ssize_t i
|
||||
cdef Py_ssize_t min_i
|
||||
|
||||
# early stop if at least one pixel of the neighborhood has the same g
|
||||
if histo[g]>0:
|
||||
return < np.uint8_t > 0
|
||||
if histo[g] > 0:
|
||||
return <np.uint8_t>0
|
||||
|
||||
for i in range(g, -1, -1):
|
||||
if histo[i]:
|
||||
break
|
||||
min_i = g-i
|
||||
min_i = g - i
|
||||
for i in range(g, 256):
|
||||
if histo[i]:
|
||||
break
|
||||
if i-g < min_i:
|
||||
return < np.uint8_t > (i-g)
|
||||
if i - g < min_i:
|
||||
return <np.uint8_t>(i - g)
|
||||
else:
|
||||
return < np.uint8_t > min_i
|
||||
return <np.uint8_t>min_i
|
||||
|
||||
cdef inline np.uint8_t kernel_entropy(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1, Py_ssize_t s0,
|
||||
Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_entropy(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef Py_ssize_t i
|
||||
cdef float e,p
|
||||
|
||||
e = 0.
|
||||
|
||||
for i in range(256):
|
||||
p = histo[i]/pop
|
||||
if p>0:
|
||||
e -= p*log2(p)
|
||||
p = histo[i] / pop
|
||||
if p > 0:
|
||||
e -= p * log2(p)
|
||||
|
||||
return < np.uint8_t > e*10
|
||||
return <np.uint8_t>e*10
|
||||
|
||||
cdef inline np.uint8_t kernel_otsu(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1, Py_ssize_t s0,
|
||||
Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_otsu(Py_ssize_t * histo, float pop, np.uint8_t g,
|
||||
float p0, float p1, Py_ssize_t s0,
|
||||
Py_ssize_t s1):
|
||||
cdef Py_ssize_t i
|
||||
cdef Py_ssize_t max_i
|
||||
cdef float P, mu1, mu2, q1,new_q1, sigma_b, max_sigma_b
|
||||
cdef float mu = 0.
|
||||
|
||||
# compute local mean
|
||||
|
||||
if pop:
|
||||
for i in range(256):
|
||||
mu += histo[i] * i
|
||||
mu = (mu / pop)
|
||||
else:
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
# maximizing the between class variance
|
||||
max_i = 0
|
||||
@@ -289,21 +301,24 @@ cdef inline np.uint8_t kernel_otsu(
|
||||
max_sigma_b = 0.
|
||||
|
||||
for i in range(1,256):
|
||||
P = histo[i]/pop
|
||||
P = histo[i] / pop
|
||||
new_q1 = q1 + P
|
||||
if new_q1>0:
|
||||
mu1 = (q1*mu1 + i*P)/new_q1
|
||||
mu2 = (mu-new_q1*mu1)/(1.-new_q1)
|
||||
sigma_b = new_q1*(1.-new_q1)*(mu1-mu2)**2
|
||||
if sigma_b>max_sigma_b:
|
||||
if new_q1 > 0:
|
||||
mu1 = (q1 * mu1 + i * P) / new_q1
|
||||
mu2 = (mu - new_q1*mu1) / (1. - new_q1)
|
||||
sigma_b = new_q1 * (1. - new_q1) * (mu1 - mu2)**2
|
||||
if sigma_b > max_sigma_b:
|
||||
max_sigma_b = sigma_b
|
||||
max_i = i
|
||||
q1 = new_q1
|
||||
|
||||
if g>max_i:
|
||||
return < np.uint8_t > 255
|
||||
if g > max_i:
|
||||
return <np.uint8_t>255
|
||||
else:
|
||||
return < np.uint8_t > 0
|
||||
return <np.uint8_t>0
|
||||
|
||||
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# python wrappers
|
||||
# used only internally
|
||||
@@ -315,9 +330,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def bottomhat(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -325,9 +339,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def equalize(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -335,9 +348,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def gradient(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -345,9 +357,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def maximum(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -355,7 +366,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def mean(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -363,7 +375,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def meansubstraction(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -371,9 +384,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def median(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -381,7 +393,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def minimum(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -389,7 +402,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def morph_contr_enh(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -397,9 +411,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def modal(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -407,7 +420,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def pop(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -415,7 +429,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def threshold(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -423,9 +438,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,
|
||||
<Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def tophat(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -433,7 +447,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def noise_filter(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -441,18 +456,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, <Py_ssize_t>0, <Py_ssize_t>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, <Py_ssize_t>0, <Py_ssize_t>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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
|
||||
import numpy as np
|
||||
cimport numpy as np
|
||||
|
||||
# import main loop
|
||||
from skimage.filter.rank._core8 cimport _core8, uint8_max, uint8_min
|
||||
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# kernels uint8 (SOFT version using percentiles)
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
cdef inline np.uint8_t kernel_autolevel(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1, Py_ssize_t s0,
|
||||
Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_autolevel(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef int i, imin, imax, sum, delta
|
||||
|
||||
if pop:
|
||||
@@ -37,16 +37,17 @@ cdef inline np.uint8_t kernel_autolevel(
|
||||
break
|
||||
delta = imax - imin
|
||||
if delta > 0:
|
||||
return < np.uint8_t > (255 * (uint8_min(uint8_max(imin, g), imax) - imin) / delta)
|
||||
return <np.uint8_t>(255 \
|
||||
* (uint8_min(uint8_max(imin, g), imax) - imin) / delta)
|
||||
else:
|
||||
return < np.uint8_t > (imax - imin)
|
||||
return <np.uint8_t>(imax - imin)
|
||||
else:
|
||||
return < np.uint8_t > (128)
|
||||
return <np.uint8_t>(128)
|
||||
|
||||
|
||||
cdef inline np.uint8_t kernel_gradient(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1, Py_ssize_t s0,
|
||||
Py_ssize_t s1):
|
||||
cdef inline np.uint8_t kernel_gradient(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef int i, imin, imax, sum, delta
|
||||
|
||||
if pop:
|
||||
@@ -64,14 +65,14 @@ cdef inline np.uint8_t kernel_gradient(
|
||||
imax = i
|
||||
break
|
||||
|
||||
return < np.uint8_t > (imax - imin)
|
||||
return <np.uint8_t>(imax - imin)
|
||||
else:
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
|
||||
cdef inline np.uint8_t kernel_mean(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1, Py_ssize_t s0,
|
||||
Py_ssize_t s1):
|
||||
cdef inline np.uint8_t kernel_mean(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef int i, sum, mean, n
|
||||
|
||||
if pop:
|
||||
@@ -84,15 +85,18 @@ cdef inline np.uint8_t kernel_mean(
|
||||
n += histo[i]
|
||||
mean += histo[i] * i
|
||||
if n > 0:
|
||||
return < np.uint8_t > (1.0 * mean / n)
|
||||
return <np.uint8_t>(1.0 * mean / n)
|
||||
else:
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
else:
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
cdef inline np.uint8_t kernel_mean_substraction(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_mean_substraction(Py_ssize_t * histo,
|
||||
float pop,
|
||||
np.uint8_t g,
|
||||
float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef int i, sum, mean, n
|
||||
|
||||
if pop:
|
||||
@@ -105,15 +109,17 @@ cdef inline np.uint8_t kernel_mean_substraction(
|
||||
n += histo[i]
|
||||
mean += histo[i] * i
|
||||
if n > 0:
|
||||
return < np.uint8_t > ((g - (mean / n)) * .5 + 127)
|
||||
return <np.uint8_t>((g - (mean / n)) * .5 + 127)
|
||||
else:
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
else:
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
cdef inline np.uint8_t kernel_morph_contr_enh(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_morph_contr_enh(Py_ssize_t * histo,
|
||||
float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef int i, imin, imax, sum, delta
|
||||
|
||||
if pop:
|
||||
@@ -131,19 +137,20 @@ cdef inline np.uint8_t kernel_morph_contr_enh(
|
||||
imax = i
|
||||
break
|
||||
if g > imax:
|
||||
return < np.uint8_t > imax
|
||||
return <np.uint8_t>imax
|
||||
if g < imin:
|
||||
return < np.uint8_t > imin
|
||||
return <np.uint8_t>imin
|
||||
if imax - g < g - imin:
|
||||
return < np.uint8_t > imax
|
||||
return <np.uint8_t>imax
|
||||
else:
|
||||
return < np.uint8_t > imin
|
||||
return <np.uint8_t>imin
|
||||
else:
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
cdef inline np.uint8_t kernel_percentile(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_percentile(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef int i
|
||||
cdef float sum = 0.
|
||||
|
||||
@@ -153,13 +160,14 @@ cdef inline np.uint8_t kernel_percentile(
|
||||
if sum >= p0 * pop:
|
||||
break
|
||||
|
||||
return < np.uint8_t > (i)
|
||||
return <np.uint8_t>(i)
|
||||
else:
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
cdef inline np.uint8_t kernel_pop(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_pop(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef int i, sum, n
|
||||
|
||||
if pop:
|
||||
@@ -169,13 +177,14 @@ cdef inline np.uint8_t kernel_pop(
|
||||
sum += histo[i]
|
||||
if (sum >= p0 * pop) and (sum <= p1 * pop):
|
||||
n += histo[i]
|
||||
return < np.uint8_t > (n)
|
||||
return <np.uint8_t>(n)
|
||||
else:
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
cdef inline np.uint8_t kernel_threshold(
|
||||
Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1, Py_ssize_t s0,
|
||||
Py_ssize_t s1):
|
||||
|
||||
cdef inline np.uint8_t kernel_threshold(Py_ssize_t * histo, float pop,
|
||||
np.uint8_t g, float p0, float p1,
|
||||
Py_ssize_t s0, Py_ssize_t s1):
|
||||
cdef int i
|
||||
cdef float sum = 0.
|
||||
|
||||
@@ -185,9 +194,10 @@ cdef inline np.uint8_t kernel_threshold(
|
||||
if sum >= p0 * pop:
|
||||
break
|
||||
|
||||
return < np.uint8_t > (255 * (g >= i))
|
||||
return <np.uint8_t>(255 * (g >= i))
|
||||
else:
|
||||
return < np.uint8_t > (0)
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# python wrappers
|
||||
@@ -201,9 +211,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,
|
||||
<Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def gradient(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -213,9 +222,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,
|
||||
<Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def mean(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -225,7 +233,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,
|
||||
<Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def mean_substraction(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -235,9 +244,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def morph_contr_enh(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -247,9 +255,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def percentile(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -259,9 +266,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, <Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def pop(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -271,7 +277,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,
|
||||
<Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
|
||||
def threshold(np.ndarray[np.uint8_t, ndim=2] image,
|
||||
@@ -281,6 +288,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,
|
||||
<Py_ssize_t>0, <Py_ssize_t>0)
|
||||
|
||||
@@ -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.")
|
||||
|
||||
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)
|
||||
|
||||
@@ -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.")
|
||||
|
||||
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)
|
||||
|
||||
+266
-209
@@ -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.")
|
||||
|
||||
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)
|
||||
return _apply(_crank8.otsu, None, image, selem, out=out,
|
||||
mask=mask, shift_x=shift_x, shift_y=shift_y)
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
import sys
|
||||
print sys.path
|
||||
import skimage
|
||||
print skimage
|
||||
|
||||
import unittest
|
||||
|
||||
import numpy as np
|
||||
from skimage.filter import rank
|
||||
|
||||
from skimage import data
|
||||
from skimage.morphology import cmorph,disk
|
||||
from skimage.filter.rank import _crank8, _crank16
|
||||
from skimage.filter.rank import _crank16_percentiles
|
||||
|
||||
|
||||
class TestSequenceFunctions(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
def test_trivial_selem(self):
|
||||
# check that min, max and mean returns identity if structuring element contains only central pixel
|
||||
|
||||
a = np.zeros((5,5),dtype='uint8')
|
||||
a[2,2] = 255
|
||||
a[2,3] = 128
|
||||
a[1,2] = 16
|
||||
elem = np.asarray([[0,0,0],[0,1,0],[0,0,0]],dtype='uint8')
|
||||
f = _crank8.mean(image=a,selem = elem,shift_x=0,shift_y=0)
|
||||
np.testing.assert_array_equal(a,f)
|
||||
f = _crank8.minimum(image=a,selem = elem,shift_x=0,shift_y=0)
|
||||
np.testing.assert_array_equal(a,f)
|
||||
f = _crank8.maximum(image=a,selem = elem,shift_x=0,shift_y=0)
|
||||
np.testing.assert_array_equal(a,f)
|
||||
|
||||
def test_smallest_selem(self):
|
||||
# check that min, max and mean returns identity if structuring element contains only central pixel
|
||||
|
||||
a = np.zeros((5,5),dtype='uint8')
|
||||
a[2,2] = 255
|
||||
a[2,3] = 128
|
||||
a[1,2] = 16
|
||||
elem = np.asarray([[1]],dtype='uint8')
|
||||
f = _crank8.mean(image=a,selem = elem,shift_x=0,shift_y=0)
|
||||
np.testing.assert_array_equal(a,f)
|
||||
f = _crank8.minimum(image=a,selem = elem,shift_x=0,shift_y=0)
|
||||
np.testing.assert_array_equal(a,f)
|
||||
f = _crank8.maximum(image=a,selem = elem,shift_x=0,shift_y=0)
|
||||
np.testing.assert_array_equal(a,f)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
|
||||
unittest.TextTestRunner(verbosity=2).run(suite)
|
||||
@@ -0,0 +1,294 @@
|
||||
import numpy as np
|
||||
from numpy.testing import run_module_suite, assert_array_equal, assert_raises
|
||||
import unittest
|
||||
|
||||
from skimage import data
|
||||
from skimage.morphology import cmorph, disk
|
||||
from skimage.filter import rank
|
||||
from skimage.filter.rank import _crank8, _crank16, _crank16_percentiles
|
||||
|
||||
|
||||
def test_random_sizes():
|
||||
# make sure the size is not a problem
|
||||
|
||||
niter = 10
|
||||
elem = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]], dtype=np.uint8)
|
||||
for m, n in np.random.random_integers(1, 100, size=(10, 2)):
|
||||
mask = np.ones((m, n), dtype=np.uint8)
|
||||
|
||||
image8 = np.ones((m, n), dtype=np.uint8)
|
||||
out8 = np.empty_like(image8)
|
||||
_crank8.mean(image=image8, selem=elem, mask=mask, out=out8,
|
||||
shift_x=0, shift_y=0)
|
||||
assert_array_equal(image8.shape, out8.shape)
|
||||
_crank8.mean(image=image8, selem=elem, mask=mask, out=out8,
|
||||
shift_x=+1, shift_y=+1)
|
||||
assert_array_equal(image8.shape, out8.shape)
|
||||
|
||||
image16 = np.ones((m, n), dtype=np.uint16)
|
||||
out16 = np.empty_like(image8, dtype=np.uint16)
|
||||
_crank16.mean(image=image16, selem=elem, mask=mask, out=out16,
|
||||
shift_x=0, shift_y=0)
|
||||
assert_array_equal(image16.shape, out16.shape)
|
||||
_crank16.mean(image=image16, selem=elem, mask=mask, out=out16,
|
||||
shift_x=+1, shift_y=+1)
|
||||
assert_array_equal(image16.shape, out16.shape)
|
||||
|
||||
_crank16_percentiles.mean(image=image16, mask=mask, out=out16,
|
||||
selem=elem, shift_x=0, shift_y=0, p0=.1, p1=.9)
|
||||
assert_array_equal(image16.shape, out16.shape)
|
||||
_crank16_percentiles.mean(image=image16, mask=mask, out=out16,
|
||||
selem=elem, shift_x=+1, shift_y=+1, p0=.1, p1=.9)
|
||||
assert_array_equal(image16.shape, out16.shape)
|
||||
|
||||
|
||||
def test_compare_with_cmorph_dilate():
|
||||
# compare the result of maximum filter with dilate
|
||||
|
||||
image = (np.random.random((100, 100)) * 256).astype(np.uint8)
|
||||
out = np.empty_like(image)
|
||||
mask = np.ones(image.shape, dtype=np.uint8)
|
||||
|
||||
for r in range(1, 20, 1):
|
||||
elem = np.ones((r, r), dtype=np.uint8)
|
||||
_crank8.maximum(image=image, selem=elem, out=out, mask=mask)
|
||||
cm = cmorph.dilate(image=image, selem=elem)
|
||||
assert_array_equal(out, cm)
|
||||
|
||||
|
||||
def test_compare_with_cmorph_erode():
|
||||
# compare the result of maximum filter with erode
|
||||
|
||||
image = (np.random.random((100, 100)) * 256).astype(np.uint8)
|
||||
out = np.empty_like(image)
|
||||
mask = np.ones(image.shape, dtype=np.uint8)
|
||||
|
||||
for r in range(1, 20, 1):
|
||||
elem = np.ones((r, r), dtype=np.uint8)
|
||||
_crank8.minimum(image=image, selem=elem, out=out, mask=mask)
|
||||
cm = cmorph.erode(image=image, selem=elem)
|
||||
assert_array_equal(out, cm)
|
||||
|
||||
|
||||
def test_bitdepth():
|
||||
# test the different bit depth for rank16
|
||||
|
||||
elem = np.ones((3, 3), dtype=np.uint8)
|
||||
out = np.empty((100, 100), dtype=np.uint16)
|
||||
mask = np.ones((100, 100), dtype=np.uint8)
|
||||
|
||||
for i in range(5):
|
||||
image = np.ones((100, 100),dtype=np.uint16) * 255 * 2**i
|
||||
r = _crank16_percentiles.mean(image=image, selem=elem, mask=mask,
|
||||
out=out, shift_x=0, shift_y=0, p0=.1, p1=.9, bitdepth=8 + i)
|
||||
|
||||
|
||||
def test_population():
|
||||
# check the number of valid pixels in the neighborhood
|
||||
|
||||
image = np.zeros((5, 5), dtype=np.uint8)
|
||||
elem = np.ones((3, 3), dtype=np.uint8)
|
||||
out = np.empty_like(image)
|
||||
mask = np.ones(image.shape, dtype=np.uint8)
|
||||
|
||||
_crank8.pop(image=image, selem=elem, out=out, mask=mask)
|
||||
r = np.array([[4, 6, 6, 6, 4],
|
||||
[6, 9, 9, 9, 6],
|
||||
[6, 9, 9, 9, 6],
|
||||
[6, 9, 9, 9, 6],
|
||||
[4, 6, 6, 6, 4]])
|
||||
assert_array_equal(r, out)
|
||||
|
||||
|
||||
def test_structuring_element8():
|
||||
# check the output for a custom structuring element
|
||||
|
||||
r = np.array([[ 0, 0, 0, 0, 0, 0],
|
||||
[ 0, 0, 0, 0, 0, 0],
|
||||
[ 0, 0, 255, 0, 0, 0],
|
||||
[ 0, 0, 255, 255, 255, 0],
|
||||
[ 0, 0, 0, 255, 255, 0],
|
||||
[ 0, 0, 0, 0, 0, 0]])
|
||||
|
||||
# 8bit
|
||||
image = np.zeros((6, 6), dtype=np.uint8)
|
||||
image[2, 2] = 255
|
||||
elem = np.asarray([[1, 1, 0], [1, 1, 1], [0, 0, 1]], dtype=np.uint8)
|
||||
out = np.empty_like(image)
|
||||
mask = np.ones(image.shape, dtype=np.uint8)
|
||||
|
||||
_crank8.maximum(image=image, selem=elem, out=out, mask=mask,
|
||||
shift_x=1, shift_y=1)
|
||||
assert_array_equal(r, out)
|
||||
|
||||
# 16bit
|
||||
image = np.zeros((6, 6), dtype=np.uint16)
|
||||
image[2, 2] = 255
|
||||
out = np.empty_like(image)
|
||||
|
||||
_crank16.maximum(image=image, selem=elem, out=out, mask=mask,
|
||||
shift_x=1, shift_y=1)
|
||||
assert_array_equal(r, out)
|
||||
|
||||
|
||||
def test_fail_on_bitdepth():
|
||||
# should fail because data bitdepth is too high for the function
|
||||
|
||||
image = np.ones((100, 100), dtype=np.uint16) * 255
|
||||
elem = np.ones((3, 3), dtype=np.uint8)
|
||||
out = np.empty_like(image)
|
||||
mask = np.ones(image.shape, dtype=np.uint8)
|
||||
assert_raises(AssertionError, _crank16_percentiles.mean, image=image,
|
||||
selem=elem, out=out, mask=mask, shift_x=0, shift_y=0, bitdepth=4)
|
||||
|
||||
|
||||
def test_inplace_output():
|
||||
# rank filters are not supposed to filter inplace
|
||||
|
||||
selem = disk(20)
|
||||
image = (np.random.random((500,500))*256).astype(np.uint8)
|
||||
out = image
|
||||
assert_raises(NotImplementedError, rank.mean, image, selem, out=out)
|
||||
|
||||
|
||||
def test_compare_autolevels():
|
||||
# compare autolevel and percentile autolevel with p0=0.0 and p1=1.0
|
||||
# should returns the same arrays
|
||||
|
||||
image = data.camera()
|
||||
|
||||
selem = disk(20)
|
||||
loc_autolevel = rank.autolevel(image, selem=selem)
|
||||
loc_perc_autolevel = rank.percentile_autolevel(image, selem=selem,
|
||||
p0=.0, p1=1.)
|
||||
|
||||
assert_array_equal(loc_autolevel, loc_perc_autolevel)
|
||||
|
||||
|
||||
def test_compare_autolevels_16bit():
|
||||
# compare autolevel(16bit) and percentile autolevel(16bit) with p0=0.0 and
|
||||
# p1=1.0 should returns the same arrays
|
||||
|
||||
image = data.camera().astype(np.uint16) * 4
|
||||
|
||||
selem = disk(20)
|
||||
loc_autolevel = rank.autolevel(image, selem=selem)
|
||||
loc_perc_autolevel = rank.percentile_autolevel(image, selem=selem,
|
||||
p0=.0, p1=1.)
|
||||
|
||||
assert_array_equal(loc_autolevel, loc_perc_autolevel)
|
||||
|
||||
|
||||
def test_compare_8bit_vs_16bit():
|
||||
# filters applied on 8bit image ore 16bit image (having only real 8bit of
|
||||
# dynamic) should be identical
|
||||
|
||||
image8 = data.camera()
|
||||
image16 = image8.astype(np.uint16)
|
||||
assert_array_equal(image8, image16)
|
||||
|
||||
methods = ['autolevel', 'bottomhat', 'equalize', 'gradient', 'maximum',
|
||||
'mean', 'meansubstraction', 'median', 'minimum', 'modal',
|
||||
'morph_contr_enh', 'pop', 'threshold', 'tophat']
|
||||
|
||||
for method in methods:
|
||||
func = getattr(rank, method)
|
||||
f8 = func(image8, disk(3))
|
||||
f16 = func(image16, disk(3))
|
||||
assert_array_equal(f8, f16)
|
||||
|
||||
|
||||
def test_trivial_selem8():
|
||||
# check that min, max and mean returns identity if structuring element
|
||||
# contains only central pixel
|
||||
|
||||
image = np.zeros((5, 5), dtype=np.uint8)
|
||||
out = np.zeros_like(image)
|
||||
mask = np.ones_like(image, dtype=np.uint8)
|
||||
image[2,2] = 255
|
||||
image[2,3] = 128
|
||||
image[1,2] = 16
|
||||
|
||||
elem = np.array([[0, 0, 0], [0, 1, 0],[0, 0, 0]], dtype=np.uint8)
|
||||
_crank8.mean(image=image, selem=elem, out=out, mask=mask,
|
||||
shift_x=0, shift_y=0)
|
||||
assert_array_equal(image, out)
|
||||
_crank8.minimum(image=image, selem=elem, out=out, mask=mask,
|
||||
shift_x=0, shift_y=0)
|
||||
assert_array_equal(image, out)
|
||||
_crank8.maximum(image=image, selem=elem, out=out, mask=mask,
|
||||
shift_x=0, shift_y=0)
|
||||
assert_array_equal(image, out)
|
||||
|
||||
|
||||
def test_trivial_selem16():
|
||||
# check that min, max and mean returns identity if structuring element
|
||||
# contains only central pixel
|
||||
|
||||
image = np.zeros((5, 5), dtype=np.uint16)
|
||||
out = np.zeros_like(image)
|
||||
mask = np.ones_like(image, dtype=np.uint8)
|
||||
image[2,2] = 255
|
||||
image[2,3] = 128
|
||||
image[1,2] = 16
|
||||
|
||||
elem = np.array([[0, 0, 0], [0, 1, 0],[0, 0, 0]], dtype=np.uint8)
|
||||
_crank16.mean(image=image, selem=elem, out=out, mask=mask,
|
||||
shift_x=0, shift_y=0)
|
||||
assert_array_equal(image, out)
|
||||
_crank16.minimum(image=image, selem=elem, out=out, mask=mask,
|
||||
shift_x=0, shift_y=0)
|
||||
assert_array_equal(image, out)
|
||||
_crank16.maximum(image=image, selem=elem, out=out, mask=mask,
|
||||
shift_x=0, shift_y=0)
|
||||
assert_array_equal(image, out)
|
||||
|
||||
|
||||
def test_smallest_selem8():
|
||||
# check that min, max and mean returns identity if structuring element
|
||||
# contains only central pixel
|
||||
|
||||
image = np.zeros((5, 5), dtype=np.uint8)
|
||||
out = np.zeros_like(image)
|
||||
mask = np.ones_like(image, dtype=np.uint8)
|
||||
image[2,2] = 255
|
||||
image[2,3] = 128
|
||||
image[1,2] = 16
|
||||
|
||||
elem = np.array([[1]], dtype=np.uint8)
|
||||
_crank8.mean(image=image, selem=elem, out=out, mask=mask,
|
||||
shift_x=0, shift_y=0)
|
||||
assert_array_equal(image, out)
|
||||
_crank8.minimum(image=image, selem=elem, out=out, mask=mask,
|
||||
shift_x=0, shift_y=0)
|
||||
assert_array_equal(image, out)
|
||||
_crank8.maximum(image=image, selem=elem, out=out, mask=mask,
|
||||
shift_x=0, shift_y=0)
|
||||
assert_array_equal(image, out)
|
||||
|
||||
|
||||
def test_smallest_selem16():
|
||||
# check that min, max and mean returns identity if structuring element
|
||||
# contains only central pixel
|
||||
|
||||
image = np.zeros((5, 5), dtype=np.uint16)
|
||||
out = np.zeros_like(image)
|
||||
mask = np.ones_like(image, dtype=np.uint8)
|
||||
image[2,2] = 255
|
||||
image[2,3] = 128
|
||||
image[1,2] = 16
|
||||
|
||||
elem = np.array([[1]], dtype=np.uint8)
|
||||
_crank16.mean(image=image, selem=elem, out=out, mask=mask,
|
||||
shift_x=0, shift_y=0)
|
||||
assert_array_equal(image, out)
|
||||
_crank16.minimum(image=image, selem=elem, out=out, mask=mask,
|
||||
shift_x=0, shift_y=0)
|
||||
assert_array_equal(image, out)
|
||||
_crank16.maximum(image=image, selem=elem, out=out, mask=mask,
|
||||
shift_x=0, shift_y=0)
|
||||
assert_array_equal(image, out)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_module_suite()
|
||||
@@ -1,191 +0,0 @@
|
||||
import sys
|
||||
print sys.path
|
||||
import skimage
|
||||
print skimage
|
||||
|
||||
import unittest
|
||||
|
||||
import numpy as np
|
||||
from skimage.filter import rank
|
||||
|
||||
from skimage import data
|
||||
from skimage.morphology import cmorph,disk
|
||||
from skimage.filter.rank import _crank8, _crank16
|
||||
from skimage.filter.rank import _crank16_percentiles
|
||||
|
||||
|
||||
class TestSequenceFunctions(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
def test_random_sizes(self):
|
||||
# make sure the size is not a problem
|
||||
|
||||
niter = 10
|
||||
elem = np.asarray([[1,1,1],[1,1,1],[1,1,1]],dtype='uint8')
|
||||
for m,n in np.random.random_integers(1,100,size=(10,2)):
|
||||
a8 = np.ones((m,n),dtype='uint8')
|
||||
r = _crank8.mean(image=a8,selem = elem,shift_x=0,shift_y=0)
|
||||
self.assertTrue(a8.shape == r.shape)
|
||||
r = _crank8.mean(image=a8,selem = elem,shift_x=+1,shift_y=+1)
|
||||
self.assertTrue(a8.shape == r.shape)
|
||||
|
||||
for m,n in np.random.random_integers(1,100,size=(10,2)):
|
||||
a16 = np.ones((m,n),dtype='uint16')
|
||||
r = _crank16.mean(image=a16,selem = elem,shift_x=0,shift_y=0)
|
||||
self.assertTrue(a16.shape == r.shape)
|
||||
r = _crank16.mean(image=a16,selem = elem,shift_x=+1,shift_y=+1)
|
||||
self.assertTrue(a16.shape == r.shape)
|
||||
|
||||
for m,n in np.random.random_integers(1,100,size=(10,2)):
|
||||
a16 = np.ones((m,n),dtype='uint16')
|
||||
r = _crank16_percentiles.mean(image=a16,selem = elem,shift_x=0,shift_y=0,p0=.1,p1=.9)
|
||||
self.assertTrue(a16.shape == r.shape)
|
||||
r = _crank16_percentiles.mean(image=a16,selem = elem,shift_x=+1,shift_y=+1,p0=.1,p1=.9)
|
||||
self.assertTrue(a16.shape == r.shape)
|
||||
|
||||
def test_compare_with_cmorph_dilate(self):
|
||||
#compare the result of maximum filter with dilate
|
||||
|
||||
a = (np.random.random((500,500))*256).astype('uint8')
|
||||
|
||||
for r in range(1,20,1):
|
||||
elem = np.ones((r,r),dtype='uint8')
|
||||
# elem = (np.random.random((r,r))>.5).astype('uint8')
|
||||
rc = _crank8.maximum(image=a,selem = elem)
|
||||
cm = cmorph.dilate(image=a,selem = elem)
|
||||
self.assertTrue((rc==cm).all())
|
||||
|
||||
def test_compare_with_cmorph_erode(self):
|
||||
#compare the result of maximum filter with erode
|
||||
|
||||
a = (np.random.random((500,500))*256).astype('uint8')
|
||||
|
||||
for r in range(1,20,1):
|
||||
elem = np.ones((r,r),dtype='uint8')
|
||||
# elem = (np.random.random((r,r))>.5).astype('uint8')
|
||||
rc = _crank8.minimum(image=a,selem = elem)
|
||||
cm = cmorph.erode(image=a,selem = elem)
|
||||
self.assertTrue((rc==cm).all())
|
||||
|
||||
def test_bitdepth(self):
|
||||
# test the different bit depth for rank16
|
||||
|
||||
elem = np.ones((3,3),dtype='uint8')
|
||||
a16 = np.ones((100,100),dtype='uint16')*255
|
||||
r = _crank16_percentiles.mean(image=a16,selem = elem,shift_x=0,shift_y=0,p0=.1,p1=.9,bitdepth=8)
|
||||
a16 = np.ones((100,100),dtype='uint16')*255*2
|
||||
r = _crank16_percentiles.mean(image=a16,selem = elem,shift_x=0,shift_y=0,p0=.1,p1=.9,bitdepth=9)
|
||||
a16 = np.ones((100,100),dtype='uint16')*255*4
|
||||
r = _crank16_percentiles.mean(image=a16,selem = elem,shift_x=0,shift_y=0,p0=.1,p1=.9,bitdepth=10)
|
||||
a16 = np.ones((100,100),dtype='uint16')*255*8
|
||||
r = _crank16_percentiles.mean(image=a16,selem = elem,shift_x=0,shift_y=0,p0=.1,p1=.9,bitdepth=11)
|
||||
a16 = np.ones((100,100),dtype='uint16')*255*16
|
||||
r = _crank16_percentiles.mean(image=a16,selem = elem,shift_x=0,shift_y=0,p0=.1,p1=.9,bitdepth=12)
|
||||
|
||||
def test_population(self):
|
||||
# check the number of valid pixels in the neighborhood
|
||||
|
||||
a = np.zeros((5,5),dtype='uint8')
|
||||
elem = np.ones((3,3),dtype='uint8')
|
||||
p = _crank8.pop(image=a,selem = elem)
|
||||
r = np.asarray([[4, 6, 6, 6, 4],
|
||||
[6, 9, 9, 9, 6],
|
||||
[6, 9, 9, 9, 6],
|
||||
[6, 9, 9, 9, 6],
|
||||
[4, 6, 6, 6, 4]])
|
||||
np.testing.assert_array_equal(r,p)
|
||||
|
||||
def test_structuring_element(self):
|
||||
# check the output for a custom structuring element
|
||||
|
||||
a = np.zeros((6,6),dtype='uint8')
|
||||
a[2,2] = 255
|
||||
elem = np.asarray([[1,1,0],[1,1,1],[0,0,1]],dtype='uint8')
|
||||
f = _crank8.maximum(image=a,selem = elem,shift_x=1,shift_y=1)
|
||||
r = np.asarray([[ 0, 0, 0, 0, 0, 0],
|
||||
[ 0, 0, 0, 0, 0, 0],
|
||||
[ 0, 0, 255, 0, 0, 0],
|
||||
[ 0, 0, 255, 255, 255, 0],
|
||||
[ 0, 0, 0, 255, 255, 0],
|
||||
[ 0, 0, 0, 0, 0, 0]])
|
||||
np.testing.assert_array_equal(r,f)
|
||||
|
||||
|
||||
@unittest.expectedFailure
|
||||
def test_fail_on_bitdepth(self):
|
||||
# should fail because data bitdepth is too high for the function
|
||||
|
||||
a16 = np.ones((100,100),dtype='uint16')*255
|
||||
elem = np.ones((3,3),dtype='uint8')
|
||||
f = _crank16_percentiles.mean(image=a16,selem = elem,shift_x=0,shift_y=0,p0=.1,p1=.9,bitdepth=4)
|
||||
|
||||
def test_output(self):
|
||||
#check rank function with external OUT output array
|
||||
|
||||
selem = disk(20)
|
||||
a = (np.random.random((500,500))*256).astype('uint8')
|
||||
out = np.zeros_like(a)
|
||||
f1 = rank.mean(a,selem,out=out)
|
||||
f2 = rank.mean(a,selem)
|
||||
np.testing.assert_array_equal(f1,f2)
|
||||
np.testing.assert_array_equal(out,f2)
|
||||
|
||||
@unittest.expectedFailure
|
||||
def test_inplace_output(self):
|
||||
#rank filters are not supposed to filter inplace
|
||||
|
||||
selem = disk(20)
|
||||
a = (np.random.random((500,500))*256).astype('uint8')
|
||||
out = a
|
||||
f = rank.mean(a,selem,out=out)
|
||||
np.testing.assert_array_equal(f,out)
|
||||
|
||||
|
||||
def test_compare_autolevels(self):
|
||||
# compare autolevel and percentile autolevel with p0=0.0 and p1=1.0
|
||||
# should returns the same arrays
|
||||
|
||||
image = data.camera()
|
||||
|
||||
selem = disk(20)
|
||||
loc_autolevel = rank.autolevel(image,selem=selem)
|
||||
loc_perc_autolevel = rank.percentile_autolevel(image,selem=selem,p0=.0,p1=1.)
|
||||
|
||||
assert (loc_autolevel==loc_perc_autolevel).all()
|
||||
|
||||
def test_compare_autolevels_16bit(self):
|
||||
# compare autolevel(16bit) and percentile autolevel(16bit) with p0=0.0 and p1=1.0
|
||||
# should returns the same arrays
|
||||
|
||||
image = data.camera().astype(np.uint16)*4
|
||||
|
||||
selem = disk(20)
|
||||
loc_autolevel = rank.autolevel(image,selem=selem)
|
||||
loc_perc_autolevel = rank.percentile_autolevel(image,selem=selem,p0=.0,p1=1.)
|
||||
|
||||
assert (loc_autolevel==loc_perc_autolevel).all()
|
||||
|
||||
def test_compare_8bit_vs_16bit(self):
|
||||
# filters applied on 8bit image ore 16bit image (having only real 8bit of dynamic)
|
||||
# should be identical
|
||||
|
||||
i8 = data.camera()
|
||||
i16 = i8.astype(np.uint16)
|
||||
assert (i8==i16).all()
|
||||
|
||||
methods = ['autolevel','bottomhat','equalize','gradient','maximum','mean'
|
||||
,'meansubstraction','median','minimum','modal','morph_contr_enh','pop','threshold', 'tophat']
|
||||
|
||||
for method in methods:
|
||||
func = eval('rank.%s'%method)
|
||||
f8 = func(i8,disk(3))
|
||||
f16 = func(i16,disk(3))
|
||||
assert (f8==f16).all()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
|
||||
unittest.TextTestRunner(verbosity=2).run(suite)
|
||||
Reference in New Issue
Block a user