diff --git a/skimage/filter/rank/__init__.py b/skimage/filter/rank/__init__.py index 361e400e..9a31a565 100644 --- a/skimage/filter/rank/__init__.py +++ b/skimage/filter/rank/__init__.py @@ -4,7 +4,7 @@ from .generic import (autolevel, bottomhat, equalize, gradient, maximum, mean, from ._percentile import (autolevel_percentile, gradient_percentile, mean_percentile, subtract_mean_percentile, enhance_contrast_percentile, percentile, - pop_percentile, threshold_percentile) + pop_percentile,sum_percentile, threshold_percentile) from .bilateral import mean_bilateral, pop_bilateral from skimage._shared.utils import deprecated diff --git a/skimage/filter/rank/_percentile.py b/skimage/filter/rank/_percentile.py index ff3b1559..7f24e3e0 100644 --- a/skimage/filter/rank/_percentile.py +++ b/skimage/filter/rank/_percentile.py @@ -310,6 +310,42 @@ def pop_percentile(image, selem, out=None, mask=None, shift_x=False, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, p0=p0, p1=p1) +def sum_percentile(image, selem, out=None, mask=None, shift_x=False, + shift_y=False, p0=0, p1=1): + """Return greyscale local sum of an image. + + sum is computed on the given structuring element. Only levels between + percentiles [p0, p1] are used. result is truncated (8bit or 16bit). + + Parameters + ---------- + image : ndarray (uint8, uint16) + Image array. + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray (same dtype as input) + If None, a new array will be allocated. + mask : ndarray + 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 + ------- + out : ndarray (same dtype as input image) + Output image. + + """ + + return _apply(percentile_cy._sum, + image, selem, out=out, mask=mask, shift_x=shift_x, + shift_y=shift_y, p0=p0, p1=p1) def threshold_percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=0): diff --git a/skimage/filter/rank/percentile_cy.pyx b/skimage/filter/rank/percentile_cy.pyx index e951a76e..bd0cbe53 100644 --- a/skimage/filter/rank/percentile_cy.pyx +++ b/skimage/filter/rank/percentile_cy.pyx @@ -90,6 +90,29 @@ cdef inline double _kernel_mean(Py_ssize_t* histo, double pop, dtype_t g, else: return 0 +cdef inline double _kernel_sum(Py_ssize_t* histo, double pop, dtype_t g, + Py_ssize_t max_bin, Py_ssize_t mid_bin, + double p0, double p1, + Py_ssize_t s0, Py_ssize_t s1): + + cdef Py_ssize_t i, sum, sum_g, n + + if pop: + sum = 0 + sum_g = 0 + n = 0 + for i in range(max_bin): + sum += histo[i] + if (sum >= p0 * pop) and (sum <= p1 * pop): + n += histo[i] + sum_g += histo[i] * i + + if n > 0: + return sum_g + else: + return 0 + else: + return 0 cdef inline double _kernel_subtract_mean(Py_ssize_t* histo, double pop, dtype_t g, @@ -245,6 +268,15 @@ def _mean(dtype_t[:, ::1] image, _core(_kernel_mean[dtype_t], image, selem, mask, out, shift_x, shift_y, p0, p1, 0, 0, max_bin) +def _sum(dtype_t[:, ::1] image, + char[:, ::1] selem, + char[:, ::1] mask, + dtype_t_out[:, ::1] out, + char shift_x, char shift_y, double p0, double p1, + Py_ssize_t max_bin): + + _core(_kernel_sum[dtype_t], image, selem, mask, out, + shift_x, shift_y, p0, p1, 0, 0, max_bin) def _subtract_mean(dtype_t[:, ::1] image, char[:, ::1] selem, diff --git a/skimage/filter/rank/tests/test_rank.py b/skimage/filter/rank/tests/test_rank.py index 26aa43ed..b3de866a 100644 --- a/skimage/filter/rank/tests/test_rank.py +++ b/skimage/filter/rank/tests/test_rank.py @@ -530,9 +530,41 @@ def test_sum(): [3, 6, 9, 6, 3], [2, 4, 6, 4, 2], [1, 2, 3, 2, 1]], dtype=np.uint16) - print image16 assert_array_equal(r, out16) +def test_sum_percentile(): + # check the number of valid pixels in the neighborhood + + image8 = np.array([[0, 0, 0, 0, 0], + [0, 1, 1, 1, 0], + [0, 1, 1, 1, 0], + [0, 1, 1, 1, 0], + [0, 0, 0, 0, 0]], dtype=np.uint8) + image16 = 400*np.array([[0, 0, 0, 0, 0], + [0, 1, 1, 1, 0], + [0, 1, 1, 1, 0], + [0, 1, 1, 1, 0], + [0, 0, 0, 0, 0]], dtype=np.uint16) + elem = np.ones((3, 3), dtype=np.uint8) + out8 = np.empty_like(image8) + out16 = np.empty_like(image16) + mask = np.ones(image16.shape, dtype=np.uint8) + + rank.sum_percentile(image=image8, selem=elem, out=out8, mask=mask,p0=.0,p1=1.) + r = np.array([[1, 2, 3, 2, 1], + [2, 4, 6, 4, 2], + [3, 6, 9, 6, 3], + [2, 4, 6, 4, 2], + [1, 2, 3, 2, 1]], dtype=np.uint8) + assert_array_equal(r, out8) + + rank.sum_percentile(image=image16, selem=elem, out=out16, mask=mask,p0=.0,p1=1.) + r = 400* np.array([[1, 2, 3, 2, 1], + [2, 4, 6, 4, 2], + [3, 6, 9, 6, 3], + [2, 4, 6, 4, 2], + [1, 2, 3, 2, 1]], dtype=np.uint16) + assert_array_equal(r, out16) if __name__ == "__main__": run_module_suite()