From f3c89c5364cced2311ba9f724c83d7bfa7a7b1bc Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 11:32:33 +0200 Subject: [PATCH 01/86] fix. gitignore --- .gitignore | 1 + skimage/rank/app.log | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 skimage/rank/app.log diff --git a/.gitignore b/.gitignore index 925e5886..2623ea74 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ doc/source/auto_examples/images/thumb doc/source/auto_examples/applications/ doc/source/_static/random.js .idea/ +*.log diff --git a/skimage/rank/app.log b/skimage/rank/app.log deleted file mode 100644 index 7eae20f5..00000000 --- a/skimage/rank/app.log +++ /dev/null @@ -1 +0,0 @@ -2012-10-04 09:12:19,785 MainProcess 5265 start logging in app.log From cbd1ec0c5fa5a7d7dd891a5ad7f8746e7f78de7f Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 16:09:56 +0200 Subject: [PATCH 02/86] add test/ --- skimage/rank/__init__.py | 2 +- skimage/rank/core.pxd | 1 - skimage/rank/test/test_16bitbilateral.py | 23 +++++ skimage/rank/test/test_benchmark.py | 72 ++++++++++++++ skimage/rank/{app.py => test/test_suite.py} | 101 ++------------------ skimage/rank/{ => test}/tools.py | 10 -- 6 files changed, 104 insertions(+), 105 deletions(-) create mode 100644 skimage/rank/test/test_16bitbilateral.py create mode 100644 skimage/rank/test/test_benchmark.py rename skimage/rank/{app.py => test/test_suite.py} (59%) rename skimage/rank/{ => test}/tools.py (78%) diff --git a/skimage/rank/__init__.py b/skimage/rank/__init__.py index bcc43cdc..8b0e3f5b 100644 --- a/skimage/rank/__init__.py +++ b/skimage/rank/__init__.py @@ -1 +1 @@ -from .rank import * +from .crank import * diff --git a/skimage/rank/core.pxd b/skimage/rank/core.pxd index 72facde3..bb57aec4 100644 --- a/skimage/rank/core.pxd +++ b/skimage/rank/core.pxd @@ -18,7 +18,6 @@ from libc.stdlib cimport malloc, free 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 - #--------------------------------------------------------------------------- # 8 bit core kernel #--------------------------------------------------------------------------- diff --git a/skimage/rank/test/test_16bitbilateral.py b/skimage/rank/test/test_16bitbilateral.py new file mode 100644 index 00000000..ac078b09 --- /dev/null +++ b/skimage/rank/test/test_16bitbilateral.py @@ -0,0 +1,23 @@ +import numpy as np +import matplotlib.pyplot as plt + +from skimage import data +from skimage.rank import crank_percentiles,crank16_bilateral + +if __name__ == '__main__': + a8 = (data.coins()).astype('uint8') + + a16 = (data.coins()).astype('uint16')*16 + selem = np.ones((20,20),dtype='uint8') + f1 = crank_percentiles.mean(a8,selem = selem,p0=.1,p1=.9) + f2 = crank16_bilateral.mean(a16,selem = selem,bitdepth=12,s0=500,s1=500) + + plt.figure() + plt.imshow(np.hstack((a8,f1))) + plt.colorbar() + + plt.figure() + plt.imshow(np.hstack((a16,f2))) + plt.colorbar() + + plt.show() diff --git a/skimage/rank/test/test_benchmark.py b/skimage/rank/test/test_benchmark.py new file mode 100644 index 00000000..4fee48c1 --- /dev/null +++ b/skimage/rank/test/test_benchmark.py @@ -0,0 +1,72 @@ +import numpy as np +import matplotlib.pyplot as plt + +from skimage import data +from skimage.morphology import cmorph +from skimage.rank import crank + +from tools import log_timing + +@log_timing +def cr_max(image,selem): + return crank.maximum(image=image,selem = selem) + +@log_timing +def cm_dil(image,selem): + return cmorph.dilate(image=image,selem = selem) + + +def compare(): + """comparison between + - crank.maximum rankfilter implementation + - cmorph.dilate cython implementation + on increasing structuring element size and increasing image size + """ +# a = (np.random.random((500,500))*256).astype('uint8') + a = data.camera() + + rec = [] + e_range = range(1,20,1) + for r in e_range: + elem = np.ones((r,r),dtype='uint8') + # elem = (np.random.random((r,r))>.5).astype('uint8') + rc,ms_rc = cr_max(a,elem) + rcm,ms_rcm = cm_dil(a,elem) + rec.append((ms_rc,ms_rcm)) + # check if results are identical + assert (rc==rcm).all() + + rec = np.asarray(rec) + + plt.figure() + plt.title('increasing element size') + plt.plot(e_range,rec) + plt.legend(['crank.maximum','cmorph.dilate']) + plt.figure() + plt.imshow(np.hstack((rc,rcm))) + + r = 9 + elem = np.ones((r,r),dtype='uint8') + + rec = [] + s_range = range(100,1000,100) + for s in s_range: + a = (np.random.random((s,s))*256).astype('uint8') + (rc,ms_rc) = cr_max(a,elem) + (rcm,ms_rcm) = cm_dil(a,elem) + rec.append((ms_rc,ms_rcm)) + assert (rc==rcm).all() + + rec = np.asarray(rec) + + plt.figure() + plt.title('increasing image size') + plt.plot(s_range,rec) + plt.legend(['crank.maximum','cmorph.dilate']) + plt.figure() + plt.imshow(np.hstack((rc,rcm))) + + plt.show() + +if __name__ == '__main__': + compare() \ No newline at end of file diff --git a/skimage/rank/app.py b/skimage/rank/test/test_suite.py similarity index 59% rename from skimage/rank/app.py rename to skimage/rank/test/test_suite.py index 0cf24408..61ceab48 100644 --- a/skimage/rank/app.py +++ b/skimage/rank/test/test_suite.py @@ -1,73 +1,10 @@ import unittest import numpy as np -from time import time -import matplotlib.pyplot as plt -from skimage import data -from tools import log_timing,init_logger +from skimage.rank import crank,crank16,crank16_bilateral,crank16_percentiles,crank_percentiles +from skimage.morphology import cmorph -import crank -import crank16 -import crank_percentiles -import crank16_percentiles -import crank16_bilateral -from cmorph import dilate - - -@log_timing -def c_max(image,selem): - return crank.maximum(image=image,selem = selem) - -@log_timing -def cm_max(image,selem): - return dilate(image=image,selem = selem) - -def compare(): - """comparison between - - Cython maximum rankfilter implementation - - weaves maximum rankfilter implementation - - cmorph.dilate cython implementation - on increasing structuring element size and increasing image size - """ - a = (np.random.random((500,500))*256).astype('uint8') - - rec = [] - for r in range(1,20,1): - elem = np.ones((r,r),dtype='uint8') - # elem = (np.random.random((r,r))>.5).astype('uint8') - (rc,ms_rc) = c_max(a,elem) - (rcm,ms_rcm) = cm_max(a,elem) - rec.append((ms_rc,ms_rw,ms_rcm)) - assert (rc==rcm).all() - - rec = np.asarray(rec) - - plt.plot(rec) - plt.legend(['sliding cython','sliding weaves','cmorph']) - plt.figure() - plt.imshow(np.hstack((rc,rw,rcm))) - - r = 9 - elem = np.ones((r,r),dtype='uint8') - - rec = [] - for s in range(100,1000,100): - a = (np.random.random((s,s))*256).astype('uint8') - (rc,ms_rc) = c_max(a,elem) - (rcm,ms_rcm) = cm_max(a,elem) - rec.append((ms_rc,ms_rw,ms_rcm)) - assert (rc==rcm).all() - - rec = np.asarray(rec) - - plt.figure() - plt.plot(rec) - plt.legend(['sliding cython','sliding weaves','cmorph']) - plt.figure() - plt.imshow(np.hstack((rc,rcm))) - - plt.show() class TestSequenceFunctions(unittest.TestCase): def setUp(self): @@ -106,7 +43,7 @@ class TestSequenceFunctions(unittest.TestCase): elem = np.ones((r,r),dtype='uint8') # elem = (np.random.random((r,r))>.5).astype('uint8') rc = crank.maximum(image=a,selem = elem) - cm = dilate(image=a,selem = elem) + cm = cmorph.dilate(image=a,selem = elem) self.assertTrue((rc==cm).all()) def test_bitdepth(self): @@ -139,11 +76,11 @@ class TestSequenceFunctions(unittest.TestCase): elem = np.asarray([[1,1,0],[1,1,1],[0,0,1]],dtype='uint8') f = crank.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]]) + [ 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) @@ -156,27 +93,5 @@ class TestSequenceFunctions(unittest.TestCase): if __name__ == '__main__': - logger = init_logger('app.log') - -# unittest.main() suite = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions) unittest.TextTestRunner(verbosity=2).run(suite) - - -# compare() - -# a = (data.coins()).astype('uint8') - a8 = (data.coins()).astype('uint8') - a = (data.coins()).astype('uint16')*16 - selem = np.ones((20,20),dtype='uint8') -# f1 = filter.soft_gradient(a,struct_elem = selem,bitDepth=8,infSup=[.1,.9]) -# f2 = crank16.bottomhat(a,selem = selem,bitdepth=12) - f1 = crank_percentiles.mean(a8,selem = selem,p0=.1,p1=.9) -# f2 = crank16_percentiles.mean(a,selem = selem,bitdepth=12,p0=.1,p1=.9) - f2 = crank16_bilateral.mean(a,selem = selem,bitdepth=12,s0=500,s1=500) -# plt.imshow(f2) - plt.imshow(np.hstack((a,f2))) - plt.colorbar() - plt.show() - - diff --git a/skimage/rank/tools.py b/skimage/rank/test/tools.py similarity index 78% rename from skimage/rank/tools.py rename to skimage/rank/test/tools.py index 835a8884..2fba4798 100644 --- a/skimage/rank/tools.py +++ b/skimage/rank/test/tools.py @@ -39,14 +39,4 @@ def log_timing(func): log_timing.level = 0 -def tumbnail_it(data): - """display image with its histogram - """ - h = np.histogram(data[:],100) - hn = 512*h[0]/np.max(h[0]) - plt.subplot(1,2,1) - plt.imshow(ima8,interpolation='nearest',cmap=cm.gray) - plt.subplot(1,2,2) - plt.plot(hn) - plt.colorbar() From f8f11ab8378b1f635845fdbc1ec13e66d23bec1f Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 16:12:08 +0200 Subject: [PATCH 03/86] mv test to tests --- skimage/rank/setup.py | 5 ++++- skimage/rank/{test => tests}/test_16bitbilateral.py | 0 skimage/rank/{test => tests}/test_benchmark.py | 0 skimage/rank/{test => tests}/test_suite.py | 0 skimage/rank/{test => tests}/tools.py | 0 5 files changed, 4 insertions(+), 1 deletion(-) rename skimage/rank/{test => tests}/test_16bitbilateral.py (100%) rename skimage/rank/{test => tests}/test_benchmark.py (100%) rename skimage/rank/{test => tests}/test_suite.py (100%) rename skimage/rank/{test => tests}/tools.py (100%) diff --git a/skimage/rank/setup.py b/skimage/rank/setup.py index e9af9446..8c5a595a 100644 --- a/skimage/rank/setup.py +++ b/skimage/rank/setup.py @@ -12,4 +12,7 @@ setup( Extension("crank16", ["crank16.pyx"], include_dirs=[np.get_include()]), Extension("crank16_bilateral", ["crank16_bilateral.pyx"], include_dirs=[np.get_include()]), Extension("crank16_percentiles", ["crank16_percentiles.pyx"], include_dirs=[np.get_include()])] -) \ No newline at end of file +) + + + diff --git a/skimage/rank/test/test_16bitbilateral.py b/skimage/rank/tests/test_16bitbilateral.py similarity index 100% rename from skimage/rank/test/test_16bitbilateral.py rename to skimage/rank/tests/test_16bitbilateral.py diff --git a/skimage/rank/test/test_benchmark.py b/skimage/rank/tests/test_benchmark.py similarity index 100% rename from skimage/rank/test/test_benchmark.py rename to skimage/rank/tests/test_benchmark.py diff --git a/skimage/rank/test/test_suite.py b/skimage/rank/tests/test_suite.py similarity index 100% rename from skimage/rank/test/test_suite.py rename to skimage/rank/tests/test_suite.py diff --git a/skimage/rank/test/tools.py b/skimage/rank/tests/tools.py similarity index 100% rename from skimage/rank/test/tools.py rename to skimage/rank/tests/tools.py From 5a5cdfca151a955f4a080806e061d11736d9cfc8 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 16:35:06 +0200 Subject: [PATCH 04/86] rename using scikits naming conventions --- skimage/rank/__init__.py | 1 - skimage/rank/{core.pxd => _core.pxd} | 0 skimage/rank/{core16.pxd => _core16.pxd} | 2 +- skimage/rank/{core16b.pxd => _core16b.pxd} | 2 +- skimage/rank/{core16p.pxd => _core16p.pxd} | 2 +- skimage/rank/{core8.pxd => _core8.pxd} | 2 +- skimage/rank/{core8p.pxd => _core8p.pxd} | 2 +- skimage/rank/{crank16.pyx => _crank16.pyx} | 30 ++--- ...6_bilateral.pyx => _crank16_bilateral.pyx} | 6 +- ...rcentiles.pyx => _crank16_percentiles.pyx} | 18 +-- skimage/rank/{crank.pyx => _crank8.pyx} | 30 ++--- ...ercentiles.pyx => _crank8_percentiles.pyx} | 18 +-- skimage/rank/cmorph.pyx | 118 ------------------ skimage/rank/setup.py | 46 +++++-- skimage/rank/tests/test_16bitbilateral.py | 4 +- skimage/rank/tests/test_benchmark.py | 4 +- skimage/rank/tests/test_suite.py | 13 +- 17 files changed, 106 insertions(+), 192 deletions(-) rename skimage/rank/{core.pxd => _core.pxd} (100%) rename skimage/rank/{core16.pxd => _core16.pxd} (99%) rename skimage/rank/{core16b.pxd => _core16b.pxd} (99%) rename skimage/rank/{core16p.pxd => _core16p.pxd} (98%) rename skimage/rank/{core8.pxd => _core8.pxd} (99%) rename skimage/rank/{core8p.pxd => _core8p.pxd} (99%) rename skimage/rank/{crank16.pyx => _crank16.pyx} (90%) rename skimage/rank/{crank16_bilateral.pyx => _crank16_bilateral.pyx} (98%) rename skimage/rank/{crank16_percentiles.pyx => _crank16_percentiles.pyx} (90%) rename skimage/rank/{crank.pyx => _crank8.pyx} (90%) rename skimage/rank/{crank_percentiles.pyx => _crank8_percentiles.pyx} (90%) delete mode 100644 skimage/rank/cmorph.pyx diff --git a/skimage/rank/__init__.py b/skimage/rank/__init__.py index 8b0e3f5b..e69de29b 100644 --- a/skimage/rank/__init__.py +++ b/skimage/rank/__init__.py @@ -1 +0,0 @@ -from .crank import * diff --git a/skimage/rank/core.pxd b/skimage/rank/_core.pxd similarity index 100% rename from skimage/rank/core.pxd rename to skimage/rank/_core.pxd diff --git a/skimage/rank/core16.pxd b/skimage/rank/_core16.pxd similarity index 99% rename from skimage/rank/core16.pxd rename to skimage/rank/_core16.pxd index 9973025f..ddd8c637 100644 --- a/skimage/rank/core16.pxd +++ b/skimage/rank/_core16.pxd @@ -22,7 +22,7 @@ cdef inline int int_min(int a, int b): return a if a <= b else b # 16 bit core kernel receives extra information about data bitdepth #--------------------------------------------------------------------------- -cdef inline rank16(np.uint16_t kernel(int*, float, np.uint16_t, int ,int,int ), +cdef inline _core16(np.uint16_t kernel(int*, float, np.uint16_t, int ,int,int ), np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, np.ndarray[np.uint8_t, ndim=2] mask, diff --git a/skimage/rank/core16b.pxd b/skimage/rank/_core16b.pxd similarity index 99% rename from skimage/rank/core16b.pxd rename to skimage/rank/_core16b.pxd index 38832c11..fefac53e 100644 --- a/skimage/rank/core16b.pxd +++ b/skimage/rank/_core16b.pxd @@ -22,7 +22,7 @@ cdef inline int int_min(int a, int b): return a if a <= b else b # 16 bit core kernel receives extra information about data bitdepth and bilateral interval #--------------------------------------------------------------------------- -cdef inline rank16b(np.uint16_t kernel(int*, float, np.uint16_t, int ,int,int,int,int), +cdef inline _core16b(np.uint16_t kernel(int*, float, np.uint16_t, int ,int,int,int,int), np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, np.ndarray[np.uint8_t, ndim=2] mask, diff --git a/skimage/rank/core16p.pxd b/skimage/rank/_core16p.pxd similarity index 98% rename from skimage/rank/core16p.pxd rename to skimage/rank/_core16p.pxd index dbf51c54..0d698cee 100644 --- a/skimage/rank/core16p.pxd +++ b/skimage/rank/_core16p.pxd @@ -22,7 +22,7 @@ cdef inline int int_min(int a, int b): return a if a <= b else b # 16 bit core kernel receives extra information about data inferior and superior percentiles #--------------------------------------------------------------------------- -cdef inline rank16_percentile(np.uint16_t kernel(int*, float, np.uint16_t,int,int,int, float, float), +cdef inline _core16p(np.uint16_t kernel(int*, float, np.uint16_t,int,int,int, float, float), np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, np.ndarray[np.uint8_t, ndim=2] mask, diff --git a/skimage/rank/core8.pxd b/skimage/rank/_core8.pxd similarity index 99% rename from skimage/rank/core8.pxd rename to skimage/rank/_core8.pxd index 0c901c8b..3d5ddac3 100644 --- a/skimage/rank/core8.pxd +++ b/skimage/rank/_core8.pxd @@ -22,7 +22,7 @@ cdef inline int int_min(int a, int b): return a if a <= b else b # 8 bit core kernel #--------------------------------------------------------------------------- -cdef inline rank8(np.uint8_t kernel(int*, float, np.uint8_t), +cdef inline _core8(np.uint8_t kernel(int*, float, np.uint8_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, diff --git a/skimage/rank/core8p.pxd b/skimage/rank/_core8p.pxd similarity index 99% rename from skimage/rank/core8p.pxd rename to skimage/rank/_core8p.pxd index 25e3ffcf..dfab17be 100644 --- a/skimage/rank/core8p.pxd +++ b/skimage/rank/_core8p.pxd @@ -22,7 +22,7 @@ cdef inline int int_min(int a, int b): return a if a <= b else b # 8 bit core kernel receives extra information about data inferior and superior percentiles #--------------------------------------------------------------------------- -cdef inline rank8_percentile(np.uint8_t kernel(int*, float, np.uint8_t, float, float), +cdef inline _core8p(np.uint8_t kernel(int*, float, np.uint8_t, float, float), np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, np.ndarray[np.uint8_t, ndim=2] mask, diff --git a/skimage/rank/crank16.pyx b/skimage/rank/_crank16.pyx similarity index 90% rename from skimage/rank/crank16.pyx rename to skimage/rank/_crank16.pyx index cd0bacd4..e1e64bed 100644 --- a/skimage/rank/crank16.pyx +++ b/skimage/rank/_crank16.pyx @@ -15,7 +15,7 @@ import numpy as np cimport numpy as np # import main loop -from core16 cimport rank16 +from _core16 cimport _core16 # ----------------------------------------------------------------- # kernels uint16 take extra parameter for defining the bitdepth @@ -198,7 +198,7 @@ def autolevel(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8): """bottom hat """ - return rank16(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,bitdepth) def bottomhat(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -207,7 +207,7 @@ def bottomhat(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8): """bottom hat """ - return rank16(kernel_bottomhat,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_bottomhat,image,selem,mask,out,shift_x,shift_y,bitdepth) def egalise(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -216,7 +216,7 @@ def egalise(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8): """local egalisation of the gray level """ - return rank16(kernel_egalise,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_egalise,image,selem,mask,out,shift_x,shift_y,bitdepth) def gradient(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -225,7 +225,7 @@ def gradient(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8): """local maximum - local minimum gray level """ - return rank16(kernel_gradient,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_gradient,image,selem,mask,out,shift_x,shift_y,bitdepth) def maximum(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -234,7 +234,7 @@ def maximum(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8): """local maximum gray level """ - return rank16(kernel_maximum,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_maximum,image,selem,mask,out,shift_x,shift_y,bitdepth) def mean(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -243,7 +243,7 @@ def mean(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8): """average gray level (clipped on uint8) """ - return rank16(kernel_mean,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_mean,image,selem,mask,out,shift_x,shift_y,bitdepth) def meansubstraction(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -252,7 +252,7 @@ def meansubstraction(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8): """(g - average gray level)/2+midbin (clipped on uint8) """ - return rank16(kernel_meansubstraction,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_meansubstraction,image,selem,mask,out,shift_x,shift_y,bitdepth) def median(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -261,7 +261,7 @@ def median(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8): """local median """ - return rank16(kernel_median,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_median,image,selem,mask,out,shift_x,shift_y,bitdepth) def minimum(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -270,7 +270,7 @@ def minimum(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8): """local minimum gray level """ - return rank16(kernel_minimum,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_minimum,image,selem,mask,out,shift_x,shift_y,bitdepth) def morph_contr_enh(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -279,7 +279,7 @@ def morph_contr_enh(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8): """morphological contrast enhancement """ - return rank16(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y,bitdepth) def modal(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -288,7 +288,7 @@ def modal(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8): """local mode """ - return rank16(kernel_modal,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_modal,image,selem,mask,out,shift_x,shift_y,bitdepth) def pop(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -297,7 +297,7 @@ def pop(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8): """returns the number of actual pixels of the structuring element inside the mask """ - return rank16(kernel_pop,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_pop,image,selem,mask,out,shift_x,shift_y,bitdepth) def threshold(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -306,7 +306,7 @@ def threshold(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8): """returns maxbin-1 if gray level higher than local mean, 0 else """ - return rank16(kernel_threshold,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_threshold,image,selem,mask,out,shift_x,shift_y,bitdepth) def tophat(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -315,4 +315,4 @@ def tophat(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8): """top hat """ - return rank16(kernel_tophat,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_tophat,image,selem,mask,out,shift_x,shift_y,bitdepth) diff --git a/skimage/rank/crank16_bilateral.pyx b/skimage/rank/_crank16_bilateral.pyx similarity index 98% rename from skimage/rank/crank16_bilateral.pyx rename to skimage/rank/_crank16_bilateral.pyx index 313b83d6..440d28e3 100644 --- a/skimage/rank/crank16_bilateral.pyx +++ b/skimage/rank/_crank16_bilateral.pyx @@ -15,7 +15,7 @@ import numpy as np cimport numpy as np # import main loop -from core16b cimport rank16b +from _core16b cimport _core16b # ----------------------------------------------------------------- # kernels uint16 take extra parameter for defining the bitdepth @@ -257,7 +257,7 @@ 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 rank16b(kernel_mean,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) + return _core16b(kernel_mean,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) #def meansubstraction(np.ndarray[np.uint16_t, ndim=2] image, # np.ndarray[np.uint8_t, ndim=2] selem, @@ -311,7 +311,7 @@ def pop(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8, int s0=1, int s1=1): """returns the number of actual pixels of the structuring element inside the mask """ - return rank16b(kernel_pop,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) + return _core16b(kernel_pop,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) #def threshold(np.ndarray[np.uint16_t, ndim=2] image, # np.ndarray[np.uint8_t, ndim=2] selem, diff --git a/skimage/rank/crank16_percentiles.pyx b/skimage/rank/_crank16_percentiles.pyx similarity index 90% rename from skimage/rank/crank16_percentiles.pyx rename to skimage/rank/_crank16_percentiles.pyx index 7756bc19..54c25d40 100644 --- a/skimage/rank/crank16_percentiles.pyx +++ b/skimage/rank/_crank16_percentiles.pyx @@ -15,7 +15,7 @@ import numpy as np cimport numpy as np # import main loop -from core16p cimport rank16_percentile +from _core16p cimport _core16p # ----------------------------------------------------------------- # kernels uint8 (SOFT version using percentiles) @@ -194,7 +194,7 @@ def autolevel(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8, float p0=0., float p1=0.): """bottom hat """ - return rank16_percentile(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) + return _core16p(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) def gradient(np.ndarray[np.uint16_t, ndim=2] image, @@ -204,7 +204,7 @@ def gradient(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8, float p0=0., float p1=0.): """return p0,p1 percentile gradient """ - return rank16_percentile(kernel_gradient,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) + return _core16p(kernel_gradient,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) def mean(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -213,7 +213,7 @@ def mean(np.ndarray[np.uint16_t, ndim=2] image, 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 rank16_percentile(kernel_mean,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) + return _core16p(kernel_mean,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) def mean_substraction(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -222,7 +222,7 @@ def mean_substraction(np.ndarray[np.uint16_t, ndim=2] image, 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 rank16_percentile(kernel_mean_substraction,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) + return _core16p(kernel_mean_substraction,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) def morph_contr_enh(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -231,7 +231,7 @@ def morph_contr_enh(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8, float p0=0., float p1=0.): """reforce contrast using percentiles """ - return rank16_percentile(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) + return _core16p(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) def percentile(np.ndarray[np.uint16_t, ndim=2] image, @@ -241,7 +241,7 @@ def percentile(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8, float p0=0., float p1=0.): """return p0 percentile """ - return rank16_percentile(kernel_percentile,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) + return _core16p(kernel_percentile,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) def pop(np.ndarray[np.uint16_t, ndim=2] image, @@ -251,7 +251,7 @@ def pop(np.ndarray[np.uint16_t, ndim=2] image, 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 rank16_percentile(kernel_pop,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) + return _core16p(kernel_pop,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) def threshold(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -260,4 +260,4 @@ def threshold(np.ndarray[np.uint16_t, ndim=2] image, 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 rank16_percentile(kernel_threshold,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) + return _core16p(kernel_threshold,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) diff --git a/skimage/rank/crank.pyx b/skimage/rank/_crank8.pyx similarity index 90% rename from skimage/rank/crank.pyx rename to skimage/rank/_crank8.pyx index 59016eed..cb74021e 100644 --- a/skimage/rank/crank.pyx +++ b/skimage/rank/_crank8.pyx @@ -15,7 +15,7 @@ import numpy as np cimport numpy as np # import main loop -from core8 cimport rank8 +from _core8 cimport _core8 # ----------------------------------------------------------------- # kernels uint8 @@ -199,7 +199,7 @@ def autolevel(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """bottom hat """ - return rank8(kernel_autolevel,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_autolevel,image,selem,mask,out,shift_x,shift_y) def bottomhat(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -208,7 +208,7 @@ def bottomhat(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """bottom hat """ - return rank8(kernel_bottomhat,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_bottomhat,image,selem,mask,out,shift_x,shift_y) def egalise(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -217,7 +217,7 @@ def egalise(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """local egalisation of the gray level """ - return rank8(kernel_egalise,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_egalise,image,selem,mask,out,shift_x,shift_y) def gradient(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -226,7 +226,7 @@ def gradient(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """local maximum - local minimum gray level """ - return rank8(kernel_gradient,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_gradient,image,selem,mask,out,shift_x,shift_y) def maximum(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -235,7 +235,7 @@ def maximum(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """local maximum gray level """ - return rank8(kernel_maximum,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_maximum,image,selem,mask,out,shift_x,shift_y) def mean(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -244,7 +244,7 @@ def mean(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """average gray level (clipped on uint8) """ - return rank8(kernel_mean,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_mean,image,selem,mask,out,shift_x,shift_y) def meansubstraction(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -253,7 +253,7 @@ def meansubstraction(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """(g - average gray level)/2+127 (clipped on uint8) """ - return rank8(kernel_meansubstraction,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_meansubstraction,image,selem,mask,out,shift_x,shift_y) def median(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -262,7 +262,7 @@ def median(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """local median """ - return rank8(kernel_median,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_median,image,selem,mask,out,shift_x,shift_y) def minimum(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -271,7 +271,7 @@ def minimum(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """local minimum gray level """ - return rank8(kernel_minimum,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_minimum,image,selem,mask,out,shift_x,shift_y) def morph_contr_enh(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -280,7 +280,7 @@ def morph_contr_enh(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """morphological contrast enhancement """ - return rank8(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y) def modal(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -289,7 +289,7 @@ def modal(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """local mode """ - return rank8(kernel_modal,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_modal,image,selem,mask,out,shift_x,shift_y) def pop(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -298,7 +298,7 @@ def pop(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """returns the number of actual pixels of the structuring element inside the mask """ - return rank8(kernel_pop,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_pop,image,selem,mask,out,shift_x,shift_y) def threshold(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -307,7 +307,7 @@ def threshold(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """returns 255 if gray level higher than local mean, 0 else """ - return rank8(kernel_threshold,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_threshold,image,selem,mask,out,shift_x,shift_y) def tophat(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -316,5 +316,5 @@ def tophat(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """top hat """ - return rank8(kernel_tophat,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_tophat,image,selem,mask,out,shift_x,shift_y) diff --git a/skimage/rank/crank_percentiles.pyx b/skimage/rank/_crank8_percentiles.pyx similarity index 90% rename from skimage/rank/crank_percentiles.pyx rename to skimage/rank/_crank8_percentiles.pyx index d4d6312f..81730313 100644 --- a/skimage/rank/crank_percentiles.pyx +++ b/skimage/rank/_crank8_percentiles.pyx @@ -15,7 +15,7 @@ import numpy as np cimport numpy as np # import main loop -from core8p cimport rank8_percentile +from _core8p cimport _core8p # ----------------------------------------------------------------- # kernels uint8 (SOFT version using percentiles) @@ -189,7 +189,7 @@ def autolevel(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0, float p0=0., float p1=0.): """bottom hat """ - return rank8_percentile(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,p0,p1) + return _core8p(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,p0,p1) def gradient(np.ndarray[np.uint8_t, ndim=2] image, @@ -199,7 +199,7 @@ 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 rank8_percentile(kernel_gradient,image,selem,mask,out,shift_x,shift_y,p0,p1) + return _core8p(kernel_gradient,image,selem,mask,out,shift_x,shift_y,p0,p1) def mean(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -208,7 +208,7 @@ 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 rank8_percentile(kernel_mean,image,selem,mask,out,shift_x,shift_y,p0,p1) + return _core8p(kernel_mean,image,selem,mask,out,shift_x,shift_y,p0,p1) def mean_substraction(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -217,7 +217,7 @@ 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 rank8_percentile(kernel_mean_substraction,image,selem,mask,out,shift_x,shift_y,p0,p1) + return _core8p(kernel_mean_substraction,image,selem,mask,out,shift_x,shift_y,p0,p1) def morph_contr_enh(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -226,7 +226,7 @@ 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 rank8_percentile(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y,p0,p1) + return _core8p(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y,p0,p1) def percentile(np.ndarray[np.uint8_t, ndim=2] image, @@ -236,7 +236,7 @@ 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 rank8_percentile(kernel_percentile,image,selem,mask,out,shift_x,shift_y,p0,p1) + return _core8p(kernel_percentile,image,selem,mask,out,shift_x,shift_y,p0,p1) def pop(np.ndarray[np.uint8_t, ndim=2] image, @@ -246,7 +246,7 @@ 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 rank8_percentile(kernel_pop,image,selem,mask,out,shift_x,shift_y,p0,p1) + return _core8p(kernel_pop,image,selem,mask,out,shift_x,shift_y,p0,p1) def threshold(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -255,4 +255,4 @@ 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 rank8_percentile(kernel_threshold,image,selem,mask,out,shift_x,shift_y,p0,p1) + return _core8p(kernel_threshold,image,selem,mask,out,shift_x,shift_y,p0,p1) diff --git a/skimage/rank/cmorph.pyx b/skimage/rank/cmorph.pyx deleted file mode 100644 index 9b8b3a27..00000000 --- a/skimage/rank/cmorph.pyx +++ /dev/null @@ -1,118 +0,0 @@ -#cython: cdivision=True -#cython: boundscheck=False -#cython: nonecheck=False -#cython: wraparound=False - -import numpy as np -cimport numpy as np -from libc.stdlib cimport malloc, free - - -def dilate(np.ndarray[np.uint8_t, ndim=2] image, - np.ndarray[np.uint8_t, ndim=2] selem, - np.ndarray[np.uint8_t, ndim=2] out=None, - char shift_x=0, char shift_y=0): - - cdef int rows = image.shape[0] - cdef int cols = image.shape[1] - cdef int srows = selem.shape[0] - cdef int scols = selem.shape[1] - - cdef int centre_r = int(selem.shape[0] / 2) - shift_y - cdef int centre_c = int(selem.shape[1] / 2) - shift_x - - image = np.ascontiguousarray(image) - if out is None: - out = np.zeros((rows, cols), dtype=np.uint8) - else: - out = np.ascontiguousarray(out) - - cdef np.uint8_t* out_data = out.data - cdef np.uint8_t* image_data = image.data - - cdef int r, c, rr, cc, s, value, local_max - - cdef int selem_num = np.sum(selem != 0) - cdef int* sr = malloc(selem_num * sizeof(int)) - cdef int* sc = malloc(selem_num * sizeof(int)) - - s = 0 - for r in range(srows): - for c in range(scols): - if selem[r, c] != 0: - sr[s] = r - centre_r - sc[s] = c - centre_c - s += 1 - - for r in range(rows): - for c in range(cols): - local_max = 0 - for s in range(selem_num): - rr = r + sr[s] - cc = c + sc[s] - if 0 <= rr < rows and 0 <= cc < cols: - value = image_data[rr * cols + cc] - if value > local_max: - local_max = value - - out_data[r * cols + c] = local_max - - free(sr) - free(sc) - - return out - - -def erode(np.ndarray[np.uint8_t, ndim=2] image, - np.ndarray[np.uint8_t, ndim=2] selem, - np.ndarray[np.uint8_t, ndim=2] out=None, - char shift_x=0, char shift_y=0): - - cdef int rows = image.shape[0] - cdef int cols = image.shape[1] - cdef int srows = selem.shape[0] - cdef int scols = selem.shape[1] - - cdef int centre_r = int(selem.shape[0] / 2) - shift_y - cdef int centre_c = int(selem.shape[1] / 2) - shift_x - - image = np.ascontiguousarray(image) - if out is None: - out = np.zeros((rows, cols), dtype=np.uint8) - else: - out = np.ascontiguousarray(out) - - cdef np.uint8_t* out_data = out.data - cdef np.uint8_t* image_data = image.data - - cdef int r, c, rr, cc, s, value, local_min - - cdef int selem_num = np.sum(selem != 0) - cdef int* sr = malloc(selem_num * sizeof(int)) - cdef int* sc = malloc(selem_num * sizeof(int)) - - s = 0 - for r in range(srows): - for c in range(scols): - if selem[r, c] != 0: - sr[s] = r - centre_r - sc[s] = c - centre_c - s += 1 - - for r in range(rows): - for c in range(cols): - local_min = 255 - for s in range(selem_num): - rr = r + sr[s] - cc = c + sc[s] - if 0 <= rr < rows and 0 <= cc < cols: - value = image_data[rr * cols + cc] - if value < local_min: - local_min = value - - out_data[r * cols + c] = local_min - - free(sr) - free(sc) - - return out diff --git a/skimage/rank/setup.py b/skimage/rank/setup.py index 8c5a595a..e8b2691d 100644 --- a/skimage/rank/setup.py +++ b/skimage/rank/setup.py @@ -6,13 +6,45 @@ from Cython.Distutils import build_ext setup( cmdclass = {'build_ext': build_ext}, - ext_modules = [Extension("cmorph", ["cmorph.pyx"], include_dirs=[np.get_include()]), - Extension("crank", ["crank.pyx"], include_dirs=[np.get_include()]), - Extension("crank_percentiles", ["crank_percentiles.pyx"], include_dirs=[np.get_include()]), - Extension("crank16", ["crank16.pyx"], include_dirs=[np.get_include()]), - Extension("crank16_bilateral", ["crank16_bilateral.pyx"], include_dirs=[np.get_include()]), - Extension("crank16_percentiles", ["crank16_percentiles.pyx"], include_dirs=[np.get_include()])] + ext_modules = [Extension("crank8", ["_crank8.pyx"], include_dirs=[np.get_include()]), + Extension("crank8_percentiles", ["_crank8_percentiles.pyx"], include_dirs=[np.get_include()]), + Extension("crank16", ["_crank16.pyx"], include_dirs=[np.get_include()]), + Extension("crank16_bilateral", ["_crank16_bilateral.pyx"], include_dirs=[np.get_include()]), + Extension("crank16_percentiles", ["_crank16_percentiles.pyx"], include_dirs=[np.get_include()])] ) - +##!/usr/bin/env python +# +#import os +#from skimage._build import cython +# +#base_path = os.path.abspath(os.path.dirname(__file__)) +# +# +#def configuration(parent_package='', top_path=None): +# from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs +# +# config = Configuration('rank', parent_package, top_path) +# config.add_data_dir('tests') +# +# cython(['_texture.pyx'], working_path=base_path) +# cython(['_template.pyx'], working_path=base_path) +# +# config.add_extension('_texture', sources=['_texture.c'], +# include_dirs=[get_numpy_include_dirs(), '../_shared']) +# config.add_extension('_template', sources=['_template.c'], +# include_dirs=[get_numpy_include_dirs(), '../_shared']) +# +# return config +# +#if __name__ == '__main__': +# from numpy.distutils.core import setup +# setup(maintainer='scikits-image Developers', +# author='scikits-image Developers', +# maintainer_email='scikits-image@googlegroups.com', +# description='Features', +# url='https://github.com/scikits-image/scikits-image', +# license='SciPy License (BSD Style)', +# **(configuration(top_path='').todict()) +# ) diff --git a/skimage/rank/tests/test_16bitbilateral.py b/skimage/rank/tests/test_16bitbilateral.py index ac078b09..98d76573 100644 --- a/skimage/rank/tests/test_16bitbilateral.py +++ b/skimage/rank/tests/test_16bitbilateral.py @@ -2,14 +2,14 @@ import numpy as np import matplotlib.pyplot as plt from skimage import data -from skimage.rank import crank_percentiles,crank16_bilateral +from skimage.rank import crank8_percentiles,crank16_bilateral if __name__ == '__main__': a8 = (data.coins()).astype('uint8') a16 = (data.coins()).astype('uint16')*16 selem = np.ones((20,20),dtype='uint8') - f1 = crank_percentiles.mean(a8,selem = selem,p0=.1,p1=.9) + f1 = crank8_percentiles.mean(a8,selem = selem,p0=.1,p1=.9) f2 = crank16_bilateral.mean(a16,selem = selem,bitdepth=12,s0=500,s1=500) plt.figure() diff --git a/skimage/rank/tests/test_benchmark.py b/skimage/rank/tests/test_benchmark.py index 4fee48c1..c67742e3 100644 --- a/skimage/rank/tests/test_benchmark.py +++ b/skimage/rank/tests/test_benchmark.py @@ -3,13 +3,13 @@ import matplotlib.pyplot as plt from skimage import data from skimage.morphology import cmorph -from skimage.rank import crank +from skimage.rank import crank8 from tools import log_timing @log_timing def cr_max(image,selem): - return crank.maximum(image=image,selem = selem) + return crank8.maximum(image=image,selem = selem) @log_timing def cm_dil(image,selem): diff --git a/skimage/rank/tests/test_suite.py b/skimage/rank/tests/test_suite.py index 61ceab48..0dcb21ab 100644 --- a/skimage/rank/tests/test_suite.py +++ b/skimage/rank/tests/test_suite.py @@ -2,7 +2,8 @@ import unittest import numpy as np -from skimage.rank import crank,crank16,crank16_bilateral,crank16_percentiles,crank_percentiles +from skimage.rank import crank8,crank8_percentiles +from skimage.rank import crank16,crank16_bilateral,crank16_percentiles from skimage.morphology import cmorph class TestSequenceFunctions(unittest.TestCase): @@ -16,9 +17,9 @@ class TestSequenceFunctions(unittest.TestCase): 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 = crank.mean(image=a8,selem = elem,shift_x=0,shift_y=0) + r = crank8.mean(image=a8,selem = elem,shift_x=0,shift_y=0) self.assertTrue(a8.shape == r.shape) - r = crank.mean(image=a8,selem = elem,shift_x=+1,shift_y=+1) + 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)): @@ -42,7 +43,7 @@ class TestSequenceFunctions(unittest.TestCase): for r in range(1,20,1): elem = np.ones((r,r),dtype='uint8') # elem = (np.random.random((r,r))>.5).astype('uint8') - rc = crank.maximum(image=a,selem = elem) + rc = crank8.maximum(image=a,selem = elem) cm = cmorph.dilate(image=a,selem = elem) self.assertTrue((rc==cm).all()) @@ -62,7 +63,7 @@ class TestSequenceFunctions(unittest.TestCase): def test_population(self): a = np.zeros((5,5),dtype='uint8') elem = np.ones((3,3),dtype='uint8') - p = crank.pop(image=a,selem = elem) + 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], @@ -74,7 +75,7 @@ class TestSequenceFunctions(unittest.TestCase): 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 = crank.maximum(image=a,selem = elem,shift_x=1,shift_y=1) + 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], From 483507f4dfa02a9c0d43b1c4f1cabb12e225c5b7 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 17:15:10 +0200 Subject: [PATCH 05/86] try to fix rank setup --- skimage/rank/setup.py | 27 +++++++++++++++-------- skimage/rank/tests/test_16bitbilateral.py | 3 ++- skimage/setup.py | 1 + 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/skimage/rank/setup.py b/skimage/rank/setup.py index e8b2691d..c16f902f 100644 --- a/skimage/rank/setup.py +++ b/skimage/rank/setup.py @@ -26,24 +26,33 @@ setup( # from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs # # config = Configuration('rank', parent_package, top_path) -# config.add_data_dir('tests') +## config.add_data_dir('tests') # -# cython(['_texture.pyx'], working_path=base_path) -# cython(['_template.pyx'], working_path=base_path) +# cython(['_crank8.pyx'], working_path=base_path) +# cython(['_crank8_percentiles.pyx'], working_path=base_path) +# cython(['_crank16.pyx'], working_path=base_path) +# cython(['_crank16_percentiles.pyx'], working_path=base_path) +# cython(['_crank16_bilateral.pyx'], working_path=base_path) # -# config.add_extension('_texture', sources=['_texture.c'], -# include_dirs=[get_numpy_include_dirs(), '../_shared']) -# config.add_extension('_template', sources=['_template.c'], -# include_dirs=[get_numpy_include_dirs(), '../_shared']) +# config.add_extension('crank8', sources=['_crank8.c'], +# include_dirs=[get_numpy_include_dirs()]) +# config.add_extension('crank8_percentiles', sources=['_crank8_percentiles.c'], +# include_dirs=[get_numpy_include_dirs()]) +# config.add_extension('crank16', sources=['_crank16.c'], +# include_dirs=[get_numpy_include_dirs()]) +# config.add_extension('crank16_percentiles', sources=['_crank16_percentiles.c'], +# include_dirs=[get_numpy_include_dirs()]) +# config.add_extension('crank16_bilateral', sources=['_crank16_bilateral.c'], +# include_dirs=[get_numpy_include_dirs()]) # # return config # #if __name__ == '__main__': # from numpy.distutils.core import setup # setup(maintainer='scikits-image Developers', -# author='scikits-image Developers', +# author='Olivier Debeir', # maintainer_email='scikits-image@googlegroups.com', -# description='Features', +# description='Rank filters', # url='https://github.com/scikits-image/scikits-image', # license='SciPy License (BSD Style)', # **(configuration(top_path='').todict()) diff --git a/skimage/rank/tests/test_16bitbilateral.py b/skimage/rank/tests/test_16bitbilateral.py index 98d76573..8001a25f 100644 --- a/skimage/rank/tests/test_16bitbilateral.py +++ b/skimage/rank/tests/test_16bitbilateral.py @@ -2,7 +2,8 @@ import numpy as np import matplotlib.pyplot as plt from skimage import data -from skimage.rank import crank8_percentiles,crank16_bilateral +from skimage.rank import crank8_percentiles +from skimage.rank import crank16_bilateral if __name__ == '__main__': a8 = (data.coins()).astype('uint8') diff --git a/skimage/setup.py b/skimage/setup.py index 1082ba07..7ed50b65 100644 --- a/skimage/setup.py +++ b/skimage/setup.py @@ -16,6 +16,7 @@ def configuration(parent_package='', top_path=None): config.add_subpackage('io') config.add_subpackage('measure') config.add_subpackage('morphology') + config.add_subpackage('rank') config.add_subpackage('transform') config.add_subpackage('util') config.add_subpackage('segmentation') From b2c413dad0e0dc01b75ccd33b57a0825e4e71af0 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 17:30:21 +0200 Subject: [PATCH 06/86] rename some test to demo --- ...bitbilateral.py => demo_16bitbilateral.py} | 0 skimage/rank/tests/demo_all.py | 24 +++++++++++++++++++ .../{test_benchmark.py => demo_benchmark.py} | 0 3 files changed, 24 insertions(+) rename skimage/rank/tests/{test_16bitbilateral.py => demo_16bitbilateral.py} (100%) create mode 100644 skimage/rank/tests/demo_all.py rename skimage/rank/tests/{test_benchmark.py => demo_benchmark.py} (100%) diff --git a/skimage/rank/tests/test_16bitbilateral.py b/skimage/rank/tests/demo_16bitbilateral.py similarity index 100% rename from skimage/rank/tests/test_16bitbilateral.py rename to skimage/rank/tests/demo_16bitbilateral.py diff --git a/skimage/rank/tests/demo_all.py b/skimage/rank/tests/demo_all.py new file mode 100644 index 00000000..8001a25f --- /dev/null +++ b/skimage/rank/tests/demo_all.py @@ -0,0 +1,24 @@ +import numpy as np +import matplotlib.pyplot as plt + +from skimage import data +from skimage.rank import crank8_percentiles +from skimage.rank import crank16_bilateral + +if __name__ == '__main__': + a8 = (data.coins()).astype('uint8') + + a16 = (data.coins()).astype('uint16')*16 + selem = np.ones((20,20),dtype='uint8') + f1 = crank8_percentiles.mean(a8,selem = selem,p0=.1,p1=.9) + f2 = crank16_bilateral.mean(a16,selem = selem,bitdepth=12,s0=500,s1=500) + + plt.figure() + plt.imshow(np.hstack((a8,f1))) + plt.colorbar() + + plt.figure() + plt.imshow(np.hstack((a16,f2))) + plt.colorbar() + + plt.show() diff --git a/skimage/rank/tests/test_benchmark.py b/skimage/rank/tests/demo_benchmark.py similarity index 100% rename from skimage/rank/tests/test_benchmark.py rename to skimage/rank/tests/demo_benchmark.py From 6c19054aba87467bbb0b99e1d19cbe17490e7580 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 17:59:03 +0200 Subject: [PATCH 07/86] add demo all --- skimage/rank/tests/demo_all.py | 66 +++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 13 deletions(-) diff --git a/skimage/rank/tests/demo_all.py b/skimage/rank/tests/demo_all.py index 8001a25f..a509db33 100644 --- a/skimage/rank/tests/demo_all.py +++ b/skimage/rank/tests/demo_all.py @@ -2,23 +2,63 @@ import numpy as np import matplotlib.pyplot as plt from skimage import data -from skimage.rank import crank8_percentiles -from skimage.rank import crank16_bilateral +from skimage.morphology.selem import disk +from skimage.rank import crank8,crank8_percentiles +from skimage.rank import crank16,crank16_percentiles,crank16_bilateral if __name__ == '__main__': - a8 = (data.coins()).astype('uint8') + a8 = data.camera() + a16 = a8.astype('uint16')*16 +# selem = np.ones((30,30),dtype='uint8') + selem = disk(5) - a16 = (data.coins()).astype('uint16')*16 - selem = np.ones((20,20),dtype='uint8') - f1 = crank8_percentiles.mean(a8,selem = selem,p0=.1,p1=.9) - f2 = crank16_bilateral.mean(a16,selem = selem,bitdepth=12,s0=500,s1=500) +# for n in dir(crank16): +# method = eval('crank16.%s'%n) +# t = type(method) +# if t == type(crank8.maximum): +# print n,t +# f = method(a16,selem = selem,bitdepth=12) +# +# plt.figure() +# plt.subplot(1,2,1) +# plt.imshow(a16) +# plt.colorbar() +# plt.subplot(1,2,2) +# plt.imshow(f) +# plt.colorbar() +# plt.title(method) - plt.figure() - plt.imshow(np.hstack((a8,f1))) - plt.colorbar() +# for n in dir(crank8): +# method = eval('crank8.%s'%n) +# t = type(method) +# if t == type(crank8.maximum): +# print n,t +# f = method(a8,selem = selem) +# +# plt.figure() +# plt.subplot(1,2,1) +# plt.imshow(a8) +# plt.colorbar() +# plt.subplot(1,2,2) +# plt.imshow(f) +# plt.colorbar() +# plt.title(method) - plt.figure() - plt.imshow(np.hstack((a16,f2))) - plt.colorbar() + for n in dir(crank8_percentiles): + method = eval('crank8_percentiles.%s'%n) + t = type(method) + if t == type(crank8.maximum): + print n,t + f = method(a8,selem = selem,p0=.1,p1=.9) + plt.figure() + plt.subplot(1,2,1) + plt.imshow(a8) + plt.colorbar() + plt.subplot(1,2,2) + plt.imshow(f) + plt.colorbar() + plt.title(method) + + # plt.show() From 8f0a207866e9de4cc8886c04016ef1b2c56f300e Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 18:02:54 +0200 Subject: [PATCH 08/86] add demo all (cont.) --- skimage/rank/tests/demo_all.py | 43 ++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/skimage/rank/tests/demo_all.py b/skimage/rank/tests/demo_all.py index a509db33..d005d61a 100644 --- a/skimage/rank/tests/demo_all.py +++ b/skimage/rank/tests/demo_all.py @@ -44,21 +44,54 @@ if __name__ == '__main__': # plt.colorbar() # plt.title(method) - for n in dir(crank8_percentiles): - method = eval('crank8_percentiles.%s'%n) +# for n in dir(crank8_percentiles): +# method = eval('crank8_percentiles.%s'%n) +# t = type(method) +# if t == type(crank8.maximum): +# print n,t +# f = method(a8,selem = selem,p0=.1,p1=.9) +# +# plt.figure() +# plt.subplot(1,2,1) +# plt.imshow(a8) +# plt.colorbar() +# plt.subplot(1,2,2) +# plt.imshow(f) +# plt.colorbar() +# plt.title(method) + +# for n in dir(crank16_percentiles): +# method = eval('crank16_percentiles.%s'%n) +# t = type(method) +# if t == type(crank8.maximum): +# print n,t +# f = method(a16,selem = selem,bitdepth=12,p0=.1,p1=.9) +# +# plt.figure() +# plt.subplot(1,2,1) +# plt.imshow(a16) +# plt.colorbar() +# plt.subplot(1,2,2) +# plt.imshow(f) +# plt.colorbar() +# plt.title(method) + + selem = disk(50) + for n in dir(crank16_bilateral): + method = eval('crank16_bilateral.%s'%n) t = type(method) if t == type(crank8.maximum): print n,t - f = method(a8,selem = selem,p0=.1,p1=.9) + f = method(a16,selem = selem,bitdepth=12,s0=300,s1=300) plt.figure() plt.subplot(1,2,1) - plt.imshow(a8) + plt.imshow(a16) plt.colorbar() plt.subplot(1,2,2) plt.imshow(f) plt.colorbar() plt.title(method) - # + # plt.show() From be4d866a9bf35d0b8ddc7608dd88558ff39ea82a Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 18:03:08 +0200 Subject: [PATCH 09/86] add demo all (cont.) --- skimage/rank/tests/demo_all.py | 120 ++++++++++++++++----------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/skimage/rank/tests/demo_all.py b/skimage/rank/tests/demo_all.py index d005d61a..8e09048e 100644 --- a/skimage/rank/tests/demo_all.py +++ b/skimage/rank/tests/demo_all.py @@ -12,69 +12,69 @@ if __name__ == '__main__': # selem = np.ones((30,30),dtype='uint8') selem = disk(5) -# for n in dir(crank16): -# method = eval('crank16.%s'%n) -# t = type(method) -# if t == type(crank8.maximum): -# print n,t -# f = method(a16,selem = selem,bitdepth=12) -# -# plt.figure() -# plt.subplot(1,2,1) -# plt.imshow(a16) -# plt.colorbar() -# plt.subplot(1,2,2) -# plt.imshow(f) -# plt.colorbar() -# plt.title(method) + for n in dir(crank16): + method = eval('crank16.%s'%n) + t = type(method) + if t == type(crank8.maximum): + print n,t + f = method(a16,selem = selem,bitdepth=12) -# for n in dir(crank8): -# method = eval('crank8.%s'%n) -# t = type(method) -# if t == type(crank8.maximum): -# print n,t -# f = method(a8,selem = selem) -# -# plt.figure() -# plt.subplot(1,2,1) -# plt.imshow(a8) -# plt.colorbar() -# plt.subplot(1,2,2) -# plt.imshow(f) -# plt.colorbar() -# plt.title(method) + plt.figure() + plt.subplot(1,2,1) + plt.imshow(a16) + plt.colorbar() + plt.subplot(1,2,2) + plt.imshow(f) + plt.colorbar() + plt.title(method) -# for n in dir(crank8_percentiles): -# method = eval('crank8_percentiles.%s'%n) -# t = type(method) -# if t == type(crank8.maximum): -# print n,t -# f = method(a8,selem = selem,p0=.1,p1=.9) -# -# plt.figure() -# plt.subplot(1,2,1) -# plt.imshow(a8) -# plt.colorbar() -# plt.subplot(1,2,2) -# plt.imshow(f) -# plt.colorbar() -# plt.title(method) + for n in dir(crank8): + method = eval('crank8.%s'%n) + t = type(method) + if t == type(crank8.maximum): + print n,t + f = method(a8,selem = selem) -# for n in dir(crank16_percentiles): -# method = eval('crank16_percentiles.%s'%n) -# t = type(method) -# if t == type(crank8.maximum): -# print n,t -# f = method(a16,selem = selem,bitdepth=12,p0=.1,p1=.9) -# -# plt.figure() -# plt.subplot(1,2,1) -# plt.imshow(a16) -# plt.colorbar() -# plt.subplot(1,2,2) -# plt.imshow(f) -# plt.colorbar() -# plt.title(method) + plt.figure() + plt.subplot(1,2,1) + plt.imshow(a8) + plt.colorbar() + plt.subplot(1,2,2) + plt.imshow(f) + plt.colorbar() + plt.title(method) + + for n in dir(crank8_percentiles): + method = eval('crank8_percentiles.%s'%n) + t = type(method) + if t == type(crank8.maximum): + print n,t + f = method(a8,selem = selem,p0=.1,p1=.9) + + plt.figure() + plt.subplot(1,2,1) + plt.imshow(a8) + plt.colorbar() + plt.subplot(1,2,2) + plt.imshow(f) + plt.colorbar() + plt.title(method) + + for n in dir(crank16_percentiles): + method = eval('crank16_percentiles.%s'%n) + t = type(method) + if t == type(crank8.maximum): + print n,t + f = method(a16,selem = selem,bitdepth=12,p0=.1,p1=.9) + + plt.figure() + plt.subplot(1,2,1) + plt.imshow(a16) + plt.colorbar() + plt.subplot(1,2,2) + plt.imshow(f) + plt.colorbar() + plt.title(method) selem = disk(50) for n in dir(crank16_bilateral): From 806bbbcb65990ee5fe2b345fb9f010b5cd711a7c Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 18:23:33 +0200 Subject: [PATCH 10/86] add readme --- skimage/rank/README.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/skimage/rank/README.rst b/skimage/rank/README.rst index b15001e6..ef56f997 100644 --- a/skimage/rank/README.rst +++ b/skimage/rank/README.rst @@ -1,5 +1,13 @@ To use this to build your Cython file use the commandline options: +**To do** + +* add simple examples + +* add doc + + + .. sourcecode:: text $ python setup.py build_ext --inplace \ No newline at end of file From db3803fd72b0c136acd1c86e3bce434bdd6cd29d Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 10:56:05 +0200 Subject: [PATCH 11/86] add py wrappers --- skimage/rank/__init__.py | 3 + skimage/rank/bilateral_rank.py | 18 +++++ skimage/rank/percentile_rank.py | 58 ++++++++++++++ skimage/rank/rank.py | 112 +++++++++++++++++++++++++++ skimage/rank/setup.py | 20 ++--- skimage/rank/tests/demo_benchmark.py | 8 +- skimage/rank/tests/test_rank.py | 10 +++ 7 files changed, 215 insertions(+), 14 deletions(-) create mode 100644 skimage/rank/bilateral_rank.py create mode 100644 skimage/rank/percentile_rank.py create mode 100644 skimage/rank/rank.py create mode 100644 skimage/rank/tests/test_rank.py diff --git a/skimage/rank/__init__.py b/skimage/rank/__init__.py index e69de29b..09812649 100644 --- a/skimage/rank/__init__.py +++ b/skimage/rank/__init__.py @@ -0,0 +1,3 @@ +from .rank import * +from .percentile_rank import * +from .bilateral_rank import * \ No newline at end of file diff --git a/skimage/rank/bilateral_rank.py b/skimage/rank/bilateral_rank.py new file mode 100644 index 00000000..eaa6f8d9 --- /dev/null +++ b/skimage/rank/bilateral_rank.py @@ -0,0 +1,18 @@ +""" +:author: Olivier Debeir, 2012 +:license: modified BSD +""" + +__docformat__ = 'restructuredtext en' + +import warnings +from skimage import img_as_ubyte + +__all__ = ['bilateral_mean'] + + + +def bilateral_mean(image, selem, out=None, shift_x=False, shift_y=False, s0=10, s1=10): + pass + + diff --git a/skimage/rank/percentile_rank.py b/skimage/rank/percentile_rank.py new file mode 100644 index 00000000..49f87dd4 --- /dev/null +++ b/skimage/rank/percentile_rank.py @@ -0,0 +1,58 @@ +""" +:author: Olivier Debeir, 2012 +:license: modified BSD +""" + +__docformat__ = 'restructuredtext en' + +import warnings +from skimage import img_as_ubyte + +__all__ = ['percentile_mean'] + + +def percentile_mean(image, selem, out=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 pixel values contained inside the + percentile interval [p0,p1] are taken into account. + + Parameters + ---------- + image : ndarray + Image array (uint8 array or uint16). + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, a new array will be allocated. + shift_x, shift_y : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local mean : uint8 array or uint16 array depending on input image + The result of the local mean. + + Examples + -------- + to be updated + >>> # Erosion shrinks bright regions + >>> from skimage.morphology import square + >>> bright_square = 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) + >>> erosion(bright_square, square(3)) + array([[0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 1, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0]], dtype=uint8) + + """ + pass + diff --git a/skimage/rank/rank.py b/skimage/rank/rank.py new file mode 100644 index 00000000..d569a12b --- /dev/null +++ b/skimage/rank/rank.py @@ -0,0 +1,112 @@ +""" +:author: Olivier Debeir, 2012 +:license: modified BSD +""" + +__docformat__ = 'restructuredtext en' + +import warnings +from skimage import img_as_ubyte + +__all__ = ['mean','percentile_mean','bilateral_mean'] + + +def percentile_mean(image, selem, out=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 pixel values contained inside the + percentile interval [p0,p1] are taken into account. + + Parameters + ---------- + image : ndarray + Image array (uint8 array or uint16). + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, a new array will be allocated. + shift_x, shift_y : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local mean : uint8 array or uint16 array depending on input image + The result of the local mean. + + Examples + -------- + to be updated + >>> # Erosion shrinks bright regions + >>> from skimage.morphology import square + >>> bright_square = 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) + >>> erosion(bright_square, square(3)) + array([[0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 1, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0]], dtype=uint8) + + """ + pass + +def bilateral_mean(image, selem, out=None, shift_x=False, shift_y=False, s0=10, s1=10): + pass + +def mean(image, selem, out=None, shift_x=False, shift_y=False): + """Return greyscale local mean of an image. + + Mean is computed on the given structuring element. + + Parameters + ---------- + image : ndarray + Image array (uint8 array or uint16). + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, a new array will be allocated. + shift_x, shift_y : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local mean : uint8 array or uint16 array depending on input image + The result of the local mean. + + Examples + -------- + to be updated + >>> # Erosion shrinks bright regions + >>> from skimage.morphology import square + >>> bright_square = 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) + >>> erosion(bright_square, square(3)) + array([[0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 1, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0]], dtype=uint8) + + """ + pass +# if image is out: +# raise NotImplementedError("In-place erosion not supported!") +# image = img_as_ubyte(image) +# selem = img_as_ubyte(selem) +# return cmorph.erode(image, selem, out=out, +# shift_x=shift_x, shift_y=shift_y) + + diff --git a/skimage/rank/setup.py b/skimage/rank/setup.py index c16f902f..581e64ed 100644 --- a/skimage/rank/setup.py +++ b/skimage/rank/setup.py @@ -6,11 +6,11 @@ from Cython.Distutils import build_ext setup( cmdclass = {'build_ext': build_ext}, - ext_modules = [Extension("crank8", ["_crank8.pyx"], include_dirs=[np.get_include()]), - Extension("crank8_percentiles", ["_crank8_percentiles.pyx"], include_dirs=[np.get_include()]), - Extension("crank16", ["_crank16.pyx"], include_dirs=[np.get_include()]), - Extension("crank16_bilateral", ["_crank16_bilateral.pyx"], include_dirs=[np.get_include()]), - Extension("crank16_percentiles", ["_crank16_percentiles.pyx"], include_dirs=[np.get_include()])] + ext_modules = [Extension("_crank8", ["_crank8.pyx"], include_dirs=[np.get_include()]), + Extension("_crank8_percentiles", ["_crank8_percentiles.pyx"], include_dirs=[np.get_include()]), + Extension("_crank16", ["_crank16.pyx"], include_dirs=[np.get_include()]), + Extension("_crank16_bilateral", ["_crank16_bilateral.pyx"], include_dirs=[np.get_include()]), + Extension("_crank16_percentiles", ["_crank16_percentiles.pyx"], include_dirs=[np.get_include()])] ) @@ -34,15 +34,15 @@ setup( # cython(['_crank16_percentiles.pyx'], working_path=base_path) # cython(['_crank16_bilateral.pyx'], working_path=base_path) # -# config.add_extension('crank8', sources=['_crank8.c'], +# config.add_extension('_crank8', sources=['_crank8.c'], # include_dirs=[get_numpy_include_dirs()]) -# config.add_extension('crank8_percentiles', sources=['_crank8_percentiles.c'], +# config.add_extension('_crank8_percentiles', sources=['_crank8_percentiles.c'], # include_dirs=[get_numpy_include_dirs()]) -# config.add_extension('crank16', sources=['_crank16.c'], +# config.add_extension('_crank16', sources=['_crank16.c'], # include_dirs=[get_numpy_include_dirs()]) -# config.add_extension('crank16_percentiles', sources=['_crank16_percentiles.c'], +# config.add_extension('_crank16_percentiles', sources=['_crank16_percentiles.c'], # include_dirs=[get_numpy_include_dirs()]) -# config.add_extension('crank16_bilateral', sources=['_crank16_bilateral.c'], +# config.add_extension('_crank16_bilateral', sources=['_crank16_bilateral.c'], # include_dirs=[get_numpy_include_dirs()]) # # return config diff --git a/skimage/rank/tests/demo_benchmark.py b/skimage/rank/tests/demo_benchmark.py index c67742e3..f6fe32bb 100644 --- a/skimage/rank/tests/demo_benchmark.py +++ b/skimage/rank/tests/demo_benchmark.py @@ -2,18 +2,18 @@ import numpy as np import matplotlib.pyplot as plt from skimage import data -from skimage.morphology import cmorph -from skimage.rank import crank8 +from skimage.morphology import dilation +from skimage.rank import _crank8 from tools import log_timing @log_timing def cr_max(image,selem): - return crank8.maximum(image=image,selem = selem) + return _crank8.maximum(image=image,selem = selem) @log_timing def cm_dil(image,selem): - return cmorph.dilate(image=image,selem = selem) + return dilation(image=image,selem = selem) def compare(): diff --git a/skimage/rank/tests/test_rank.py b/skimage/rank/tests/test_rank.py new file mode 100644 index 00000000..2a1e253d --- /dev/null +++ b/skimage/rank/tests/test_rank.py @@ -0,0 +1,10 @@ +import numpy as np +import matplotlib.pyplot as plt + +from skimage import data +import skimage.rank as rank + +print dir(rank) + + + From 4661dfb0e616ce46537cfc830f69b69566417b04 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 11:26:14 +0200 Subject: [PATCH 12/86] fix bitdepth in rank.py --- skimage/rank/rank.py | 86 ++++++++++++--------------------- skimage/rank/tests/test_rank.py | 21 ++++++++ 2 files changed, 51 insertions(+), 56 deletions(-) diff --git a/skimage/rank/rank.py b/skimage/rank/rank.py index d569a12b..7e4d16a2 100644 --- a/skimage/rank/rank.py +++ b/skimage/rank/rank.py @@ -7,59 +7,23 @@ __docformat__ = 'restructuredtext en' import warnings from skimage import img_as_ubyte +import numpy as np -__all__ = ['mean','percentile_mean','bilateral_mean'] +import _crank16,_crank8 +__all__ = ['mean'] -def percentile_mean(image, selem, out=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 pixel values contained inside the - percentile interval [p0,p1] are taken into account. - - Parameters - ---------- - image : ndarray - Image array (uint8 array or uint16). - selem : ndarray - The neighborhood expressed as a 2-D array of 1's and 0's. - out : ndarray - The array to store the result of the morphology. If None is - passed, a new array will be allocated. - shift_x, shift_y : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. - - Returns - ------- - local mean : uint8 array or uint16 array depending on input image - The result of the local mean. - - Examples - -------- - to be updated - >>> # Erosion shrinks bright regions - >>> from skimage.morphology import square - >>> bright_square = 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) - >>> erosion(bright_square, square(3)) - array([[0, 0, 0, 0, 0], - [0, 0, 0, 0, 0], - [0, 0, 1, 0, 0], - [0, 0, 0, 0, 0], - [0, 0, 0, 0, 0]], dtype=uint8) - +def find_bitdepth(image): + """returns the max bith depth of a uint16 image """ - pass + umax = np.max(image) + if umax>2: + return int(np.log2(umax)) + else: + return 1 -def bilateral_mean(image, selem, out=None, shift_x=False, shift_y=False, s0=10, s1=10): - pass -def mean(image, selem, out=None, shift_x=False, shift_y=False): +def mean(image, selem, mask=None, out=None, shift_x=False, shift_y=False): """Return greyscale local mean of an image. Mean is computed on the given structuring element. @@ -67,7 +31,11 @@ def mean(image, selem, out=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). + 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 + 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). selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray @@ -101,12 +69,18 @@ def mean(image, selem, out=None, shift_x=False, shift_y=False): [0, 0, 0, 0, 0]], dtype=uint8) """ - pass -# if image is out: -# raise NotImplementedError("In-place erosion not supported!") -# image = img_as_ubyte(image) -# selem = img_as_ubyte(selem) -# return cmorph.erode(image, selem, out=out, -# shift_x=shift_x, shift_y=shift_y) - + if image is out: + raise NotImplementedError("In-place erosion not supported!") + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8.mean(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image are supported!") + return _crank16.mean(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,bitdepth=bitdepth+1) + else: + raise TypeError("only uint8 and uint16 image supported!") diff --git a/skimage/rank/tests/test_rank.py b/skimage/rank/tests/test_rank.py index 2a1e253d..77dae32b 100644 --- a/skimage/rank/tests/test_rank.py +++ b/skimage/rank/tests/test_rank.py @@ -2,9 +2,30 @@ import numpy as np import matplotlib.pyplot as plt from skimage import data +from skimage.morphology.selem import disk import skimage.rank as rank print dir(rank) +print rank.mean +print rank.percentile_mean +print rank.bilateral_mean + +a8 = data.camera() +a16 = a8.astype('uint16')*16 +selem = disk(10) + +f8 = rank.mean(a8,selem) +f16 = rank.mean(a16,selem) + +plt.figure() +plt.imshow(np.hstack((a8,f8))) +plt.colorbar() +plt.figure() +plt.imshow(np.hstack((a16,f16))) +plt.colorbar() +plt.show() + + From d9efa0bc6c85317d847de4d8b865c2e41cf75da1 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 11:28:27 +0200 Subject: [PATCH 13/86] update setup to be compatible with scikits-image --- skimage/rank/setup.py | 114 +++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/skimage/rank/setup.py b/skimage/rank/setup.py index 581e64ed..4f57209a 100644 --- a/skimage/rank/setup.py +++ b/skimage/rank/setup.py @@ -1,59 +1,59 @@ -import numpy as np - -from distutils.core import setup -from distutils.extension import Extension -from Cython.Distutils import build_ext - -setup( - cmdclass = {'build_ext': build_ext}, - ext_modules = [Extension("_crank8", ["_crank8.pyx"], include_dirs=[np.get_include()]), - Extension("_crank8_percentiles", ["_crank8_percentiles.pyx"], include_dirs=[np.get_include()]), - Extension("_crank16", ["_crank16.pyx"], include_dirs=[np.get_include()]), - Extension("_crank16_bilateral", ["_crank16_bilateral.pyx"], include_dirs=[np.get_include()]), - Extension("_crank16_percentiles", ["_crank16_percentiles.pyx"], include_dirs=[np.get_include()])] -) +#import numpy as np +# +#from distutils.core import setup +#from distutils.extension import Extension +#from Cython.Distutils import build_ext +# +#setup( +# cmdclass = {'build_ext': build_ext}, +# ext_modules = [Extension("_crank8", ["_crank8.pyx"], include_dirs=[np.get_include()]), +# Extension("_crank8_percentiles", ["_crank8_percentiles.pyx"], include_dirs=[np.get_include()]), +# Extension("_crank16", ["_crank16.pyx"], include_dirs=[np.get_include()]), +# Extension("_crank16_bilateral", ["_crank16_bilateral.pyx"], include_dirs=[np.get_include()]), +# Extension("_crank16_percentiles", ["_crank16_percentiles.pyx"], include_dirs=[np.get_include()])] +#) -##!/usr/bin/env python -# -#import os -#from skimage._build import cython -# -#base_path = os.path.abspath(os.path.dirname(__file__)) -# -# -#def configuration(parent_package='', top_path=None): -# from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs -# -# config = Configuration('rank', parent_package, top_path) -## config.add_data_dir('tests') -# -# cython(['_crank8.pyx'], working_path=base_path) -# cython(['_crank8_percentiles.pyx'], working_path=base_path) -# cython(['_crank16.pyx'], working_path=base_path) -# cython(['_crank16_percentiles.pyx'], working_path=base_path) -# cython(['_crank16_bilateral.pyx'], working_path=base_path) -# -# config.add_extension('_crank8', sources=['_crank8.c'], -# include_dirs=[get_numpy_include_dirs()]) -# config.add_extension('_crank8_percentiles', sources=['_crank8_percentiles.c'], -# include_dirs=[get_numpy_include_dirs()]) -# config.add_extension('_crank16', sources=['_crank16.c'], -# include_dirs=[get_numpy_include_dirs()]) -# config.add_extension('_crank16_percentiles', sources=['_crank16_percentiles.c'], -# include_dirs=[get_numpy_include_dirs()]) -# config.add_extension('_crank16_bilateral', sources=['_crank16_bilateral.c'], -# include_dirs=[get_numpy_include_dirs()]) -# -# return config -# -#if __name__ == '__main__': -# from numpy.distutils.core import setup -# setup(maintainer='scikits-image Developers', -# author='Olivier Debeir', -# maintainer_email='scikits-image@googlegroups.com', -# description='Rank filters', -# url='https://github.com/scikits-image/scikits-image', -# license='SciPy License (BSD Style)', -# **(configuration(top_path='').todict()) -# ) +#!/usr/bin/env python + +import os +from skimage._build import cython + +base_path = os.path.abspath(os.path.dirname(__file__)) + + +def configuration(parent_package='', top_path=None): + from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs + + config = Configuration('rank', parent_package, top_path) +# config.add_data_dir('tests') + + cython(['_crank8.pyx'], working_path=base_path) + cython(['_crank8_percentiles.pyx'], working_path=base_path) + cython(['_crank16.pyx'], working_path=base_path) + cython(['_crank16_percentiles.pyx'], working_path=base_path) + cython(['_crank16_bilateral.pyx'], working_path=base_path) + + config.add_extension('_crank8', sources=['_crank8.c'], + include_dirs=[get_numpy_include_dirs()]) + config.add_extension('_crank8_percentiles', sources=['_crank8_percentiles.c'], + include_dirs=[get_numpy_include_dirs()]) + config.add_extension('_crank16', sources=['_crank16.c'], + include_dirs=[get_numpy_include_dirs()]) + config.add_extension('_crank16_percentiles', sources=['_crank16_percentiles.c'], + include_dirs=[get_numpy_include_dirs()]) + config.add_extension('_crank16_bilateral', sources=['_crank16_bilateral.c'], + include_dirs=[get_numpy_include_dirs()]) + + return config + +if __name__ == '__main__': + from numpy.distutils.core import setup + setup(maintainer='scikits-image Developers', + author='Olivier Debeir', + maintainer_email='scikits-image@googlegroups.com', + description='Rank filters', + url='https://github.com/scikits-image/scikits-image', + license='SciPy License (BSD Style)', + **(configuration(top_path='').todict()) + ) From 5e14bf201bc063d882078a1d7b7e8c22a5d830be Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 12:09:03 +0200 Subject: [PATCH 14/86] add percentile mean --- skimage/rank/generic.py | 10 ++++++ skimage/rank/percentile_rank.py | 30 +++++++++++++++--- skimage/rank/rank.py | 54 +++++++++++++++++---------------- skimage/rank/tests/test_rank.py | 11 +++++++ 4 files changed, 75 insertions(+), 30 deletions(-) create mode 100644 skimage/rank/generic.py diff --git a/skimage/rank/generic.py b/skimage/rank/generic.py new file mode 100644 index 00000000..e8808e5e --- /dev/null +++ b/skimage/rank/generic.py @@ -0,0 +1,10 @@ +import numpy as np + +def find_bitdepth(image): + """returns the max bith depth of a uint16 image + """ + umax = np.max(image) + if umax>2: + return int(np.log2(umax)) + else: + return 1 diff --git a/skimage/rank/percentile_rank.py b/skimage/rank/percentile_rank.py index 49f87dd4..840a302f 100644 --- a/skimage/rank/percentile_rank.py +++ b/skimage/rank/percentile_rank.py @@ -7,11 +7,14 @@ __docformat__ = 'restructuredtext en' import warnings from skimage import img_as_ubyte +import numpy as np + +from .generic import find_bitdepth +import _crank16_percentiles,_crank8_percentiles __all__ = ['percentile_mean'] - -def percentile_mean(image, selem, out=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 pixel values contained inside the @@ -20,16 +23,22 @@ def percentile_mean(image, selem, out=None, shift_x=False, shift_y=False, p0=.0, Parameters ---------- image : ndarray - Image array (uint8 array or uint16). + 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 The array to store the result of the morphology. If None is passed, 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 : bool shift structuring element about center point. This only affects eccentric structuring elements (i.e. selem with even numbered sides). Shift is bounded to the structuring element sizes. + p0, p1 : float in [0.,...,1.] + define the [p0,p1] percentile interval to be considered for computing the value. Returns ------- @@ -54,5 +63,18 @@ def percentile_mean(image, selem, out=None, shift_x=False, shift_y=False, p0=.0, [0, 0, 0, 0, 0]], dtype=uint8) """ - pass + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8_percentiles.mean(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16_percentiles.mean(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!") + diff --git a/skimage/rank/rank.py b/skimage/rank/rank.py index 7e4d16a2..c26fd033 100644 --- a/skimage/rank/rank.py +++ b/skimage/rank/rank.py @@ -9,21 +9,13 @@ import warnings from skimage import img_as_ubyte import numpy as np +from .generic import find_bitdepth import _crank16,_crank8 __all__ = ['mean'] -def find_bitdepth(image): - """returns the max bith depth of a uint16 image - """ - umax = np.max(image) - if umax>2: - return int(np.log2(umax)) - else: - return 1 - -def mean(image, selem, mask=None, out=None, shift_x=False, shift_y=False): +def mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Return greyscale local mean of an image. Mean is computed on the given structuring element. @@ -33,14 +25,14 @@ def mean(image, selem, mask=None, out=None, shift_x=False, shift_y=False): 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 - 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). selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. out : ndarray The array to store the result of the morphology. If None is passed, 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 : bool shift structuring element about center point. This only affects eccentric structuring elements (i.e. selem with even numbered sides). @@ -54,33 +46,43 @@ def mean(image, selem, mask=None, out=None, shift_x=False, shift_y=False): Examples -------- to be updated - >>> # Erosion shrinks bright regions + >>> # Local mean >>> from skimage.morphology import square - >>> bright_square = np.array([[0, 0, 0, 0, 0], + >>> ima8 = 255*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) - >>> erosion(bright_square, square(3)) - array([[0, 0, 0, 0, 0], - [0, 0, 0, 0, 0], - [0, 0, 1, 0, 0], - [0, 0, 0, 0, 0], - [0, 0, 0, 0, 0]], dtype=uint8) + >>> mean(ima8, square(3)) + array([[ 63, 85, 127, 85, 63], + [ 85, 113, 170, 113, 85], + [127, 170, 255, 170, 127], + [ 85, 113, 170, 113, 85], + [ 63, 85, 127, 85, 63]], dtype=uint8) + + >>> ima16 = 4095*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) + >>> mean(ima16, square(3)) + array([[1023, 1365, 2047, 1365, 1023], + [1365, 1820, 2730, 1820, 1365], + [2047, 2730, 4095, 2730, 2047], + [1365, 1820, 2730, 1820, 1365], + [1023, 1365, 2047, 1365, 1023]], dtype=uint16) """ - if image is out: - raise NotImplementedError("In-place erosion not supported!") selem = img_as_ubyte(selem) if mask is not None: mask = img_as_ubyte(mask) if image.dtype == np.uint8: - return _crank8.mean(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask) + return _crank8.mean(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) elif image.dtype == np.uint16: bitdepth = find_bitdepth(image) if bitdepth>11: - raise ValueError("only uint16 <4096 image are supported!") - return _crank16.mean(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,bitdepth=bitdepth+1) + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16.mean(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!") diff --git a/skimage/rank/tests/test_rank.py b/skimage/rank/tests/test_rank.py index 77dae32b..75dd7f65 100644 --- a/skimage/rank/tests/test_rank.py +++ b/skimage/rank/tests/test_rank.py @@ -24,6 +24,17 @@ plt.colorbar() plt.figure() plt.imshow(np.hstack((a16,f16))) plt.colorbar() + +f8 = rank.percentile_mean(a8,selem,p0=.1,p1=.9) +f16 = rank.percentile_mean(a16,selem,p0=.1,p1=.9) + +plt.figure() +plt.imshow(np.hstack((a8,f8))) +plt.colorbar() +plt.figure() +plt.imshow(np.hstack((a16,f16))) +plt.colorbar() + plt.show() From 007e13609cefb58596998c09283f4ef9d5ae2b59 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 14:46:48 +0200 Subject: [PATCH 15/86] add other rank filters --- skimage/rank/rank.py | 927 ++++++++++++++++++++++++++++++++- skimage/rank/tests/demo_all.py | 44 +- 2 files changed, 950 insertions(+), 21 deletions(-) diff --git a/skimage/rank/rank.py b/skimage/rank/rank.py index c26fd033..9045f04e 100644 --- a/skimage/rank/rank.py +++ b/skimage/rank/rank.py @@ -9,11 +9,365 @@ import warnings from skimage import img_as_ubyte import numpy as np -from .generic import find_bitdepth +from generic import find_bitdepth import _crank16,_crank8 -__all__ = ['mean'] +__all__ = ['autolevel','bottomhat','egalise','gradient','maximum','mean' + ,'meansubstraction','median','minimum','modal','morph_contr_enh','pop'] +def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): + """Return greyscale local autolevel of an image. + + Autolevel is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local autolevel : uint8 array or uint16 array depending on input image + The result of the local autolevel. + + Examples + -------- + to be updated + >>> # Local mean + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> autolevel(ima8, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 255, 255, 255, 0], + [ 0, 255, 0, 255, 0], + [ 0, 255, 255, 255, 0], + [ 0, 0, 0, 0, 0]], dtype=uint8) + + >>> ima16 = 4095*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) + >>> autolevel(ima16, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 4096, 4096, 4096, 0], + [ 0, 4096, 0, 4096, 0], + [ 0, 4096, 4096, 4096, 0], + [ 0, 0, 0, 0, 0]], dtype=uint16) + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8.autolevel(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16.autolevel(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!") + +def bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): + """Return greyscale local bottomhat of an image. + + Bottomhat is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local bottomhat : uint8 array or uint16 array depending on input image + The result of the local bottomhat. + + Examples + -------- + to be updated + >>> # Local mean + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> bottomhat(ima8, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 255, 255, 255, 0], + [ 0, 255, 0, 255, 0], + [ 0, 255, 255, 255, 0], + [ 0, 0, 0, 0, 0]], dtype=uint8) + + >>> ima16 = 4095*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) + >>> bottomhat(ima16, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 4095, 0, 4095, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 0, 0, 0, 0]], dtype=uint16) + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8.bottomhat(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16.bottomhat(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!") + +def egalise(image, selem, out=None, mask=None, shift_x=False, shift_y=False): + """Return greyscale local egalise of an image. + + egalise is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local egalise : uint8 array or uint16 array depending on input image + The result of the local egalise. + + Examples + -------- + to be updated + >>> # Local mean + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> egalise(ima8, square(3)) + array([[191, 170, 127, 170, 191], + [170, 255, 255, 255, 170], + [127, 255, 255, 255, 127], + [170, 255, 255, 255, 170], + [191, 170, 127, 170, 191]], dtype=uint8) + + >>> ima16 = 4095*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) + >>> egalise(ima16, square(3)) + array([[3072, 2730, 2048, 2730, 3072], + [2730, 4096, 4096, 4096, 2730], + [2048, 4096, 4096, 4096, 2048], + [2730, 4096, 4096, 4096, 2730], + [3072, 2730, 2048, 2730, 3072]], dtype=uint16) + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8.egalise(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16.egalise(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!") + +def gradient(image, selem, out=None, mask=None, shift_x=False, shift_y=False): + """Return greyscale local gradient of an image. + + gradient is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local gradient : uint8 array or uint16 array depending on input image + The result of the local gradient. + + Examples + -------- + to be updated + >>> # Local gradient + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> gradient(ima8, square(3)) + array([[255, 255, 255, 255, 255], + [255, 255, 255, 255, 255], + [255, 255, 0, 255, 255], + [255, 255, 255, 255, 255], + [255, 255, 255, 255, 255]], dtype=uint8) + + >>> ima16 = 4095*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) + >>> gradient(ima16, square(3)) + array([[4095, 4095, 4095, 4095, 4095], + [4095, 4095, 4095, 4095, 4095], + [4095, 4095, 0, 4095, 4095], + [4095, 4095, 4095, 4095, 4095], + [4095, 4095, 4095, 4095, 4095]], dtype=uint16) + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8.gradient(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16.gradient(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!") + + +def maximum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): + """Return greyscale local maximum of an image. + + maximum is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local maximum : uint8 array or uint16 array depending on input image + The result of the local maximum. + + Examples + -------- + to be updated + >>> # Local maximum + >>> from skimage.morphology import square + >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], + ... [0, 0, 0, 0, 0], + ... [0, 0, 1, 0, 0], + ... [0, 0, 0, 0, 0], + ... [0, 0, 0, 0, 0]], dtype=np.uint8) + >>> maximum(ima8, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 255, 255, 255, 0], + [ 0, 255, 255, 255, 0], + [ 0, 255, 255, 255, 0], + [ 0, 0, 0, 0, 0]], dtype=uint8) + + >>> ima16 = 4095*np.array([[0, 0, 0, 0, 0], + ... [0, 0, 0, 0, 0], + ... [0, 0, 1, 0, 0], + ... [0, 0, 0, 0, 0], + ... [0, 0, 0, 0, 0]], dtype=np.uint16) + >>> maximum(ima16, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 0, 0, 0, 0]], dtype=uint16) + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8.maximum(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16.maximum(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!") def mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Return greyscale local mean of an image. @@ -86,3 +440,572 @@ def mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False): else: raise TypeError("only uint8 and uint16 image supported!") +def meansubstraction(image, selem, out=None, mask=None, shift_x=False, shift_y=False): + """Return greyscale local meansubstraction of an image. + + meansubstraction is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local meansubstraction : uint8 array or uint16 array depending on input image + The result of the local meansubstraction. + + Examples + -------- + to be updated + >>> # Local meansubstraction + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> meansubstraction(ima8, square(3)) + array([[ 95, 84, 63, 84, 95], + [ 84, 197, 169, 197, 84], + [ 63, 169, 127, 169, 63], + [ 84, 197, 169, 197, 84], + [ 95, 84, 63, 84, 95]], dtype=uint8) + + >>> ima16 = 4095*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) + >>> meansubstraction(ima16, square(3)) + array([[1536, 1365, 1024, 1365, 1536], + [1365, 3185, 2730, 3185, 1365], + [1024, 2730, 2048, 2730, 1024], + [1365, 3185, 2730, 3185, 1365], + [1536, 1365, 1024, 1365, 1536]], dtype=uint16) + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8.meansubstraction(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16.meansubstraction(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!") + +def median(image, selem, out=None, mask=None, shift_x=False, shift_y=False): + """Return greyscale local median of an image. + + median is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local median : uint8 array or uint16 array depending on input image + The result of the local median. + + Examples + -------- + to be updated + >>> # Local median + >>> from skimage.morphology import square + >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], + ... [0, 1, 1, 1, 0], + ... [0, 1, 0, 1, 0], + ... [0, 1, 1, 1, 0], + ... [0, 0, 0, 0, 0]], dtype=np.uint8) + >>> median(ima8, square(3)) + array([[ 0, 0, 255, 0, 0], + [ 0, 0, 255, 0, 0], + [255, 255, 255, 255, 255], + [ 0, 0, 255, 0, 0], + [ 0, 0, 255, 0, 0]], dtype=uint8) + + >>> ima16 = 4095*np.array([[0, 0, 0, 0, 0], + ... [0, 1, 1, 1, 0], + ... [0, 1, 0, 1, 0], + ... [0, 1, 1, 1, 0], + ... [0, 0, 0, 0, 0]], dtype=np.uint16) + >>> median(ima16, square(3)) + array([[ 0, 0, 4095, 0, 0], + [ 0, 0, 4095, 0, 0], + [4095, 4095, 4095, 4095, 4095], + [ 0, 0, 4095, 0, 0], + [ 0, 0, 4095, 0, 0]], dtype=uint16) + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8.median(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16.median(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!") + +def minimum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): + """Return greyscale local minimum of an image. + + minimum is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local minimum : uint8 array or uint16 array depending on input image + The result of the local minimum. + + Examples + -------- + to be updated + >>> # Local minimum + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> minimum(ima8, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0], + [ 0, 0, 255, 0, 0], + [ 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0]], dtype=uint8) + + + >>> ima16 = 4095*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) + >>> minimum(ima16, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0], + [ 0, 0, 4095, 0, 0], + [ 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0]], dtype=uint16) + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8.minimum(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16.minimum(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!") + +def modal(image, selem, out=None, mask=None, shift_x=False, shift_y=False): + """Return greyscale local modal of an image. + + modal is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local modal : uint8 array or uint16 array depending on input image + The result of the local modal. + + Examples + -------- + to be updated + >>> # Local modal + >>> from skimage.morphology import square + >>> ima8 = np.array([[0, 0, 0, 0, 0], + ... [0, 1, 1, 1, 0], + ... [0, 1, 5, 6, 0], + ... [0, 1, 5, 5, 0], + ... [0, 0, 0, 5, 0]], dtype=np.uint8) + >>> modal(ima8, square(3)) + array([[0, 0, 0, 0, 0], + [0, 0, 1, 0, 0], + [0, 1, 1, 0, 0], + [0, 0, 5, 0, 0], + [0, 0, 5, 0, 0]], dtype=uint8) + + + >>> ima16 = 100*np.array([[0, 0, 0, 0, 0], + ... [0, 1, 1, 1, 0], + ... [0, 1, 5, 6, 0], + ... [0, 1, 5, 5, 0], + ... [0, 0, 0, 5, 0]], dtype=np.uint16) + >>> modal(ima16, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 0, 100, 0, 0], + [ 0, 100, 100, 0, 0], + [ 0, 0, 500, 0, 0], + [ 0, 0, 500, 0, 0]], dtype=uint16) + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8.modal(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16.modal(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!") + +def morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, shift_y=False): + """Return greyscale local morph_contr_enh of an image. + + morph_contr_enh is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local morph_contr_enh : uint8 array or uint16 array depending on input image + The result of the local morph_contr_enh. + + Examples + -------- + to be updated + >>> # Local mean + >>> from skimage.morphology import square + >>> ima8 = 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) + >>> morph_contr_enh(ima8, square(3)) + 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=uint8) + + >>> ima16 = 4095*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) + >>> morph_contr_enh(ima16, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 0, 0, 0, 0]], dtype=uint16) + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8.morph_contr_enh(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16.morph_contr_enh(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!") + +def pop(image, selem, out=None, mask=None, shift_x=False, shift_y=False): + """Return greyscale local pop of an image. + + pop is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local pop : uint8 array or uint16 array depending on input image + The result of the local pop. + + Examples + -------- + to be updated + >>> # Local mean + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> pop(ima8, square(3)) + 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]], dtype=uint8) + + >>> ima16 = 4095*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) + >>> pop(ima16, square(3)) + 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]], dtype=uint16) + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8.pop(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16.pop(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!") + +def threshold(image, selem, out=None, mask=None, shift_x=False, shift_y=False): + """Return greyscale local threshold of an image. + + threshold is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local threshold : uint8 array or uint16 array depending on input image + The result of the local threshold. + + Examples + -------- + to be updated + >>> # Local mean + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> threshold(ima8, square(3)) + array([[0, 0, 0, 0, 0], + [0, 1, 1, 1, 0], + [0, 1, 0, 1, 0], + [0, 1, 1, 1, 0], + [0, 0, 0, 0, 0]], dtype=uint8) + + >>> ima16 = 4095*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) + >>> threshold(ima16, square(3)) + array([[0, 0, 0, 0, 0], + [0, 1, 1, 1, 0], + [0, 1, 0, 1, 0], + [0, 1, 1, 1, 0], + [0, 0, 0, 0, 0]], dtype=uint16) + + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8.threshold(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16.threshold(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!") + +def tophat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): + """Return greyscale local tophat of an image. + + tophat is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local tophat : uint8 array or uint16 array depending on input image + The result of the local tophat. + + Examples + -------- + to be updated + >>> # Local mean + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> tophat(ima8, square(3)) + array([[255, 255, 255, 255, 255], + [255, 0, 0, 0, 255], + [255, 0, 0, 0, 255], + [255, 0, 0, 0, 255], + [255, 255, 255, 255, 255]], dtype=uint8) + + >>> ima16 = 4095*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) + >>> tophat(ima16, square(3)) + array([[4095, 4095, 4095, 4095, 4095], + [4095, 0, 0, 0, 4095], + [4095, 0, 0, 0, 4095], + [4095, 0, 0, 0, 4095], + [4095, 4095, 4095, 4095, 4095]], dtype=uint16) + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8.tophat(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16.tophat(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!") \ No newline at end of file diff --git a/skimage/rank/tests/demo_all.py b/skimage/rank/tests/demo_all.py index 8e09048e..da592c3d 100644 --- a/skimage/rank/tests/demo_all.py +++ b/skimage/rank/tests/demo_all.py @@ -1,21 +1,23 @@ import numpy as np import matplotlib.pyplot as plt +from pprint import pprint from skimage import data from skimage.morphology.selem import disk -from skimage.rank import crank8,crank8_percentiles -from skimage.rank import crank16,crank16_percentiles,crank16_bilateral +from skimage.rank import _crank8,_crank8_percentiles +from skimage.rank import _crank16,_crank16_percentiles,_crank16_bilateral -if __name__ == '__main__': +def plot_all(): a8 = data.camera() a16 = a8.astype('uint16')*16 -# selem = np.ones((30,30),dtype='uint8') + # selem = np.ones((30,30),dtype='uint8') selem = disk(5) - for n in dir(crank16): - method = eval('crank16.%s'%n) + + for n in dir(_crank16): + method = eval('_crank16.%s'%n) t = type(method) - if t == type(crank8.maximum): + if t == type(_crank8.maximum): print n,t f = method(a16,selem = selem,bitdepth=12) @@ -28,10 +30,10 @@ if __name__ == '__main__': plt.colorbar() plt.title(method) - for n in dir(crank8): - method = eval('crank8.%s'%n) + for n in dir(_crank8): + method = eval('_crank8.%s'%n) t = type(method) - if t == type(crank8.maximum): + if t == type(_crank8.maximum): print n,t f = method(a8,selem = selem) @@ -44,10 +46,10 @@ if __name__ == '__main__': plt.colorbar() plt.title(method) - for n in dir(crank8_percentiles): - method = eval('crank8_percentiles.%s'%n) + for n in dir(_crank8_percentiles): + method = eval('_crank8_percentiles.%s'%n) t = type(method) - if t == type(crank8.maximum): + if t == type(_crank8.maximum): print n,t f = method(a8,selem = selem,p0=.1,p1=.9) @@ -60,10 +62,10 @@ if __name__ == '__main__': plt.colorbar() plt.title(method) - for n in dir(crank16_percentiles): - method = eval('crank16_percentiles.%s'%n) + for n in dir(_crank16_percentiles): + method = eval('_crank16_percentiles.%s'%n) t = type(method) - if t == type(crank8.maximum): + if t == type(_crank8.maximum): print n,t f = method(a16,selem = selem,bitdepth=12,p0=.1,p1=.9) @@ -77,10 +79,10 @@ if __name__ == '__main__': plt.title(method) selem = disk(50) - for n in dir(crank16_bilateral): - method = eval('crank16_bilateral.%s'%n) + for n in dir(_crank16_bilateral): + method = eval('_crank16_bilateral.%s'%n) t = type(method) - if t == type(crank8.maximum): + if t == type(_crank8.maximum): print n,t f = method(a16,selem = selem,bitdepth=12,s0=300,s1=300) @@ -95,3 +97,7 @@ if __name__ == '__main__': # plt.show() + +if __name__ == '__main__': +# plot_all() + pprint(dir(_crank8)) \ No newline at end of file From fb6017e46931582cbbd93b6c4062b8ff891f4265 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 15:22:59 +0200 Subject: [PATCH 16/86] add percentile filters - in progress --- skimage/rank/percentile_rank.py | 1034 ++++++++++++++++++++++++++++++- 1 file changed, 1016 insertions(+), 18 deletions(-) diff --git a/skimage/rank/percentile_rank.py b/skimage/rank/percentile_rank.py index 840a302f..d658dfb4 100644 --- a/skimage/rank/percentile_rank.py +++ b/skimage/rank/percentile_rank.py @@ -9,16 +9,371 @@ import warnings from skimage import img_as_ubyte import numpy as np -from .generic import find_bitdepth +from generic import find_bitdepth import _crank16_percentiles,_crank8_percentiles -__all__ = ['percentile_mean'] +__all__ = ['percentile_autolevel','percentile_bottomhat','percentile_egalise','percentile_gradient', + 'percentile_maximum','percentile_mean','percentile_meansubstraction','percentile_median', + 'percentile_minimum','percentile_modal','percentile_morph_contr_enh','percentile_pop'] -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. +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. - Mean is computed on the given structuring element. Only pixel values contained inside the - percentile interval [p0,p1] are taken into account. + Autolevel is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local autolevel : uint8 array or uint16 array depending on input image + The result of the local autolevel. + + Examples + -------- + to be updated + >>> # Local mean + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> percentile_autolevel(ima8, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 255, 255, 255, 0], + [ 0, 255, 0, 255, 0], + [ 0, 255, 255, 255, 0], + [ 0, 0, 0, 0, 0]], dtype=uint8) + + >>> ima16 = 4095*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) + >>> percentile_eautolevel(ima16, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 4096, 4096, 4096, 0], + [ 0, 4096, 0, 4096, 0], + [ 0, 4096, 4096, 4096, 0], + [ 0, 0, 0, 0, 0]], dtype=uint16) + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8_percentiles.autolevel(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16_percentiles.autolevel(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!") + +def percentile_bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): + """Return greyscale local bottomhat of an image. + + Bottomhat is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local bottomhat : uint8 array or uint16 array depending on input image + The result of the local bottomhat. + + Examples + -------- + to be updated + >>> # Local mean + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> bottomhat(ima8, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 255, 255, 255, 0], + [ 0, 255, 0, 255, 0], + [ 0, 255, 255, 255, 0], + [ 0, 0, 0, 0, 0]], dtype=uint8) + + >>> ima16 = 4095*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) + >>> bottomhat(ima16, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 4095, 0, 4095, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 0, 0, 0, 0]], dtype=uint16) + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8_percentiles.bottomhat(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16_percentiles.bottomhat(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!") + +def percentile_egalise(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): + """Return greyscale local egalise of an image. + + egalise is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local egalise : uint8 array or uint16 array depending on input image + The result of the local egalise. + + Examples + -------- + to be updated + >>> # Local mean + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> egalise(ima8, square(3)) + array([[191, 170, 127, 170, 191], + [170, 255, 255, 255, 170], + [127, 255, 255, 255, 127], + [170, 255, 255, 255, 170], + [191, 170, 127, 170, 191]], dtype=uint8) + + >>> ima16 = 4095*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) + >>> egalise(ima16, square(3)) + array([[3072, 2730, 2048, 2730, 3072], + [2730, 4096, 4096, 4096, 2730], + [2048, 4096, 4096, 4096, 2048], + [2730, 4096, 4096, 4096, 2730], + [3072, 2730, 2048, 2730, 3072]], dtype=uint16) + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8_percentiles.egalise(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16_percentiles.egalise(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!") + +def percentile_gradient(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): + """Return greyscale local gradient of an image. + + gradient is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local gradient : uint8 array or uint16 array depending on input image + The result of the local gradient. + + Examples + -------- + to be updated + >>> # Local gradient + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> gradient(ima8, square(3)) + array([[255, 255, 255, 255, 255], + [255, 255, 255, 255, 255], + [255, 255, 0, 255, 255], + [255, 255, 255, 255, 255], + [255, 255, 255, 255, 255]], dtype=uint8) + + >>> ima16 = 4095*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) + >>> gradient(ima16, square(3)) + array([[4095, 4095, 4095, 4095, 4095], + [4095, 4095, 4095, 4095, 4095], + [4095, 4095, 0, 4095, 4095], + [4095, 4095, 4095, 4095, 4095], + [4095, 4095, 4095, 4095, 4095]], dtype=uint16) + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8_percentiles.gradient(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16_percentiles.gradient(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!") + + +def percentile_maximum(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): + """Return greyscale local maximum of an image. + + maximum is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local maximum : uint8 array or uint16 array depending on input image + The result of the local maximum. + + Examples + -------- + to be updated + >>> # Local maximum + >>> from skimage.morphology import square + >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], + ... [0, 0, 0, 0, 0], + ... [0, 0, 1, 0, 0], + ... [0, 0, 0, 0, 0], + ... [0, 0, 0, 0, 0]], dtype=np.uint8) + >>> maximum(ima8, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 255, 255, 255, 0], + [ 0, 255, 255, 255, 0], + [ 0, 255, 255, 255, 0], + [ 0, 0, 0, 0, 0]], dtype=uint8) + + >>> ima16 = 4095*np.array([[0, 0, 0, 0, 0], + ... [0, 0, 0, 0, 0], + ... [0, 0, 1, 0, 0], + ... [0, 0, 0, 0, 0], + ... [0, 0, 0, 0, 0]], dtype=np.uint16) + >>> maximum(ima16, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 0, 0, 0, 0]], dtype=uint16) + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8_percentiles.maximum(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16_percentiles.maximum(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!") + +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. Parameters ---------- @@ -37,8 +392,6 @@ def percentile_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa shift structuring element about center point. This only affects eccentric structuring elements (i.e. selem with even numbered sides). Shift is bounded to the structuring element sizes. - p0, p1 : float in [0.,...,1.] - define the [p0,p1] percentile interval to be considered for computing the value. Returns ------- @@ -48,19 +401,31 @@ def percentile_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa Examples -------- to be updated - >>> # Erosion shrinks bright regions + >>> # Local mean >>> from skimage.morphology import square - >>> bright_square = np.array([[0, 0, 0, 0, 0], + >>> ima8 = 255*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) - >>> erosion(bright_square, square(3)) - array([[0, 0, 0, 0, 0], - [0, 0, 0, 0, 0], - [0, 0, 1, 0, 0], - [0, 0, 0, 0, 0], - [0, 0, 0, 0, 0]], dtype=uint8) + >>> mean(ima8, square(3)) + array([[ 63, 85, 127, 85, 63], + [ 85, 113, 170, 113, 85], + [127, 170, 255, 170, 127], + [ 85, 113, 170, 113, 85], + [ 63, 85, 127, 85, 63]], dtype=uint8) + + >>> ima16 = 4095*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) + >>> mean(ima16, square(3)) + array([[1023, 1365, 2047, 1365, 1023], + [1365, 1820, 2730, 1820, 1365], + [2047, 2730, 4095, 2730, 2047], + [1365, 1820, 2730, 1820, 1365], + [1023, 1365, 2047, 1365, 1023]], dtype=uint16) """ selem = img_as_ubyte(selem) @@ -72,9 +437,642 @@ def percentile_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa bitdepth = find_bitdepth(image) if bitdepth>11: raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16_percentiles.mean(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,bitdepth=bitdepth+1, - out=out,p0=p0,p1=p1) + return _crank16_percentiles.mean(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!") +def percentile_meansubstraction(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): + """Return greyscale local meansubstraction of an image. + meansubstraction is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local meansubstraction : uint8 array or uint16 array depending on input image + The result of the local meansubstraction. + + Examples + -------- + to be updated + >>> # Local meansubstraction + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> meansubstraction(ima8, square(3)) + array([[ 95, 84, 63, 84, 95], + [ 84, 197, 169, 197, 84], + [ 63, 169, 127, 169, 63], + [ 84, 197, 169, 197, 84], + [ 95, 84, 63, 84, 95]], dtype=uint8) + + >>> ima16 = 4095*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) + >>> meansubstraction(ima16, square(3)) + array([[1536, 1365, 1024, 1365, 1536], + [1365, 3185, 2730, 3185, 1365], + [1024, 2730, 2048, 2730, 1024], + [1365, 3185, 2730, 3185, 1365], + [1536, 1365, 1024, 1365, 1536]], dtype=uint16) + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8_percentiles.meansubstraction(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16_percentiles.meansubstraction(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!") + +def percentile_median(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): + """Return greyscale local median of an image. + + median is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local median : uint8 array or uint16 array depending on input image + The result of the local median. + + Examples + -------- + to be updated + >>> # Local median + >>> from skimage.morphology import square + >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], + ... [0, 1, 1, 1, 0], + ... [0, 1, 0, 1, 0], + ... [0, 1, 1, 1, 0], + ... [0, 0, 0, 0, 0]], dtype=np.uint8) + >>> median(ima8, square(3)) + array([[ 0, 0, 255, 0, 0], + [ 0, 0, 255, 0, 0], + [255, 255, 255, 255, 255], + [ 0, 0, 255, 0, 0], + [ 0, 0, 255, 0, 0]], dtype=uint8) + + >>> ima16 = 4095*np.array([[0, 0, 0, 0, 0], + ... [0, 1, 1, 1, 0], + ... [0, 1, 0, 1, 0], + ... [0, 1, 1, 1, 0], + ... [0, 0, 0, 0, 0]], dtype=np.uint16) + >>> median(ima16, square(3)) + array([[ 0, 0, 4095, 0, 0], + [ 0, 0, 4095, 0, 0], + [4095, 4095, 4095, 4095, 4095], + [ 0, 0, 4095, 0, 0], + [ 0, 0, 4095, 0, 0]], dtype=uint16) + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8_percentiles.median(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16_percentiles.median(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!") + +def percentile_minimum(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): + """Return greyscale local minimum of an image. + + minimum is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local minimum : uint8 array or uint16 array depending on input image + The result of the local minimum. + + Examples + -------- + to be updated + >>> # Local minimum + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> minimum(ima8, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0], + [ 0, 0, 255, 0, 0], + [ 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0]], dtype=uint8) + + + >>> ima16 = 4095*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) + >>> minimum(ima16, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0], + [ 0, 0, 4095, 0, 0], + [ 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0]], dtype=uint16) + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8_percentiles.minimum(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16_percentiles.minimum(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!") + +def percentile_modal(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): + """Return greyscale local modal of an image. + + modal is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local modal : uint8 array or uint16 array depending on input image + The result of the local modal. + + Examples + -------- + to be updated + >>> # Local modal + >>> from skimage.morphology import square + >>> ima8 = np.array([[0, 0, 0, 0, 0], + ... [0, 1, 1, 1, 0], + ... [0, 1, 5, 6, 0], + ... [0, 1, 5, 5, 0], + ... [0, 0, 0, 5, 0]], dtype=np.uint8) + >>> modal(ima8, square(3)) + array([[0, 0, 0, 0, 0], + [0, 0, 1, 0, 0], + [0, 1, 1, 0, 0], + [0, 0, 5, 0, 0], + [0, 0, 5, 0, 0]], dtype=uint8) + + + >>> ima16 = 100*np.array([[0, 0, 0, 0, 0], + ... [0, 1, 1, 1, 0], + ... [0, 1, 5, 6, 0], + ... [0, 1, 5, 5, 0], + ... [0, 0, 0, 5, 0]], dtype=np.uint16) + >>> modal(ima16, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 0, 100, 0, 0], + [ 0, 100, 100, 0, 0], + [ 0, 0, 500, 0, 0], + [ 0, 0, 500, 0, 0]], dtype=uint16) + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8_percentiles.modal(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16_percentiles.modal(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!") + +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. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local morph_contr_enh : uint8 array or uint16 array depending on input image + The result of the local morph_contr_enh. + + Examples + -------- + to be updated + >>> # Local mean + >>> from skimage.morphology import square + >>> ima8 = 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) + >>> morph_contr_enh(ima8, square(3)) + 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=uint8) + + >>> ima16 = 4095*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) + >>> morph_contr_enh(ima16, square(3)) + array([[ 0, 0, 0, 0, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 0, 0, 0, 0]], dtype=uint16) + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8_percentiles.morph_contr_enh(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16_percentiles.morph_contr_enh(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!") + +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. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local pop : uint8 array or uint16 array depending on input image + The result of the local pop. + + Examples + -------- + to be updated + >>> # Local mean + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> pop(ima8, square(3)) + 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]], dtype=uint8) + + >>> ima16 = 4095*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) + >>> pop(ima16, square(3)) + 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]], dtype=uint16) + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8_percentiles.pop(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16_percentiles.pop(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!") + +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. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local threshold : uint8 array or uint16 array depending on input image + The result of the local threshold. + + Examples + -------- + to be updated + >>> # Local mean + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> threshold(ima8, square(3)) + array([[0, 0, 0, 0, 0], + [0, 1, 1, 1, 0], + [0, 1, 0, 1, 0], + [0, 1, 1, 1, 0], + [0, 0, 0, 0, 0]], dtype=uint8) + + >>> ima16 = 4095*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) + >>> threshold(ima16, square(3)) + array([[0, 0, 0, 0, 0], + [0, 1, 1, 1, 0], + [0, 1, 0, 1, 0], + [0, 1, 1, 1, 0], + [0, 0, 0, 0, 0]], dtype=uint16) + + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8_percentiles.threshold(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16_percentiles.threshold(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!") + +def percentile_tophat(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): + """Return greyscale local tophat of an image. + + tophat is computed on the given structuring element. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + + Returns + ------- + local tophat : uint8 array or uint16 array depending on input image + The result of the local tophat. + + Examples + -------- + to be updated + >>> # Local mean + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> tophat(ima8, square(3)) + array([[255, 255, 255, 255, 255], + [255, 0, 0, 0, 255], + [255, 0, 0, 0, 255], + [255, 0, 0, 0, 255], + [255, 255, 255, 255, 255]], dtype=uint8) + + >>> ima16 = 4095*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) + >>> tophat(ima16, square(3)) + array([[4095, 4095, 4095, 4095, 4095], + [4095, 0, 0, 0, 4095], + [4095, 0, 0, 0, 4095], + [4095, 0, 0, 0, 4095], + [4095, 4095, 4095, 4095, 4095]], dtype=uint16) + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8_percentiles.tophat(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16_percentiles.tophat(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!") + +#__all__ = ['percentile_mean'] + +#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 pixel values contained inside the +# percentile interval [p0,p1] are taken into account. +# +# 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 +# selem : ndarray +# The neighborhood expressed as a 2-D array of 1's and 0's. +# out : ndarray +# The array to store the result of the morphology. If None is +# passed, 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 : bool +# shift structuring element about center point. This only affects +# eccentric structuring elements (i.e. selem with even numbered sides). +# Shift is bounded to the structuring element sizes. +# 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 +# The result of the local mean. +# +# Examples +# -------- +# to be updated +# >>> # Erosion shrinks bright regions +# >>> from skimage.morphology import square +# >>> bright_square = 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) +# >>> erosion(bright_square, square(3)) +# array([[0, 0, 0, 0, 0], +# [0, 0, 0, 0, 0], +# [0, 0, 1, 0, 0], +# [0, 0, 0, 0, 0], +# [0, 0, 0, 0, 0]], dtype=uint8) +# +# """ +# selem = img_as_ubyte(selem) +# if mask is not None: +# mask = img_as_ubyte(mask) +# if image.dtype == np.uint8: +# return _crank8_percentiles.mean(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) +# elif image.dtype == np.uint16: +# bitdepth = find_bitdepth(image) +# if bitdepth>11: +# raise ValueError("only uint16 <4096 image (12bit) supported!") +# return _crank16_percentiles.mean(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!") +# +# From f5e4ae9923be3707e8255ffde5ac9e11b5c4e0b0 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 16:08:30 +0200 Subject: [PATCH 17/86] add percentile filters --- skimage/rank/_crank8_percentiles.pyx | 2 +- skimage/rank/percentile_rank.py | 766 +++++---------------------- 2 files changed, 148 insertions(+), 620 deletions(-) diff --git a/skimage/rank/_crank8_percentiles.pyx b/skimage/rank/_crank8_percentiles.pyx index 81730313..23fe079f 100644 --- a/skimage/rank/_crank8_percentiles.pyx +++ b/skimage/rank/_crank8_percentiles.pyx @@ -187,7 +187,7 @@ 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, float p0=0., float p1=0.): - """bottom hat + """autolevel """ return _core8p(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,p0,p1) diff --git a/skimage/rank/percentile_rank.py b/skimage/rank/percentile_rank.py index d658dfb4..924bdd7a 100644 --- a/skimage/rank/percentile_rank.py +++ b/skimage/rank/percentile_rank.py @@ -12,14 +12,14 @@ import numpy as np from generic import find_bitdepth import _crank16_percentiles,_crank8_percentiles -__all__ = ['percentile_autolevel','percentile_bottomhat','percentile_egalise','percentile_gradient', - 'percentile_maximum','percentile_mean','percentile_meansubstraction','percentile_median', +__all__ = ['percentile_autolevel','percentile_gradient', + 'percentile_mean','percentile_mean_substraction','percentile_median', 'percentile_minimum','percentile_modal','percentile_morph_contr_enh','percentile_pop'] 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. + Autolevel is computed on the given structuring element. Only levels between percentiles [p0,p1] ,are used. Parameters ---------- @@ -38,6 +38,8 @@ def percentile_autolevel(image, selem, out=None, mask=None, shift_x=False, shift shift structuring element about center point. This only affects eccentric structuring elements (i.e. selem with even numbered sides). Shift is bounded to the structuring element sizes. + p0, p1 : float in [0.,...,1.] + define the [p0,p1] percentile interval to be considered for computing the value. Returns ------- @@ -54,10 +56,10 @@ def percentile_autolevel(image, selem, out=None, mask=None, shift_x=False, shift ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> percentile_autolevel(ima8, square(3)) + >>> percentile_autolevel(ima8, square(3), p0=0.,p1=1.) array([[ 0, 0, 0, 0, 0], [ 0, 255, 255, 255, 0], - [ 0, 255, 0, 255, 0], + [ 0, 255, 255, 255, 0], [ 0, 255, 255, 255, 0], [ 0, 0, 0, 0, 0]], dtype=uint8) @@ -66,11 +68,11 @@ def percentile_autolevel(image, selem, out=None, mask=None, shift_x=False, shift ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> percentile_eautolevel(ima16, square(3)) + >>> percentile_autolevel(ima16, square(3), p0=0.,p1=1.) array([[ 0, 0, 0, 0, 0], - [ 0, 4096, 4096, 4096, 0], - [ 0, 4096, 0, 4096, 0], - [ 0, 4096, 4096, 4096, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 4095, 4095, 4095, 0], [ 0, 0, 0, 0, 0]], dtype=uint16) """ @@ -87,150 +89,10 @@ def percentile_autolevel(image, selem, out=None, mask=None, shift_x=False, shift else: raise TypeError("only uint8 and uint16 image supported!") -def percentile_bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): - """Return greyscale local bottomhat of an image. - - Bottomhat is computed on the given structuring element. - - 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 - selem : ndarray - The neighborhood expressed as a 2-D array of 1's and 0's. - out : ndarray - The array to store the result of the morphology. If None is - passed, 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. - - Returns - ------- - local bottomhat : uint8 array or uint16 array depending on input image - The result of the local bottomhat. - - Examples - -------- - to be updated - >>> # Local mean - >>> from skimage.morphology import square - >>> ima8 = 255*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) - >>> bottomhat(ima8, square(3)) - array([[ 0, 0, 0, 0, 0], - [ 0, 255, 255, 255, 0], - [ 0, 255, 0, 255, 0], - [ 0, 255, 255, 255, 0], - [ 0, 0, 0, 0, 0]], dtype=uint8) - - >>> ima16 = 4095*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) - >>> bottomhat(ima16, square(3)) - array([[ 0, 0, 0, 0, 0], - [ 0, 4095, 4095, 4095, 0], - [ 0, 4095, 0, 4095, 0], - [ 0, 4095, 4095, 4095, 0], - [ 0, 0, 0, 0, 0]], dtype=uint16) - """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8_percentiles.bottomhat(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16_percentiles.bottomhat(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!") - -def percentile_egalise(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): - """Return greyscale local egalise of an image. - - egalise is computed on the given structuring element. - - 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 - selem : ndarray - The neighborhood expressed as a 2-D array of 1's and 0's. - out : ndarray - The array to store the result of the morphology. If None is - passed, 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. - - Returns - ------- - local egalise : uint8 array or uint16 array depending on input image - The result of the local egalise. - - Examples - -------- - to be updated - >>> # Local mean - >>> from skimage.morphology import square - >>> ima8 = 255*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) - >>> egalise(ima8, square(3)) - array([[191, 170, 127, 170, 191], - [170, 255, 255, 255, 170], - [127, 255, 255, 255, 127], - [170, 255, 255, 255, 170], - [191, 170, 127, 170, 191]], dtype=uint8) - - >>> ima16 = 4095*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) - >>> egalise(ima16, square(3)) - array([[3072, 2730, 2048, 2730, 3072], - [2730, 4096, 4096, 4096, 2730], - [2048, 4096, 4096, 4096, 2048], - [2730, 4096, 4096, 4096, 2730], - [3072, 2730, 2048, 2730, 3072]], dtype=uint16) - """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8_percentiles.egalise(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16_percentiles.egalise(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!") - def percentile_gradient(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): - """Return greyscale local gradient of an image. + """Return greyscale local percentile_gradient of an image. - gradient is computed on the given structuring element. + percentile_gradient is computed on the given structuring element. Only levels between percentiles [p0,p1] ,are used. Parameters ---------- @@ -249,11 +111,13 @@ def percentile_gradient(image, selem, out=None, mask=None, shift_x=False, shift_ shift structuring element about center point. This only affects eccentric structuring elements (i.e. selem with even numbered sides). Shift is bounded to the structuring element sizes. + p0, p1 : float in [0.,...,1.] + define the [p0,p1] percentile interval to be considered for computing the value. Returns ------- - local gradient : uint8 array or uint16 array depending on input image - The result of the local gradient. + local percentile_gradient : uint8 array or uint16 array depending on input image + The result of the local percentile_gradient. Examples -------- @@ -265,10 +129,10 @@ def percentile_gradient(image, selem, out=None, mask=None, shift_x=False, shift_ ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> gradient(ima8, square(3)) + >>> percentile_gradient(ima8, square(3), p0=0.,p1=1.) array([[255, 255, 255, 255, 255], [255, 255, 255, 255, 255], - [255, 255, 0, 255, 255], + [255, 255, 255, 255, 255], [255, 255, 255, 255, 255], [255, 255, 255, 255, 255]], dtype=uint8) @@ -277,10 +141,10 @@ def percentile_gradient(image, selem, out=None, mask=None, shift_x=False, shift_ ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> gradient(ima16, square(3)) + >>> percentile_gradient(ima16, square(3), p0=0.,p1=1.) array([[4095, 4095, 4095, 4095, 4095], [4095, 4095, 4095, 4095, 4095], - [4095, 4095, 0, 4095, 4095], + [4095, 4095, 4095, 4095, 4095], [4095, 4095, 4095, 4095, 4095], [4095, 4095, 4095, 4095, 4095]], dtype=uint16) @@ -299,81 +163,10 @@ def percentile_gradient(image, selem, out=None, mask=None, shift_x=False, shift_ raise TypeError("only uint8 and uint16 image supported!") -def percentile_maximum(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): - """Return greyscale local maximum of an image. - - maximum is computed on the given structuring element. - - 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 - selem : ndarray - The neighborhood expressed as a 2-D array of 1's and 0's. - out : ndarray - The array to store the result of the morphology. If None is - passed, 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. - - Returns - ------- - local maximum : uint8 array or uint16 array depending on input image - The result of the local maximum. - - Examples - -------- - to be updated - >>> # Local maximum - >>> from skimage.morphology import square - >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], - ... [0, 0, 0, 0, 0], - ... [0, 0, 1, 0, 0], - ... [0, 0, 0, 0, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> maximum(ima8, square(3)) - array([[ 0, 0, 0, 0, 0], - [ 0, 255, 255, 255, 0], - [ 0, 255, 255, 255, 0], - [ 0, 255, 255, 255, 0], - [ 0, 0, 0, 0, 0]], dtype=uint8) - - >>> ima16 = 4095*np.array([[0, 0, 0, 0, 0], - ... [0, 0, 0, 0, 0], - ... [0, 0, 1, 0, 0], - ... [0, 0, 0, 0, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> maximum(ima16, square(3)) - array([[ 0, 0, 0, 0, 0], - [ 0, 4095, 4095, 4095, 0], - [ 0, 4095, 4095, 4095, 0], - [ 0, 4095, 4095, 4095, 0], - [ 0, 0, 0, 0, 0]], dtype=uint16) - - """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8_percentiles.maximum(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16_percentiles.maximum(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!") - 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. + Mean is computed on the given structuring element. Only levels between percentiles [p0,p1] ,are used. Parameters ---------- @@ -392,6 +185,8 @@ def percentile_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa shift structuring element about center point. This only affects eccentric structuring elements (i.e. selem with even numbered sides). Shift is bounded to the structuring element sizes. + p0, p1 : float in [0.,...,1.] + define the [p0,p1] percentile interval to be considered for computing the value. Returns ------- @@ -408,7 +203,7 @@ def percentile_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> mean(ima8, square(3)) + >>> percentile_mean(ima8, square(3),p0=0.,p1=1.) array([[ 63, 85, 127, 85, 63], [ 85, 113, 170, 113, 85], [127, 170, 255, 170, 127], @@ -420,7 +215,7 @@ def percentile_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> mean(ima16, square(3)) + >>> percentile_mean(ima16, square(3),p0=0.,p1=1.) array([[1023, 1365, 2047, 1365, 1023], [1365, 1820, 2730, 1820, 1365], [2047, 2730, 4095, 2730, 2047], @@ -441,10 +236,10 @@ def percentile_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa else: raise TypeError("only uint8 and uint16 image supported!") -def percentile_meansubstraction(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): - """Return greyscale local meansubstraction of an image. +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. - meansubstraction is computed on the given structuring element. + mean_substraction is computed on the given structuring element. Only levels between percentiles [p0,p1] ,are used. Parameters ---------- @@ -463,27 +258,29 @@ def percentile_meansubstraction(image, selem, out=None, mask=None, shift_x=False shift structuring element about center point. This only affects eccentric structuring elements (i.e. selem with even numbered sides). Shift is bounded to the structuring element sizes. + p0, p1 : float in [0.,...,1.] + define the [p0,p1] percentile interval to be considered for computing the value. Returns ------- - local meansubstraction : uint8 array or uint16 array depending on input image - The result of the local meansubstraction. + local mean_substraction : uint8 array or uint16 array depending on input image + The result of the local mean_substraction. Examples -------- to be updated - >>> # Local meansubstraction + >>> # Local mean_substraction >>> from skimage.morphology import square >>> ima8 = 255*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) - >>> meansubstraction(ima8, square(3)) + >>> percentile_mean_substraction(ima8, square(3), p0=0.,p1=1.) array([[ 95, 84, 63, 84, 95], - [ 84, 197, 169, 197, 84], + [ 84, 198, 169, 198, 84], [ 63, 169, 127, 169, 63], - [ 84, 197, 169, 197, 84], + [ 84, 198, 169, 198, 84], [ 95, 84, 63, 84, 95]], dtype=uint8) >>> ima16 = 4095*np.array([[0, 0, 0, 0, 0], @@ -491,7 +288,7 @@ def percentile_meansubstraction(image, selem, out=None, mask=None, shift_x=False ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> meansubstraction(ima16, square(3)) + >>> percentile_mean_substraction(ima16, square(3), p0=0.,p1=1.) array([[1536, 1365, 1024, 1365, 1536], [1365, 3185, 2730, 3185, 1365], [1024, 2730, 2048, 2730, 1024], @@ -503,234 +300,20 @@ def percentile_meansubstraction(image, selem, out=None, mask=None, shift_x=False if mask is not None: mask = img_as_ubyte(mask) if image.dtype == np.uint8: - return _crank8_percentiles.meansubstraction(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) + return _crank8_percentiles.mean_substraction(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) elif image.dtype == np.uint16: bitdepth = find_bitdepth(image) if bitdepth>11: raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16_percentiles.meansubstraction(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,bitdepth=bitdepth+1,out=out,p0=p0,p1=p1) + return _crank16_percentiles.mean_substraction(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!") -def percentile_median(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): - """Return greyscale local median of an image. - - median is computed on the given structuring element. - - 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 - selem : ndarray - The neighborhood expressed as a 2-D array of 1's and 0's. - out : ndarray - The array to store the result of the morphology. If None is - passed, 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. - - Returns - ------- - local median : uint8 array or uint16 array depending on input image - The result of the local median. - - Examples - -------- - to be updated - >>> # Local median - >>> from skimage.morphology import square - >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], - ... [0, 1, 1, 1, 0], - ... [0, 1, 0, 1, 0], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> median(ima8, square(3)) - array([[ 0, 0, 255, 0, 0], - [ 0, 0, 255, 0, 0], - [255, 255, 255, 255, 255], - [ 0, 0, 255, 0, 0], - [ 0, 0, 255, 0, 0]], dtype=uint8) - - >>> ima16 = 4095*np.array([[0, 0, 0, 0, 0], - ... [0, 1, 1, 1, 0], - ... [0, 1, 0, 1, 0], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> median(ima16, square(3)) - array([[ 0, 0, 4095, 0, 0], - [ 0, 0, 4095, 0, 0], - [4095, 4095, 4095, 4095, 4095], - [ 0, 0, 4095, 0, 0], - [ 0, 0, 4095, 0, 0]], dtype=uint16) - - """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8_percentiles.median(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16_percentiles.median(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!") - -def percentile_minimum(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): - """Return greyscale local minimum of an image. - - minimum is computed on the given structuring element. - - 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 - selem : ndarray - The neighborhood expressed as a 2-D array of 1's and 0's. - out : ndarray - The array to store the result of the morphology. If None is - passed, 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. - - Returns - ------- - local minimum : uint8 array or uint16 array depending on input image - The result of the local minimum. - - Examples - -------- - to be updated - >>> # Local minimum - >>> from skimage.morphology import square - >>> ima8 = 255*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) - >>> minimum(ima8, square(3)) - array([[ 0, 0, 0, 0, 0], - [ 0, 0, 0, 0, 0], - [ 0, 0, 255, 0, 0], - [ 0, 0, 0, 0, 0], - [ 0, 0, 0, 0, 0]], dtype=uint8) - - - >>> ima16 = 4095*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) - >>> minimum(ima16, square(3)) - array([[ 0, 0, 0, 0, 0], - [ 0, 0, 0, 0, 0], - [ 0, 0, 4095, 0, 0], - [ 0, 0, 0, 0, 0], - [ 0, 0, 0, 0, 0]], dtype=uint16) - - """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8_percentiles.minimum(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16_percentiles.minimum(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!") - -def percentile_modal(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): - """Return greyscale local modal of an image. - - modal is computed on the given structuring element. - - 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 - selem : ndarray - The neighborhood expressed as a 2-D array of 1's and 0's. - out : ndarray - The array to store the result of the morphology. If None is - passed, 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. - - Returns - ------- - local modal : uint8 array or uint16 array depending on input image - The result of the local modal. - - Examples - -------- - to be updated - >>> # Local modal - >>> from skimage.morphology import square - >>> ima8 = np.array([[0, 0, 0, 0, 0], - ... [0, 1, 1, 1, 0], - ... [0, 1, 5, 6, 0], - ... [0, 1, 5, 5, 0], - ... [0, 0, 0, 5, 0]], dtype=np.uint8) - >>> modal(ima8, square(3)) - array([[0, 0, 0, 0, 0], - [0, 0, 1, 0, 0], - [0, 1, 1, 0, 0], - [0, 0, 5, 0, 0], - [0, 0, 5, 0, 0]], dtype=uint8) - - - >>> ima16 = 100*np.array([[0, 0, 0, 0, 0], - ... [0, 1, 1, 1, 0], - ... [0, 1, 5, 6, 0], - ... [0, 1, 5, 5, 0], - ... [0, 0, 0, 5, 0]], dtype=np.uint16) - >>> modal(ima16, square(3)) - array([[ 0, 0, 0, 0, 0], - [ 0, 0, 100, 0, 0], - [ 0, 100, 100, 0, 0], - [ 0, 0, 500, 0, 0], - [ 0, 0, 500, 0, 0]], dtype=uint16) - - """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8_percentiles.modal(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16_percentiles.modal(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!") 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. + morph_contr_enh is computed on the given structuring element. Only levels between percentiles [p0,p1] ,are used. Parameters ---------- @@ -749,6 +332,8 @@ def percentile_morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, shift structuring element about center point. This only affects eccentric structuring elements (i.e. selem with even numbered sides). Shift is bounded to the structuring element sizes. + p0, p1 : float in [0.,...,1.] + define the [p0,p1] percentile interval to be considered for computing the value. Returns ------- @@ -760,24 +345,24 @@ def percentile_morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, to be updated >>> # Local mean >>> from skimage.morphology import square - >>> ima8 = np.array([[0, 0, 0, 0, 0], + >>> ima8 = 255*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) - >>> morph_contr_enh(ima8, square(3)) - 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=uint8) + >>> percentile_morph_contr_enh(ima8, square(3), p0=0.,p1=1.) + array([[ 0, 0, 0, 0, 0], + [ 0, 255, 255, 255, 0], + [ 0, 255, 255, 255, 0], + [ 0, 255, 255, 255, 0], + [ 0, 0, 0, 0, 0]], dtype=uint8) >>> ima16 = 4095*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) - >>> morph_contr_enh(ima16, square(3)) + >>> percentile_morph_contr_enh(ima16, square(3), p0=0.,p1=1.) array([[ 0, 0, 0, 0, 0], [ 0, 4095, 4095, 4095, 0], [ 0, 4095, 4095, 4095, 0], @@ -798,10 +383,10 @@ def percentile_morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, else: raise TypeError("only uint8 and uint16 image supported!") -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. +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. - pop is computed on the given structuring element. + percentile is computed on the given structuring element. Only levels between percentiles [p0,p1] ,are used. Parameters ---------- @@ -820,6 +405,82 @@ def percentile_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal shift structuring element about center point. This only affects eccentric structuring elements (i.e. selem with even numbered sides). Shift is bounded to the structuring element sizes. + 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 + The result of the local percentile. + + Examples + -------- + to be updated + >>> # Local mean + >>> from skimage.morphology import square + >>> ima8 = 128*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) + >>> percentile(ima8, square(3), p0=0.,p1=1.) + array([[0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0]], dtype=uint8) + + >>> ima16 = 4095*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) + >>> percentile(ima16, square(3), p0=0.,p1=1.) + array([[0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0]], dtype=uint16) + + + """ + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return _crank8_percentiles.percentile(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) + elif image.dtype == np.uint16: + bitdepth = find_bitdepth(image) + if bitdepth>11: + raise ValueError("only uint16 <4096 image (12bit) supported!") + return _crank16_percentiles.percentile(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!") + +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. + + 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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + p0, p1 : float in [0.,...,1.] + define the [p0,p1] percentile interval to be considered for computing the value. Returns ------- @@ -836,7 +497,7 @@ def percentile_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> pop(ima8, square(3)) + >>> percentile_pop(ima8, square(3), p0=0.,p1=1.) array([[4, 6, 6, 6, 4], [6, 9, 9, 9, 6], [6, 9, 9, 9, 6], @@ -848,7 +509,7 @@ def percentile_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> pop(ima16, square(3)) + >>> percentile_pop(ima16, square(3), p0=0.,p1=1.) array([[4, 6, 6, 6, 4], [6, 9, 9, 9, 6], [6, 9, 9, 9, 6], @@ -872,7 +533,7 @@ def percentile_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal 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. + threshold is computed on the given structuring element. Only levels between percentiles [p0,p1] ,are used. Parameters ---------- @@ -891,6 +552,8 @@ def percentile_threshold(image, selem, out=None, mask=None, shift_x=False, shift shift structuring element about center point. This only affects eccentric structuring elements (i.e. selem with even numbered sides). Shift is bounded to the structuring element sizes. + p0, p1 : float in [0.,...,1.] + define the [p0,p1] percentile interval to be considered for computing the value. Returns ------- @@ -907,24 +570,24 @@ def percentile_threshold(image, selem, out=None, mask=None, shift_x=False, shift ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> threshold(ima8, square(3)) - array([[0, 0, 0, 0, 0], - [0, 1, 1, 1, 0], - [0, 1, 0, 1, 0], - [0, 1, 1, 1, 0], - [0, 0, 0, 0, 0]], dtype=uint8) + >>> percentile_threshold(ima8, square(3), p0=0.,p1=1.) + array([[255, 255, 255, 255, 255], + [255, 255, 255, 255, 255], + [255, 255, 255, 255, 255], + [255, 255, 255, 255, 255], + [255, 255, 255, 255, 255]], dtype=uint8) >>> ima16 = 4095*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) - >>> threshold(ima16, square(3)) - array([[0, 0, 0, 0, 0], - [0, 1, 1, 1, 0], - [0, 1, 0, 1, 0], - [0, 1, 1, 1, 0], - [0, 0, 0, 0, 0]], dtype=uint16) + >>> percentile_threshold(ima16, square(3), p0=0.,p1=1.) + array([[4095, 4095, 4095, 4095, 4095], + [4095, 4095, 4095, 4095, 4095], + [4095, 4095, 4095, 4095, 4095], + [4095, 4095, 4095, 4095, 4095], + [4095, 4095, 4095, 4095, 4095]], dtype=uint16) """ @@ -941,138 +604,3 @@ def percentile_threshold(image, selem, out=None, mask=None, shift_x=False, shift else: raise TypeError("only uint8 and uint16 image supported!") -def percentile_tophat(image, selem, out=None, mask=None, shift_x=False, shift_y=False, p0=.0, p1=1.): - """Return greyscale local tophat of an image. - - tophat is computed on the given structuring element. - - 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 - selem : ndarray - The neighborhood expressed as a 2-D array of 1's and 0's. - out : ndarray - The array to store the result of the morphology. If None is - passed, 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. - - Returns - ------- - local tophat : uint8 array or uint16 array depending on input image - The result of the local tophat. - - Examples - -------- - to be updated - >>> # Local mean - >>> from skimage.morphology import square - >>> ima8 = 255*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) - >>> tophat(ima8, square(3)) - array([[255, 255, 255, 255, 255], - [255, 0, 0, 0, 255], - [255, 0, 0, 0, 255], - [255, 0, 0, 0, 255], - [255, 255, 255, 255, 255]], dtype=uint8) - - >>> ima16 = 4095*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) - >>> tophat(ima16, square(3)) - array([[4095, 4095, 4095, 4095, 4095], - [4095, 0, 0, 0, 4095], - [4095, 0, 0, 0, 4095], - [4095, 0, 0, 0, 4095], - [4095, 4095, 4095, 4095, 4095]], dtype=uint16) - """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8_percentiles.tophat(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16_percentiles.tophat(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!") - -#__all__ = ['percentile_mean'] - -#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 pixel values contained inside the -# percentile interval [p0,p1] are taken into account. -# -# 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 -# selem : ndarray -# The neighborhood expressed as a 2-D array of 1's and 0's. -# out : ndarray -# The array to store the result of the morphology. If None is -# passed, 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 : bool -# shift structuring element about center point. This only affects -# eccentric structuring elements (i.e. selem with even numbered sides). -# Shift is bounded to the structuring element sizes. -# 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 -# The result of the local mean. -# -# Examples -# -------- -# to be updated -# >>> # Erosion shrinks bright regions -# >>> from skimage.morphology import square -# >>> bright_square = 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) -# >>> erosion(bright_square, square(3)) -# array([[0, 0, 0, 0, 0], -# [0, 0, 0, 0, 0], -# [0, 0, 1, 0, 0], -# [0, 0, 0, 0, 0], -# [0, 0, 0, 0, 0]], dtype=uint8) -# -# """ -# selem = img_as_ubyte(selem) -# if mask is not None: -# mask = img_as_ubyte(mask) -# if image.dtype == np.uint8: -# return _crank8_percentiles.mean(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) -# elif image.dtype == np.uint16: -# bitdepth = find_bitdepth(image) -# if bitdepth>11: -# raise ValueError("only uint16 <4096 image (12bit) supported!") -# return _crank16_percentiles.mean(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!") -# -# From c4b091d4075af11705920d919b1d959cf73c4de4 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 16:19:04 +0200 Subject: [PATCH 18/86] =?UTF-8?q?add=20bilateral=20filters=20pop=20and=20m?= =?UTF-8?q?ean=C2=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skimage/rank/bilateral_rank.py | 155 ++++++++++++++++++++++++++++++++- 1 file changed, 153 insertions(+), 2 deletions(-) diff --git a/skimage/rank/bilateral_rank.py b/skimage/rank/bilateral_rank.py index eaa6f8d9..4e8d3b6a 100644 --- a/skimage/rank/bilateral_rank.py +++ b/skimage/rank/bilateral_rank.py @@ -8,11 +8,162 @@ __docformat__ = 'restructuredtext en' import warnings from skimage import img_as_ubyte +import numpy as np + +from generic import find_bitdepth +import _crank16_bilateral + + __all__ = ['bilateral_mean'] +def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False, s0=10, s1=10): + """Return greyscale local bilateral_mean of an image. -def bilateral_mean(image, selem, out=None, shift_x=False, shift_y=False, s0=10, s1=10): - pass + bilateral mean is computed on the given structuring element. Only levels between [g-s0,g+s1] ,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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + s0, s1 : int + define the [s0,s1] interval to be considered for computing the value. + + Returns + ------- + local bilateral mean : uint16 array (uint8 image are casted to uint16) + The result of the local bilateral mean. + + Examples + -------- + to be updated + >>> # Local mean + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> bilateral_mean(ima8, square(3), s0=10,s1=10) + array([[ 0, 0, 0, 0, 0], + [ 0, 255, 255, 255, 0], + [ 0, 255, 255, 255, 0], + [ 0, 255, 255, 255, 0], + [ 0, 0, 0, 0, 0]], dtype=uint16) + + >>> ima16 = 4095*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) + >>> bilateral_mean(ima16, square(3), s0=10,s1=10) + array([[ 0, 0, 0, 0, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 0, 0, 0, 0]], dtype=uint16) + + """ + 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 + 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 _crank16_bilateral.mean(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,bitdepth=bitdepth+1,out=out,s0=s0,s1=s1) + + +def bilateral_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=False, s0=10, s1=10): + """Return greyscale local bilateral_pop of an image. + + bilateral pop is computed on the given structuring element. Only levels between [g-s0,g+s1] ,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 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + The array to store the result of the morphology. If None is + passed, 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 : bool + shift structuring element about center point. This only affects + eccentric structuring elements (i.e. selem with even numbered sides). + Shift is bounded to the structuring element sizes. + s0, s1 : int + define the [s0,s1] interval to be considered for computing the value. + + Returns + ------- + local bilateral pop : uint16 array (uint8 image are casted to uint16) + The result of the local bilateral pop. + + Examples + -------- + to be updated + >>> # Local mean + >>> from skimage.morphology import square + >>> ima8 = 255*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) + >>> bilateral_pop(ima8, square(3), s0=10,s1=10) + array([[3, 4, 3, 4, 3], + [4, 4, 6, 4, 4], + [3, 6, 9, 6, 3], + [4, 4, 6, 4, 4], + [3, 4, 3, 4, 3]], dtype=uint16) + + >>> ima16 = 4095*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) + >>> bilateral_pop(ima16, square(3), s0=10,s1=10) + array([[3, 4, 3, 4, 3], + [4, 4, 6, 4, 4], + [3, 6, 9, 6, 3], + [4, 4, 6, 4, 4], + [3, 4, 3, 4, 3]], dtype=uint16) + + """ + 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 + 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 _crank16_bilateral.pop(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,bitdepth=bitdepth+1,out=out,s0=s0,s1=s1) From 9b36d56234c1572f27d278e5f1feeee7e0fac887 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 17:00:26 +0200 Subject: [PATCH 19/86] add full test --- skimage/rank/bilateral_rank.py | 2 +- skimage/rank/percentile_rank.py | 4 +- skimage/rank/tests/demo_all.py | 149 +++++++++++++------------------- 3 files changed, 65 insertions(+), 90 deletions(-) diff --git a/skimage/rank/bilateral_rank.py b/skimage/rank/bilateral_rank.py index 4e8d3b6a..a76133a6 100644 --- a/skimage/rank/bilateral_rank.py +++ b/skimage/rank/bilateral_rank.py @@ -14,7 +14,7 @@ from generic import find_bitdepth import _crank16_bilateral -__all__ = ['bilateral_mean'] +__all__ = ['bilateral_mean','bilateral_pop'] def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False, s0=10, s1=10): diff --git a/skimage/rank/percentile_rank.py b/skimage/rank/percentile_rank.py index 924bdd7a..b6af753c 100644 --- a/skimage/rank/percentile_rank.py +++ b/skimage/rank/percentile_rank.py @@ -13,8 +13,8 @@ from generic import find_bitdepth import _crank16_percentiles,_crank8_percentiles __all__ = ['percentile_autolevel','percentile_gradient', - 'percentile_mean','percentile_mean_substraction','percentile_median', - 'percentile_minimum','percentile_modal','percentile_morph_contr_enh','percentile_pop'] + 'percentile_mean','percentile_mean_substraction', + 'percentile_morph_contr_enh','percentile_pop'] 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. diff --git a/skimage/rank/tests/demo_all.py b/skimage/rank/tests/demo_all.py index da592c3d..8df5c3e7 100644 --- a/skimage/rank/tests/demo_all.py +++ b/skimage/rank/tests/demo_all.py @@ -4,100 +4,75 @@ from pprint import pprint from skimage import data from skimage.morphology.selem import disk -from skimage.rank import _crank8,_crank8_percentiles -from skimage.rank import _crank16,_crank16_percentiles,_crank16_bilateral +import skimage.rank as rank def plot_all(): a8 = data.camera() a16 = a8.astype('uint16')*16 - # selem = np.ones((30,30),dtype='uint8') selem = disk(5) + name_list = sorted([n for n in dir(rank) if n[0] is not '_']) + print name_list - for n in dir(_crank16): - method = eval('_crank16.%s'%n) - t = type(method) - if t == type(_crank8.maximum): - print n,t - f = method(a16,selem = selem,bitdepth=12) - - plt.figure() - plt.subplot(1,2,1) - plt.imshow(a16) - plt.colorbar() - plt.subplot(1,2,2) - plt.imshow(f) - plt.colorbar() - plt.title(method) - - for n in dir(_crank8): - method = eval('_crank8.%s'%n) - t = type(method) - if t == type(_crank8.maximum): - print n,t - f = method(a8,selem = selem) - - plt.figure() - plt.subplot(1,2,1) - plt.imshow(a8) - plt.colorbar() - plt.subplot(1,2,2) - plt.imshow(f) - plt.colorbar() - plt.title(method) - - for n in dir(_crank8_percentiles): - method = eval('_crank8_percentiles.%s'%n) - t = type(method) - if t == type(_crank8.maximum): - print n,t - f = method(a8,selem = selem,p0=.1,p1=.9) - - plt.figure() - plt.subplot(1,2,1) - plt.imshow(a8) - plt.colorbar() - plt.subplot(1,2,2) - plt.imshow(f) - plt.colorbar() - plt.title(method) - - for n in dir(_crank16_percentiles): - method = eval('_crank16_percentiles.%s'%n) - t = type(method) - if t == type(_crank8.maximum): - print n,t - f = method(a16,selem = selem,bitdepth=12,p0=.1,p1=.9) - - plt.figure() - plt.subplot(1,2,1) - plt.imshow(a16) - plt.colorbar() - plt.subplot(1,2,2) - plt.imshow(f) - plt.colorbar() - plt.title(method) - - selem = disk(50) - for n in dir(_crank16_bilateral): - method = eval('_crank16_bilateral.%s'%n) - t = type(method) - if t == type(_crank8.maximum): - print n,t - f = method(a16,selem = selem,bitdepth=12,s0=300,s1=300) - - plt.figure() - plt.subplot(1,2,1) - plt.imshow(a16) - plt.colorbar() - plt.subplot(1,2,2) - plt.imshow(f) - plt.colorbar() - plt.title(method) - - # + for n in name_list: + if n.rfind('bilateral')==0: + print n + method = eval('rank.%s'%n) + if type(method) == type(rank.maximum): + print method + f8 = method(a8,selem = selem,s0=10,s1=10) + f16 = method(a16,selem = selem,s0=10,s1=10) + plt.figure() + plt.subplot(2,2,1) + plt.imshow(a8) + plt.colorbar() + plt.subplot(2,2,2) + plt.imshow(f8) + plt.colorbar() + plt.subplot(2,2,3) + plt.imshow(f16) + plt.colorbar() + plt.title(method) + for n in name_list: + if n.rfind('percentile')==0: + print n + method = eval('rank.%s'%n) + if type(method) == type(rank.maximum): + print method + f8 = method(a8,selem = selem,p0=.1,p1=.9) + f16 = method(a16,selem = selem,p0=.1,p1=.9) + plt.figure() + plt.subplot(2,2,1) + plt.imshow(a8) + plt.colorbar() + plt.subplot(2,2,2) + plt.imshow(f8) + plt.colorbar() + plt.subplot(2,2,3) + plt.imshow(f16) + plt.colorbar() + plt.title(method) + for n in name_list: + if n.find('percentile')==-1 and n.find('bilateral')==-1: + print n + method = eval('rank.%s'%n) + if type(method) == type(rank.maximum): + print method + f8 = method(a8,selem = selem) + f16 = method(a16,selem = selem) + plt.figure() + plt.subplot(2,2,1) + plt.imshow(a8) + plt.colorbar() + plt.subplot(2,2,2) + plt.imshow(f8) + plt.colorbar() + plt.subplot(2,2,3) + plt.imshow(f16) + plt.colorbar() + plt.title(method) plt.show() if __name__ == '__main__': -# plot_all() - pprint(dir(_crank8)) \ No newline at end of file + plot_all() + pprint(dir(rank)) \ No newline at end of file From 15251cdd509420aeb18804c412fbac074cc621f9 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 17:15:33 +0200 Subject: [PATCH 20/86] adapt tests --- skimage/rank/README.rst | 12 ++++---- skimage/rank/rank.py | 2 +- skimage/rank/tests/demo_16bitbilateral.py | 15 +++++++--- skimage/rank/tests/demo_benchmark.py | 4 +-- skimage/rank/tests/test_suite.py | 34 +++++++++++------------ 5 files changed, 37 insertions(+), 30 deletions(-) diff --git a/skimage/rank/README.rst b/skimage/rank/README.rst index ef56f997..68d2a1fe 100644 --- a/skimage/rank/README.rst +++ b/skimage/rank/README.rst @@ -1,13 +1,13 @@ To use this to build your Cython file use the commandline options: +.. sourcecode:: text + + $ python setup.py build_ext --inplace + + **To do** * add simple examples -* add doc +* add/check existing doc - - -.. sourcecode:: text - - $ python setup.py build_ext --inplace \ No newline at end of file diff --git a/skimage/rank/rank.py b/skimage/rank/rank.py index 9045f04e..51430236 100644 --- a/skimage/rank/rank.py +++ b/skimage/rank/rank.py @@ -13,7 +13,7 @@ from generic import find_bitdepth import _crank16,_crank8 __all__ = ['autolevel','bottomhat','egalise','gradient','maximum','mean' - ,'meansubstraction','median','minimum','modal','morph_contr_enh','pop'] + ,'meansubstraction','median','minimum','modal','morph_contr_enh','pop','threshold', 'tophat'] def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Return greyscale local autolevel of an image. diff --git a/skimage/rank/tests/demo_16bitbilateral.py b/skimage/rank/tests/demo_16bitbilateral.py index 8001a25f..2a302e6a 100644 --- a/skimage/rank/tests/demo_16bitbilateral.py +++ b/skimage/rank/tests/demo_16bitbilateral.py @@ -2,16 +2,19 @@ import numpy as np import matplotlib.pyplot as plt from skimage import data -from skimage.rank import crank8_percentiles -from skimage.rank import crank16_bilateral +from skimage.morphology import disk +import skimage.rank as rank if __name__ == '__main__': a8 = (data.coins()).astype('uint8') a16 = (data.coins()).astype('uint16')*16 selem = np.ones((20,20),dtype='uint8') - f1 = crank8_percentiles.mean(a8,selem = selem,p0=.1,p1=.9) - f2 = crank16_bilateral.mean(a16,selem = selem,bitdepth=12,s0=500,s1=500) + f1 = rank.percentile_mean(a8,selem = selem,p0=.1,p1=.9) + f2 = rank.bilateral_mean(a16,selem = selem,s0=500,s1=500) + + selem = disk(50) + f3 = rank.egalise(a16,selem = selem) plt.figure() plt.imshow(np.hstack((a8,f1))) @@ -21,4 +24,8 @@ if __name__ == '__main__': plt.imshow(np.hstack((a16,f2))) plt.colorbar() + plt.figure() + plt.imshow(np.hstack((a16,f3))) + plt.colorbar() + plt.show() diff --git a/skimage/rank/tests/demo_benchmark.py b/skimage/rank/tests/demo_benchmark.py index f6fe32bb..42971133 100644 --- a/skimage/rank/tests/demo_benchmark.py +++ b/skimage/rank/tests/demo_benchmark.py @@ -3,13 +3,13 @@ import matplotlib.pyplot as plt from skimage import data from skimage.morphology import dilation -from skimage.rank import _crank8 +import skimage.rank as rank from tools import log_timing @log_timing def cr_max(image,selem): - return _crank8.maximum(image=image,selem = selem) + return rank.maximum(image=image,selem = selem) @log_timing def cm_dil(image,selem): diff --git a/skimage/rank/tests/test_suite.py b/skimage/rank/tests/test_suite.py index 0dcb21ab..51c7f60b 100644 --- a/skimage/rank/tests/test_suite.py +++ b/skimage/rank/tests/test_suite.py @@ -2,8 +2,8 @@ import unittest import numpy as np -from skimage.rank import crank8,crank8_percentiles -from skimage.rank import crank16,crank16_bilateral,crank16_percentiles +from skimage.rank import _crank8,_crank8_percentiles +from skimage.rank import _crank16,_crank16_bilateral,_crank16_percentiles from skimage.morphology import cmorph class TestSequenceFunctions(unittest.TestCase): @@ -17,23 +17,23 @@ class TestSequenceFunctions(unittest.TestCase): 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) + 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) + 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) + 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) + 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) + 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) + 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(self): @@ -43,27 +43,27 @@ class TestSequenceFunctions(unittest.TestCase): 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) + rc = _crank8.maximum(image=a,selem = elem) cm = cmorph.dilate(image=a,selem = elem) self.assertTrue((rc==cm).all()) def test_bitdepth(self): 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) + 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) + 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) + 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) + 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) + r = _crank16_percentiles.mean(image=a16,selem = elem,shift_x=0,shift_y=0,p0=.1,p1=.9,bitdepth=12) def test_population(self): a = np.zeros((5,5),dtype='uint8') elem = np.ones((3,3),dtype='uint8') - p = crank8.pop(image=a,selem = elem) + 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], @@ -75,7 +75,7 @@ class TestSequenceFunctions(unittest.TestCase): 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) + 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], @@ -90,7 +90,7 @@ class TestSequenceFunctions(unittest.TestCase): # 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) + f = _crank16_percentiles.mean(image=a16,selem = elem,shift_x=0,shift_y=0,p0=.1,p1=.9,bitdepth=4) if __name__ == '__main__': From 28cef2e42c3d856e18da1d3d47f5498cec8a020a Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 17:48:15 +0200 Subject: [PATCH 21/86] add examples - to be cont. --- doc/examples/plot_lena_bilateral_denoise.py | 55 +++++++++++++ doc/examples/plot_local_equalize.py | 86 +++++++++++++++++++++ doc/examples/plot_local_threshold.py | 62 +++++++++++++++ 3 files changed, 203 insertions(+) create mode 100644 doc/examples/plot_lena_bilateral_denoise.py create mode 100644 doc/examples/plot_local_equalize.py create mode 100644 doc/examples/plot_local_threshold.py diff --git a/doc/examples/plot_lena_bilateral_denoise.py b/doc/examples/plot_lena_bilateral_denoise.py new file mode 100644 index 00000000..fbee7d67 --- /dev/null +++ b/doc/examples/plot_lena_bilateral_denoise.py @@ -0,0 +1,55 @@ +""" +==================================================== +Denoising the picture of Lena using total variation +==================================================== + +In this example, we denoise a noisy version of the picture of Lena +using the total variation denoising filter. The result of this filter +is an image that has a minimal total variation norm, while being as +close to the initial image as possible. The total variation is the L1 +norm of the gradient of the image, and minimizing the total variation +typically produces "posterized" images with flat domains separated by +sharp edges. + +It is possible to change the degree of posterization by controlling +the tradeoff between denoising and faithfulness to the original image. + +""" + +import numpy as np +import matplotlib.pyplot as plt + +from skimage import data, color, img_as_ubyte +from skimage.filter import tv_denoise +from skimage.rank import bilateral_mean +from skimage.morphology import disk + +l = img_as_ubyte(color.rgb2gray(data.lena())) +l = l[230:290, 220:320] + +noisy = l + 0.4 * l.std() * np.random.random(l.shape) + +selem = disk(30) +bilateral_denoised = bilateral_mean(noisy.astype(np.uint8), selem=selem,s0=10,s1=10) + +plt.figure(figsize=(8, 2)) + +plt.subplot(131) +plt.imshow(noisy, cmap=plt.cm.gray, vmin=40, vmax=220) +plt.axis('off') +plt.title('noisy', fontsize=20) +plt.subplot(132) +plt.imshow(bilateral_denoised, cmap=plt.cm.gray, vmin=40, vmax=220) +plt.axis('off') +plt.title('bilateral denoising', fontsize=20) + +selem = disk(30) +bilateral_denoised = bilateral_mean(noisy.astype(np.uint8), selem=selem,s0=30,s1=30) +plt.subplot(133) +plt.imshow(bilateral_denoised, cmap=plt.cm.gray, vmin=40, vmax=220) +plt.axis('off') +plt.title('(more) bilateral denoising', fontsize=20) + +plt.subplots_adjust(wspace=0.02, hspace=0.02, top=0.9, bottom=0, left=0, + right=1) +plt.show() diff --git a/doc/examples/plot_local_equalize.py b/doc/examples/plot_local_equalize.py new file mode 100644 index 00000000..e79ddbed --- /dev/null +++ b/doc/examples/plot_local_equalize.py @@ -0,0 +1,86 @@ +""" +=============================== +Local Histogram Equalization +=============================== + +This examples enhances an image with low contrast, using a method called +*local histogram equalization*, which "spreads out the most frequent intensity +values" in an image . The equalized image has a roughly linear cumulative +distribution function for each pixel neigborhood. + +to be adjusted... + +.. [1] http://en.wikipedia.org/wiki/Histogram_equalization +.. [2] http://homepages.inf.ed.ac.uk/rbf/HIPR2/stretch.htm + +""" + +from skimage import data +from skimage.util.dtype import dtype_range +from skimage import exposure +from skimage.rank import egalise +from skimage.morphology import disk + + +import matplotlib.pyplot as plt + +import numpy as np + +def plot_img_and_hist(img, axes, bins=256): + """Plot an image along with its histogram and cumulative histogram. + + """ + ax_img, ax_hist = axes + ax_cdf = ax_hist.twinx() + + # Display image + ax_img.imshow(img, cmap=plt.cm.gray) + ax_img.set_axis_off() + + # Display histogram + ax_hist.hist(img.ravel(), bins=bins) + ax_hist.ticklabel_format(axis='y', style='scientific', scilimits=(0, 0)) + ax_hist.set_xlabel('Pixel intensity') + + xmin, xmax = dtype_range[img.dtype.type] + ax_hist.set_xlim(xmin, xmax) + + # Display cumulative distribution + img_cdf, bins = exposure.cumulative_distribution(img, bins) + ax_cdf.plot(bins, img_cdf, 'r') + + return ax_img, ax_hist, ax_cdf + + +# Load an example image +img = data.moon() + +# Contrast stretching +p2 = np.percentile(img, 2) +p98 = np.percentile(img, 98) +img_rescale = exposure.rescale_intensity(img, in_range=(p2, p98)) + +# Equalization +selem = disk(30) +img_eq = egalise(img,selem=selem) + + +# Display results +f, axes = plt.subplots(2, 3, figsize=(8, 4)) + +ax_img, ax_hist, ax_cdf = plot_img_and_hist(img, axes[:, 0]) +ax_img.set_title('Low contrast image') +ax_hist.set_ylabel('Number of pixels') + +ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_rescale, axes[:, 1]) +ax_img.set_title('Contrast stretching') + +ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_eq, axes[:, 2]) +ax_img.set_title('Local Histogram equalization') +ax_cdf.set_ylabel('Fraction of total intensity') + + +# prevent overlap of y-axis labels +plt.subplots_adjust(wspace=0.4) +plt.show() + diff --git a/doc/examples/plot_local_threshold.py b/doc/examples/plot_local_threshold.py new file mode 100644 index 00000000..3b9a42fb --- /dev/null +++ b/doc/examples/plot_local_threshold.py @@ -0,0 +1,62 @@ +""" +===================== +Local Thresholding +===================== + +Thresholding is the simplest way to segment objects from a background. If that +background is relatively uniform, then you can use a global threshold value to +binarize the image by pixel-intensity. If there's large variation in the +background intensity, however, adaptive thresholding (a.k.a. local or dynamic +thresholding) may produce better results. + +Here, we binarize an image using the `threshold_adaptive` function, which +calculates thresholds in regions of size `block_size` surrounding each pixel +(i.e. local neighborhoods). Each threshold value is the weighted mean of the +local neighborhood minus an offset value. + +Added local threshold using rank filter + +to be adjusted ... + +""" +import matplotlib.pyplot as plt + +from skimage import data +from skimage.filter import threshold_otsu, threshold_adaptive + +from skimage.rank import threshold +from skimage.morphology import disk + + +image = data.page() + +global_thresh = threshold_otsu(image) +binary_global = image > global_thresh + +block_size = 40 +binary_adaptive = threshold_adaptive(image, block_size, offset=10) + +selem = disk(10) +loc_thresh = threshold(image,selem=selem) + +fig, axes = plt.subplots(nrows=4, figsize=(7, 8)) +ax0, ax1, ax2, ax3 = axes +plt.gray() + +ax0.imshow(image) +ax0.set_title('Image') + +ax1.imshow(binary_global) +ax1.set_title('Global thresholding') + +ax2.imshow(binary_adaptive) +ax2.set_title('Adaptive thresholding') + +ax3.imshow(loc_thresh) +ax3.set_title('Local thresholding') + + +for ax in axes: + ax.axis('off') + +plt.show() From 31ab620aed8db8420da29aaaea9da1fbc472dcf6 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 18:05:48 +0200 Subject: [PATCH 22/86] add readme --- skimage/rank/README.rst | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/skimage/rank/README.rst b/skimage/rank/README.rst index 68d2a1fe..aae62162 100644 --- a/skimage/rank/README.rst +++ b/skimage/rank/README.rst @@ -7,7 +7,29 @@ To use this to build your Cython file use the commandline options: **To do** -* add simple examples +* add simple examples, adapt documentation on existing examples * add/check existing doc +* adapting tests for each type of filter + +**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 + + ...-----------------------\ +/--------------------------/ +\-------------------------- ... + +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. + From 0b531c8060673e55d0526ee9dd5f3d27b76c93b3 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 11:13:58 +0200 Subject: [PATCH 23/86] add ref --- skimage/rank/rank.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/skimage/rank/rank.py b/skimage/rank/rank.py index 51430236..946f5a49 100644 --- a/skimage/rank/rank.py +++ b/skimage/rank/rank.py @@ -1,4 +1,10 @@ -""" +"""rank.py - rankfilter for local (custom kernel) maximum, minimum, median, mean, auto-level, egalize, etc + +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. + :author: Olivier Debeir, 2012 :license: modified BSD """ From 203cdbd21f68ca0f624ad8b5fb0556b58f96c2ae Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 11:29:28 +0200 Subject: [PATCH 24/86] add comment to bilateral denoising example --- doc/examples/plot_lena_bilateral_denoise.py | 23 ++++++++------------- doc/examples/plot_local_threshold.py | 10 ++++++--- skimage/rank/rank.py | 2 +- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/doc/examples/plot_lena_bilateral_denoise.py b/doc/examples/plot_lena_bilateral_denoise.py index fbee7d67..9fd20285 100644 --- a/doc/examples/plot_lena_bilateral_denoise.py +++ b/doc/examples/plot_lena_bilateral_denoise.py @@ -1,26 +1,22 @@ """ ==================================================== -Denoising the picture of Lena using total variation +Denoising the picture of Lena using bilateral filter ==================================================== In this example, we denoise a noisy version of the picture of Lena -using the total variation denoising filter. The result of this filter -is an image that has a minimal total variation norm, while being as -close to the initial image as possible. The total variation is the L1 -norm of the gradient of the image, and minimizing the total variation -typically produces "posterized" images with flat domains separated by -sharp edges. - -It is possible to change the degree of posterization by controlling -the tradeoff between denoising and faithfulness to the original image. +using an approximation of a bilateral filter. +The pixels used to compute a local mean respect these conditions: +- be close to the central pixel, i.e. belong to the given structuring element. +- have a similar gray level, similarity is fixed by an interval [-s0,+s1] centered on the central pixel gray level. +The filter used is an approximation of a classical bilateral filter in the sens that kernel are usually gaussian +both in spatial and spectral dimensions. """ import numpy as np import matplotlib.pyplot as plt from skimage import data, color, img_as_ubyte -from skimage.filter import tv_denoise from skimage.rank import bilateral_mean from skimage.morphology import disk @@ -44,12 +40,11 @@ plt.axis('off') plt.title('bilateral denoising', fontsize=20) selem = disk(30) -bilateral_denoised = bilateral_mean(noisy.astype(np.uint8), selem=selem,s0=30,s1=30) +bilateral_denoised = bilateral_mean(noisy.astype(np.uint8), selem=selem,s0=40,s1=40) plt.subplot(133) plt.imshow(bilateral_denoised, cmap=plt.cm.gray, vmin=40, vmax=220) plt.axis('off') plt.title('(more) bilateral denoising', fontsize=20) -plt.subplots_adjust(wspace=0.02, hspace=0.02, top=0.9, bottom=0, left=0, - right=1) +plt.subplots_adjust(wspace=0.02, hspace=0.02, top=0.9, bottom=0, left=0,right=1) plt.show() diff --git a/doc/examples/plot_local_threshold.py b/doc/examples/plot_local_threshold.py index 3b9a42fb..01077571 100644 --- a/doc/examples/plot_local_threshold.py +++ b/doc/examples/plot_local_threshold.py @@ -24,7 +24,7 @@ import matplotlib.pyplot as plt from skimage import data from skimage.filter import threshold_otsu, threshold_adaptive -from skimage.rank import threshold +from skimage.rank import threshold,morph_contr_enh from skimage.morphology import disk @@ -38,9 +38,10 @@ binary_adaptive = threshold_adaptive(image, block_size, offset=10) selem = disk(10) loc_thresh = threshold(image,selem=selem) +loc_morph_contr_enh = morph_contr_enh(image,selem=selem) -fig, axes = plt.subplots(nrows=4, figsize=(7, 8)) -ax0, ax1, ax2, ax3 = axes +fig, axes = plt.subplots(nrows=5, figsize=(7, 8)) +ax0, ax1, ax2, ax3, ax4 = axes plt.gray() ax0.imshow(image) @@ -55,6 +56,9 @@ ax2.set_title('Adaptive thresholding') ax3.imshow(loc_thresh) ax3.set_title('Local thresholding') +ax4.imshow(loc_morph_contr_enh) +ax4.set_title('Local morphological contrast enhancement') + for ax in axes: ax.axis('off') diff --git a/skimage/rank/rank.py b/skimage/rank/rank.py index 946f5a49..42e5c23e 100644 --- a/skimage/rank/rank.py +++ b/skimage/rank/rank.py @@ -1,6 +1,6 @@ """rank.py - rankfilter for local (custom kernel) maximum, minimum, median, mean, auto-level, egalize, 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. From 36c12c5cccad24ce7492bed508c0525764e8dba4 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 11:37:22 +0200 Subject: [PATCH 25/86] compare local and global equalise in example --- doc/examples/plot_local_equalize.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/doc/examples/plot_local_equalize.py b/doc/examples/plot_local_equalize.py index e79ddbed..840f2a1f 100644 --- a/doc/examples/plot_local_equalize.py +++ b/doc/examples/plot_local_equalize.py @@ -5,13 +5,14 @@ Local Histogram Equalization This examples enhances an image with low contrast, using a method called *local histogram equalization*, which "spreads out the most frequent intensity -values" in an image . The equalized image has a roughly linear cumulative -distribution function for each pixel neigborhood. +values" in an image . The equalized image [1]_ has a roughly linear cumulative +distribution function for each pixel neighborhood. The local version [2]_ of the histogram +equalization emphasized every local graylevel variations. to be adjusted... .. [1] http://en.wikipedia.org/wiki/Histogram_equalization -.. [2] http://homepages.inf.ed.ac.uk/rbf/HIPR2/stretch.htm +.. [2] http://en.wikipedia.org/wiki/Adaptive_histogram_equalization """ @@ -58,7 +59,7 @@ img = data.moon() # Contrast stretching p2 = np.percentile(img, 2) p98 = np.percentile(img, 98) -img_rescale = exposure.rescale_intensity(img, in_range=(p2, p98)) +img_rescale = exposure.equalize(img) # Equalization selem = disk(30) @@ -73,10 +74,10 @@ ax_img.set_title('Low contrast image') ax_hist.set_ylabel('Number of pixels') ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_rescale, axes[:, 1]) -ax_img.set_title('Contrast stretching') +ax_img.set_title('Global equalise') ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_eq, axes[:, 2]) -ax_img.set_title('Local Histogram equalization') +ax_img.set_title('Local equalize') ax_cdf.set_ylabel('Fraction of total intensity') From c18f07ede1f00fdc6b945e593ae8c874b27073e9 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 11:41:18 +0200 Subject: [PATCH 26/86] rename egalise to equalize --- doc/examples/plot_local_equalize.py | 4 ++-- skimage/rank/_crank8.pyx | 6 +++--- skimage/rank/rank.py | 20 ++++++++++---------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/doc/examples/plot_local_equalize.py b/doc/examples/plot_local_equalize.py index 840f2a1f..ec28067d 100644 --- a/doc/examples/plot_local_equalize.py +++ b/doc/examples/plot_local_equalize.py @@ -19,7 +19,7 @@ to be adjusted... from skimage import data from skimage.util.dtype import dtype_range from skimage import exposure -from skimage.rank import egalise +from skimage import rank from skimage.morphology import disk @@ -63,7 +63,7 @@ img_rescale = exposure.equalize(img) # Equalization selem = disk(30) -img_eq = egalise(img,selem=selem) +img_eq = rank.equalize(img,selem=selem) # Display results diff --git a/skimage/rank/_crank8.pyx b/skimage/rank/_crank8.pyx index cb74021e..12e0577e 100644 --- a/skimage/rank/_crank8.pyx +++ b/skimage/rank/_crank8.pyx @@ -49,7 +49,7 @@ cdef inline np.uint8_t kernel_bottomhat(int* histo, float pop, np.uint8_t g): return (g-i) -cdef inline np.uint8_t kernel_egalise(int* histo, float pop, np.uint8_t g): +cdef inline np.uint8_t kernel_equalize(int* histo, float pop, np.uint8_t g): cdef int i cdef float sum = 0. @@ -210,14 +210,14 @@ def bottomhat(np.ndarray[np.uint8_t, ndim=2] image, """ return _core8(kernel_bottomhat,image,selem,mask,out,shift_x,shift_y) -def egalise(np.ndarray[np.uint8_t, ndim=2] image, +def equalize(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): """local egalisation of the gray level """ - return _core8(kernel_egalise,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_equalize,image,selem,mask,out,shift_x,shift_y) def gradient(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, diff --git a/skimage/rank/rank.py b/skimage/rank/rank.py index 42e5c23e..2a7caab9 100644 --- a/skimage/rank/rank.py +++ b/skimage/rank/rank.py @@ -18,7 +18,7 @@ import numpy as np from generic import find_bitdepth import _crank16,_crank8 -__all__ = ['autolevel','bottomhat','egalise','gradient','maximum','mean' +__all__ = ['autolevel','bottomhat','equalize','gradient','maximum','mean' ,'meansubstraction','median','minimum','modal','morph_contr_enh','pop','threshold', 'tophat'] def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): @@ -162,10 +162,10 @@ def bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): else: raise TypeError("only uint8 and uint16 image supported!") -def egalise(image, selem, out=None, mask=None, shift_x=False, shift_y=False): - """Return greyscale local egalise of an image. +def equalize(image, selem, out=None, mask=None, shift_x=False, shift_y=False): + """Return greyscale local equalize of an image. - egalise is computed on the given structuring element. + equalize is computed on the given structuring element. Parameters ---------- @@ -187,8 +187,8 @@ def egalise(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Returns ------- - local egalise : uint8 array or uint16 array depending on input image - The result of the local egalise. + local equalize : uint8 array or uint16 array depending on input image + The result of the local equalize. Examples -------- @@ -200,7 +200,7 @@ def egalise(image, selem, out=None, mask=None, shift_x=False, shift_y=False): ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> egalise(ima8, square(3)) + >>> equalize(ima8, square(3)) array([[191, 170, 127, 170, 191], [170, 255, 255, 255, 170], [127, 255, 255, 255, 127], @@ -212,7 +212,7 @@ def egalise(image, selem, out=None, mask=None, shift_x=False, shift_y=False): ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> egalise(ima16, square(3)) + >>> equalize(ima16, square(3)) array([[3072, 2730, 2048, 2730, 3072], [2730, 4096, 4096, 4096, 2730], [2048, 4096, 4096, 4096, 2048], @@ -223,12 +223,12 @@ def egalise(image, selem, out=None, mask=None, shift_x=False, shift_y=False): if mask is not None: mask = img_as_ubyte(mask) if image.dtype == np.uint8: - return _crank8.egalise(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) + return _crank8.equalize(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) elif image.dtype == np.uint16: bitdepth = find_bitdepth(image) if bitdepth>11: raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16.egalise(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,bitdepth=bitdepth+1,out=out) + return _crank16.equalize(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!") From edd39df07c34d17b00a96cba2ef4651c4c60a629 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 11:44:03 +0200 Subject: [PATCH 27/86] clean-up code --- skimage/rank/setup.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/skimage/rank/setup.py b/skimage/rank/setup.py index 4f57209a..efe23515 100644 --- a/skimage/rank/setup.py +++ b/skimage/rank/setup.py @@ -1,19 +1,3 @@ -#import numpy as np -# -#from distutils.core import setup -#from distutils.extension import Extension -#from Cython.Distutils import build_ext -# -#setup( -# cmdclass = {'build_ext': build_ext}, -# ext_modules = [Extension("_crank8", ["_crank8.pyx"], include_dirs=[np.get_include()]), -# Extension("_crank8_percentiles", ["_crank8_percentiles.pyx"], include_dirs=[np.get_include()]), -# Extension("_crank16", ["_crank16.pyx"], include_dirs=[np.get_include()]), -# Extension("_crank16_bilateral", ["_crank16_bilateral.pyx"], include_dirs=[np.get_include()]), -# Extension("_crank16_percentiles", ["_crank16_percentiles.pyx"], include_dirs=[np.get_include()])] -#) - - #!/usr/bin/env python import os From 2214123932191f52e42b57e7bbee1aac89658ce3 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 14:14:13 +0200 Subject: [PATCH 28/86] compare ctmf.median_filter with rank.median --- skimage/rank/tests/demo_benchmark.py | 63 +++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/skimage/rank/tests/demo_benchmark.py b/skimage/rank/tests/demo_benchmark.py index 42971133..74200b70 100644 --- a/skimage/rank/tests/demo_benchmark.py +++ b/skimage/rank/tests/demo_benchmark.py @@ -4,6 +4,7 @@ import matplotlib.pyplot as plt from skimage import data from skimage.morphology import dilation import skimage.rank as rank +from skimage.filter import median_filter from tools import log_timing @@ -11,15 +12,24 @@ from tools import log_timing def cr_max(image,selem): return rank.maximum(image=image,selem = selem) +@log_timing +def cr_med(image,selem): + return rank.median(image=image,selem = selem) + @log_timing def cm_dil(image,selem): return dilation(image=image,selem = selem) +@log_timing +def ctmf_med(image,radius): + return median_filter(image=image,radius=radius) + def compare(): """comparison between - crank.maximum rankfilter implementation - cmorph.dilate cython implementation + on increasing structuring element size and increasing image size """ # a = (np.random.random((500,500))*256).astype('uint8') @@ -68,5 +78,56 @@ def compare(): plt.show() +def compare_median(): + """comparison between + - crank.median rankfilter implementation + - ctmf.median_filter filter + + on increasing structuring element size and increasing image size + """ + a = data.camera() + + rec = [] + e_range = range(2,40,2) + for r in e_range: + elem = np.ones((2*r,2*r),dtype='uint8') + # elem = (np.random.random((r,r))>.5).astype('uint8') + rc,ms_rc = cr_med(a,elem) + rctmf,ms_rctmf = ctmf_med(a,r) + rec.append((ms_rc,ms_rctmf)) + # check if results are identical +# assert (rc==rctmf).all() + + rec = np.asarray(rec) + + plt.figure() + plt.title('increasing element size') + plt.plot(e_range,rec) + plt.legend(['rank.median','ctmf.median_filter']) + plt.figure() + plt.imshow(np.hstack((rc,rctmf))) + plt.show() + r = 9 + elem = np.ones((r,r),dtype='uint8') + + rec = [] + s_range = range(100,1000,100) + for s in s_range: + a = (np.random.random((s,s))*256).astype('uint8') + (rc,ms_rc) = cr_max(a,elem) + rctmf,ms_rctmf = ctmf_med(a,r) + rec.append((ms_rc,ms_rctmf)) +# assert (rc==rcm).all() + + rec = np.asarray(rec) + + plt.figure() + plt.title('increasing image size') + plt.plot(s_range,rec) + plt.legend(['rank.median','ctmf.median_filter']) + plt.figure() + plt.imshow(np.hstack((rc,rctmf))) + + plt.show() if __name__ == '__main__': - compare() \ No newline at end of file + compare_median() \ No newline at end of file From 4f2dde57076164ae84c774751b4d39cabe6c21fb Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 14:30:29 +0200 Subject: [PATCH 29/86] add comment --- skimage/rank/percentile_rank.py | 15 ++++++++++++++- skimage/rank/rank.py | 7 ++++++- skimage/rank/tests/demo_benchmark.py | 15 ++++++++++----- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/skimage/rank/percentile_rank.py b/skimage/rank/percentile_rank.py index b6af753c..6cc273e3 100644 --- a/skimage/rank/percentile_rank.py +++ b/skimage/rank/percentile_rank.py @@ -1,4 +1,17 @@ -""" +"""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. + +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. + +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 + :author: Olivier Debeir, 2012 :license: modified BSD """ diff --git a/skimage/rank/rank.py b/skimage/rank/rank.py index 2a7caab9..5dfa85bc 100644 --- a/skimage/rank/rank.py +++ b/skimage/rank/rank.py @@ -1,10 +1,15 @@ -"""rank.py - rankfilter for local (custom kernel) maximum, minimum, median, mean, auto-level, egalize, etc +"""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 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 + +result image is 8 or 16 bit with respect to the input image + :author: Olivier Debeir, 2012 :license: modified BSD """ diff --git a/skimage/rank/tests/demo_benchmark.py b/skimage/rank/tests/demo_benchmark.py index 74200b70..c3046083 100644 --- a/skimage/rank/tests/demo_benchmark.py +++ b/skimage/rank/tests/demo_benchmark.py @@ -25,7 +25,7 @@ def ctmf_med(image,radius): return median_filter(image=image,radius=radius) -def compare(): +def compare_dilate(): """comparison between - crank.maximum rankfilter implementation - cmorph.dilate cython implementation @@ -88,9 +88,9 @@ def compare_median(): a = data.camera() rec = [] - e_range = range(2,40,2) + e_range = range(2,40,4) for r in e_range: - elem = np.ones((2*r,2*r),dtype='uint8') + elem = np.ones((2*r+1,2*r+1),dtype='uint8') # elem = (np.random.random((r,r))>.5).astype('uint8') rc,ms_rc = cr_med(a,elem) rctmf,ms_rctmf = ctmf_med(a,r) @@ -106,9 +106,11 @@ def compare_median(): plt.legend(['rank.median','ctmf.median_filter']) plt.figure() plt.imshow(np.hstack((rc,rctmf))) - plt.show() + plt.ylabel('time (ms)') + plt.xlabel('element radius') + r = 9 - elem = np.ones((r,r),dtype='uint8') + elem = np.ones((r*2+1,r*2+1),dtype='uint8') rec = [] s_range = range(100,1000,100) @@ -127,7 +129,10 @@ def compare_median(): plt.legend(['rank.median','ctmf.median_filter']) plt.figure() plt.imshow(np.hstack((rc,rctmf))) + plt.ylabel('time (ms)') + plt.xlabel('image size') plt.show() if __name__ == '__main__': +# compare_dilate() compare_median() \ No newline at end of file From 935f424e9fb19a1e0f0a6969d3b5dac50c3d7b8b Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 15:34:54 +0200 Subject: [PATCH 30/86] fix percentile autolevel --- doc/examples/plot_local_autolevels.py | 45 +++++++++++++++++++++++++++ skimage/rank/_core16.pxd | 4 --- skimage/rank/_core16b.pxd | 4 --- skimage/rank/_core8.pxd | 4 --- skimage/rank/_core8p.pxd | 4 +-- skimage/rank/_crank8.pyx | 10 +++--- skimage/rank/_crank8_percentiles.pyx | 18 ++++++----- skimage/rank/tests/test_suite.py | 14 ++++++++- 8 files changed, 77 insertions(+), 26 deletions(-) create mode 100644 doc/examples/plot_local_autolevels.py diff --git a/doc/examples/plot_local_autolevels.py b/doc/examples/plot_local_autolevels.py new file mode 100644 index 00000000..5b3ba758 --- /dev/null +++ b/doc/examples/plot_local_autolevels.py @@ -0,0 +1,45 @@ +""" +===================== +Local Autolevel +===================== + +Local autolevel stretch local histogram between 0 and max_graylevel (e.g. 255 for 8 bit image). +The following code shows the difference between autolevel and percentile auto_level where [min,max] interval +is replaced by [p0,p1] percentiles interval + +""" +import matplotlib.pyplot as plt + +from skimage import data + +from skimage.rank import percentile_autolevel,autolevel +from skimage.morphology import disk + + +image = data.camera() + +selem = disk(20) +loc_autolevel = autolevel(image,selem=selem) +loc_perc_autolevel = percentile_autolevel(image,selem=selem,p0=.0,p1=1.0) + +assert (loc_autolevel==loc_perc_autolevel).all() + +loc_perc_autolevel = percentile_autolevel(image,selem=selem,p0=.01,p1=.99) + +fig, axes = plt.subplots(nrows=3, figsize=(7, 8)) +ax0, ax1, ax2 = axes +plt.gray() + +ax0.imshow(image) +ax0.set_title('Image') + +ax1.imshow(loc_autolevel) +ax1.set_title('Autolevel') + +ax2.imshow(loc_perc_autolevel,vmin=0,vmax=255) +ax2.set_title('percentile autolevel') + +for ax in axes: + ax.axis('off') + +plt.show() diff --git a/skimage/rank/_core16.pxd b/skimage/rank/_core16.pxd index ddd8c637..26a8e948 100644 --- a/skimage/rank/_core16.pxd +++ b/skimage/rank/_core16.pxd @@ -14,10 +14,6 @@ import numpy as np cimport numpy as np from libc.stdlib cimport malloc, free -# 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 - #--------------------------------------------------------------------------- # 16 bit core kernel receives extra information about data bitdepth #--------------------------------------------------------------------------- diff --git a/skimage/rank/_core16b.pxd b/skimage/rank/_core16b.pxd index fefac53e..cf3cb4c4 100644 --- a/skimage/rank/_core16b.pxd +++ b/skimage/rank/_core16b.pxd @@ -14,10 +14,6 @@ import numpy as np cimport numpy as np from libc.stdlib cimport malloc, free -# 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 - #--------------------------------------------------------------------------- # 16 bit core kernel receives extra information about data bitdepth and bilateral interval #--------------------------------------------------------------------------- diff --git a/skimage/rank/_core8.pxd b/skimage/rank/_core8.pxd index 3d5ddac3..4ea92121 100644 --- a/skimage/rank/_core8.pxd +++ b/skimage/rank/_core8.pxd @@ -14,10 +14,6 @@ import numpy as np cimport numpy as np from libc.stdlib cimport malloc, free -# 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 - #--------------------------------------------------------------------------- # 8 bit core kernel #--------------------------------------------------------------------------- diff --git a/skimage/rank/_core8p.pxd b/skimage/rank/_core8p.pxd index dfab17be..b878143e 100644 --- a/skimage/rank/_core8p.pxd +++ b/skimage/rank/_core8p.pxd @@ -15,8 +15,8 @@ cimport numpy as np from libc.stdlib cimport malloc, free # 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 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 receives extra information about data inferior and superior percentiles diff --git a/skimage/rank/_crank8.pyx b/skimage/rank/_crank8.pyx index 12e0577e..96624eb5 100644 --- a/skimage/rank/_crank8.pyx +++ b/skimage/rank/_crank8.pyx @@ -33,11 +33,13 @@ cdef inline np.uint8_t kernel_autolevel(int* histo, float pop, np.uint8_t g): if histo[i]: imin = i break - delta = imax-imin - if delta>0: - return (255.*(g-imin)/delta) + delta = imax-imin + if delta>0: + return (255.*(g-imin)/delta) + else: + return (imax-imin) else: - return (imax-imin) + return (0) cdef inline np.uint8_t kernel_bottomhat(int* histo, float pop, np.uint8_t g): cdef int i diff --git a/skimage/rank/_crank8_percentiles.pyx b/skimage/rank/_crank8_percentiles.pyx index 23fe079f..3082e23a 100644 --- a/skimage/rank/_crank8_percentiles.pyx +++ b/skimage/rank/_crank8_percentiles.pyx @@ -15,7 +15,7 @@ import numpy as np cimport numpy as np # import main loop -from _core8p cimport _core8p +from _core8p cimport _core8p,uint8_max,uint8_min # ----------------------------------------------------------------- # kernels uint8 (SOFT version using percentiles) @@ -27,25 +27,29 @@ cdef inline np.uint8_t kernel_autolevel(int* histo, float pop, np.uint8_t g, flo if pop: sum = 0 p1 = 1.0-p1 + imin = 0 + imax = 255 + for i in range(256): sum += histo[i] - if sum>=p0*pop: + if sum>(p0*pop): imin = i break sum = 0 for i in range(255,-1,-1): sum += histo[i] - if sum>=p1*pop: + if sum>(p1*pop): imax = i break - delta = imax-imin if delta>0: - return (255.*(g-imin)/delta) +# return (255.) +# return (delta) + return (255*(uint8_min(uint8_max(imin,g),imax)-imin)/delta) else: - return (0) + return (imax-imin) else: - return (0) + return (128) cdef inline np.uint8_t kernel_gradient(int* histo, float pop, np.uint8_t g, float p0, float p1): diff --git a/skimage/rank/tests/test_suite.py b/skimage/rank/tests/test_suite.py index 51c7f60b..5d47138b 100644 --- a/skimage/rank/tests/test_suite.py +++ b/skimage/rank/tests/test_suite.py @@ -4,7 +4,10 @@ import numpy as np from skimage.rank import _crank8,_crank8_percentiles from skimage.rank import _crank16,_crank16_bilateral,_crank16_percentiles -from skimage.morphology import cmorph +from skimage.morphology import cmorph,disk +from skimage import data +from skimage import rank + class TestSequenceFunctions(unittest.TestCase): @@ -92,6 +95,15 @@ class TestSequenceFunctions(unittest.TestCase): 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_compare_autolevels(self): + 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() + if __name__ == '__main__': suite = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions) From 5fdc11c4fdbf0ebbae918a9d17e5c6f7f320ea8f Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 15:40:05 +0200 Subject: [PATCH 31/86] fix percentile autolevel --- skimage/rank/_crank16_percentiles.pyx | 16 ++++++---------- skimage/rank/_crank8_percentiles.pyx | 2 -- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/skimage/rank/_crank16_percentiles.pyx b/skimage/rank/_crank16_percentiles.pyx index 54c25d40..8d0446ff 100644 --- a/skimage/rank/_crank16_percentiles.pyx +++ b/skimage/rank/_crank16_percentiles.pyx @@ -15,10 +15,10 @@ import numpy as np cimport numpy as np # import main loop -from _core16p cimport _core16p +from _core16p cimport _core16p,int_min,int_max # ----------------------------------------------------------------- -# kernels uint8 (SOFT version using percentiles) +# kernels uint16 (SOFT version using percentiles) # ----------------------------------------------------------------- cdef inline np.uint16_t kernel_autolevel(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin, float p0, float p1): @@ -29,25 +29,21 @@ cdef inline np.uint16_t kernel_autolevel(int* histo, float pop, np.uint16_t g,in p1 = 1.0-p1 for i in range(maxbin): sum += histo[i] - if sum>=p0*pop: + if sum>p0*pop: imin = i break sum = 0 for i in range(maxbin-1,-1,-1): sum += histo[i] - if sum>=p1*pop: + if sum>p1*pop: imax = i break delta = imax-imin - if g>imax: - return (maxbin-1) - if g(0) if delta>0: - return ((maxbin-1)*1.*(g-imin)/delta) + return (255*(int_min(int_max(imin,g),imax)-imin)/delta) else: - return (0) + return (imax-imin) else: return (0) diff --git a/skimage/rank/_crank8_percentiles.pyx b/skimage/rank/_crank8_percentiles.pyx index 3082e23a..6b81c8bd 100644 --- a/skimage/rank/_crank8_percentiles.pyx +++ b/skimage/rank/_crank8_percentiles.pyx @@ -43,8 +43,6 @@ cdef inline np.uint8_t kernel_autolevel(int* histo, float pop, np.uint8_t g, flo break delta = imax-imin if delta>0: -# return (255.) -# return (delta) return (255*(uint8_min(uint8_max(imin,g),imax)-imin)/delta) else: return (imax-imin) From b55044ef1c4ce2ce9846eb8af986e0f625f2e799 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 15:45:43 +0200 Subject: [PATCH 32/86] adapt autolevel example --- doc/examples/plot_local_autolevels.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/doc/examples/plot_local_autolevels.py b/doc/examples/plot_local_autolevels.py index 5b3ba758..842215d5 100644 --- a/doc/examples/plot_local_autolevels.py +++ b/doc/examples/plot_local_autolevels.py @@ -9,6 +9,7 @@ is replaced by [p0,p1] percentiles interval """ import matplotlib.pyplot as plt +import numpy as np from skimage import data @@ -20,11 +21,12 @@ image = data.camera() selem = disk(20) loc_autolevel = autolevel(image,selem=selem) -loc_perc_autolevel = percentile_autolevel(image,selem=selem,p0=.0,p1=1.0) +loc_perc_autolevel0 = percentile_autolevel(image,selem=selem,p0=.00,p1=1.0) +loc_perc_autolevel1 = percentile_autolevel(image,selem=selem,p0=.01,p1=.99) +loc_perc_autolevel2 = percentile_autolevel(image,selem=selem,p0=.05,p1=.95) +loc_perc_autolevel3 = percentile_autolevel(image,selem=selem,p0=.1,p1=.9) -assert (loc_autolevel==loc_perc_autolevel).all() - -loc_perc_autolevel = percentile_autolevel(image,selem=selem,p0=.01,p1=.99) +loc_perc_autolevel = np.hstack((loc_perc_autolevel0,loc_perc_autolevel1,loc_perc_autolevel2,loc_perc_autolevel3)) fig, axes = plt.subplots(nrows=3, figsize=(7, 8)) ax0, ax1, ax2 = axes @@ -37,7 +39,7 @@ ax1.imshow(loc_autolevel) ax1.set_title('Autolevel') ax2.imshow(loc_perc_autolevel,vmin=0,vmax=255) -ax2.set_title('percentile autolevel') +ax2.set_title('percentile autolevel 0%,1%,5% and 10%') for ax in axes: ax.axis('off') From ec2278a646763a5360755c2a453627e62c08763a Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 15:48:36 +0200 Subject: [PATCH 33/86] fix 16bit percentile --- skimage/rank/_crank16_percentiles.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/skimage/rank/_crank16_percentiles.pyx b/skimage/rank/_crank16_percentiles.pyx index 8d0446ff..6c67a54e 100644 --- a/skimage/rank/_crank16_percentiles.pyx +++ b/skimage/rank/_crank16_percentiles.pyx @@ -118,13 +118,13 @@ cdef inline np.uint16_t kernel_morph_contr_enh(int* histo, float pop, np.uint16_ p1 = 1.0-p1 for i in range(maxbin): sum += histo[i] - if sum>=p0*pop: + if sum>p0*pop: imin = i break sum = 0 for i in range((maxbin-1),-1,-1): sum += histo[i] - if sum>=p1*pop: + if sum>p1*pop: imax = i break if g>imax: From 7e7b1d4aacbaeafd567dc42bd3d1a07a99e0d996 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 15:50:50 +0200 Subject: [PATCH 34/86] clean-up code --- skimage/rank/_core.pxd | 7 ------- skimage/rank/_core16p.pxd | 7 ------- skimage/rank/_core8p.pxd | 7 ------- skimage/rank/_crank16_percentiles.pyx | 8 -------- skimage/rank/_crank8_percentiles.pyx | 8 -------- 5 files changed, 37 deletions(-) diff --git a/skimage/rank/_core.pxd b/skimage/rank/_core.pxd index bb57aec4..fbae2b24 100644 --- a/skimage/rank/_core.pxd +++ b/skimage/rank/_core.pxd @@ -1,10 +1,3 @@ -""" to compile this use: ->>> python setup.py build_ext --inplace - -to generate html report use: ->>> cython -a core.pxd -""" - #cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False diff --git a/skimage/rank/_core16p.pxd b/skimage/rank/_core16p.pxd index 0d698cee..1ce9b4cd 100644 --- a/skimage/rank/_core16p.pxd +++ b/skimage/rank/_core16p.pxd @@ -1,10 +1,3 @@ -""" to compile this use: ->>> python setup.py build_ext --inplace - -to generate html report use: ->>> cython -a core16p.pxd -""" - #cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False diff --git a/skimage/rank/_core8p.pxd b/skimage/rank/_core8p.pxd index b878143e..9b4fbd29 100644 --- a/skimage/rank/_core8p.pxd +++ b/skimage/rank/_core8p.pxd @@ -1,10 +1,3 @@ -""" to compile this use: ->>> python setup.py build_ext --inplace - -to generate html report use: ->>> cython -a core8p.pxd -""" - #cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False diff --git a/skimage/rank/_crank16_percentiles.pyx b/skimage/rank/_crank16_percentiles.pyx index 6c67a54e..0f07196e 100644 --- a/skimage/rank/_crank16_percentiles.pyx +++ b/skimage/rank/_crank16_percentiles.pyx @@ -1,11 +1,3 @@ -""" to compile this use: ->>> python setup.py build_ext --inplace - -to generate html report use: ->>> cython -a crank_percentiles.pxd - -""" - #cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False diff --git a/skimage/rank/_crank8_percentiles.pyx b/skimage/rank/_crank8_percentiles.pyx index 6b81c8bd..2299f04a 100644 --- a/skimage/rank/_crank8_percentiles.pyx +++ b/skimage/rank/_crank8_percentiles.pyx @@ -1,11 +1,3 @@ -""" to compile this use: ->>> python setup.py build_ext --inplace - -to generate html report use: ->>> cython -a crank_percentiles.pxd - -""" - #cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False From c1eca2525f2d21ad1a2cfc135a927f5e5b2d0ac8 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 15:53:00 +0200 Subject: [PATCH 35/86] fix equalize --- skimage/rank/_crank16.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skimage/rank/_crank16.pyx b/skimage/rank/_crank16.pyx index e1e64bed..bd60c3e8 100644 --- a/skimage/rank/_crank16.pyx +++ b/skimage/rank/_crank16.pyx @@ -209,7 +209,7 @@ def bottomhat(np.ndarray[np.uint16_t, ndim=2] image, """ return _core16(kernel_bottomhat,image,selem,mask,out,shift_x,shift_y,bitdepth) -def egalise(np.ndarray[np.uint16_t, ndim=2] image, +def equalize(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, From c35f6754afb278850dcf793d6198ed57cb4b4036 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 15:54:55 +0200 Subject: [PATCH 36/86] fix other equalize --- skimage/rank/_crank16.pyx | 4 ++-- skimage/rank/tests/demo_16bitbilateral.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/skimage/rank/_crank16.pyx b/skimage/rank/_crank16.pyx index bd60c3e8..573db50f 100644 --- a/skimage/rank/_crank16.pyx +++ b/skimage/rank/_crank16.pyx @@ -49,7 +49,7 @@ cdef inline np.uint16_t kernel_bottomhat(int* histo, float pop, np.uint16_t g,in return (g-i) -cdef inline np.uint16_t kernel_egalise(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): +cdef inline np.uint16_t kernel_equalize(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): cdef int i cdef float sum = 0. @@ -216,7 +216,7 @@ def equalize(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8): """local egalisation of the gray level """ - return _core16(kernel_egalise,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_equalize,image,selem,mask,out,shift_x,shift_y,bitdepth) def gradient(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, diff --git a/skimage/rank/tests/demo_16bitbilateral.py b/skimage/rank/tests/demo_16bitbilateral.py index 2a302e6a..85fd510c 100644 --- a/skimage/rank/tests/demo_16bitbilateral.py +++ b/skimage/rank/tests/demo_16bitbilateral.py @@ -14,7 +14,7 @@ if __name__ == '__main__': f2 = rank.bilateral_mean(a16,selem = selem,s0=500,s1=500) selem = disk(50) - f3 = rank.egalise(a16,selem = selem) + f3 = rank.equalize(a16,selem = selem) plt.figure() plt.imshow(np.hstack((a8,f1))) From 2ada9ef6b896483e5667b492b58006f1e7d6d793 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 16:46:37 +0200 Subject: [PATCH 37/86] add marked watershed example --- doc/examples/plot_lena_bilateral_denoise.py | 1 + doc/examples/plot_marked_watershed.py | 53 +++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 doc/examples/plot_marked_watershed.py diff --git a/doc/examples/plot_lena_bilateral_denoise.py b/doc/examples/plot_lena_bilateral_denoise.py index 9fd20285..57593867 100644 --- a/doc/examples/plot_lena_bilateral_denoise.py +++ b/doc/examples/plot_lena_bilateral_denoise.py @@ -1,3 +1,4 @@ + """ ==================================================== Denoising the picture of Lena using bilateral filter diff --git a/doc/examples/plot_marked_watershed.py b/doc/examples/plot_marked_watershed.py new file mode 100644 index 00000000..8f65e344 --- /dev/null +++ b/doc/examples/plot_marked_watershed.py @@ -0,0 +1,53 @@ +""" +================================ +Markers for watershed transform +================================ + +The watershed is a classical algorithm used for **segmentation**, that +is, for separating different objects in an image. + +See Wikipedia_ for more details on the algorithm. + +.. _Wikipedia: http://en.wikipedia.org/wiki/Watershed_(image_processing) + +""" + +import numpy as np +from scipy import ndimage +import matplotlib.pyplot as plt +from skimage.morphology import watershed,disk +from skimage import rank +from skimage import data +from scipy import ndimage + +# Generate an initial image with two overlapping circles +image = data.camera() + +# denoise image +denoised = rank.median(image,disk(2)) + +# find continuous region (low gradient) --> markers +markers = rank.gradient(denoised,disk(5))<10 +markers = ndimage.label(markers)[0] + +#local gradient +gradient = rank.gradient(denoised,disk(2)) + +# process the watershed +labels = watershed(gradient, markers) + +# display results +fig, axes = plt.subplots(ncols=4, figsize=(8, 2.7)) +ax0, ax1, ax2, ax3 = axes + +ax0.imshow(image, cmap=plt.cm.gray, interpolation='nearest') +ax1.imshow(gradient, cmap=plt.cm.spectral, interpolation='nearest') +ax2.imshow(markers, cmap=plt.cm.spectral, interpolation='nearest') +ax3.imshow(image, cmap=plt.cm.gray, interpolation='nearest') +ax3.imshow(labels, cmap=plt.cm.spectral, interpolation='nearest',alpha=.7) + +for ax in axes: + ax.axis('off') + +plt.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1) +plt.show() From 3d268dd4388f4f68f085a21acde84025c948e522 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 16:47:34 +0200 Subject: [PATCH 38/86] add marked watershed example (cont.) --- doc/examples/plot_marked_watershed.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/examples/plot_marked_watershed.py b/doc/examples/plot_marked_watershed.py index 8f65e344..1db4f507 100644 --- a/doc/examples/plot_marked_watershed.py +++ b/doc/examples/plot_marked_watershed.py @@ -6,6 +6,8 @@ Markers for watershed transform The watershed is a classical algorithm used for **segmentation**, that is, for separating different objects in an image. +Here a marker image is build from the region of low gradient inside the image. + See Wikipedia_ for more details on the algorithm. .. _Wikipedia: http://en.wikipedia.org/wiki/Watershed_(image_processing) From fee2df8d424342d64ba1e0575cdb35335f8652cb Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 16:47:57 +0200 Subject: [PATCH 39/86] add marked watershed example (cont.) --- doc/examples/plot_marked_watershed.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/examples/plot_marked_watershed.py b/doc/examples/plot_marked_watershed.py index 1db4f507..0be25007 100644 --- a/doc/examples/plot_marked_watershed.py +++ b/doc/examples/plot_marked_watershed.py @@ -22,7 +22,7 @@ from skimage import rank from skimage import data from scipy import ndimage -# Generate an initial image with two overlapping circles +# original data image = data.camera() # denoise image From 29d133b290c079ef6491facda5afcac04e8eeede Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 17:32:35 +0200 Subject: [PATCH 40/86] add local test --- doc/examples/plot_watershed.py | 2 +- skimage/rank/tests/test_morph_contr_enh.py | 28 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 skimage/rank/tests/test_morph_contr_enh.py diff --git a/doc/examples/plot_watershed.py b/doc/examples/plot_watershed.py index a1cd18cf..9fce196f 100644 --- a/doc/examples/plot_watershed.py +++ b/doc/examples/plot_watershed.py @@ -26,7 +26,7 @@ See Wikipedia_ for more details on the algorithm. """ import numpy as np -from scipy import ndimage +e import matplotlib.pyplot as plt from skimage.morphology import watershed, is_local_maximum diff --git a/skimage/rank/tests/test_morph_contr_enh.py b/skimage/rank/tests/test_morph_contr_enh.py new file mode 100644 index 00000000..812e81c5 --- /dev/null +++ b/skimage/rank/tests/test_morph_contr_enh.py @@ -0,0 +1,28 @@ +import numpy as np +import matplotlib.pyplot as plt +import gdal + +from skimage.morphology import disk +import skimage.rank as rank + +filename = 'iko_pan_Ja1.tif' +im16 = gdal.Open(filename).ReadAsArray().astype(np.uint16) + +plt.figure() +plt.imshow(im16,cmap=plt.cm.gray) +plt.colorbar() + +f0 = rank.median(im16,disk(1)) +f1 = rank.bilateral_mean(im16,disk(20),s0=200,s1=200) +f2 = rank.equalize(f1,disk(10)) +f3 = rank.bottomhat(f1,disk(1)) + +plt.figure() +plt.imshow(f2,cmap=plt.cm.gray,interpolation='nearest') +plt.colorbar() + +plt.show() + + + + From 76a02de83afd9173a1ed253fa1a6163821c4d649 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 11 Oct 2012 11:41:37 +0200 Subject: [PATCH 41/86] remove unused _core --- skimage/rank/_core.pxd | 1046 ---------------------------------------- 1 file changed, 1046 deletions(-) delete mode 100644 skimage/rank/_core.pxd diff --git a/skimage/rank/_core.pxd b/skimage/rank/_core.pxd deleted file mode 100644 index fbae2b24..00000000 --- a/skimage/rank/_core.pxd +++ /dev/null @@ -1,1046 +0,0 @@ -#cython: cdivision=True -#cython: boundscheck=False -#cython: nonecheck=False -#cython: wraparound=False - -import numpy as np -cimport numpy as np -from libc.stdlib cimport malloc, free - -# 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 - -#--------------------------------------------------------------------------- -# 8 bit core kernel -#--------------------------------------------------------------------------- - -cdef inline rank8(np.uint8_t kernel(int*, float, np.uint8_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): - """ Main loop, this function computes the histogram for each image point - - data is uint8 - - result is uint8 casted - """ - - cdef int rows = image.shape[0] - cdef int cols = image.shape[1] - cdef int srows = selem.shape[0] - cdef int scols = selem.shape[1] - - cdef int centre_r = int(selem.shape[0] / 2) + shift_y - cdef int centre_c = int(selem.shape[1] / 2) + shift_x - - # check that structuring element center is inside the element bounding box - assert centre_r >= 0 - assert centre_c >= 0 - 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 out is None: - out = np.zeros((rows, cols), dtype=np.uint8) - else: - out = np.ascontiguousarray(out) - - # create extended image and mask - cdef int erows = rows+srows-1 - cdef int ecols = cols+scols-1 - - cdef np.ndarray emask = np.zeros((erows, ecols), dtype=np.uint8) - cdef np.ndarray eimage = np.zeros((erows, ecols), dtype=np.uint8) - - eimage[centre_r:rows+centre_r,centre_c:cols+centre_c] = image - emask[centre_r:rows+centre_r,centre_c:cols+centre_c] = mask - - eimage = np.ascontiguousarray(eimage) - mask = np.ascontiguousarray(mask) - - # define pointers to the data - cdef np.uint8_t* eimage_data = eimage.data - cdef np.uint8_t* emask_data = emask.data - - cdef np.uint8_t* out_data = out.data - cdef np.uint8_t* image_data = image.data - cdef np.uint8_t* mask_data = mask.data - - # define local variable types - cdef int r, c, rr, cc, s, value, local_max, i, even_row - cdef float pop # number of pixels actually inside the neighborhood (float) - - # allocate memory with malloc - cdef int max_se = srows*scols - cdef int n_se_n, n_se_s, n_se_e, n_se_w - - cdef int selem_num = np.sum(selem != 0) - cdef int* sr = malloc(selem_num * sizeof(int)) - cdef int* sc = malloc(selem_num * sizeof(int)) - cdef int* histo = malloc(256 * sizeof(int)) - cdef int* se_e_r = malloc(max_se * sizeof(int)) - cdef int* se_e_c = malloc(max_se * sizeof(int)) - cdef int* se_w_r = malloc(max_se * sizeof(int)) - cdef int* se_w_c = malloc(max_se * sizeof(int)) - cdef int* se_n_r = malloc(max_se * sizeof(int)) - cdef int* se_n_c = malloc(max_se * sizeof(int)) - cdef int* se_s_r = malloc(max_se * sizeof(int)) - cdef int* se_s_c = malloc(max_se * sizeof(int)) - - # 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 - - t = np.hstack((np.zeros((selem.shape[0],1)),selem)) - t_w = np.diff(t,axis=1)==1 - - t = np.vstack((selem,np.zeros((1,selem.shape[1])))) - t_s = np.diff(t,axis=0)==-1 - - t = np.vstack((np.zeros((1,selem.shape[1])),selem)) - t_n = np.diff(t,axis=0)==1 - - n_se_n = n_se_s = n_se_e = n_se_w = 0 - - for r in range(srows): - for c in range(scols): - if t_e[r,c]: - se_e_r[n_se_e] = r - centre_r - se_e_c[n_se_e] = c - centre_c - n_se_e += 1 - if t_w[r,c]: - se_w_r[n_se_w] = r - centre_r - se_w_c[n_se_w] = c - centre_c - n_se_w += 1 - if t_n[r,c]: - se_n_r[n_se_n] = r - centre_r - se_n_c[n_se_n] = c - centre_c - n_se_n += 1 - if t_s[r,c]: - se_s_r[n_se_s] = r - centre_r - se_s_c[n_se_s] = c - centre_c - n_se_s += 1 - - # initial population and histogram - for i in range(256): - histo[i] = 0 - - pop = 0 - - for r in range(srows): - for c in range(scols): - rr = r - cc = c - if selem[r, c]: - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - - r = 0 - c = 0 - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) - # kernel ------------------------------------------- - - # main loop - r = 0 - for even_row in range(0,rows,2): - # ---> west to east - for c in range(1,cols): - for s in range(n_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(n_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(n_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(n_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) - # kernel ------------------------------------------- - - # ---> east to west - for c in range(cols-2,-1,-1): - for s in range(n_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(n_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c + 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(n_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(n_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) - # kernel ------------------------------------------- - - # release memory allocated by malloc - free(sr) - free(sc) - - free(se_e_r) - free(se_e_c) - free(se_w_r) - free(se_w_c) - free(se_n_r) - free(se_n_c) - free(se_s_r) - free(se_s_c) - - free(histo) - - return out - -#--------------------------------------------------------------------------- -# 16 bit core, kernel receive extra information about data bitdepth -#--------------------------------------------------------------------------- - -cdef inline rank16(np.uint16_t kernel(int*, float, np.uint16_t, int ,int,int ), -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,int bitdepth): - """ Main loop, this function computes the histogram for each image point - - data is uint8 - - result is uint8 casted - """ - - cdef int rows = image.shape[0] - cdef int cols = image.shape[1] - cdef int srows = selem.shape[0] - cdef int scols = selem.shape[1] - - cdef int centre_r = int(selem.shape[0] / 2) + shift_y - cdef int centre_c = int(selem.shape[1] / 2) + shift_x - - # check that structuring element center is inside the element bounding box - assert centre_r >= 0 - assert centre_c >= 0 - assert centre_r < srows - assert centre_c < scols - assert bitdepth in range(2,13) - - 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 int maxbin=maxbin_list[bitdepth],midbin=midbin_list[bitdepth] - - assert (imageeimage.data - cdef np.uint8_t* emask_data = emask.data - - cdef np.uint16_t* out_data = out.data - cdef np.uint16_t* image_data = image.data - cdef np.uint8_t* mask_data = mask.data - - # define local variable types - cdef int r, c, rr, cc, s, value, local_max, i, even_row - cdef float pop # number of pixels actually inside the neighborhood (float) - - # allocate memory with malloc - cdef int max_se = srows*scols - cdef int n_se_n, n_se_s, n_se_e, n_se_w - - cdef int selem_num = np.sum(selem != 0) - cdef int* sr = malloc(selem_num * sizeof(int)) - cdef int* sc = malloc(selem_num * sizeof(int)) - cdef int* histo = malloc(maxbin * sizeof(int)) - cdef int* se_e_r = malloc(max_se * sizeof(int)) - cdef int* se_e_c = malloc(max_se * sizeof(int)) - cdef int* se_w_r = malloc(max_se * sizeof(int)) - cdef int* se_w_c = malloc(max_se * sizeof(int)) - cdef int* se_n_r = malloc(max_se * sizeof(int)) - cdef int* se_n_c = malloc(max_se * sizeof(int)) - cdef int* se_s_r = malloc(max_se * sizeof(int)) - cdef int* se_s_c = malloc(max_se * sizeof(int)) - - # 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 - - t = np.hstack((np.zeros((selem.shape[0],1)),selem)) - t_w = np.diff(t,axis=1)==1 - - t = np.vstack((selem,np.zeros((1,selem.shape[1])))) - t_s = np.diff(t,axis=0)==-1 - - t = np.vstack((np.zeros((1,selem.shape[1])),selem)) - t_n = np.diff(t,axis=0)==1 - - n_se_n = n_se_s = n_se_e = n_se_w = 0 - - for r in range(srows): - for c in range(scols): - if t_e[r,c]: - se_e_r[n_se_e] = r - centre_r - se_e_c[n_se_e] = c - centre_c - n_se_e += 1 - if t_w[r,c]: - se_w_r[n_se_w] = r - centre_r - se_w_c[n_se_w] = c - centre_c - n_se_w += 1 - if t_n[r,c]: - se_n_r[n_se_n] = r - centre_r - se_n_c[n_se_n] = c - centre_c - n_se_n += 1 - if t_s[r,c]: - se_s_r[n_se_s] = r - centre_r - se_s_c[n_se_s] = c - centre_c - n_se_s += 1 - - # initial population and histogram - for i in range(maxbin): - histo[i] = 0 - - pop = 0 - - for r in range(srows): - for c in range(scols): - rr = r - cc = c - if selem[r, c]: - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - - r = 0 - c = 0 - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin) - # kernel ------------------------------------------- - - # main loop - r = 0 - for even_row in range(0,rows,2): - # ---> west to east - for c in range(1,cols): - for s in range(n_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(n_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(n_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(n_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin) - # kernel ------------------------------------------- - - # ---> east to west - for c in range(cols-2,-1,-1): - for s in range(n_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(n_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c + 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(n_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(n_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin) - # kernel ------------------------------------------- - - # release memory allocated by malloc - free(sr) - free(sc) - - free(se_e_r) - free(se_e_c) - free(se_w_r) - free(se_w_c) - free(se_n_r) - free(se_n_c) - free(se_s_r) - free(se_s_c) - - free(histo) - - return out - -#--------------------------------------------------------------------------- -# 8 bit core kernel receive extra information about data inferior and superior percentiles -#--------------------------------------------------------------------------- - -cdef inline rank8_percentile(np.uint8_t kernel(int*, float, np.uint8_t, float, float), -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): - """ Main loop, this function computes the histogram for each image point - - data is uint8 - - result is uint8 casted - """ - - cdef int rows = image.shape[0] - cdef int cols = image.shape[1] - cdef int srows = selem.shape[0] - cdef int scols = selem.shape[1] - - cdef int centre_r = int(selem.shape[0] / 2) + shift_y - cdef int centre_c = int(selem.shape[1] / 2) + shift_x - - # check that structuring element center is inside the element bounding box - assert centre_r >= 0 - assert centre_c >= 0 - 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 out is None: - out = np.zeros((rows, cols), dtype=np.uint8) - else: - out = np.ascontiguousarray(out) - - # create extended image and mask - cdef int erows = rows+srows-1 - cdef int ecols = cols+scols-1 - - cdef np.ndarray emask = np.zeros((erows, ecols), dtype=np.uint8) - cdef np.ndarray eimage = np.zeros((erows, ecols), dtype=np.uint8) - - eimage[centre_r:rows+centre_r,centre_c:cols+centre_c] = image - emask[centre_r:rows+centre_r,centre_c:cols+centre_c] = mask - - eimage = np.ascontiguousarray(eimage) - mask = np.ascontiguousarray(mask) - - # define pointers to the data - cdef np.uint8_t* eimage_data = eimage.data - cdef np.uint8_t* emask_data = emask.data - - cdef np.uint8_t* out_data = out.data - cdef np.uint8_t* image_data = image.data - cdef np.uint8_t* mask_data = mask.data - - # define local variable types - cdef int r, c, rr, cc, s, value, local_max, i, even_row - cdef float pop # number of pixels actually inside the neighborhood (float) - - # allocate memory with malloc - cdef int max_se = srows*scols - cdef int n_se_n, n_se_s, n_se_e, n_se_w - - cdef int selem_num = np.sum(selem != 0) - cdef int* sr = malloc(selem_num * sizeof(int)) - cdef int* sc = malloc(selem_num * sizeof(int)) - cdef int* histo = malloc(256 * sizeof(int)) - cdef int* se_e_r = malloc(max_se * sizeof(int)) - cdef int* se_e_c = malloc(max_se * sizeof(int)) - cdef int* se_w_r = malloc(max_se * sizeof(int)) - cdef int* se_w_c = malloc(max_se * sizeof(int)) - cdef int* se_n_r = malloc(max_se * sizeof(int)) - cdef int* se_n_c = malloc(max_se * sizeof(int)) - cdef int* se_s_r = malloc(max_se * sizeof(int)) - cdef int* se_s_c = malloc(max_se * sizeof(int)) - - # 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 - - t = np.hstack((np.zeros((selem.shape[0],1)),selem)) - t_w = np.diff(t,axis=1)==1 - - t = np.vstack((selem,np.zeros((1,selem.shape[1])))) - t_s = np.diff(t,axis=0)==-1 - - t = np.vstack((np.zeros((1,selem.shape[1])),selem)) - t_n = np.diff(t,axis=0)==1 - - n_se_n = n_se_s = n_se_e = n_se_w = 0 - - for r in range(srows): - for c in range(scols): - if t_e[r,c]: - se_e_r[n_se_e] = r - centre_r - se_e_c[n_se_e] = c - centre_c - n_se_e += 1 - if t_w[r,c]: - se_w_r[n_se_w] = r - centre_r - se_w_c[n_se_w] = c - centre_c - n_se_w += 1 - if t_n[r,c]: - se_n_r[n_se_n] = r - centre_r - se_n_c[n_se_n] = c - centre_c - n_se_n += 1 - if t_s[r,c]: - se_s_r[n_se_s] = r - centre_r - se_s_c[n_se_s] = c - centre_c - n_se_s += 1 - - # initial population and histogram - for i in range(256): - histo[i] = 0 - - pop = 0 - - for r in range(srows): - for c in range(scols): - rr = r - cc = c - if selem[r, c]: - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - - r = 0 - c = 0 - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) - # kernel ------------------------------------------- - - # main loop - r = 0 - for even_row in range(0,rows,2): - # ---> west to east - for c in range(1,cols): - for s in range(n_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(n_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(n_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(n_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) - # kernel ------------------------------------------- - - # ---> east to west - for c in range(cols-2,-1,-1): - for s in range(n_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(n_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c + 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(n_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(n_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) - # kernel ------------------------------------------- - - # release memory allocated by malloc - free(sr) - free(sc) - - free(se_e_r) - free(se_e_c) - free(se_w_r) - free(se_w_c) - free(se_n_r) - free(se_n_c) - free(se_s_r) - free(se_s_c) - - free(histo) - - return out - -#--------------------------------------------------------------------------- -# 16 bit core kernel receive extra information about data inferior and superior percentiles -#--------------------------------------------------------------------------- - -cdef inline rank16_percentile(np.uint16_t kernel(int*, float, np.uint16_t,int,int,int, float, float), -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,int bitdepth, float p0, float p1): - """ Main loop, this function computes the histogram for each image point - - data is uint16 - - result is uint16 casted - """ - - cdef int rows = image.shape[0] - cdef int cols = image.shape[1] - cdef int srows = selem.shape[0] - cdef int scols = selem.shape[1] - - cdef int centre_r = int(selem.shape[0] / 2) + shift_y - cdef int centre_c = int(selem.shape[1] / 2) + shift_x - - # check that structuring element center is inside the element bounding box - assert centre_r >= 0 - assert centre_c >= 0 - assert centre_r < srows - assert centre_c < scols - - assert bitdepth in range(2,13) - - 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 int maxbin=maxbin_list[bitdepth],midbin=midbin_list[bitdepth] - - assert (imageeimage.data - cdef np.uint8_t* emask_data = emask.data - - cdef np.uint16_t* out_data = out.data - cdef np.uint16_t* image_data = image.data - cdef np.uint8_t* mask_data = mask.data - - # define local variable types - cdef int r, c, rr, cc, s, value, local_max, i, even_row - cdef float pop # number of pixels actually inside the neighborhood (float) - - # allocate memory with malloc - cdef int max_se = srows*scols - cdef int n_se_n, n_se_s, n_se_e, n_se_w - - cdef int selem_num = np.sum(selem != 0) - cdef int* sr = malloc(selem_num * sizeof(int)) - cdef int* sc = malloc(selem_num * sizeof(int)) - cdef int* histo = malloc(maxbin * sizeof(int)) - cdef int* se_e_r = malloc(max_se * sizeof(int)) - cdef int* se_e_c = malloc(max_se * sizeof(int)) - cdef int* se_w_r = malloc(max_se * sizeof(int)) - cdef int* se_w_c = malloc(max_se * sizeof(int)) - cdef int* se_n_r = malloc(max_se * sizeof(int)) - cdef int* se_n_c = malloc(max_se * sizeof(int)) - cdef int* se_s_r = malloc(max_se * sizeof(int)) - cdef int* se_s_c = malloc(max_se * sizeof(int)) - - # 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 - - t = np.hstack((np.zeros((selem.shape[0],1)),selem)) - t_w = np.diff(t,axis=1)==1 - - t = np.vstack((selem,np.zeros((1,selem.shape[1])))) - t_s = np.diff(t,axis=0)==-1 - - t = np.vstack((np.zeros((1,selem.shape[1])),selem)) - t_n = np.diff(t,axis=0)==1 - - n_se_n = n_se_s = n_se_e = n_se_w = 0 - - for r in range(srows): - for c in range(scols): - if t_e[r,c]: - se_e_r[n_se_e] = r - centre_r - se_e_c[n_se_e] = c - centre_c - n_se_e += 1 - if t_w[r,c]: - se_w_r[n_se_w] = r - centre_r - se_w_c[n_se_w] = c - centre_c - n_se_w += 1 - if t_n[r,c]: - se_n_r[n_se_n] = r - centre_r - se_n_c[n_se_n] = c - centre_c - n_se_n += 1 - if t_s[r,c]: - se_s_r[n_se_s] = r - centre_r - se_s_c[n_se_s] = c - centre_c - n_se_s += 1 - - # initial population and histogram - for i in range(maxbin): - histo[i] = 0 - - pop = 0 - - for r in range(srows): - for c in range(scols): - rr = r - cc = c - if selem[r, c]: - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - - r = 0 - c = 0 - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,p0,p1) - # kernel ------------------------------------------- - - # main loop - r = 0 - for even_row in range(0,rows,2): - # ---> west to east - for c in range(1,cols): - for s in range(n_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(n_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,p0,p1) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(n_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(n_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,p0,p1) - # kernel ------------------------------------------- - - # ---> east to west - for c in range(cols-2,-1,-1): - for s in range(n_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(n_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c + 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,p0,p1) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(n_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(n_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,p0,p1) - # kernel ------------------------------------------- - - # release memory allocated by malloc - free(sr) - free(sc) - - free(se_e_r) - free(se_e_c) - free(se_w_r) - free(se_w_c) - free(se_n_r) - free(se_n_c) - free(se_s_r) - free(se_s_c) - - free(histo) - - return out \ No newline at end of file From 45cf1d77e6e9cf7864a838921914b50016efdde7 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 11 Oct 2012 12:03:34 +0200 Subject: [PATCH 42/86] add exhaustive comparison between 8bit and 16bit filters --- skimage/rank/rank.py | 6 +++++- skimage/rank/tests/test_suite.py | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/skimage/rank/rank.py b/skimage/rank/rank.py index 5dfa85bc..bc7dadff 100644 --- a/skimage/rank/rank.py +++ b/skimage/rank/rank.py @@ -1019,4 +1019,8 @@ def tophat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): raise ValueError("only uint16 <4096 image (12bit) supported!") return _crank16.tophat(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!") \ No newline at end of file + raise TypeError("only uint8 and uint16 image supported!") + +if __name__ == "__main__": + import doctest + doctest.testmod(verbose=True) \ No newline at end of file diff --git a/skimage/rank/tests/test_suite.py b/skimage/rank/tests/test_suite.py index 5d47138b..97345f4f 100644 --- a/skimage/rank/tests/test_suite.py +++ b/skimage/rank/tests/test_suite.py @@ -104,6 +104,25 @@ class TestSequenceFunctions(unittest.TestCase): 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) + 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) + print func + f8 = func(i8,disk(3)) + f16 = func(i16,disk(3)) +# if (f8==f16).all() is False: + if not (f8==f16).all(): + + print f8 + print f16 + + + if __name__ == '__main__': suite = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions) From 58bc49d9446d6b7d189d770faf12a61be9510f6b Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 11 Oct 2012 12:13:01 +0200 Subject: [PATCH 43/86] fix 8bit-16bit discepencies --- skimage/rank/_crank16.pyx | 6 +++--- skimage/rank/tests/test_suite.py | 11 ++++------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/skimage/rank/_crank16.pyx b/skimage/rank/_crank16.pyx index 573db50f..90a7e8bb 100644 --- a/skimage/rank/_crank16.pyx +++ b/skimage/rank/_crank16.pyx @@ -35,7 +35,7 @@ cdef inline np.uint16_t kernel_autolevel(int* histo, float pop, np.uint16_t g,in break delta = imax-imin if delta>0: - return (maxbin*1.*(g-imin)/delta) + return (1.*(maxbin-1)*(g-imin)/delta) else: return (imax-imin) @@ -59,7 +59,7 @@ cdef inline np.uint16_t kernel_equalize(int* histo, float pop, np.uint16_t g,int if i>=g: break - return ((maxbin*1.*sum)/pop) + return (((maxbin-1)*sum)/pop) else: return (0) @@ -107,7 +107,7 @@ cdef inline np.uint16_t kernel_meansubstraction(int* histo, float pop, np.uint16 if pop: for i in range(maxbin): mean += histo[i]*i - return ((g-mean/pop)/2.+midbin) + return ((g-mean/pop)/2.+(midbin-1)) else: return (0) diff --git a/skimage/rank/tests/test_suite.py b/skimage/rank/tests/test_suite.py index 97345f4f..0887fa8f 100644 --- a/skimage/rank/tests/test_suite.py +++ b/skimage/rank/tests/test_suite.py @@ -108,19 +108,16 @@ class TestSequenceFunctions(unittest.TestCase): # 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) - print func f8 = func(i8,disk(3)) f16 = func(i16,disk(3)) -# if (f8==f16).all() is False: - if not (f8==f16).all(): - - print f8 - print f16 - + assert (f8==f16).all() if __name__ == '__main__': From dec07b64fbe5c5f098455d319b4de0dc3c4ea2db Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 11 Oct 2012 12:19:45 +0200 Subject: [PATCH 44/86] fix doctest in rank --- skimage/rank/rank.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/skimage/rank/rank.py b/skimage/rank/rank.py index bc7dadff..cefb06ac 100644 --- a/skimage/rank/rank.py +++ b/skimage/rank/rank.py @@ -78,9 +78,9 @@ def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): ... [0, 0, 0, 0, 0]], dtype=np.uint16) >>> autolevel(ima16, square(3)) array([[ 0, 0, 0, 0, 0], - [ 0, 4096, 4096, 4096, 0], - [ 0, 4096, 0, 4096, 0], - [ 0, 4096, 4096, 4096, 0], + [ 0, 4095, 4095, 4095, 0], + [ 0, 4095, 0, 4095, 0], + [ 0, 4095, 4095, 4095, 0], [ 0, 0, 0, 0, 0]], dtype=uint16) """ @@ -218,11 +218,11 @@ def equalize(image, selem, out=None, mask=None, shift_x=False, shift_y=False): ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) >>> equalize(ima16, square(3)) - array([[3072, 2730, 2048, 2730, 3072], - [2730, 4096, 4096, 4096, 2730], - [2048, 4096, 4096, 4096, 2048], - [2730, 4096, 4096, 4096, 2730], - [3072, 2730, 2048, 2730, 3072]], dtype=uint16) + array([[3071, 2730, 2047, 2730, 3071], + [2730, 4095, 4095, 4095, 2730], + [2047, 4095, 4095, 4095, 2047], + [2730, 4095, 4095, 4095, 2730], + [3071, 2730, 2047, 2730, 3071]], dtype=uint16) """ selem = img_as_ubyte(selem) if mask is not None: @@ -502,11 +502,11 @@ def meansubstraction(image, selem, out=None, mask=None, shift_x=False, shift_y=F ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) >>> meansubstraction(ima16, square(3)) - array([[1536, 1365, 1024, 1365, 1536], - [1365, 3185, 2730, 3185, 1365], - [1024, 2730, 2048, 2730, 1024], - [1365, 3185, 2730, 3185, 1365], - [1536, 1365, 1024, 1365, 1536]], dtype=uint16) + array([[1535, 1364, 1023, 1364, 1535], + [1364, 3184, 2729, 3184, 1364], + [1023, 2729, 2047, 2729, 1023], + [1364, 3184, 2729, 3184, 1364], + [1535, 1364, 1023, 1364, 1535]], dtype=uint16) """ selem = img_as_ubyte(selem) From f10cc429606151963a74f3dac56c5ae70d7dface Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 12 Oct 2012 17:03:03 +0200 Subject: [PATCH 45/86] remove ascontiguousarray(eimage) --- skimage/rank/_core16.pxd | 1 - skimage/rank/_core16b.pxd | 1 - skimage/rank/_core16p.pxd | 1 - skimage/rank/_core8.pxd | 1 - skimage/rank/_core8p.pxd | 1 - 5 files changed, 5 deletions(-) diff --git a/skimage/rank/_core16.pxd b/skimage/rank/_core16.pxd index 26a8e948..9ead95e0 100644 --- a/skimage/rank/_core16.pxd +++ b/skimage/rank/_core16.pxd @@ -75,7 +75,6 @@ char shift_x, char shift_y,int bitdepth): eimage[centre_r:rows+centre_r,centre_c:cols+centre_c] = image emask[centre_r:rows+centre_r,centre_c:cols+centre_c] = mask - eimage = np.ascontiguousarray(eimage) mask = np.ascontiguousarray(mask) # define pointers to the data diff --git a/skimage/rank/_core16b.pxd b/skimage/rank/_core16b.pxd index cf3cb4c4..d75611a7 100644 --- a/skimage/rank/_core16b.pxd +++ b/skimage/rank/_core16b.pxd @@ -76,7 +76,6 @@ char shift_x, char shift_y,int bitdepth, int s0, int s1): eimage[centre_r:rows+centre_r,centre_c:cols+centre_c] = image emask[centre_r:rows+centre_r,centre_c:cols+centre_c] = mask - eimage = np.ascontiguousarray(eimage) mask = np.ascontiguousarray(mask) # define pointers to the data diff --git a/skimage/rank/_core16p.pxd b/skimage/rank/_core16p.pxd index 1ce9b4cd..9f3a99af 100644 --- a/skimage/rank/_core16p.pxd +++ b/skimage/rank/_core16p.pxd @@ -72,7 +72,6 @@ char shift_x, char shift_y,int bitdepth, float p0, float p1): eimage[centre_r:rows+centre_r,centre_c:cols+centre_c] = image emask[centre_r:rows+centre_r,centre_c:cols+centre_c] = mask - eimage = np.ascontiguousarray(eimage) mask = np.ascontiguousarray(mask) # define pointers to the data diff --git a/skimage/rank/_core8.pxd b/skimage/rank/_core8.pxd index 4ea92121..d9fbee0f 100644 --- a/skimage/rank/_core8.pxd +++ b/skimage/rank/_core8.pxd @@ -65,7 +65,6 @@ char shift_x, char shift_y): eimage[centre_r:rows+centre_r,centre_c:cols+centre_c] = image emask[centre_r:rows+centre_r,centre_c:cols+centre_c] = mask - eimage = np.ascontiguousarray(eimage) mask = np.ascontiguousarray(mask) # define pointers to the data diff --git a/skimage/rank/_core8p.pxd b/skimage/rank/_core8p.pxd index 9b4fbd29..75ceaf89 100644 --- a/skimage/rank/_core8p.pxd +++ b/skimage/rank/_core8p.pxd @@ -62,7 +62,6 @@ char shift_x, char shift_y, float p0, float p1): eimage[centre_r:rows+centre_r,centre_c:cols+centre_c] = image emask[centre_r:rows+centre_r,centre_c:cols+centre_c] = mask - eimage = np.ascontiguousarray(eimage) mask = np.ascontiguousarray(mask) # define pointers to the data From 35e2e60a9be211cdc7e4f02f331dca3cd9a76c9e Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 12 Oct 2012 17:13:35 +0200 Subject: [PATCH 46/86] remoce sr,sc from cores --- skimage/rank/_core16.pxd | 4 ---- skimage/rank/_core16b.pxd | 4 ---- skimage/rank/_core16p.pxd | 4 ---- skimage/rank/_core8.pxd | 4 ---- skimage/rank/_core8p.pxd | 4 ---- 5 files changed, 20 deletions(-) diff --git a/skimage/rank/_core16.pxd b/skimage/rank/_core16.pxd index 9ead95e0..eb9f4886 100644 --- a/skimage/rank/_core16.pxd +++ b/skimage/rank/_core16.pxd @@ -94,8 +94,6 @@ char shift_x, char shift_y,int bitdepth): cdef int n_se_n, n_se_s, n_se_e, n_se_w cdef int selem_num = np.sum(selem != 0) - cdef int* sr = malloc(selem_num * sizeof(int)) - cdef int* sc = malloc(selem_num * sizeof(int)) cdef int* histo = malloc(maxbin * sizeof(int)) cdef int* se_e_r = malloc(max_se * sizeof(int)) cdef int* se_e_c = malloc(max_se * sizeof(int)) @@ -263,8 +261,6 @@ char shift_x, char shift_y,int bitdepth): # kernel ------------------------------------------- # release memory allocated by malloc - free(sr) - free(sc) free(se_e_r) free(se_e_c) diff --git a/skimage/rank/_core16b.pxd b/skimage/rank/_core16b.pxd index d75611a7..b18b1fd8 100644 --- a/skimage/rank/_core16b.pxd +++ b/skimage/rank/_core16b.pxd @@ -95,8 +95,6 @@ char shift_x, char shift_y,int bitdepth, int s0, int s1): cdef int n_se_n, n_se_s, n_se_e, n_se_w cdef int selem_num = np.sum(selem != 0) - cdef int* sr = malloc(selem_num * sizeof(int)) - cdef int* sc = malloc(selem_num * sizeof(int)) cdef int* histo = malloc(maxbin * sizeof(int)) cdef int* se_e_r = malloc(max_se * sizeof(int)) cdef int* se_e_c = malloc(max_se * sizeof(int)) @@ -264,8 +262,6 @@ char shift_x, char shift_y,int bitdepth, int s0, int s1): # kernel ------------------------------------------- # release memory allocated by malloc - free(sr) - free(sc) free(se_e_r) free(se_e_c) diff --git a/skimage/rank/_core16p.pxd b/skimage/rank/_core16p.pxd index 9f3a99af..19a53b67 100644 --- a/skimage/rank/_core16p.pxd +++ b/skimage/rank/_core16p.pxd @@ -91,8 +91,6 @@ char shift_x, char shift_y,int bitdepth, float p0, float p1): cdef int n_se_n, n_se_s, n_se_e, n_se_w cdef int selem_num = np.sum(selem != 0) - cdef int* sr = malloc(selem_num * sizeof(int)) - cdef int* sc = malloc(selem_num * sizeof(int)) cdef int* histo = malloc(maxbin * sizeof(int)) cdef int* se_e_r = malloc(max_se * sizeof(int)) cdef int* se_e_c = malloc(max_se * sizeof(int)) @@ -260,8 +258,6 @@ char shift_x, char shift_y,int bitdepth, float p0, float p1): # kernel ------------------------------------------- # release memory allocated by malloc - free(sr) - free(sc) free(se_e_r) free(se_e_c) diff --git a/skimage/rank/_core8.pxd b/skimage/rank/_core8.pxd index d9fbee0f..fefa98e4 100644 --- a/skimage/rank/_core8.pxd +++ b/skimage/rank/_core8.pxd @@ -84,8 +84,6 @@ char shift_x, char shift_y): cdef int n_se_n, n_se_s, n_se_e, n_se_w cdef int selem_num = np.sum(selem != 0) - cdef int* sr = malloc(selem_num * sizeof(int)) - cdef int* sc = malloc(selem_num * sizeof(int)) cdef int* histo = malloc(256 * sizeof(int)) cdef int* se_e_r = malloc(max_se * sizeof(int)) cdef int* se_e_c = malloc(max_se * sizeof(int)) @@ -248,8 +246,6 @@ char shift_x, char shift_y): # kernel ------------------------------------------- # release memory allocated by malloc - free(sr) - free(sc) free(se_e_r) free(se_e_c) diff --git a/skimage/rank/_core8p.pxd b/skimage/rank/_core8p.pxd index 75ceaf89..347c7ef5 100644 --- a/skimage/rank/_core8p.pxd +++ b/skimage/rank/_core8p.pxd @@ -81,8 +81,6 @@ char shift_x, char shift_y, float p0, float p1): cdef int n_se_n, n_se_s, n_se_e, n_se_w cdef int selem_num = np.sum(selem != 0) - cdef int* sr = malloc(selem_num * sizeof(int)) - cdef int* sc = malloc(selem_num * sizeof(int)) cdef int* histo = malloc(256 * sizeof(int)) cdef int* se_e_r = malloc(max_se * sizeof(int)) cdef int* se_e_c = malloc(max_se * sizeof(int)) @@ -245,8 +243,6 @@ char shift_x, char shift_y, float p0, float p1): # kernel ------------------------------------------- # release memory allocated by malloc - free(sr) - free(sc) free(se_e_r) free(se_e_c) From b9f016a7d281df3a1ae71f21f769ff684e9891a2 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 12 Oct 2012 17:19:38 +0200 Subject: [PATCH 47/86] remoce selem_num --- skimage/rank/_core16.pxd | 1 - skimage/rank/_core16b.pxd | 1 - skimage/rank/_core16p.pxd | 1 - skimage/rank/_core8.pxd | 1 - skimage/rank/_core8p.pxd | 1 - 5 files changed, 5 deletions(-) diff --git a/skimage/rank/_core16.pxd b/skimage/rank/_core16.pxd index eb9f4886..3ecb6314 100644 --- a/skimage/rank/_core16.pxd +++ b/skimage/rank/_core16.pxd @@ -93,7 +93,6 @@ char shift_x, char shift_y,int bitdepth): cdef int max_se = srows*scols cdef int n_se_n, n_se_s, n_se_e, n_se_w - cdef int selem_num = np.sum(selem != 0) cdef int* histo = malloc(maxbin * sizeof(int)) cdef int* se_e_r = malloc(max_se * sizeof(int)) cdef int* se_e_c = malloc(max_se * sizeof(int)) diff --git a/skimage/rank/_core16b.pxd b/skimage/rank/_core16b.pxd index b18b1fd8..5f5b3e81 100644 --- a/skimage/rank/_core16b.pxd +++ b/skimage/rank/_core16b.pxd @@ -94,7 +94,6 @@ char shift_x, char shift_y,int bitdepth, int s0, int s1): cdef int max_se = srows*scols cdef int n_se_n, n_se_s, n_se_e, n_se_w - cdef int selem_num = np.sum(selem != 0) cdef int* histo = malloc(maxbin * sizeof(int)) cdef int* se_e_r = malloc(max_se * sizeof(int)) cdef int* se_e_c = malloc(max_se * sizeof(int)) diff --git a/skimage/rank/_core16p.pxd b/skimage/rank/_core16p.pxd index 19a53b67..bf50ca35 100644 --- a/skimage/rank/_core16p.pxd +++ b/skimage/rank/_core16p.pxd @@ -90,7 +90,6 @@ char shift_x, char shift_y,int bitdepth, float p0, float p1): cdef int max_se = srows*scols cdef int n_se_n, n_se_s, n_se_e, n_se_w - cdef int selem_num = np.sum(selem != 0) cdef int* histo = malloc(maxbin * sizeof(int)) cdef int* se_e_r = malloc(max_se * sizeof(int)) cdef int* se_e_c = malloc(max_se * sizeof(int)) diff --git a/skimage/rank/_core8.pxd b/skimage/rank/_core8.pxd index fefa98e4..ece629c5 100644 --- a/skimage/rank/_core8.pxd +++ b/skimage/rank/_core8.pxd @@ -83,7 +83,6 @@ char shift_x, char shift_y): cdef int max_se = srows*scols cdef int n_se_n, n_se_s, n_se_e, n_se_w - cdef int selem_num = np.sum(selem != 0) cdef int* histo = malloc(256 * sizeof(int)) cdef int* se_e_r = malloc(max_se * sizeof(int)) cdef int* se_e_c = malloc(max_se * sizeof(int)) diff --git a/skimage/rank/_core8p.pxd b/skimage/rank/_core8p.pxd index 347c7ef5..675c4a5d 100644 --- a/skimage/rank/_core8p.pxd +++ b/skimage/rank/_core8p.pxd @@ -80,7 +80,6 @@ char shift_x, char shift_y, float p0, float p1): cdef int max_se = srows*scols cdef int n_se_n, n_se_s, n_se_e, n_se_w - cdef int selem_num = np.sum(selem != 0) cdef int* histo = malloc(256 * sizeof(int)) cdef int* se_e_r = malloc(max_se * sizeof(int)) cdef int* se_e_c = malloc(max_se * sizeof(int)) From 32d40f80eebc681e6e493a214ece0237af5baa76 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 12 Oct 2012 17:34:04 +0200 Subject: [PATCH 48/86] add comment --- skimage/rank/_core16.pxd | 8 ++++++++ skimage/rank/_core16b.pxd | 8 ++++++++ skimage/rank/_core16p.pxd | 8 ++++++++ skimage/rank/_core8.pxd | 8 ++++++++ skimage/rank/_core8p.pxd | 8 ++++++++ 5 files changed, 40 insertions(+) diff --git a/skimage/rank/_core16.pxd b/skimage/rank/_core16.pxd index 3ecb6314..791f5fb9 100644 --- a/skimage/rank/_core16.pxd +++ b/skimage/rank/_core16.pxd @@ -91,9 +91,17 @@ char shift_x, char shift_y,int bitdepth): # allocate memory with malloc cdef int max_se = srows*scols + + # number of element in each attack border cdef int n_se_n, n_se_s, n_se_e, n_se_w + # the current local histogram distribution cdef int* histo = malloc(maxbin * sizeof(int)) + + # 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 int* se_e_r = malloc(max_se * sizeof(int)) cdef int* se_e_c = malloc(max_se * sizeof(int)) cdef int* se_w_r = malloc(max_se * sizeof(int)) diff --git a/skimage/rank/_core16b.pxd b/skimage/rank/_core16b.pxd index 5f5b3e81..3007a2fb 100644 --- a/skimage/rank/_core16b.pxd +++ b/skimage/rank/_core16b.pxd @@ -92,9 +92,17 @@ char shift_x, char shift_y,int bitdepth, int s0, int s1): # allocate memory with malloc cdef int max_se = srows*scols + + # number of element in each attack border cdef int n_se_n, n_se_s, n_se_e, n_se_w + # the current local histogram distribution cdef int* histo = malloc(maxbin * sizeof(int)) + + # 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 int* se_e_r = malloc(max_se * sizeof(int)) cdef int* se_e_c = malloc(max_se * sizeof(int)) cdef int* se_w_r = malloc(max_se * sizeof(int)) diff --git a/skimage/rank/_core16p.pxd b/skimage/rank/_core16p.pxd index bf50ca35..484a6a6b 100644 --- a/skimage/rank/_core16p.pxd +++ b/skimage/rank/_core16p.pxd @@ -88,9 +88,17 @@ char shift_x, char shift_y,int bitdepth, float p0, float p1): # allocate memory with malloc cdef int max_se = srows*scols + + # number of element in each attack border cdef int n_se_n, n_se_s, n_se_e, n_se_w + # the current local histogram distribution cdef int* histo = malloc(maxbin * sizeof(int)) + + # 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 int* se_e_r = malloc(max_se * sizeof(int)) cdef int* se_e_c = malloc(max_se * sizeof(int)) cdef int* se_w_r = malloc(max_se * sizeof(int)) diff --git a/skimage/rank/_core8.pxd b/skimage/rank/_core8.pxd index ece629c5..325f779d 100644 --- a/skimage/rank/_core8.pxd +++ b/skimage/rank/_core8.pxd @@ -81,9 +81,17 @@ char shift_x, char shift_y): # allocate memory with malloc cdef int max_se = srows*scols + + # number of element in each attack border cdef int n_se_n, n_se_s, n_se_e, n_se_w + # the current local histogram distribution cdef int* histo = malloc(256 * sizeof(int)) + + # 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 int* se_e_r = malloc(max_se * sizeof(int)) cdef int* se_e_c = malloc(max_se * sizeof(int)) cdef int* se_w_r = malloc(max_se * sizeof(int)) diff --git a/skimage/rank/_core8p.pxd b/skimage/rank/_core8p.pxd index 675c4a5d..5fa278d5 100644 --- a/skimage/rank/_core8p.pxd +++ b/skimage/rank/_core8p.pxd @@ -78,9 +78,17 @@ char shift_x, char shift_y, float p0, float p1): # allocate memory with malloc cdef int max_se = srows*scols + + # number of element in each attack border cdef int n_se_n, n_se_s, n_se_e, n_se_w + # the current local histogram distribution cdef int* histo = malloc(256 * sizeof(int)) + + # 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 int* se_e_r = malloc(max_se * sizeof(int)) cdef int* se_e_c = malloc(max_se * sizeof(int)) cdef int* se_w_r = malloc(max_se * sizeof(int)) From 894cb13f501deb45ca1f30d926d9c8dae47f22b7 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 12 Oct 2012 17:47:51 +0200 Subject: [PATCH 49/86] rename n_se_n to num_se_n etc, removed commented code --- skimage/rank/_core16.pxd | 44 ++--- skimage/rank/_core16b.pxd | 44 ++--- skimage/rank/_core16p.pxd | 44 ++--- skimage/rank/_core8.pxd | 44 ++--- skimage/rank/_core8p.pxd | 44 ++--- skimage/rank/_crank16_bilateral.pyx | 261 +--------------------------- 6 files changed, 112 insertions(+), 369 deletions(-) diff --git a/skimage/rank/_core16.pxd b/skimage/rank/_core16.pxd index 791f5fb9..1a3194de 100644 --- a/skimage/rank/_core16.pxd +++ b/skimage/rank/_core16.pxd @@ -93,7 +93,7 @@ char shift_x, char shift_y,int bitdepth): cdef int max_se = srows*scols # number of element in each attack border - cdef int n_se_n, n_se_s, n_se_e, n_se_w + cdef int num_se_n, num_se_s, num_se_e, num_se_w # the current local histogram distribution cdef int* histo = malloc(maxbin * sizeof(int)) @@ -126,26 +126,26 @@ char shift_x, char shift_y,int bitdepth): t = np.vstack((np.zeros((1,selem.shape[1])),selem)) t_n = np.diff(t,axis=0)==1 - n_se_n = n_se_s = n_se_e = n_se_w = 0 + num_se_n = num_se_s = num_se_e = num_se_w = 0 for r in range(srows): for c in range(scols): if t_e[r,c]: - se_e_r[n_se_e] = r - centre_r - se_e_c[n_se_e] = c - centre_c - n_se_e += 1 + se_e_r[num_se_e] = r - centre_r + se_e_c[num_se_e] = c - centre_c + num_se_e += 1 if t_w[r,c]: - se_w_r[n_se_w] = r - centre_r - se_w_c[n_se_w] = c - centre_c - n_se_w += 1 + se_w_r[num_se_w] = r - centre_r + se_w_c[num_se_w] = c - centre_c + num_se_w += 1 if t_n[r,c]: - se_n_r[n_se_n] = r - centre_r - se_n_c[n_se_n] = c - centre_c - n_se_n += 1 + se_n_r[num_se_n] = r - centre_r + se_n_c[num_se_n] = c - centre_c + num_se_n += 1 if t_s[r,c]: - se_s_r[n_se_s] = r - centre_r - se_s_c[n_se_s] = c - centre_c - n_se_s += 1 + se_s_r[num_se_s] = r - centre_r + se_s_c[num_se_s] = c - centre_c + num_se_s += 1 # initial population and histogram for i in range(maxbin): @@ -175,14 +175,14 @@ char shift_x, char shift_y,int bitdepth): for even_row in range(0,rows,2): # ---> west to east for c in range(1,cols): - for s in range(n_se_e): + for s in range(num_se_e): rr = r + se_e_r[s] + centre_r cc = c + se_e_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_w): + for s in range(num_se_w): rr = r + se_w_r[s] + centre_r cc = c + se_w_c[s] + centre_c - 1 if emask_data[rr * ecols + cc]: @@ -200,14 +200,14 @@ char shift_x, char shift_y,int bitdepth): break # ---> north to south - for s in range(n_se_s): + for s in range(num_se_s): rr = r + se_s_r[s] + centre_r cc = c + se_s_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_n): + for s in range(num_se_n): rr = r + se_n_r[s] + centre_r - 1 cc = c + se_n_c[s] + centre_c if emask_data[rr * ecols + cc]: @@ -222,14 +222,14 @@ char shift_x, char shift_y,int bitdepth): # ---> east to west for c in range(cols-2,-1,-1): - for s in range(n_se_w): + for s in range(num_se_w): rr = r + se_w_r[s] + centre_r cc = c + se_w_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_e): + for s in range(num_se_e): rr = r + se_e_r[s] + centre_r cc = c + se_e_c[s] + centre_c + 1 if emask_data[rr * ecols + cc]: @@ -247,14 +247,14 @@ char shift_x, char shift_y,int bitdepth): break # ---> north to south - for s in range(n_se_s): + for s in range(num_se_s): rr = r + se_s_r[s] + centre_r cc = c + se_s_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_n): + for s in range(num_se_n): rr = r + se_n_r[s] + centre_r - 1 cc = c + se_n_c[s] + centre_c if emask_data[rr * ecols + cc]: diff --git a/skimage/rank/_core16b.pxd b/skimage/rank/_core16b.pxd index 3007a2fb..163662b5 100644 --- a/skimage/rank/_core16b.pxd +++ b/skimage/rank/_core16b.pxd @@ -94,7 +94,7 @@ char shift_x, char shift_y,int bitdepth, int s0, int s1): cdef int max_se = srows*scols # number of element in each attack border - cdef int n_se_n, n_se_s, n_se_e, n_se_w + cdef int num_se_n, num_se_s, num_se_e, num_se_w # the current local histogram distribution cdef int* histo = malloc(maxbin * sizeof(int)) @@ -127,26 +127,26 @@ char shift_x, char shift_y,int bitdepth, int s0, int s1): t = np.vstack((np.zeros((1,selem.shape[1])),selem)) t_n = np.diff(t,axis=0)==1 - n_se_n = n_se_s = n_se_e = n_se_w = 0 + num_se_n = num_se_s = num_se_e = num_se_w = 0 for r in range(srows): for c in range(scols): if t_e[r,c]: - se_e_r[n_se_e] = r - centre_r - se_e_c[n_se_e] = c - centre_c - n_se_e += 1 + se_e_r[num_se_e] = r - centre_r + se_e_c[num_se_e] = c - centre_c + num_se_e += 1 if t_w[r,c]: - se_w_r[n_se_w] = r - centre_r - se_w_c[n_se_w] = c - centre_c - n_se_w += 1 + se_w_r[num_se_w] = r - centre_r + se_w_c[num_se_w] = c - centre_c + num_se_w += 1 if t_n[r,c]: - se_n_r[n_se_n] = r - centre_r - se_n_c[n_se_n] = c - centre_c - n_se_n += 1 + se_n_r[num_se_n] = r - centre_r + se_n_c[num_se_n] = c - centre_c + num_se_n += 1 if t_s[r,c]: - se_s_r[n_se_s] = r - centre_r - se_s_c[n_se_s] = c - centre_c - n_se_s += 1 + se_s_r[num_se_s] = r - centre_r + se_s_c[num_se_s] = c - centre_c + num_se_s += 1 # initial population and histogram for i in range(maxbin): @@ -176,14 +176,14 @@ char shift_x, char shift_y,int bitdepth, int s0, int s1): for even_row in range(0,rows,2): # ---> west to east for c in range(1,cols): - for s in range(n_se_e): + for s in range(num_se_e): rr = r + se_e_r[s] + centre_r cc = c + se_e_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_w): + for s in range(num_se_w): rr = r + se_w_r[s] + centre_r cc = c + se_w_c[s] + centre_c - 1 if emask_data[rr * ecols + cc]: @@ -201,14 +201,14 @@ char shift_x, char shift_y,int bitdepth, int s0, int s1): break # ---> north to south - for s in range(n_se_s): + for s in range(num_se_s): rr = r + se_s_r[s] + centre_r cc = c + se_s_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_n): + for s in range(num_se_n): rr = r + se_n_r[s] + centre_r - 1 cc = c + se_n_c[s] + centre_c if emask_data[rr * ecols + cc]: @@ -223,14 +223,14 @@ char shift_x, char shift_y,int bitdepth, int s0, int s1): # ---> east to west for c in range(cols-2,-1,-1): - for s in range(n_se_w): + for s in range(num_se_w): rr = r + se_w_r[s] + centre_r cc = c + se_w_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_e): + for s in range(num_se_e): rr = r + se_e_r[s] + centre_r cc = c + se_e_c[s] + centre_c + 1 if emask_data[rr * ecols + cc]: @@ -248,14 +248,14 @@ char shift_x, char shift_y,int bitdepth, int s0, int s1): break # ---> north to south - for s in range(n_se_s): + for s in range(num_se_s): rr = r + se_s_r[s] + centre_r cc = c + se_s_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_n): + for s in range(num_se_n): rr = r + se_n_r[s] + centre_r - 1 cc = c + se_n_c[s] + centre_c if emask_data[rr * ecols + cc]: diff --git a/skimage/rank/_core16p.pxd b/skimage/rank/_core16p.pxd index 484a6a6b..9e992b6b 100644 --- a/skimage/rank/_core16p.pxd +++ b/skimage/rank/_core16p.pxd @@ -90,7 +90,7 @@ char shift_x, char shift_y,int bitdepth, float p0, float p1): cdef int max_se = srows*scols # number of element in each attack border - cdef int n_se_n, n_se_s, n_se_e, n_se_w + cdef int num_se_n, num_se_s, num_se_e, num_se_w # the current local histogram distribution cdef int* histo = malloc(maxbin * sizeof(int)) @@ -123,26 +123,26 @@ char shift_x, char shift_y,int bitdepth, float p0, float p1): t = np.vstack((np.zeros((1,selem.shape[1])),selem)) t_n = np.diff(t,axis=0)==1 - n_se_n = n_se_s = n_se_e = n_se_w = 0 + num_se_n = num_se_s = num_se_e = num_se_w = 0 for r in range(srows): for c in range(scols): if t_e[r,c]: - se_e_r[n_se_e] = r - centre_r - se_e_c[n_se_e] = c - centre_c - n_se_e += 1 + se_e_r[num_se_e] = r - centre_r + se_e_c[num_se_e] = c - centre_c + num_se_e += 1 if t_w[r,c]: - se_w_r[n_se_w] = r - centre_r - se_w_c[n_se_w] = c - centre_c - n_se_w += 1 + se_w_r[num_se_w] = r - centre_r + se_w_c[num_se_w] = c - centre_c + num_se_w += 1 if t_n[r,c]: - se_n_r[n_se_n] = r - centre_r - se_n_c[n_se_n] = c - centre_c - n_se_n += 1 + se_n_r[num_se_n] = r - centre_r + se_n_c[num_se_n] = c - centre_c + num_se_n += 1 if t_s[r,c]: - se_s_r[n_se_s] = r - centre_r - se_s_c[n_se_s] = c - centre_c - n_se_s += 1 + se_s_r[num_se_s] = r - centre_r + se_s_c[num_se_s] = c - centre_c + num_se_s += 1 # initial population and histogram for i in range(maxbin): @@ -172,14 +172,14 @@ char shift_x, char shift_y,int bitdepth, float p0, float p1): for even_row in range(0,rows,2): # ---> west to east for c in range(1,cols): - for s in range(n_se_e): + for s in range(num_se_e): rr = r + se_e_r[s] + centre_r cc = c + se_e_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_w): + for s in range(num_se_w): rr = r + se_w_r[s] + centre_r cc = c + se_w_c[s] + centre_c - 1 if emask_data[rr * ecols + cc]: @@ -197,14 +197,14 @@ char shift_x, char shift_y,int bitdepth, float p0, float p1): break # ---> north to south - for s in range(n_se_s): + for s in range(num_se_s): rr = r + se_s_r[s] + centre_r cc = c + se_s_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_n): + for s in range(num_se_n): rr = r + se_n_r[s] + centre_r - 1 cc = c + se_n_c[s] + centre_c if emask_data[rr * ecols + cc]: @@ -219,14 +219,14 @@ char shift_x, char shift_y,int bitdepth, float p0, float p1): # ---> east to west for c in range(cols-2,-1,-1): - for s in range(n_se_w): + for s in range(num_se_w): rr = r + se_w_r[s] + centre_r cc = c + se_w_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_e): + for s in range(num_se_e): rr = r + se_e_r[s] + centre_r cc = c + se_e_c[s] + centre_c + 1 if emask_data[rr * ecols + cc]: @@ -244,14 +244,14 @@ char shift_x, char shift_y,int bitdepth, float p0, float p1): break # ---> north to south - for s in range(n_se_s): + for s in range(num_se_s): rr = r + se_s_r[s] + centre_r cc = c + se_s_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_n): + for s in range(num_se_n): rr = r + se_n_r[s] + centre_r - 1 cc = c + se_n_c[s] + centre_c if emask_data[rr * ecols + cc]: diff --git a/skimage/rank/_core8.pxd b/skimage/rank/_core8.pxd index 325f779d..d24297cb 100644 --- a/skimage/rank/_core8.pxd +++ b/skimage/rank/_core8.pxd @@ -83,7 +83,7 @@ char shift_x, char shift_y): cdef int max_se = srows*scols # number of element in each attack border - cdef int n_se_n, n_se_s, n_se_e, n_se_w + cdef int num_se_n, num_se_s, num_se_e, num_se_w # the current local histogram distribution cdef int* histo = malloc(256 * sizeof(int)) @@ -116,26 +116,26 @@ char shift_x, char shift_y): t = np.vstack((np.zeros((1,selem.shape[1])),selem)) t_n = np.diff(t,axis=0)==1 - n_se_n = n_se_s = n_se_e = n_se_w = 0 + num_se_n = num_se_s = num_se_e = num_se_w = 0 for r in range(srows): for c in range(scols): if t_e[r,c]: - se_e_r[n_se_e] = r - centre_r - se_e_c[n_se_e] = c - centre_c - n_se_e += 1 + se_e_r[num_se_e] = r - centre_r + se_e_c[num_se_e] = c - centre_c + num_se_e += 1 if t_w[r,c]: - se_w_r[n_se_w] = r - centre_r - se_w_c[n_se_w] = c - centre_c - n_se_w += 1 + se_w_r[num_se_w] = r - centre_r + se_w_c[num_se_w] = c - centre_c + num_se_w += 1 if t_n[r,c]: - se_n_r[n_se_n] = r - centre_r - se_n_c[n_se_n] = c - centre_c - n_se_n += 1 + se_n_r[num_se_n] = r - centre_r + se_n_c[num_se_n] = c - centre_c + num_se_n += 1 if t_s[r,c]: - se_s_r[n_se_s] = r - centre_r - se_s_c[n_se_s] = c - centre_c - n_se_s += 1 + se_s_r[num_se_s] = r - centre_r + se_s_c[num_se_s] = c - centre_c + num_se_s += 1 # initial population and histogram for i in range(256): @@ -164,14 +164,14 @@ char shift_x, char shift_y): for even_row in range(0,rows,2): # ---> west to east for c in range(1,cols): - for s in range(n_se_e): + for s in range(num_se_e): rr = r + se_e_r[s] + centre_r cc = c + se_e_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_w): + for s in range(num_se_w): rr = r + se_w_r[s] + centre_r cc = c + se_w_c[s] + centre_c - 1 if emask_data[rr * ecols + cc]: @@ -188,14 +188,14 @@ char shift_x, char shift_y): break # ---> north to south - for s in range(n_se_s): + for s in range(num_se_s): rr = r + se_s_r[s] + centre_r cc = c + se_s_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_n): + for s in range(num_se_n): rr = r + se_n_r[s] + centre_r - 1 cc = c + se_n_c[s] + centre_c if emask_data[rr * ecols + cc]: @@ -209,14 +209,14 @@ char shift_x, char shift_y): # ---> east to west for c in range(cols-2,-1,-1): - for s in range(n_se_w): + for s in range(num_se_w): rr = r + se_w_r[s] + centre_r cc = c + se_w_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_e): + for s in range(num_se_e): rr = r + se_e_r[s] + centre_r cc = c + se_e_c[s] + centre_c + 1 if emask_data[rr * ecols + cc]: @@ -233,14 +233,14 @@ char shift_x, char shift_y): break # ---> north to south - for s in range(n_se_s): + for s in range(num_se_s): rr = r + se_s_r[s] + centre_r cc = c + se_s_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_n): + for s in range(num_se_n): rr = r + se_n_r[s] + centre_r - 1 cc = c + se_n_c[s] + centre_c if emask_data[rr * ecols + cc]: diff --git a/skimage/rank/_core8p.pxd b/skimage/rank/_core8p.pxd index 5fa278d5..b1adac70 100644 --- a/skimage/rank/_core8p.pxd +++ b/skimage/rank/_core8p.pxd @@ -80,7 +80,7 @@ char shift_x, char shift_y, float p0, float p1): cdef int max_se = srows*scols # number of element in each attack border - cdef int n_se_n, n_se_s, n_se_e, n_se_w + cdef int num_se_n, num_se_s, num_se_e, num_se_w # the current local histogram distribution cdef int* histo = malloc(256 * sizeof(int)) @@ -113,26 +113,26 @@ char shift_x, char shift_y, float p0, float p1): t = np.vstack((np.zeros((1,selem.shape[1])),selem)) t_n = np.diff(t,axis=0)==1 - n_se_n = n_se_s = n_se_e = n_se_w = 0 + num_se_n = num_se_s = num_se_e = num_se_w = 0 for r in range(srows): for c in range(scols): if t_e[r,c]: - se_e_r[n_se_e] = r - centre_r - se_e_c[n_se_e] = c - centre_c - n_se_e += 1 + se_e_r[num_se_e] = r - centre_r + se_e_c[num_se_e] = c - centre_c + num_se_e += 1 if t_w[r,c]: - se_w_r[n_se_w] = r - centre_r - se_w_c[n_se_w] = c - centre_c - n_se_w += 1 + se_w_r[num_se_w] = r - centre_r + se_w_c[num_se_w] = c - centre_c + num_se_w += 1 if t_n[r,c]: - se_n_r[n_se_n] = r - centre_r - se_n_c[n_se_n] = c - centre_c - n_se_n += 1 + se_n_r[num_se_n] = r - centre_r + se_n_c[num_se_n] = c - centre_c + num_se_n += 1 if t_s[r,c]: - se_s_r[n_se_s] = r - centre_r - se_s_c[n_se_s] = c - centre_c - n_se_s += 1 + se_s_r[num_se_s] = r - centre_r + se_s_c[num_se_s] = c - centre_c + num_se_s += 1 # initial population and histogram for i in range(256): @@ -161,14 +161,14 @@ char shift_x, char shift_y, float p0, float p1): for even_row in range(0,rows,2): # ---> west to east for c in range(1,cols): - for s in range(n_se_e): + for s in range(num_se_e): rr = r + se_e_r[s] + centre_r cc = c + se_e_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_w): + for s in range(num_se_w): rr = r + se_w_r[s] + centre_r cc = c + se_w_c[s] + centre_c - 1 if emask_data[rr * ecols + cc]: @@ -185,14 +185,14 @@ char shift_x, char shift_y, float p0, float p1): break # ---> north to south - for s in range(n_se_s): + for s in range(num_se_s): rr = r + se_s_r[s] + centre_r cc = c + se_s_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_n): + for s in range(num_se_n): rr = r + se_n_r[s] + centre_r - 1 cc = c + se_n_c[s] + centre_c if emask_data[rr * ecols + cc]: @@ -206,14 +206,14 @@ char shift_x, char shift_y, float p0, float p1): # ---> east to west for c in range(cols-2,-1,-1): - for s in range(n_se_w): + for s in range(num_se_w): rr = r + se_w_r[s] + centre_r cc = c + se_w_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_e): + for s in range(num_se_e): rr = r + se_e_r[s] + centre_r cc = c + se_e_c[s] + centre_c + 1 if emask_data[rr * ecols + cc]: @@ -230,14 +230,14 @@ char shift_x, char shift_y, float p0, float p1): break # ---> north to south - for s in range(n_se_s): + for s in range(num_se_s): rr = r + se_s_r[s] + centre_r cc = c + se_s_c[s] + centre_c if emask_data[rr * ecols + cc]: value = eimage_data[rr * ecols + cc] histo[value] += 1 pop += 1. - for s in range(n_se_n): + for s in range(num_se_n): rr = r + se_n_r[s] + centre_r - 1 cc = c + se_n_c[s] + centre_c if emask_data[rr * ecols + cc]: diff --git a/skimage/rank/_crank16_bilateral.pyx b/skimage/rank/_crank16_bilateral.pyx index 440d28e3..e783d7ea 100644 --- a/skimage/rank/_crank16_bilateral.pyx +++ b/skimage/rank/_crank16_bilateral.pyx @@ -21,73 +21,6 @@ from _core16b cimport _core16b # kernels uint16 take extra parameter for defining the bitdepth # ----------------------------------------------------------------- -#cdef inline np.uint16_t kernel_autolevel(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): -# cdef int i,imin,imax,delta -# -# if pop: -# for i in range(maxbin-1,-1,-1): -# if histo[i]: -# imax = i -# break -# for i in range(maxbin): -# if histo[i]: -# imin = i -# break -# delta = imax-imin -# if delta>0: -# return (maxbin*1.*(g-imin)/delta) -# else: -# return (imax-imin) -# -#cdef inline np.uint16_t kernel_bottomhat(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): -# cdef int i -# -# for i in range(maxbin): -# if histo[i]: -# break -# -# return (g-i) -# -# -#cdef inline np.uint16_t kernel_egalise(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): -# cdef int i -# cdef float sum = 0. -# -# if pop: -# for i in range(maxbin): -# sum += histo[i] -# if i>=g: -# break -# -# return ((maxbin*1.*sum)/pop) -# else: -# return (0) -# -#cdef inline np.uint16_t kernel_gradient(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): -# cdef int i,imin,imax -# -# if pop: -# for i in range(maxbin-1,-1,-1): -# if histo[i]: -# imax = i -# break -# for i in range(maxbin): -# if histo[i]: -# imin = i -# break -# return (imax-imin) -# else: -# return (0) -# -#cdef inline np.uint16_t kernel_maximum(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): -# cdef int i -# -# if pop: -# for i in range(maxbin-1,-1,-1): -# if histo[i]: -# return (i) -# -# return (0) cdef inline np.uint16_t kernel_mean(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin, int s0, int s1): cdef int i,bilat_pop=0 @@ -105,71 +38,7 @@ cdef inline np.uint16_t kernel_mean(int* histo, float pop, np.uint16_t g,int bit else: return (0) -#cdef inline np.uint16_t kernel_meansubstraction(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): -# cdef int i -# cdef float mean = 0. -# -# if pop: -# for i in range(maxbin): -# mean += histo[i]*i -# return ((g-mean/pop)/2.+midbin) -# else: -# return (0) -# -#cdef inline np.uint16_t kernel_median(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): -# cdef int i -# cdef float sum = pop/2.0 -# -# if pop: -# for i in range(maxbin): -# if histo[i]: -# sum -= histo[i] -# if sum<0: -# return (i) -# -# return (0) -# -#cdef inline np.uint16_t kernel_minimum(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): -# cdef int i -# -# if pop: -# for i in range(maxbin): -# if histo[i]: -# return (i) -# -# return (0) -# -#cdef inline np.uint16_t kernel_modal(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): -# cdef int hmax=0,imax=0 -# -# if pop: -# for i in range(maxbin): -# if histo[i]>hmax: -# hmax = histo[i] -# imax = i -# return (imax) -# -# return (0) -# -#cdef inline np.uint16_t kernel_morph_contr_enh(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): -# cdef int i,imin,imax -# -# if pop: -# for i in range(maxbin-1,-1,-1): -# if histo[i]: -# imax = i -# break -# for i in range(maxbin): -# if histo[i]: -# imin = i -# break -# if imax-g < g-imin: -# return (imax) -# else: -# return (imin) -# else: -# return (0) -# + cdef inline np.uint16_t kernel_pop(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin, int s0, int s1): cdef int i,bilat_pop=0 @@ -181,75 +50,10 @@ cdef inline np.uint16_t kernel_pop(int* histo, float pop, np.uint16_t g,int bitd else: return (0) -# -#cdef inline np.uint16_t kernel_threshold(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): -# cdef int i -# cdef float mean = 0. -# -# if pop: -# for i in range(maxbin): -# mean += histo[i]*i -# return (g>(mean/pop)) -# else: -# return (0) -# -#cdef inline np.uint16_t kernel_tophat(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): -# cdef int i -# -# for i in range(maxbin-1,-1,-1): -# if histo[i]: -# break -# -# return (i-g) # ----------------------------------------------------------------- # python wrappers # ----------------------------------------------------------------- -#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, int s0=1, int s1=1): -# """bottom hat -# """ -# return rank16b(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) -# -#def bottomhat(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, int s0=1, int s1=1): -# """bottom hat -# """ -# return rank16b(kernel_bottomhat,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) -# -#def egalise(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, int s0=1, int s1=1): -# """local egalisation of the gray level -# """ -# return rank16b(kernel_egalise,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) -# -#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, int s0=1, int s1=1): -# """local maximum - local minimum gray level -# """ -# return rank16b(kernel_gradient,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) -# -#def maximum(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, int s0=1, int s1=1): -# """local maximum gray level -# """ -# return rank16b(kernel_maximum,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) - 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, @@ -259,51 +63,7 @@ def mean(np.ndarray[np.uint16_t, ndim=2] image, """ return _core16b(kernel_mean,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) -#def meansubstraction(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, int s0=1, int s1=1): -# """(g - average gray level)/2+midbin (clipped on uint8) -# """ -# return rank16b(kernel_meansubstraction,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) -# -#def median(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, int s0=1, int s1=1): -# """local median -# """ -# return rank16b(kernel_median,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) -# -#def minimum(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, int s0=1, int s1=1): -# """local minimum gray level -# """ -# return rank16b(kernel_minimum,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) -# -#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, int s0=1, int s1=1): -# """morphological contrast enhancement -# """ -# return rank16b(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) -# -#def modal(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, int s0=1, int s1=1): -# """local mode -# """ -# return rank16b(kernel_modal,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) -# + 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, @@ -313,20 +73,3 @@ def pop(np.ndarray[np.uint16_t, ndim=2] image, """ return _core16b(kernel_pop,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) -#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, int s0=1, int s1=1): -# """returns maxbin-1 if gray level higher than local mean, 0 else -# """ -# return rank16b(kernel_threshold,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) -# -#def tophat(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, int s0=1, int s1=1): -# """top hat -# """ -# return rank16b(kernel_tophat,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) From e83a456ebccdad73ae6a9d475e408d224c313a3f Mon Sep 17 00:00:00 2001 From: odebeir Date: Sat, 13 Oct 2012 09:47:25 +0200 Subject: [PATCH 50/86] fix pxd-pyx confusion --- skimage/rank/_core16.pxd | 273 +----------------------------------- skimage/rank/_core16.pyx | 283 +++++++++++++++++++++++++++++++++++++ skimage/rank/_core16b.pxd | 274 +----------------------------------- skimage/rank/_core16b.pyx | 284 ++++++++++++++++++++++++++++++++++++++ skimage/rank/_core16p.pxd | 272 +----------------------------------- skimage/rank/_core16p.pyx | 282 +++++++++++++++++++++++++++++++++++++ skimage/rank/_core8.pxd | 259 +--------------------------------- skimage/rank/_core8.pyx | 269 ++++++++++++++++++++++++++++++++++++ skimage/rank/_core8p.pxd | 255 +--------------------------------- skimage/rank/_core8p.pyx | 266 +++++++++++++++++++++++++++++++++++ skimage/rank/setup.py | 18 +++ 11 files changed, 1411 insertions(+), 1324 deletions(-) create mode 100644 skimage/rank/_core16.pyx create mode 100644 skimage/rank/_core16b.pyx create mode 100644 skimage/rank/_core16p.pyx create mode 100644 skimage/rank/_core8.pyx create mode 100644 skimage/rank/_core8p.pyx diff --git a/skimage/rank/_core16.pxd b/skimage/rank/_core16.pxd index 1a3194de..d00ef37e 100644 --- a/skimage/rank/_core16.pxd +++ b/skimage/rank/_core16.pxd @@ -1,18 +1,4 @@ -""" to compile this use: ->>> python setup.py build_ext --inplace - -to generate html report use: ->>> cython -a core16.pxd -""" - -#cython: cdivision=True -#cython: boundscheck=False -#cython: nonecheck=False -#cython: wraparound=False - -import numpy as np cimport numpy as np -from libc.stdlib cimport malloc, free #--------------------------------------------------------------------------- # 16 bit core kernel receives extra information about data bitdepth @@ -23,261 +9,4 @@ 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,int bitdepth): - """ Main loop, this function computes the histogram for each image point - - data is uint8 - - result is uint8 casted - """ - - cdef int rows = image.shape[0] - cdef int cols = image.shape[1] - cdef int srows = selem.shape[0] - cdef int scols = selem.shape[1] - - cdef int centre_r = int(selem.shape[0] / 2) + shift_y - cdef int centre_c = int(selem.shape[1] / 2) + shift_x - - # check that structuring element center is inside the element bounding box - assert centre_r >= 0 - assert centre_c >= 0 - assert centre_r < srows - assert centre_c < scols - assert bitdepth in range(2,13) - - 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 int maxbin=maxbin_list[bitdepth],midbin=midbin_list[bitdepth] - - assert (imageeimage.data - cdef np.uint8_t* emask_data = emask.data - - cdef np.uint16_t* out_data = out.data - cdef np.uint16_t* image_data = image.data - cdef np.uint8_t* mask_data = mask.data - - # define local variable types - cdef int r, c, rr, cc, s, value, local_max, i, even_row - cdef float pop # number of pixels actually inside the neighborhood (float) - - # allocate memory with malloc - cdef int max_se = srows*scols - - # number of element in each attack border - cdef int num_se_n, num_se_s, num_se_e, num_se_w - - # the current local histogram distribution - cdef int* histo = malloc(maxbin * sizeof(int)) - - # 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 int* se_e_r = malloc(max_se * sizeof(int)) - cdef int* se_e_c = malloc(max_se * sizeof(int)) - cdef int* se_w_r = malloc(max_se * sizeof(int)) - cdef int* se_w_c = malloc(max_se * sizeof(int)) - cdef int* se_n_r = malloc(max_se * sizeof(int)) - cdef int* se_n_c = malloc(max_se * sizeof(int)) - cdef int* se_s_r = malloc(max_se * sizeof(int)) - cdef int* se_s_c = malloc(max_se * sizeof(int)) - - # 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 - - t = np.hstack((np.zeros((selem.shape[0],1)),selem)) - t_w = np.diff(t,axis=1)==1 - - t = np.vstack((selem,np.zeros((1,selem.shape[1])))) - t_s = np.diff(t,axis=0)==-1 - - t = np.vstack((np.zeros((1,selem.shape[1])),selem)) - t_n = np.diff(t,axis=0)==1 - - num_se_n = num_se_s = num_se_e = num_se_w = 0 - - for r in range(srows): - for c in range(scols): - if t_e[r,c]: - se_e_r[num_se_e] = r - centre_r - se_e_c[num_se_e] = c - centre_c - num_se_e += 1 - if t_w[r,c]: - se_w_r[num_se_w] = r - centre_r - se_w_c[num_se_w] = c - centre_c - num_se_w += 1 - if t_n[r,c]: - se_n_r[num_se_n] = r - centre_r - se_n_c[num_se_n] = c - centre_c - num_se_n += 1 - if t_s[r,c]: - se_s_r[num_se_s] = r - centre_r - se_s_c[num_se_s] = c - centre_c - num_se_s += 1 - - # initial population and histogram - for i in range(maxbin): - histo[i] = 0 - - pop = 0 - - for r in range(srows): - for c in range(scols): - rr = r - cc = c - if selem[r, c]: - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - - r = 0 - c = 0 - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin) - # kernel ------------------------------------------- - - # main loop - r = 0 - for even_row in range(0,rows,2): - # ---> west to east - for c in range(1,cols): - for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin) - # kernel ------------------------------------------- - - # ---> east to west - for c in range(cols-2,-1,-1): - for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c + 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin) - # kernel ------------------------------------------- - - # release memory allocated by malloc - - free(se_e_r) - free(se_e_c) - free(se_w_r) - free(se_w_c) - free(se_n_r) - free(se_n_c) - free(se_s_r) - free(se_s_c) - - free(histo) - - return out +char shift_x, char shift_y,int bitdepth) \ No newline at end of file diff --git a/skimage/rank/_core16.pyx b/skimage/rank/_core16.pyx new file mode 100644 index 00000000..1a3194de --- /dev/null +++ b/skimage/rank/_core16.pyx @@ -0,0 +1,283 @@ +""" to compile this use: +>>> python setup.py build_ext --inplace + +to generate html report use: +>>> cython -a core16.pxd +""" + +#cython: cdivision=True +#cython: boundscheck=False +#cython: nonecheck=False +#cython: wraparound=False + +import numpy as np +cimport numpy as np +from libc.stdlib cimport malloc, free + +#--------------------------------------------------------------------------- +# 16 bit core kernel receives extra information about data bitdepth +#--------------------------------------------------------------------------- + +cdef inline _core16(np.uint16_t kernel(int*, float, np.uint16_t, int ,int,int ), +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,int bitdepth): + """ Main loop, this function computes the histogram for each image point + - data is uint8 + - result is uint8 casted + """ + + cdef int rows = image.shape[0] + cdef int cols = image.shape[1] + cdef int srows = selem.shape[0] + cdef int scols = selem.shape[1] + + cdef int centre_r = int(selem.shape[0] / 2) + shift_y + cdef int centre_c = int(selem.shape[1] / 2) + shift_x + + # check that structuring element center is inside the element bounding box + assert centre_r >= 0 + assert centre_c >= 0 + assert centre_r < srows + assert centre_c < scols + assert bitdepth in range(2,13) + + 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 int maxbin=maxbin_list[bitdepth],midbin=midbin_list[bitdepth] + + assert (imageeimage.data + cdef np.uint8_t* emask_data = emask.data + + cdef np.uint16_t* out_data = out.data + cdef np.uint16_t* image_data = image.data + cdef np.uint8_t* mask_data = mask.data + + # define local variable types + cdef int r, c, rr, cc, s, value, local_max, i, even_row + cdef float pop # number of pixels actually inside the neighborhood (float) + + # allocate memory with malloc + cdef int max_se = srows*scols + + # number of element in each attack border + cdef int num_se_n, num_se_s, num_se_e, num_se_w + + # the current local histogram distribution + cdef int* histo = malloc(maxbin * sizeof(int)) + + # 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 int* se_e_r = malloc(max_se * sizeof(int)) + cdef int* se_e_c = malloc(max_se * sizeof(int)) + cdef int* se_w_r = malloc(max_se * sizeof(int)) + cdef int* se_w_c = malloc(max_se * sizeof(int)) + cdef int* se_n_r = malloc(max_se * sizeof(int)) + cdef int* se_n_c = malloc(max_se * sizeof(int)) + cdef int* se_s_r = malloc(max_se * sizeof(int)) + cdef int* se_s_c = malloc(max_se * sizeof(int)) + + # 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 + + t = np.hstack((np.zeros((selem.shape[0],1)),selem)) + t_w = np.diff(t,axis=1)==1 + + t = np.vstack((selem,np.zeros((1,selem.shape[1])))) + t_s = np.diff(t,axis=0)==-1 + + t = np.vstack((np.zeros((1,selem.shape[1])),selem)) + t_n = np.diff(t,axis=0)==1 + + num_se_n = num_se_s = num_se_e = num_se_w = 0 + + for r in range(srows): + for c in range(scols): + if t_e[r,c]: + se_e_r[num_se_e] = r - centre_r + se_e_c[num_se_e] = c - centre_c + num_se_e += 1 + if t_w[r,c]: + se_w_r[num_se_w] = r - centre_r + se_w_c[num_se_w] = c - centre_c + num_se_w += 1 + if t_n[r,c]: + se_n_r[num_se_n] = r - centre_r + se_n_c[num_se_n] = c - centre_c + num_se_n += 1 + if t_s[r,c]: + se_s_r[num_se_s] = r - centre_r + se_s_c[num_se_s] = c - centre_c + num_se_s += 1 + + # initial population and histogram + for i in range(maxbin): + histo[i] = 0 + + pop = 0 + + for r in range(srows): + for c in range(scols): + rr = r + cc = c + if selem[r, c]: + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + + r = 0 + c = 0 + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + bitdepth,maxbin,midbin) + # kernel ------------------------------------------- + + # main loop + r = 0 + for even_row in range(0,rows,2): + # ---> west to east + for c in range(1,cols): + for s in range(num_se_e): + rr = r + se_e_r[s] + centre_r + cc = c + se_e_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_w): + rr = r + se_w_r[s] + centre_r + cc = c + se_w_c[s] + centre_c - 1 + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + bitdepth,maxbin,midbin) + # kernel ------------------------------------------- + + r += 1 # pass to the next row + if r>=rows: + break + + # ---> north to south + for s in range(num_se_s): + rr = r + se_s_r[s] + centre_r + cc = c + se_s_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_n): + rr = r + se_n_r[s] + centre_r - 1 + cc = c + se_n_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + bitdepth,maxbin,midbin) + # kernel ------------------------------------------- + + # ---> east to west + for c in range(cols-2,-1,-1): + for s in range(num_se_w): + rr = r + se_w_r[s] + centre_r + cc = c + se_w_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_e): + rr = r + se_e_r[s] + centre_r + cc = c + se_e_c[s] + centre_c + 1 + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + bitdepth,maxbin,midbin) + # kernel ------------------------------------------- + + r += 1 # pass to the next row + if r>=rows: + break + + # ---> north to south + for s in range(num_se_s): + rr = r + se_s_r[s] + centre_r + cc = c + se_s_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_n): + rr = r + se_n_r[s] + centre_r - 1 + cc = c + se_n_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + bitdepth,maxbin,midbin) + # kernel ------------------------------------------- + + # release memory allocated by malloc + + free(se_e_r) + free(se_e_c) + free(se_w_r) + free(se_w_c) + free(se_n_r) + free(se_n_c) + free(se_s_r) + free(se_s_c) + + free(histo) + + return out diff --git a/skimage/rank/_core16b.pxd b/skimage/rank/_core16b.pxd index 163662b5..b972ae9a 100644 --- a/skimage/rank/_core16b.pxd +++ b/skimage/rank/_core16b.pxd @@ -1,18 +1,4 @@ -""" to compile this use: ->>> python setup.py build_ext --inplace - -to generate html report use: ->>> cython -a core16b.pxd -""" - -#cython: cdivision=True -#cython: boundscheck=False -#cython: nonecheck=False -#cython: wraparound=False - -import numpy as np cimport numpy as np -from libc.stdlib cimport malloc, free #--------------------------------------------------------------------------- # 16 bit core kernel receives extra information about data bitdepth and bilateral interval @@ -23,262 +9,4 @@ 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,int bitdepth, int s0, int s1): - """ Main loop, this function computes the histogram for each image point - - data is uint8 - - result is uint8 casted - - only pixel inside [s0,s1] centered on g are taken into account - """ - - cdef int rows = image.shape[0] - cdef int cols = image.shape[1] - cdef int srows = selem.shape[0] - cdef int scols = selem.shape[1] - - cdef int centre_r = int(selem.shape[0] / 2) + shift_y - cdef int centre_c = int(selem.shape[1] / 2) + shift_x - - # check that structuring element center is inside the element bounding box - assert centre_r >= 0 - assert centre_c >= 0 - assert centre_r < srows - assert centre_c < scols - assert bitdepth in range(2,13) - - 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 int maxbin=maxbin_list[bitdepth],midbin=midbin_list[bitdepth] - - assert (imageeimage.data - cdef np.uint8_t* emask_data = emask.data - - cdef np.uint16_t* out_data = out.data - cdef np.uint16_t* image_data = image.data - cdef np.uint8_t* mask_data = mask.data - - # define local variable types - cdef int r, c, rr, cc, s, value, local_max, i, even_row - cdef float pop # number of pixels actually inside the neighborhood (float) - - # allocate memory with malloc - cdef int max_se = srows*scols - - # number of element in each attack border - cdef int num_se_n, num_se_s, num_se_e, num_se_w - - # the current local histogram distribution - cdef int* histo = malloc(maxbin * sizeof(int)) - - # 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 int* se_e_r = malloc(max_se * sizeof(int)) - cdef int* se_e_c = malloc(max_se * sizeof(int)) - cdef int* se_w_r = malloc(max_se * sizeof(int)) - cdef int* se_w_c = malloc(max_se * sizeof(int)) - cdef int* se_n_r = malloc(max_se * sizeof(int)) - cdef int* se_n_c = malloc(max_se * sizeof(int)) - cdef int* se_s_r = malloc(max_se * sizeof(int)) - cdef int* se_s_c = malloc(max_se * sizeof(int)) - - # 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 - - t = np.hstack((np.zeros((selem.shape[0],1)),selem)) - t_w = np.diff(t,axis=1)==1 - - t = np.vstack((selem,np.zeros((1,selem.shape[1])))) - t_s = np.diff(t,axis=0)==-1 - - t = np.vstack((np.zeros((1,selem.shape[1])),selem)) - t_n = np.diff(t,axis=0)==1 - - num_se_n = num_se_s = num_se_e = num_se_w = 0 - - for r in range(srows): - for c in range(scols): - if t_e[r,c]: - se_e_r[num_se_e] = r - centre_r - se_e_c[num_se_e] = c - centre_c - num_se_e += 1 - if t_w[r,c]: - se_w_r[num_se_w] = r - centre_r - se_w_c[num_se_w] = c - centre_c - num_se_w += 1 - if t_n[r,c]: - se_n_r[num_se_n] = r - centre_r - se_n_c[num_se_n] = c - centre_c - num_se_n += 1 - if t_s[r,c]: - se_s_r[num_se_s] = r - centre_r - se_s_c[num_se_s] = c - centre_c - num_se_s += 1 - - # initial population and histogram - for i in range(maxbin): - histo[i] = 0 - - pop = 0 - - for r in range(srows): - for c in range(scols): - rr = r - cc = c - if selem[r, c]: - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - - r = 0 - c = 0 - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,s0,s1) - # kernel ------------------------------------------- - - # main loop - r = 0 - for even_row in range(0,rows,2): - # ---> west to east - for c in range(1,cols): - for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,s0,s1) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,s0,s1) - # kernel ------------------------------------------- - - # ---> east to west - for c in range(cols-2,-1,-1): - for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c + 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,s0,s1) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,s0,s1) - # kernel ------------------------------------------- - - # release memory allocated by malloc - - free(se_e_r) - free(se_e_c) - free(se_w_r) - free(se_w_c) - free(se_n_r) - free(se_n_c) - free(se_s_r) - free(se_s_c) - - free(histo) - - return out +char shift_x, char shift_y,int bitdepth, int s0, int s1) \ No newline at end of file diff --git a/skimage/rank/_core16b.pyx b/skimage/rank/_core16b.pyx new file mode 100644 index 00000000..163662b5 --- /dev/null +++ b/skimage/rank/_core16b.pyx @@ -0,0 +1,284 @@ +""" to compile this use: +>>> python setup.py build_ext --inplace + +to generate html report use: +>>> cython -a core16b.pxd +""" + +#cython: cdivision=True +#cython: boundscheck=False +#cython: nonecheck=False +#cython: wraparound=False + +import numpy as np +cimport numpy as np +from libc.stdlib cimport malloc, free + +#--------------------------------------------------------------------------- +# 16 bit core kernel receives extra information about data bitdepth and bilateral interval +#--------------------------------------------------------------------------- + +cdef inline _core16b(np.uint16_t kernel(int*, float, np.uint16_t, int ,int,int,int,int), +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,int bitdepth, int s0, int s1): + """ Main loop, this function computes the histogram for each image point + - data is uint8 + - result is uint8 casted + - only pixel inside [s0,s1] centered on g are taken into account + """ + + cdef int rows = image.shape[0] + cdef int cols = image.shape[1] + cdef int srows = selem.shape[0] + cdef int scols = selem.shape[1] + + cdef int centre_r = int(selem.shape[0] / 2) + shift_y + cdef int centre_c = int(selem.shape[1] / 2) + shift_x + + # check that structuring element center is inside the element bounding box + assert centre_r >= 0 + assert centre_c >= 0 + assert centre_r < srows + assert centre_c < scols + assert bitdepth in range(2,13) + + 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 int maxbin=maxbin_list[bitdepth],midbin=midbin_list[bitdepth] + + assert (imageeimage.data + cdef np.uint8_t* emask_data = emask.data + + cdef np.uint16_t* out_data = out.data + cdef np.uint16_t* image_data = image.data + cdef np.uint8_t* mask_data = mask.data + + # define local variable types + cdef int r, c, rr, cc, s, value, local_max, i, even_row + cdef float pop # number of pixels actually inside the neighborhood (float) + + # allocate memory with malloc + cdef int max_se = srows*scols + + # number of element in each attack border + cdef int num_se_n, num_se_s, num_se_e, num_se_w + + # the current local histogram distribution + cdef int* histo = malloc(maxbin * sizeof(int)) + + # 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 int* se_e_r = malloc(max_se * sizeof(int)) + cdef int* se_e_c = malloc(max_se * sizeof(int)) + cdef int* se_w_r = malloc(max_se * sizeof(int)) + cdef int* se_w_c = malloc(max_se * sizeof(int)) + cdef int* se_n_r = malloc(max_se * sizeof(int)) + cdef int* se_n_c = malloc(max_se * sizeof(int)) + cdef int* se_s_r = malloc(max_se * sizeof(int)) + cdef int* se_s_c = malloc(max_se * sizeof(int)) + + # 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 + + t = np.hstack((np.zeros((selem.shape[0],1)),selem)) + t_w = np.diff(t,axis=1)==1 + + t = np.vstack((selem,np.zeros((1,selem.shape[1])))) + t_s = np.diff(t,axis=0)==-1 + + t = np.vstack((np.zeros((1,selem.shape[1])),selem)) + t_n = np.diff(t,axis=0)==1 + + num_se_n = num_se_s = num_se_e = num_se_w = 0 + + for r in range(srows): + for c in range(scols): + if t_e[r,c]: + se_e_r[num_se_e] = r - centre_r + se_e_c[num_se_e] = c - centre_c + num_se_e += 1 + if t_w[r,c]: + se_w_r[num_se_w] = r - centre_r + se_w_c[num_se_w] = c - centre_c + num_se_w += 1 + if t_n[r,c]: + se_n_r[num_se_n] = r - centre_r + se_n_c[num_se_n] = c - centre_c + num_se_n += 1 + if t_s[r,c]: + se_s_r[num_se_s] = r - centre_r + se_s_c[num_se_s] = c - centre_c + num_se_s += 1 + + # initial population and histogram + for i in range(maxbin): + histo[i] = 0 + + pop = 0 + + for r in range(srows): + for c in range(scols): + rr = r + cc = c + if selem[r, c]: + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + + r = 0 + c = 0 + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + bitdepth,maxbin,midbin,s0,s1) + # kernel ------------------------------------------- + + # main loop + r = 0 + for even_row in range(0,rows,2): + # ---> west to east + for c in range(1,cols): + for s in range(num_se_e): + rr = r + se_e_r[s] + centre_r + cc = c + se_e_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_w): + rr = r + se_w_r[s] + centre_r + cc = c + se_w_c[s] + centre_c - 1 + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + bitdepth,maxbin,midbin,s0,s1) + # kernel ------------------------------------------- + + r += 1 # pass to the next row + if r>=rows: + break + + # ---> north to south + for s in range(num_se_s): + rr = r + se_s_r[s] + centre_r + cc = c + se_s_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_n): + rr = r + se_n_r[s] + centre_r - 1 + cc = c + se_n_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + bitdepth,maxbin,midbin,s0,s1) + # kernel ------------------------------------------- + + # ---> east to west + for c in range(cols-2,-1,-1): + for s in range(num_se_w): + rr = r + se_w_r[s] + centre_r + cc = c + se_w_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_e): + rr = r + se_e_r[s] + centre_r + cc = c + se_e_c[s] + centre_c + 1 + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + bitdepth,maxbin,midbin,s0,s1) + # kernel ------------------------------------------- + + r += 1 # pass to the next row + if r>=rows: + break + + # ---> north to south + for s in range(num_se_s): + rr = r + se_s_r[s] + centre_r + cc = c + se_s_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_n): + rr = r + se_n_r[s] + centre_r - 1 + cc = c + se_n_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + bitdepth,maxbin,midbin,s0,s1) + # kernel ------------------------------------------- + + # release memory allocated by malloc + + free(se_e_r) + free(se_e_c) + free(se_w_r) + free(se_w_c) + free(se_n_r) + free(se_n_c) + free(se_s_r) + free(se_s_c) + + free(histo) + + return out diff --git a/skimage/rank/_core16p.pxd b/skimage/rank/_core16p.pxd index 9e992b6b..d162540c 100644 --- a/skimage/rank/_core16p.pxd +++ b/skimage/rank/_core16p.pxd @@ -1,15 +1,8 @@ -#cython: cdivision=True -#cython: boundscheck=False -#cython: nonecheck=False -#cython: wraparound=False - -import numpy as np cimport numpy as np -from libc.stdlib cimport malloc, free # 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 int int_max(int a, int b) +cdef inline int int_min(int a, int b) #--------------------------------------------------------------------------- # 16 bit core kernel receives extra information about data inferior and superior percentiles @@ -20,263 +13,4 @@ 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,int bitdepth, float p0, float p1): - """ Main loop, this function computes the histogram for each image point - - data is uint16 - - result is uint16 casted - """ - - cdef int rows = image.shape[0] - cdef int cols = image.shape[1] - cdef int srows = selem.shape[0] - cdef int scols = selem.shape[1] - - cdef int centre_r = int(selem.shape[0] / 2) + shift_y - cdef int centre_c = int(selem.shape[1] / 2) + shift_x - - # check that structuring element center is inside the element bounding box - assert centre_r >= 0 - assert centre_c >= 0 - assert centre_r < srows - assert centre_c < scols - - assert bitdepth in range(2,13) - - 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 int maxbin=maxbin_list[bitdepth],midbin=midbin_list[bitdepth] - - assert (imageeimage.data - cdef np.uint8_t* emask_data = emask.data - - cdef np.uint16_t* out_data = out.data - cdef np.uint16_t* image_data = image.data - cdef np.uint8_t* mask_data = mask.data - - # define local variable types - cdef int r, c, rr, cc, s, value, local_max, i, even_row - cdef float pop # number of pixels actually inside the neighborhood (float) - - # allocate memory with malloc - cdef int max_se = srows*scols - - # number of element in each attack border - cdef int num_se_n, num_se_s, num_se_e, num_se_w - - # the current local histogram distribution - cdef int* histo = malloc(maxbin * sizeof(int)) - - # 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 int* se_e_r = malloc(max_se * sizeof(int)) - cdef int* se_e_c = malloc(max_se * sizeof(int)) - cdef int* se_w_r = malloc(max_se * sizeof(int)) - cdef int* se_w_c = malloc(max_se * sizeof(int)) - cdef int* se_n_r = malloc(max_se * sizeof(int)) - cdef int* se_n_c = malloc(max_se * sizeof(int)) - cdef int* se_s_r = malloc(max_se * sizeof(int)) - cdef int* se_s_c = malloc(max_se * sizeof(int)) - - # 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 - - t = np.hstack((np.zeros((selem.shape[0],1)),selem)) - t_w = np.diff(t,axis=1)==1 - - t = np.vstack((selem,np.zeros((1,selem.shape[1])))) - t_s = np.diff(t,axis=0)==-1 - - t = np.vstack((np.zeros((1,selem.shape[1])),selem)) - t_n = np.diff(t,axis=0)==1 - - num_se_n = num_se_s = num_se_e = num_se_w = 0 - - for r in range(srows): - for c in range(scols): - if t_e[r,c]: - se_e_r[num_se_e] = r - centre_r - se_e_c[num_se_e] = c - centre_c - num_se_e += 1 - if t_w[r,c]: - se_w_r[num_se_w] = r - centre_r - se_w_c[num_se_w] = c - centre_c - num_se_w += 1 - if t_n[r,c]: - se_n_r[num_se_n] = r - centre_r - se_n_c[num_se_n] = c - centre_c - num_se_n += 1 - if t_s[r,c]: - se_s_r[num_se_s] = r - centre_r - se_s_c[num_se_s] = c - centre_c - num_se_s += 1 - - # initial population and histogram - for i in range(maxbin): - histo[i] = 0 - - pop = 0 - - for r in range(srows): - for c in range(scols): - rr = r - cc = c - if selem[r, c]: - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - - r = 0 - c = 0 - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,p0,p1) - # kernel ------------------------------------------- - - # main loop - r = 0 - for even_row in range(0,rows,2): - # ---> west to east - for c in range(1,cols): - for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,p0,p1) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,p0,p1) - # kernel ------------------------------------------- - - # ---> east to west - for c in range(cols-2,-1,-1): - for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c + 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,p0,p1) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,p0,p1) - # kernel ------------------------------------------- - - # release memory allocated by malloc - - free(se_e_r) - free(se_e_c) - free(se_w_r) - free(se_w_c) - free(se_n_r) - free(se_n_c) - free(se_s_r) - free(se_s_c) - - free(histo) - - return out - - +char shift_x, char shift_y,int bitdepth, float p0, float p1) \ No newline at end of file diff --git a/skimage/rank/_core16p.pyx b/skimage/rank/_core16p.pyx new file mode 100644 index 00000000..9e992b6b --- /dev/null +++ b/skimage/rank/_core16p.pyx @@ -0,0 +1,282 @@ +#cython: cdivision=True +#cython: boundscheck=False +#cython: nonecheck=False +#cython: wraparound=False + +import numpy as np +cimport numpy as np +from libc.stdlib cimport malloc, free + +# 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 + +#--------------------------------------------------------------------------- +# 16 bit core kernel receives extra information about data inferior and superior percentiles +#--------------------------------------------------------------------------- + +cdef inline _core16p(np.uint16_t kernel(int*, float, np.uint16_t,int,int,int, float, float), +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,int bitdepth, float p0, float p1): + """ Main loop, this function computes the histogram for each image point + - data is uint16 + - result is uint16 casted + """ + + cdef int rows = image.shape[0] + cdef int cols = image.shape[1] + cdef int srows = selem.shape[0] + cdef int scols = selem.shape[1] + + cdef int centre_r = int(selem.shape[0] / 2) + shift_y + cdef int centre_c = int(selem.shape[1] / 2) + shift_x + + # check that structuring element center is inside the element bounding box + assert centre_r >= 0 + assert centre_c >= 0 + assert centre_r < srows + assert centre_c < scols + + assert bitdepth in range(2,13) + + 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 int maxbin=maxbin_list[bitdepth],midbin=midbin_list[bitdepth] + + assert (imageeimage.data + cdef np.uint8_t* emask_data = emask.data + + cdef np.uint16_t* out_data = out.data + cdef np.uint16_t* image_data = image.data + cdef np.uint8_t* mask_data = mask.data + + # define local variable types + cdef int r, c, rr, cc, s, value, local_max, i, even_row + cdef float pop # number of pixels actually inside the neighborhood (float) + + # allocate memory with malloc + cdef int max_se = srows*scols + + # number of element in each attack border + cdef int num_se_n, num_se_s, num_se_e, num_se_w + + # the current local histogram distribution + cdef int* histo = malloc(maxbin * sizeof(int)) + + # 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 int* se_e_r = malloc(max_se * sizeof(int)) + cdef int* se_e_c = malloc(max_se * sizeof(int)) + cdef int* se_w_r = malloc(max_se * sizeof(int)) + cdef int* se_w_c = malloc(max_se * sizeof(int)) + cdef int* se_n_r = malloc(max_se * sizeof(int)) + cdef int* se_n_c = malloc(max_se * sizeof(int)) + cdef int* se_s_r = malloc(max_se * sizeof(int)) + cdef int* se_s_c = malloc(max_se * sizeof(int)) + + # 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 + + t = np.hstack((np.zeros((selem.shape[0],1)),selem)) + t_w = np.diff(t,axis=1)==1 + + t = np.vstack((selem,np.zeros((1,selem.shape[1])))) + t_s = np.diff(t,axis=0)==-1 + + t = np.vstack((np.zeros((1,selem.shape[1])),selem)) + t_n = np.diff(t,axis=0)==1 + + num_se_n = num_se_s = num_se_e = num_se_w = 0 + + for r in range(srows): + for c in range(scols): + if t_e[r,c]: + se_e_r[num_se_e] = r - centre_r + se_e_c[num_se_e] = c - centre_c + num_se_e += 1 + if t_w[r,c]: + se_w_r[num_se_w] = r - centre_r + se_w_c[num_se_w] = c - centre_c + num_se_w += 1 + if t_n[r,c]: + se_n_r[num_se_n] = r - centre_r + se_n_c[num_se_n] = c - centre_c + num_se_n += 1 + if t_s[r,c]: + se_s_r[num_se_s] = r - centre_r + se_s_c[num_se_s] = c - centre_c + num_se_s += 1 + + # initial population and histogram + for i in range(maxbin): + histo[i] = 0 + + pop = 0 + + for r in range(srows): + for c in range(scols): + rr = r + cc = c + if selem[r, c]: + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + + r = 0 + c = 0 + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + bitdepth,maxbin,midbin,p0,p1) + # kernel ------------------------------------------- + + # main loop + r = 0 + for even_row in range(0,rows,2): + # ---> west to east + for c in range(1,cols): + for s in range(num_se_e): + rr = r + se_e_r[s] + centre_r + cc = c + se_e_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_w): + rr = r + se_w_r[s] + centre_r + cc = c + se_w_c[s] + centre_c - 1 + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + bitdepth,maxbin,midbin,p0,p1) + # kernel ------------------------------------------- + + r += 1 # pass to the next row + if r>=rows: + break + + # ---> north to south + for s in range(num_se_s): + rr = r + se_s_r[s] + centre_r + cc = c + se_s_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_n): + rr = r + se_n_r[s] + centre_r - 1 + cc = c + se_n_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + bitdepth,maxbin,midbin,p0,p1) + # kernel ------------------------------------------- + + # ---> east to west + for c in range(cols-2,-1,-1): + for s in range(num_se_w): + rr = r + se_w_r[s] + centre_r + cc = c + se_w_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_e): + rr = r + se_e_r[s] + centre_r + cc = c + se_e_c[s] + centre_c + 1 + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + bitdepth,maxbin,midbin,p0,p1) + # kernel ------------------------------------------- + + r += 1 # pass to the next row + if r>=rows: + break + + # ---> north to south + for s in range(num_se_s): + rr = r + se_s_r[s] + centre_r + cc = c + se_s_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_n): + rr = r + se_n_r[s] + centre_r - 1 + cc = c + se_n_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + bitdepth,maxbin,midbin,p0,p1) + # kernel ------------------------------------------- + + # release memory allocated by malloc + + free(se_e_r) + free(se_e_c) + free(se_w_r) + free(se_w_c) + free(se_n_r) + free(se_n_c) + free(se_s_r) + free(se_s_c) + + free(histo) + + return out + + diff --git a/skimage/rank/_core8.pxd b/skimage/rank/_core8.pxd index d24297cb..aa3fe527 100644 --- a/skimage/rank/_core8.pxd +++ b/skimage/rank/_core8.pxd @@ -1,18 +1,4 @@ -""" to compile this use: ->>> python setup.py build_ext --inplace - -to generate html report use: ->>> cython -a core8.pxd -""" - -#cython: cdivision=True -#cython: boundscheck=False -#cython: nonecheck=False -#cython: wraparound=False - -import numpy as np cimport numpy as np -from libc.stdlib cimport malloc, free #--------------------------------------------------------------------------- # 8 bit core kernel @@ -23,247 +9,4 @@ 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): - """ Main loop, this function computes the histogram for each image point - - data is uint8 - - result is uint8 casted - """ - - cdef int rows = image.shape[0] - cdef int cols = image.shape[1] - cdef int srows = selem.shape[0] - cdef int scols = selem.shape[1] - - cdef int centre_r = int(selem.shape[0] / 2) + shift_y - cdef int centre_c = int(selem.shape[1] / 2) + shift_x - - # check that structuring element center is inside the element bounding box - assert centre_r >= 0 - assert centre_c >= 0 - 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 out is None: - out = np.zeros((rows, cols), dtype=np.uint8) - else: - out = np.ascontiguousarray(out) - - # create extended image and mask - cdef int erows = rows+srows-1 - cdef int ecols = cols+scols-1 - - cdef np.ndarray emask = np.zeros((erows, ecols), dtype=np.uint8) - cdef np.ndarray eimage = np.zeros((erows, ecols), dtype=np.uint8) - - eimage[centre_r:rows+centre_r,centre_c:cols+centre_c] = image - emask[centre_r:rows+centre_r,centre_c:cols+centre_c] = mask - - mask = np.ascontiguousarray(mask) - - # define pointers to the data - cdef np.uint8_t* eimage_data = eimage.data - cdef np.uint8_t* emask_data = emask.data - - cdef np.uint8_t* out_data = out.data - cdef np.uint8_t* image_data = image.data - cdef np.uint8_t* mask_data = mask.data - - # define local variable types - cdef int r, c, rr, cc, s, value, local_max, i, even_row - cdef float pop # number of pixels actually inside the neighborhood (float) - - # allocate memory with malloc - cdef int max_se = srows*scols - - # number of element in each attack border - cdef int num_se_n, num_se_s, num_se_e, num_se_w - - # the current local histogram distribution - cdef int* histo = malloc(256 * sizeof(int)) - - # 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 int* se_e_r = malloc(max_se * sizeof(int)) - cdef int* se_e_c = malloc(max_se * sizeof(int)) - cdef int* se_w_r = malloc(max_se * sizeof(int)) - cdef int* se_w_c = malloc(max_se * sizeof(int)) - cdef int* se_n_r = malloc(max_se * sizeof(int)) - cdef int* se_n_c = malloc(max_se * sizeof(int)) - cdef int* se_s_r = malloc(max_se * sizeof(int)) - cdef int* se_s_c = malloc(max_se * sizeof(int)) - - # 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 - - t = np.hstack((np.zeros((selem.shape[0],1)),selem)) - t_w = np.diff(t,axis=1)==1 - - t = np.vstack((selem,np.zeros((1,selem.shape[1])))) - t_s = np.diff(t,axis=0)==-1 - - t = np.vstack((np.zeros((1,selem.shape[1])),selem)) - t_n = np.diff(t,axis=0)==1 - - num_se_n = num_se_s = num_se_e = num_se_w = 0 - - for r in range(srows): - for c in range(scols): - if t_e[r,c]: - se_e_r[num_se_e] = r - centre_r - se_e_c[num_se_e] = c - centre_c - num_se_e += 1 - if t_w[r,c]: - se_w_r[num_se_w] = r - centre_r - se_w_c[num_se_w] = c - centre_c - num_se_w += 1 - if t_n[r,c]: - se_n_r[num_se_n] = r - centre_r - se_n_c[num_se_n] = c - centre_c - num_se_n += 1 - if t_s[r,c]: - se_s_r[num_se_s] = r - centre_r - se_s_c[num_se_s] = c - centre_c - num_se_s += 1 - - # initial population and histogram - for i in range(256): - histo[i] = 0 - - pop = 0 - - for r in range(srows): - for c in range(scols): - rr = r - cc = c - if selem[r, c]: - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - - r = 0 - c = 0 - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) - # kernel ------------------------------------------- - - # main loop - r = 0 - for even_row in range(0,rows,2): - # ---> west to east - for c in range(1,cols): - for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) - # kernel ------------------------------------------- - - # ---> east to west - for c in range(cols-2,-1,-1): - for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c + 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) - # kernel ------------------------------------------- - - # release memory allocated by malloc - - free(se_e_r) - free(se_e_c) - free(se_w_r) - free(se_w_c) - free(se_n_r) - free(se_n_c) - free(se_s_r) - free(se_s_c) - - free(histo) - - return out - +char shift_x, char shift_y) diff --git a/skimage/rank/_core8.pyx b/skimage/rank/_core8.pyx new file mode 100644 index 00000000..d24297cb --- /dev/null +++ b/skimage/rank/_core8.pyx @@ -0,0 +1,269 @@ +""" to compile this use: +>>> python setup.py build_ext --inplace + +to generate html report use: +>>> cython -a core8.pxd +""" + +#cython: cdivision=True +#cython: boundscheck=False +#cython: nonecheck=False +#cython: wraparound=False + +import numpy as np +cimport numpy as np +from libc.stdlib cimport malloc, free + +#--------------------------------------------------------------------------- +# 8 bit core kernel +#--------------------------------------------------------------------------- + +cdef inline _core8(np.uint8_t kernel(int*, float, np.uint8_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): + """ Main loop, this function computes the histogram for each image point + - data is uint8 + - result is uint8 casted + """ + + cdef int rows = image.shape[0] + cdef int cols = image.shape[1] + cdef int srows = selem.shape[0] + cdef int scols = selem.shape[1] + + cdef int centre_r = int(selem.shape[0] / 2) + shift_y + cdef int centre_c = int(selem.shape[1] / 2) + shift_x + + # check that structuring element center is inside the element bounding box + assert centre_r >= 0 + assert centre_c >= 0 + 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 out is None: + out = np.zeros((rows, cols), dtype=np.uint8) + else: + out = np.ascontiguousarray(out) + + # create extended image and mask + cdef int erows = rows+srows-1 + cdef int ecols = cols+scols-1 + + cdef np.ndarray emask = np.zeros((erows, ecols), dtype=np.uint8) + cdef np.ndarray eimage = np.zeros((erows, ecols), dtype=np.uint8) + + eimage[centre_r:rows+centre_r,centre_c:cols+centre_c] = image + emask[centre_r:rows+centre_r,centre_c:cols+centre_c] = mask + + mask = np.ascontiguousarray(mask) + + # define pointers to the data + cdef np.uint8_t* eimage_data = eimage.data + cdef np.uint8_t* emask_data = emask.data + + cdef np.uint8_t* out_data = out.data + cdef np.uint8_t* image_data = image.data + cdef np.uint8_t* mask_data = mask.data + + # define local variable types + cdef int r, c, rr, cc, s, value, local_max, i, even_row + cdef float pop # number of pixels actually inside the neighborhood (float) + + # allocate memory with malloc + cdef int max_se = srows*scols + + # number of element in each attack border + cdef int num_se_n, num_se_s, num_se_e, num_se_w + + # the current local histogram distribution + cdef int* histo = malloc(256 * sizeof(int)) + + # 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 int* se_e_r = malloc(max_se * sizeof(int)) + cdef int* se_e_c = malloc(max_se * sizeof(int)) + cdef int* se_w_r = malloc(max_se * sizeof(int)) + cdef int* se_w_c = malloc(max_se * sizeof(int)) + cdef int* se_n_r = malloc(max_se * sizeof(int)) + cdef int* se_n_c = malloc(max_se * sizeof(int)) + cdef int* se_s_r = malloc(max_se * sizeof(int)) + cdef int* se_s_c = malloc(max_se * sizeof(int)) + + # 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 + + t = np.hstack((np.zeros((selem.shape[0],1)),selem)) + t_w = np.diff(t,axis=1)==1 + + t = np.vstack((selem,np.zeros((1,selem.shape[1])))) + t_s = np.diff(t,axis=0)==-1 + + t = np.vstack((np.zeros((1,selem.shape[1])),selem)) + t_n = np.diff(t,axis=0)==1 + + num_se_n = num_se_s = num_se_e = num_se_w = 0 + + for r in range(srows): + for c in range(scols): + if t_e[r,c]: + se_e_r[num_se_e] = r - centre_r + se_e_c[num_se_e] = c - centre_c + num_se_e += 1 + if t_w[r,c]: + se_w_r[num_se_w] = r - centre_r + se_w_c[num_se_w] = c - centre_c + num_se_w += 1 + if t_n[r,c]: + se_n_r[num_se_n] = r - centre_r + se_n_c[num_se_n] = c - centre_c + num_se_n += 1 + if t_s[r,c]: + se_s_r[num_se_s] = r - centre_r + se_s_c[num_se_s] = c - centre_c + num_se_s += 1 + + # initial population and histogram + for i in range(256): + histo[i] = 0 + + pop = 0 + + for r in range(srows): + for c in range(scols): + rr = r + cc = c + if selem[r, c]: + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + + r = 0 + c = 0 + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) + # kernel ------------------------------------------- + + # main loop + r = 0 + for even_row in range(0,rows,2): + # ---> west to east + for c in range(1,cols): + for s in range(num_se_e): + rr = r + se_e_r[s] + centre_r + cc = c + se_e_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_w): + rr = r + se_w_r[s] + centre_r + cc = c + se_w_c[s] + centre_c - 1 + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) + # kernel ------------------------------------------- + + r += 1 # pass to the next row + if r>=rows: + break + + # ---> north to south + for s in range(num_se_s): + rr = r + se_s_r[s] + centre_r + cc = c + se_s_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_n): + rr = r + se_n_r[s] + centre_r - 1 + cc = c + se_n_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) + # kernel ------------------------------------------- + + # ---> east to west + for c in range(cols-2,-1,-1): + for s in range(num_se_w): + rr = r + se_w_r[s] + centre_r + cc = c + se_w_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_e): + rr = r + se_e_r[s] + centre_r + cc = c + se_e_c[s] + centre_c + 1 + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) + # kernel ------------------------------------------- + + r += 1 # pass to the next row + if r>=rows: + break + + # ---> north to south + for s in range(num_se_s): + rr = r + se_s_r[s] + centre_r + cc = c + se_s_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_n): + rr = r + se_n_r[s] + centre_r - 1 + cc = c + se_n_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) + # kernel ------------------------------------------- + + # release memory allocated by malloc + + free(se_e_r) + free(se_e_c) + free(se_w_r) + free(se_w_c) + free(se_n_r) + free(se_n_c) + free(se_s_r) + free(se_s_c) + + free(histo) + + return out + diff --git a/skimage/rank/_core8p.pxd b/skimage/rank/_core8p.pxd index b1adac70..8d3181e8 100644 --- a/skimage/rank/_core8p.pxd +++ b/skimage/rank/_core8p.pxd @@ -1,15 +1,8 @@ -#cython: cdivision=True -#cython: boundscheck=False -#cython: nonecheck=False -#cython: wraparound=False - -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 +cdef inline np.uint8_t uint8_max(np.uint8_t a, np.uint8_t b) +cdef inline 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 @@ -20,247 +13,5 @@ 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): - """ Main loop, this function computes the histogram for each image point - - data is uint8 - - result is uint8 casted - """ - - cdef int rows = image.shape[0] - cdef int cols = image.shape[1] - cdef int srows = selem.shape[0] - cdef int scols = selem.shape[1] - - cdef int centre_r = int(selem.shape[0] / 2) + shift_y - cdef int centre_c = int(selem.shape[1] / 2) + shift_x - - # check that structuring element center is inside the element bounding box - assert centre_r >= 0 - assert centre_c >= 0 - 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 out is None: - out = np.zeros((rows, cols), dtype=np.uint8) - else: - out = np.ascontiguousarray(out) - - # create extended image and mask - cdef int erows = rows+srows-1 - cdef int ecols = cols+scols-1 - - cdef np.ndarray emask = np.zeros((erows, ecols), dtype=np.uint8) - cdef np.ndarray eimage = np.zeros((erows, ecols), dtype=np.uint8) - - eimage[centre_r:rows+centre_r,centre_c:cols+centre_c] = image - emask[centre_r:rows+centre_r,centre_c:cols+centre_c] = mask - - mask = np.ascontiguousarray(mask) - - # define pointers to the data - cdef np.uint8_t* eimage_data = eimage.data - cdef np.uint8_t* emask_data = emask.data - - cdef np.uint8_t* out_data = out.data - cdef np.uint8_t* image_data = image.data - cdef np.uint8_t* mask_data = mask.data - - # define local variable types - cdef int r, c, rr, cc, s, value, local_max, i, even_row - cdef float pop # number of pixels actually inside the neighborhood (float) - - # allocate memory with malloc - cdef int max_se = srows*scols - - # number of element in each attack border - cdef int num_se_n, num_se_s, num_se_e, num_se_w - - # the current local histogram distribution - cdef int* histo = malloc(256 * sizeof(int)) - - # 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 int* se_e_r = malloc(max_se * sizeof(int)) - cdef int* se_e_c = malloc(max_se * sizeof(int)) - cdef int* se_w_r = malloc(max_se * sizeof(int)) - cdef int* se_w_c = malloc(max_se * sizeof(int)) - cdef int* se_n_r = malloc(max_se * sizeof(int)) - cdef int* se_n_c = malloc(max_se * sizeof(int)) - cdef int* se_s_r = malloc(max_se * sizeof(int)) - cdef int* se_s_c = malloc(max_se * sizeof(int)) - - # 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 - - t = np.hstack((np.zeros((selem.shape[0],1)),selem)) - t_w = np.diff(t,axis=1)==1 - - t = np.vstack((selem,np.zeros((1,selem.shape[1])))) - t_s = np.diff(t,axis=0)==-1 - - t = np.vstack((np.zeros((1,selem.shape[1])),selem)) - t_n = np.diff(t,axis=0)==1 - - num_se_n = num_se_s = num_se_e = num_se_w = 0 - - for r in range(srows): - for c in range(scols): - if t_e[r,c]: - se_e_r[num_se_e] = r - centre_r - se_e_c[num_se_e] = c - centre_c - num_se_e += 1 - if t_w[r,c]: - se_w_r[num_se_w] = r - centre_r - se_w_c[num_se_w] = c - centre_c - num_se_w += 1 - if t_n[r,c]: - se_n_r[num_se_n] = r - centre_r - se_n_c[num_se_n] = c - centre_c - num_se_n += 1 - if t_s[r,c]: - se_s_r[num_se_s] = r - centre_r - se_s_c[num_se_s] = c - centre_c - num_se_s += 1 - - # initial population and histogram - for i in range(256): - histo[i] = 0 - - pop = 0 - - for r in range(srows): - for c in range(scols): - rr = r - cc = c - if selem[r, c]: - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - - r = 0 - c = 0 - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) - # kernel ------------------------------------------- - - # main loop - r = 0 - for even_row in range(0,rows,2): - # ---> west to east - for c in range(1,cols): - for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) - # kernel ------------------------------------------- - - # ---> east to west - for c in range(cols-2,-1,-1): - for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c + 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) - # kernel ------------------------------------------- - - # release memory allocated by malloc - - free(se_e_r) - free(se_e_c) - free(se_w_r) - free(se_w_c) - free(se_n_r) - free(se_n_c) - free(se_s_r) - free(se_s_c) - - free(histo) - - return out +char shift_x, char shift_y, float p0, float p1) diff --git a/skimage/rank/_core8p.pyx b/skimage/rank/_core8p.pyx new file mode 100644 index 00000000..b1adac70 --- /dev/null +++ b/skimage/rank/_core8p.pyx @@ -0,0 +1,266 @@ +#cython: cdivision=True +#cython: boundscheck=False +#cython: nonecheck=False +#cython: wraparound=False + +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 receives extra information about data inferior and superior percentiles +#--------------------------------------------------------------------------- + +cdef inline _core8p(np.uint8_t kernel(int*, float, np.uint8_t, float, float), +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): + """ Main loop, this function computes the histogram for each image point + - data is uint8 + - result is uint8 casted + """ + + cdef int rows = image.shape[0] + cdef int cols = image.shape[1] + cdef int srows = selem.shape[0] + cdef int scols = selem.shape[1] + + cdef int centre_r = int(selem.shape[0] / 2) + shift_y + cdef int centre_c = int(selem.shape[1] / 2) + shift_x + + # check that structuring element center is inside the element bounding box + assert centre_r >= 0 + assert centre_c >= 0 + 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 out is None: + out = np.zeros((rows, cols), dtype=np.uint8) + else: + out = np.ascontiguousarray(out) + + # create extended image and mask + cdef int erows = rows+srows-1 + cdef int ecols = cols+scols-1 + + cdef np.ndarray emask = np.zeros((erows, ecols), dtype=np.uint8) + cdef np.ndarray eimage = np.zeros((erows, ecols), dtype=np.uint8) + + eimage[centre_r:rows+centre_r,centre_c:cols+centre_c] = image + emask[centre_r:rows+centre_r,centre_c:cols+centre_c] = mask + + mask = np.ascontiguousarray(mask) + + # define pointers to the data + cdef np.uint8_t* eimage_data = eimage.data + cdef np.uint8_t* emask_data = emask.data + + cdef np.uint8_t* out_data = out.data + cdef np.uint8_t* image_data = image.data + cdef np.uint8_t* mask_data = mask.data + + # define local variable types + cdef int r, c, rr, cc, s, value, local_max, i, even_row + cdef float pop # number of pixels actually inside the neighborhood (float) + + # allocate memory with malloc + cdef int max_se = srows*scols + + # number of element in each attack border + cdef int num_se_n, num_se_s, num_se_e, num_se_w + + # the current local histogram distribution + cdef int* histo = malloc(256 * sizeof(int)) + + # 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 int* se_e_r = malloc(max_se * sizeof(int)) + cdef int* se_e_c = malloc(max_se * sizeof(int)) + cdef int* se_w_r = malloc(max_se * sizeof(int)) + cdef int* se_w_c = malloc(max_se * sizeof(int)) + cdef int* se_n_r = malloc(max_se * sizeof(int)) + cdef int* se_n_c = malloc(max_se * sizeof(int)) + cdef int* se_s_r = malloc(max_se * sizeof(int)) + cdef int* se_s_c = malloc(max_se * sizeof(int)) + + # 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 + + t = np.hstack((np.zeros((selem.shape[0],1)),selem)) + t_w = np.diff(t,axis=1)==1 + + t = np.vstack((selem,np.zeros((1,selem.shape[1])))) + t_s = np.diff(t,axis=0)==-1 + + t = np.vstack((np.zeros((1,selem.shape[1])),selem)) + t_n = np.diff(t,axis=0)==1 + + num_se_n = num_se_s = num_se_e = num_se_w = 0 + + for r in range(srows): + for c in range(scols): + if t_e[r,c]: + se_e_r[num_se_e] = r - centre_r + se_e_c[num_se_e] = c - centre_c + num_se_e += 1 + if t_w[r,c]: + se_w_r[num_se_w] = r - centre_r + se_w_c[num_se_w] = c - centre_c + num_se_w += 1 + if t_n[r,c]: + se_n_r[num_se_n] = r - centre_r + se_n_c[num_se_n] = c - centre_c + num_se_n += 1 + if t_s[r,c]: + se_s_r[num_se_s] = r - centre_r + se_s_c[num_se_s] = c - centre_c + num_se_s += 1 + + # initial population and histogram + for i in range(256): + histo[i] = 0 + + pop = 0 + + for r in range(srows): + for c in range(scols): + rr = r + cc = c + if selem[r, c]: + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + + r = 0 + c = 0 + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) + # kernel ------------------------------------------- + + # main loop + r = 0 + for even_row in range(0,rows,2): + # ---> west to east + for c in range(1,cols): + for s in range(num_se_e): + rr = r + se_e_r[s] + centre_r + cc = c + se_e_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_w): + rr = r + se_w_r[s] + centre_r + cc = c + se_w_c[s] + centre_c - 1 + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) + # kernel ------------------------------------------- + + r += 1 # pass to the next row + if r>=rows: + break + + # ---> north to south + for s in range(num_se_s): + rr = r + se_s_r[s] + centre_r + cc = c + se_s_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_n): + rr = r + se_n_r[s] + centre_r - 1 + cc = c + se_n_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) + # kernel ------------------------------------------- + + # ---> east to west + for c in range(cols-2,-1,-1): + for s in range(num_se_w): + rr = r + se_w_r[s] + centre_r + cc = c + se_w_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_e): + rr = r + se_e_r[s] + centre_r + cc = c + se_e_c[s] + centre_c + 1 + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) + # kernel ------------------------------------------- + + r += 1 # pass to the next row + if r>=rows: + break + + # ---> north to south + for s in range(num_se_s): + rr = r + se_s_r[s] + centre_r + cc = c + se_s_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] += 1 + pop += 1. + for s in range(num_se_n): + rr = r + se_n_r[s] + centre_r - 1 + cc = c + se_n_c[s] + centre_c + if emask_data[rr * ecols + cc]: + value = eimage_data[rr * ecols + cc] + histo[value] -= 1 + pop -= 1. + + # kernel ------------------------------------------- + out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) + # kernel ------------------------------------------- + + # release memory allocated by malloc + + free(se_e_r) + free(se_e_c) + free(se_w_r) + free(se_w_c) + free(se_n_r) + free(se_n_c) + free(se_s_r) + free(se_s_c) + + free(histo) + + return out + diff --git a/skimage/rank/setup.py b/skimage/rank/setup.py index efe23515..20a59979 100644 --- a/skimage/rank/setup.py +++ b/skimage/rank/setup.py @@ -5,6 +5,8 @@ from skimage._build import cython base_path = os.path.abspath(os.path.dirname(__file__)) +import sys +sys.path.append('.') def configuration(parent_package='', top_path=None): from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs @@ -12,12 +14,28 @@ def configuration(parent_package='', top_path=None): config = Configuration('rank', parent_package, top_path) # config.add_data_dir('tests') + + cython(['_core8.pyx'], working_path=base_path) + cython(['_core8p.pyx'], working_path=base_path) + cython(['_core16.pyx'], working_path=base_path) + cython(['_core16p.pyx'], working_path=base_path) + cython(['_core16b.pyx'], working_path=base_path) cython(['_crank8.pyx'], working_path=base_path) cython(['_crank8_percentiles.pyx'], working_path=base_path) cython(['_crank16.pyx'], working_path=base_path) cython(['_crank16_percentiles.pyx'], working_path=base_path) cython(['_crank16_bilateral.pyx'], working_path=base_path) + config.add_extension('_core8', sources=['_core8.c'], + include_dirs=[get_numpy_include_dirs()]) + config.add_extension('_core8p', sources=['_core8p.c'], + include_dirs=[get_numpy_include_dirs()]) + config.add_extension('_core16', sources=['_core16.c'], + include_dirs=[get_numpy_include_dirs()]) + config.add_extension('_core16p', sources=['_core16p.c'], + include_dirs=[get_numpy_include_dirs()]) + config.add_extension('_core16b', sources=['_core16b.c'], + include_dirs=[get_numpy_include_dirs()]) config.add_extension('_crank8', sources=['_crank8.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('_crank8_percentiles', sources=['_crank8_percentiles.c'], From b9df8405c1c62133be448b97a3e12118361682a6 Mon Sep 17 00:00:00 2001 From: odebeir Date: Sat, 13 Oct 2012 10:09:06 +0200 Subject: [PATCH 51/86] restore setupfile --- skimage/rank/rank.py | 3 +++ skimage/rank/setup.py | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/skimage/rank/rank.py b/skimage/rank/rank.py index cefb06ac..52b3d570 100644 --- a/skimage/rank/rank.py +++ b/skimage/rank/rank.py @@ -1022,5 +1022,8 @@ def tophat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): raise TypeError("only uint8 and uint16 image supported!") if __name__ == "__main__": + import sys + sys.path.append('.') + import doctest doctest.testmod(verbose=True) \ No newline at end of file diff --git a/skimage/rank/setup.py b/skimage/rank/setup.py index 20a59979..207ff18f 100644 --- a/skimage/rank/setup.py +++ b/skimage/rank/setup.py @@ -5,9 +5,6 @@ from skimage._build import cython base_path = os.path.abspath(os.path.dirname(__file__)) -import sys -sys.path.append('.') - def configuration(parent_package='', top_path=None): from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs From ed82b35fc0a3ed5ce5bac241e8347d47b3bbba94 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 13:21:33 +0200 Subject: [PATCH 52/86] remplace int by Py_ssize_t and fix some doctests --- skimage/rank/_core8.pyx | 38 +++++++++++----------- skimage/rank/rank.py | 70 ++++++++++++++++++++++++----------------- 2 files changed, 61 insertions(+), 47 deletions(-) diff --git a/skimage/rank/_core8.pyx b/skimage/rank/_core8.pyx index d24297cb..cd997d89 100644 --- a/skimage/rank/_core8.pyx +++ b/skimage/rank/_core8.pyx @@ -29,13 +29,13 @@ char shift_x, char shift_y): - result is uint8 casted """ - cdef int rows = image.shape[0] - cdef int cols = image.shape[1] - cdef int srows = selem.shape[0] - cdef int scols = selem.shape[1] + cdef Py_ssize_t rows = image.shape[0] + cdef Py_ssize_t cols = image.shape[1] + cdef Py_ssize_t srows = selem.shape[0] + cdef Py_ssize_t scols = selem.shape[1] - cdef int centre_r = int(selem.shape[0] / 2) + shift_y - cdef int centre_c = int(selem.shape[1] / 2) + shift_x + cdef Py_ssize_t centre_r = int(selem.shape[0] / 2) + shift_y + cdef Py_ssize_t centre_c = int(selem.shape[1] / 2) + shift_x # check that structuring element center is inside the element bounding box assert centre_r >= 0 @@ -56,8 +56,8 @@ char shift_x, char shift_y): out = np.ascontiguousarray(out) # create extended image and mask - cdef int erows = rows+srows-1 - cdef int ecols = cols+scols-1 + cdef Py_ssize_t erows = rows+srows-1 + cdef Py_ssize_t ecols = cols+scols-1 cdef np.ndarray emask = np.zeros((erows, ecols), dtype=np.uint8) cdef np.ndarray eimage = np.zeros((erows, ecols), dtype=np.uint8) @@ -76,14 +76,14 @@ char shift_x, char shift_y): cdef np.uint8_t* mask_data = mask.data # define local variable types - cdef int r, c, rr, cc, s, value, local_max, i, even_row + 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) # allocate memory with malloc - cdef int max_se = srows*scols + cdef Py_ssize_t max_se = srows*scols # number of element in each attack border - cdef int num_se_n, num_se_s, num_se_e, num_se_w + cdef Py_ssize_t num_se_n, num_se_s, num_se_e, num_se_w # the current local histogram distribution cdef int* histo = malloc(256 * sizeof(int)) @@ -92,14 +92,14 @@ char shift_x, char shift_y): # east, west, north and south # e.g. se_e_r lists the rows of the east structuring element border - cdef int* se_e_r = malloc(max_se * sizeof(int)) - cdef int* se_e_c = malloc(max_se * sizeof(int)) - cdef int* se_w_r = malloc(max_se * sizeof(int)) - cdef int* se_w_c = malloc(max_se * sizeof(int)) - cdef int* se_n_r = malloc(max_se * sizeof(int)) - cdef int* se_n_c = malloc(max_se * sizeof(int)) - cdef int* se_s_r = malloc(max_se * sizeof(int)) - cdef int* se_s_c = malloc(max_se * sizeof(int)) + cdef Py_ssize_t* se_e_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t* se_e_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t* se_w_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t* se_w_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t* se_n_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t* se_n_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t* se_s_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t* se_s_c = malloc(max_se * sizeof(Py_ssize_t)) # build attack and release borders # by using difference along axis diff --git a/skimage/rank/rank.py b/skimage/rank/rank.py index 52b3d570..dafe0715 100644 --- a/skimage/rank/rank.py +++ b/skimage/rank/rank.py @@ -59,12 +59,13 @@ def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local mean >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*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) - >>> autolevel(ima8, square(3)) + >>> rank.autolevel(ima8, square(3)) array([[ 0, 0, 0, 0, 0], [ 0, 255, 255, 255, 0], [ 0, 255, 0, 255, 0], @@ -76,7 +77,7 @@ def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> autolevel(ima16, square(3)) + >>> rank.autolevel(ima16, square(3)) array([[ 0, 0, 0, 0, 0], [ 0, 4095, 4095, 4095, 0], [ 0, 4095, 0, 4095, 0], @@ -130,12 +131,13 @@ def bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local mean >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*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) - >>> bottomhat(ima8, square(3)) + >>> rank.bottomhat(ima8, square(3)) array([[ 0, 0, 0, 0, 0], [ 0, 255, 255, 255, 0], [ 0, 255, 0, 255, 0], @@ -147,7 +149,7 @@ def bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> bottomhat(ima16, square(3)) + >>> rank.bottomhat(ima16, square(3)) array([[ 0, 0, 0, 0, 0], [ 0, 4095, 4095, 4095, 0], [ 0, 4095, 0, 4095, 0], @@ -200,12 +202,13 @@ def equalize(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local mean >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*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) - >>> equalize(ima8, square(3)) + >>> rank.equalize(ima8, square(3)) array([[191, 170, 127, 170, 191], [170, 255, 255, 255, 170], [127, 255, 255, 255, 127], @@ -217,7 +220,7 @@ def equalize(image, selem, out=None, mask=None, shift_x=False, shift_y=False): ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> equalize(ima16, square(3)) + >>> rank.equalize(ima16, square(3)) array([[3071, 2730, 2047, 2730, 3071], [2730, 4095, 4095, 4095, 2730], [2047, 4095, 4095, 4095, 2047], @@ -270,12 +273,13 @@ def gradient(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local gradient >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*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) - >>> gradient(ima8, square(3)) + >>> rank.gradient(ima8, square(3)) array([[255, 255, 255, 255, 255], [255, 255, 255, 255, 255], [255, 255, 0, 255, 255], @@ -287,7 +291,7 @@ def gradient(image, selem, out=None, mask=None, shift_x=False, shift_y=False): ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> gradient(ima16, square(3)) + >>> rank.gradient(ima16, square(3)) array([[4095, 4095, 4095, 4095, 4095], [4095, 4095, 4095, 4095, 4095], [4095, 4095, 0, 4095, 4095], @@ -342,12 +346,13 @@ def maximum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local maximum >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0], ... [0, 0, 1, 0, 0], ... [0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> maximum(ima8, square(3)) + >>> rank.maximum(ima8, square(3)) array([[ 0, 0, 0, 0, 0], [ 0, 255, 255, 255, 0], [ 0, 255, 255, 255, 0], @@ -359,7 +364,7 @@ def maximum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): ... [0, 0, 1, 0, 0], ... [0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> maximum(ima16, square(3)) + >>> rank.maximum(ima16, square(3)) array([[ 0, 0, 0, 0, 0], [ 0, 4095, 4095, 4095, 0], [ 0, 4095, 4095, 4095, 0], @@ -413,12 +418,13 @@ def mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local mean >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*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) - >>> mean(ima8, square(3)) + >>> rank.mean(ima8, square(3)) array([[ 63, 85, 127, 85, 63], [ 85, 113, 170, 113, 85], [127, 170, 255, 170, 127], @@ -430,7 +436,7 @@ def mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False): ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> mean(ima16, square(3)) + >>> rank.mean(ima16, square(3)) array([[1023, 1365, 2047, 1365, 1023], [1365, 1820, 2730, 1820, 1365], [2047, 2730, 4095, 2730, 2047], @@ -484,12 +490,13 @@ def meansubstraction(image, selem, out=None, mask=None, shift_x=False, shift_y=F to be updated >>> # Local meansubstraction >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*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) - >>> meansubstraction(ima8, square(3)) + >>> rank.meansubstraction(ima8, square(3)) array([[ 95, 84, 63, 84, 95], [ 84, 197, 169, 197, 84], [ 63, 169, 127, 169, 63], @@ -501,7 +508,7 @@ def meansubstraction(image, selem, out=None, mask=None, shift_x=False, shift_y=F ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> meansubstraction(ima16, square(3)) + >>> rank.meansubstraction(ima16, square(3)) array([[1535, 1364, 1023, 1364, 1535], [1364, 3184, 2729, 3184, 1364], [1023, 2729, 2047, 2729, 1023], @@ -555,12 +562,13 @@ def median(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local median >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 0, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> median(ima8, square(3)) + >>> rank.median(ima8, square(3)) array([[ 0, 0, 255, 0, 0], [ 0, 0, 255, 0, 0], [255, 255, 255, 255, 255], @@ -572,7 +580,7 @@ def median(image, selem, out=None, mask=None, shift_x=False, shift_y=False): ... [0, 1, 0, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> median(ima16, square(3)) + >>> rank.median(ima16, square(3)) array([[ 0, 0, 4095, 0, 0], [ 0, 0, 4095, 0, 0], [4095, 4095, 4095, 4095, 4095], @@ -626,12 +634,13 @@ def minimum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local minimum >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*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) - >>> minimum(ima8, square(3)) + >>> rank.minimum(ima8, square(3)) array([[ 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0], [ 0, 0, 255, 0, 0], @@ -644,7 +653,7 @@ def minimum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> minimum(ima16, square(3)) + >>> rank.minimum(ima16, square(3)) array([[ 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0], [ 0, 0, 4095, 0, 0], @@ -698,12 +707,13 @@ def modal(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local modal >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 5, 6, 0], ... [0, 1, 5, 5, 0], ... [0, 0, 0, 5, 0]], dtype=np.uint8) - >>> modal(ima8, square(3)) + >>> rank.modal(ima8, square(3)) array([[0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 1, 1, 0, 0], @@ -716,7 +726,7 @@ def modal(image, selem, out=None, mask=None, shift_x=False, shift_y=False): ... [0, 1, 5, 6, 0], ... [0, 1, 5, 5, 0], ... [0, 0, 0, 5, 0]], dtype=np.uint16) - >>> modal(ima16, square(3)) + >>> rank.modal(ima16, square(3)) array([[ 0, 0, 0, 0, 0], [ 0, 0, 100, 0, 0], [ 0, 100, 100, 0, 0], @@ -770,12 +780,13 @@ def morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa to be updated >>> # Local mean >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 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) - >>> morph_contr_enh(ima8, square(3)) + >>> rank.morph_contr_enh(ima8, square(3)) array([[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 1, 1, 0], @@ -787,7 +798,7 @@ def morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> morph_contr_enh(ima16, square(3)) + >>> rank.morph_contr_enh(ima16, square(3)) array([[ 0, 0, 0, 0, 0], [ 0, 4095, 4095, 4095, 0], [ 0, 4095, 4095, 4095, 0], @@ -841,12 +852,13 @@ def pop(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local mean >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*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) - >>> pop(ima8, square(3)) + >>> rank.pop(ima8, square(3)) array([[4, 6, 6, 6, 4], [6, 9, 9, 9, 6], [6, 9, 9, 9, 6], @@ -858,7 +870,7 @@ def pop(image, selem, out=None, mask=None, shift_x=False, shift_y=False): ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> pop(ima16, square(3)) + >>> rank.pop(ima16, square(3)) array([[4, 6, 6, 6, 4], [6, 9, 9, 9, 6], [6, 9, 9, 9, 6], @@ -912,12 +924,13 @@ def threshold(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local mean >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*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) - >>> threshold(ima8, square(3)) + >>> rank.threshold(ima8, square(3)) array([[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 0, 1, 0], @@ -929,7 +942,7 @@ def threshold(image, selem, out=None, mask=None, shift_x=False, shift_y=False): ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> threshold(ima16, square(3)) + >>> rank.threshold(ima16, square(3)) array([[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 0, 1, 0], @@ -984,12 +997,13 @@ def tophat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local mean >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*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) - >>> tophat(ima8, square(3)) + >>> rank.tophat(ima8, square(3)) array([[255, 255, 255, 255, 255], [255, 0, 0, 0, 255], [255, 0, 0, 0, 255], @@ -1001,7 +1015,7 @@ def tophat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> tophat(ima16, square(3)) + >>> rank.tophat(ima16, square(3)) array([[4095, 4095, 4095, 4095, 4095], [4095, 0, 0, 0, 4095], [4095, 0, 0, 0, 4095], From b2e4827e9b3c14dc7d4a6f480603fffe65db4758 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 13:26:28 +0200 Subject: [PATCH 53/86] remplace int by Py_ssize_t and for rank8 --- skimage/rank/_core8.pxd | 2 +- skimage/rank/_core8.pyx | 4 +-- skimage/rank/_crank8.pyx | 54 ++++++++++++++++++++-------------------- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/skimage/rank/_core8.pxd b/skimage/rank/_core8.pxd index aa3fe527..6dca9f61 100644 --- a/skimage/rank/_core8.pxd +++ b/skimage/rank/_core8.pxd @@ -4,7 +4,7 @@ cimport numpy as np # 8 bit core kernel #--------------------------------------------------------------------------- -cdef inline _core8(np.uint8_t kernel(int*, float, np.uint8_t), +cdef inline _core8(np.uint8_t kernel(Py_ssize_t*, float, np.uint8_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, diff --git a/skimage/rank/_core8.pyx b/skimage/rank/_core8.pyx index cd997d89..6dc59059 100644 --- a/skimage/rank/_core8.pyx +++ b/skimage/rank/_core8.pyx @@ -18,7 +18,7 @@ from libc.stdlib cimport malloc, free # 8 bit core kernel #--------------------------------------------------------------------------- -cdef inline _core8(np.uint8_t kernel(int*, float, np.uint8_t), +cdef inline _core8(np.uint8_t kernel(Py_ssize_t*, float, np.uint8_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, @@ -86,7 +86,7 @@ char shift_x, char shift_y): cdef Py_ssize_t num_se_n, num_se_s, num_se_e, num_se_w # the current local histogram distribution - cdef int* histo = malloc(256 * sizeof(int)) + cdef Py_ssize_t* histo = malloc(256 * sizeof(Py_ssize_t)) # these lists contain the relative pixel row and column for each of the 4 attack borders # east, west, north and south diff --git a/skimage/rank/_crank8.pyx b/skimage/rank/_crank8.pyx index 96624eb5..68fbfba8 100644 --- a/skimage/rank/_crank8.pyx +++ b/skimage/rank/_crank8.pyx @@ -21,8 +21,8 @@ from _core8 cimport _core8 # kernels uint8 # ----------------------------------------------------------------- -cdef inline np.uint8_t kernel_autolevel(int* histo, float pop, np.uint8_t g): - cdef int i,imin,imax,delta +cdef inline np.uint8_t kernel_autolevel(Py_ssize_t* histo, float pop, np.uint8_t g): + cdef Py_ssize_t i,imin,imax,delta if pop: for i in range(255,-1,-1): @@ -41,8 +41,8 @@ cdef inline np.uint8_t kernel_autolevel(int* histo, float pop, np.uint8_t g): else: return (0) -cdef inline np.uint8_t kernel_bottomhat(int* histo, float pop, np.uint8_t g): - cdef int i +cdef inline np.uint8_t kernel_bottomhat(Py_ssize_t* histo, float pop, np.uint8_t g): + cdef Py_ssize_t i for i in range(256): if histo[i]: @@ -51,8 +51,8 @@ cdef inline np.uint8_t kernel_bottomhat(int* histo, float pop, np.uint8_t g): return (g-i) -cdef inline np.uint8_t kernel_equalize(int* histo, float pop, np.uint8_t g): - cdef int i +cdef inline np.uint8_t kernel_equalize(Py_ssize_t* histo, float pop, np.uint8_t g): + cdef Py_ssize_t i cdef float sum = 0. if pop: @@ -65,8 +65,8 @@ cdef inline np.uint8_t kernel_equalize(int* histo, float pop, np.uint8_t g): else: return (0) -cdef inline np.uint8_t kernel_gradient(int* histo, float pop, np.uint8_t g): - cdef int i,imin,imax +cdef inline np.uint8_t kernel_gradient(Py_ssize_t* histo, float pop, np.uint8_t g): + cdef Py_ssize_t i,imin,imax if pop: @@ -82,8 +82,8 @@ cdef inline np.uint8_t kernel_gradient(int* histo, float pop, np.uint8_t g): else: return (0) -cdef inline np.uint8_t kernel_maximum(int* histo, float pop, np.uint8_t g): - cdef int i +cdef inline np.uint8_t kernel_maximum(Py_ssize_t* histo, float pop, np.uint8_t g): + cdef Py_ssize_t i if pop: for i in range(255,-1,-1): @@ -92,8 +92,8 @@ cdef inline np.uint8_t kernel_maximum(int* histo, float pop, np.uint8_t g): return (0) -cdef inline np.uint8_t kernel_mean(int* histo, float pop, np.uint8_t g): - cdef int i +cdef inline np.uint8_t kernel_mean(Py_ssize_t* histo, float pop, np.uint8_t g): + cdef Py_ssize_t i cdef float mean = 0. if pop: @@ -103,8 +103,8 @@ cdef inline np.uint8_t kernel_mean(int* histo, float pop, np.uint8_t g): else: return (0) -cdef inline np.uint8_t kernel_meansubstraction(int* histo, float pop, np.uint8_t g): - cdef int i +cdef inline np.uint8_t kernel_meansubstraction(Py_ssize_t* histo, float pop, np.uint8_t g): + cdef Py_ssize_t i cdef float mean = 0. if pop: @@ -114,8 +114,8 @@ cdef inline np.uint8_t kernel_meansubstraction(int* histo, float pop, np.uint8_t else: return (0) -cdef inline np.uint8_t kernel_median(int* histo, float pop, np.uint8_t g): - cdef int i +cdef inline np.uint8_t kernel_median(Py_ssize_t* histo, float pop, np.uint8_t g): + cdef Py_ssize_t i cdef float sum = pop/2.0 if pop: @@ -127,8 +127,8 @@ cdef inline np.uint8_t kernel_median(int* histo, float pop, np.uint8_t g): return (0) -cdef inline np.uint8_t kernel_minimum(int* histo, float pop, np.uint8_t g): - cdef int i +cdef inline np.uint8_t kernel_minimum(Py_ssize_t* histo, float pop, np.uint8_t g): + cdef Py_ssize_t i if pop: for i in range(256): @@ -137,8 +137,8 @@ cdef inline np.uint8_t kernel_minimum(int* histo, float pop, np.uint8_t g): return (0) -cdef inline np.uint8_t kernel_modal(int* histo, float pop, np.uint8_t g): - cdef int hmax=0,imax=0 +cdef inline np.uint8_t kernel_modal(Py_ssize_t* histo, float pop, np.uint8_t g): + cdef Py_ssize_t hmax=0,imax=0 if pop: for i in range(256): @@ -149,8 +149,8 @@ cdef inline np.uint8_t kernel_modal(int* histo, float pop, np.uint8_t g): return (0) -cdef inline np.uint8_t kernel_morph_contr_enh(int* histo, float pop, np.uint8_t g): - cdef int i,imin,imax +cdef inline np.uint8_t kernel_morph_contr_enh(Py_ssize_t* histo, float pop, np.uint8_t g): + cdef Py_ssize_t i,imin,imax if pop: for i in range(255,-1,-1): @@ -168,11 +168,11 @@ cdef inline np.uint8_t kernel_morph_contr_enh(int* histo, float pop, np.uint8_t else: return (0) -cdef inline np.uint8_t kernel_pop(int* histo, float pop, np.uint8_t g): +cdef inline np.uint8_t kernel_pop(Py_ssize_t* histo, float pop, np.uint8_t g): return (pop) -cdef inline np.uint8_t kernel_threshold(int* histo, float pop, np.uint8_t g): - cdef int i +cdef inline np.uint8_t kernel_threshold(Py_ssize_t* histo, float pop, np.uint8_t g): + cdef Py_ssize_t i cdef float mean = 0. if pop: @@ -182,8 +182,8 @@ cdef inline np.uint8_t kernel_threshold(int* histo, float pop, np.uint8_t g): else: return (0) -cdef inline np.uint8_t kernel_tophat(int* histo, float pop, np.uint8_t g): - cdef int i +cdef inline np.uint8_t kernel_tophat(Py_ssize_t* histo, float pop, np.uint8_t g): + cdef Py_ssize_t i for i in range(255,-1,-1): if histo[i]: From e5e01e3b8f148585d487b12ba1eff66dbe8ee1fe Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 13:36:41 +0200 Subject: [PATCH 54/86] remplace int by Py_ssize_t and for rank16 --- skimage/rank/_core16.pxd | 4 +- skimage/rank/_core16.pyx | 46 +++++++++++----------- skimage/rank/_crank16.pyx | 82 +++++++++++++++++++-------------------- 3 files changed, 66 insertions(+), 66 deletions(-) diff --git a/skimage/rank/_core16.pxd b/skimage/rank/_core16.pxd index d00ef37e..0efd4e04 100644 --- a/skimage/rank/_core16.pxd +++ b/skimage/rank/_core16.pxd @@ -4,9 +4,9 @@ cimport numpy as np # 16 bit core kernel receives extra information about data bitdepth #--------------------------------------------------------------------------- -cdef inline _core16(np.uint16_t kernel(int*, float, np.uint16_t, int ,int,int ), +cdef inline _core16(np.uint16_t kernel(Py_ssize_t*, float, np.uint16_t, Py_ssize_t ,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,int bitdepth) \ No newline at end of file +char shift_x, char shift_y,Py_ssize_t bitdepth) \ No newline at end of file diff --git a/skimage/rank/_core16.pyx b/skimage/rank/_core16.pyx index 1a3194de..00e229d9 100644 --- a/skimage/rank/_core16.pyx +++ b/skimage/rank/_core16.pyx @@ -18,24 +18,24 @@ from libc.stdlib cimport malloc, free # 16 bit core kernel receives extra information about data bitdepth #--------------------------------------------------------------------------- -cdef inline _core16(np.uint16_t kernel(int*, float, np.uint16_t, int ,int,int ), +cdef inline _core16(np.uint16_t kernel(Py_ssize_t*, float, np.uint16_t, Py_ssize_t ,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,int bitdepth): +char shift_x, char shift_y,Py_ssize_t bitdepth): """ Main loop, this function computes the histogram for each image point - data is uint8 - result is uint8 casted """ - cdef int rows = image.shape[0] - cdef int cols = image.shape[1] - cdef int srows = selem.shape[0] - cdef int scols = selem.shape[1] + cdef Py_ssize_t rows = image.shape[0] + cdef Py_ssize_t cols = image.shape[1] + cdef Py_ssize_t srows = selem.shape[0] + cdef Py_ssize_t scols = selem.shape[1] - cdef int centre_r = int(selem.shape[0] / 2) + shift_y - cdef int centre_c = int(selem.shape[1] / 2) + shift_x + cdef Py_ssize_t centre_r = int(selem.shape[0] / 2) + shift_y + cdef Py_ssize_t centre_c = int(selem.shape[1] / 2) + shift_x # check that structuring element center is inside the element bounding box assert centre_r >= 0 @@ -49,7 +49,7 @@ char shift_x, char shift_y,int bitdepth): #set maxbin and midbin - cdef int maxbin=maxbin_list[bitdepth],midbin=midbin_list[bitdepth] + cdef Py_ssize_t maxbin=maxbin_list[bitdepth],midbin=midbin_list[bitdepth] assert (imagemask.data # define local variable types - cdef int r, c, rr, cc, s, value, local_max, i, even_row + 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) # allocate memory with malloc - cdef int max_se = srows*scols + cdef Py_ssize_t max_se = srows*scols # number of element in each attack border - cdef int num_se_n, num_se_s, num_se_e, num_se_w + cdef Py_ssize_t num_se_n, num_se_s, num_se_e, num_se_w # the current local histogram distribution - cdef int* histo = malloc(maxbin * sizeof(int)) + cdef Py_ssize_t* histo = malloc(maxbin * sizeof(Py_ssize_t)) # these lists contain the relative pixel row and column for each of the 4 attack borders # east, west, north and south # e.g. se_e_r lists the rows of the east structuring element border - cdef int* se_e_r = malloc(max_se * sizeof(int)) - cdef int* se_e_c = malloc(max_se * sizeof(int)) - cdef int* se_w_r = malloc(max_se * sizeof(int)) - cdef int* se_w_c = malloc(max_se * sizeof(int)) - cdef int* se_n_r = malloc(max_se * sizeof(int)) - cdef int* se_n_c = malloc(max_se * sizeof(int)) - cdef int* se_s_r = malloc(max_se * sizeof(int)) - cdef int* se_s_c = malloc(max_se * sizeof(int)) + cdef Py_ssize_t* se_e_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t* se_e_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t* se_w_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t* se_w_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t* se_n_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t* se_n_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t* se_s_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t* se_s_c = malloc(max_se * sizeof(Py_ssize_t)) # build attack and release borders # by using difference along axis diff --git a/skimage/rank/_crank16.pyx b/skimage/rank/_crank16.pyx index 90a7e8bb..eb08326b 100644 --- a/skimage/rank/_crank16.pyx +++ b/skimage/rank/_crank16.pyx @@ -21,8 +21,8 @@ from _core16 cimport _core16 # kernels uint16 take extra parameter for defining the bitdepth # ----------------------------------------------------------------- -cdef inline np.uint16_t kernel_autolevel(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): - cdef int i,imin,imax,delta +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): + cdef Py_ssize_t i,imin,imax,delta if pop: for i in range(maxbin-1,-1,-1): @@ -39,8 +39,8 @@ cdef inline np.uint16_t kernel_autolevel(int* histo, float pop, np.uint16_t g,in else: return (imax-imin) -cdef inline np.uint16_t kernel_bottomhat(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): - cdef int i +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): + cdef Py_ssize_t i for i in range(maxbin): if histo[i]: @@ -49,8 +49,8 @@ cdef inline np.uint16_t kernel_bottomhat(int* histo, float pop, np.uint16_t g,in return (g-i) -cdef inline np.uint16_t kernel_equalize(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): - cdef int 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): + cdef Py_ssize_t i cdef float sum = 0. if pop: @@ -63,8 +63,8 @@ cdef inline np.uint16_t kernel_equalize(int* histo, float pop, np.uint16_t g,int else: return (0) -cdef inline np.uint16_t kernel_gradient(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): - cdef int i,imin,imax +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): + cdef Py_ssize_t i,imin,imax if pop: for i in range(maxbin-1,-1,-1): @@ -79,8 +79,8 @@ cdef inline np.uint16_t kernel_gradient(int* histo, float pop, np.uint16_t g,int else: return (0) -cdef inline np.uint16_t kernel_maximum(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): - cdef int i +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): + cdef Py_ssize_t i if pop: for i in range(maxbin-1,-1,-1): @@ -89,8 +89,8 @@ cdef inline np.uint16_t kernel_maximum(int* histo, float pop, np.uint16_t g,int return (0) -cdef inline np.uint16_t kernel_mean(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): - cdef int i +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): + cdef Py_ssize_t i cdef float mean = 0. if pop: @@ -100,8 +100,8 @@ cdef inline np.uint16_t kernel_mean(int* histo, float pop, np.uint16_t g,int bit else: return (0) -cdef inline np.uint16_t kernel_meansubstraction(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): - cdef int i +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): + cdef Py_ssize_t i cdef float mean = 0. if pop: @@ -111,8 +111,8 @@ cdef inline np.uint16_t kernel_meansubstraction(int* histo, float pop, np.uint16 else: return (0) -cdef inline np.uint16_t kernel_median(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): - cdef int i +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): + cdef Py_ssize_t i cdef float sum = pop/2.0 if pop: @@ -124,8 +124,8 @@ cdef inline np.uint16_t kernel_median(int* histo, float pop, np.uint16_t g,int b return (0) -cdef inline np.uint16_t kernel_minimum(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): - cdef int i +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): + cdef Py_ssize_t i if pop: for i in range(maxbin): @@ -134,8 +134,8 @@ cdef inline np.uint16_t kernel_minimum(int* histo, float pop, np.uint16_t g,int return (0) -cdef inline np.uint16_t kernel_modal(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): - cdef int hmax=0,imax=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): + cdef Py_ssize_t hmax=0,imax=0 if pop: for i in range(maxbin): @@ -146,8 +146,8 @@ cdef inline np.uint16_t kernel_modal(int* histo, float pop, np.uint16_t g,int bi return (0) -cdef inline np.uint16_t kernel_morph_contr_enh(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): - cdef int i,imin,imax +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): + cdef Py_ssize_t i,imin,imax if pop: for i in range(maxbin-1,-1,-1): @@ -165,11 +165,11 @@ cdef inline np.uint16_t kernel_morph_contr_enh(int* histo, float pop, np.uint16_ else: return (0) -cdef inline np.uint16_t kernel_pop(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): +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): return (pop) -cdef inline np.uint16_t kernel_threshold(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): - cdef int i +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): + cdef Py_ssize_t i cdef float mean = 0. if pop: @@ -179,8 +179,8 @@ cdef inline np.uint16_t kernel_threshold(int* histo, float pop, np.uint16_t g,in else: return (0) -cdef inline np.uint16_t kernel_tophat(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin): - cdef int i +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): + cdef Py_ssize_t i for i in range(maxbin-1,-1,-1): if histo[i]: @@ -195,7 +195,7 @@ 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): + char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """bottom hat """ return _core16(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,bitdepth) @@ -204,7 +204,7 @@ def bottomhat(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): + char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """bottom hat """ return _core16(kernel_bottomhat,image,selem,mask,out,shift_x,shift_y,bitdepth) @@ -213,7 +213,7 @@ def equalize(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): + char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """local egalisation of the gray level """ return _core16(kernel_equalize,image,selem,mask,out,shift_x,shift_y,bitdepth) @@ -222,7 +222,7 @@ 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): + char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """local maximum - local minimum gray level """ return _core16(kernel_gradient,image,selem,mask,out,shift_x,shift_y,bitdepth) @@ -231,7 +231,7 @@ def maximum(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): + char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """local maximum gray level """ return _core16(kernel_maximum,image,selem,mask,out,shift_x,shift_y,bitdepth) @@ -240,7 +240,7 @@ 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): + char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """average gray level (clipped on uint8) """ return _core16(kernel_mean,image,selem,mask,out,shift_x,shift_y,bitdepth) @@ -249,7 +249,7 @@ def meansubstraction(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): + char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """(g - average gray level)/2+midbin (clipped on uint8) """ return _core16(kernel_meansubstraction,image,selem,mask,out,shift_x,shift_y,bitdepth) @@ -258,7 +258,7 @@ def median(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): + char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """local median """ return _core16(kernel_median,image,selem,mask,out,shift_x,shift_y,bitdepth) @@ -267,7 +267,7 @@ def minimum(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): + char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """local minimum gray level """ return _core16(kernel_minimum,image,selem,mask,out,shift_x,shift_y,bitdepth) @@ -276,7 +276,7 @@ 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): + char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """morphological contrast enhancement """ return _core16(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y,bitdepth) @@ -285,7 +285,7 @@ def modal(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): + char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """local mode """ return _core16(kernel_modal,image,selem,mask,out,shift_x,shift_y,bitdepth) @@ -294,7 +294,7 @@ 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): + char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """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) @@ -303,7 +303,7 @@ 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): + char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """returns maxbin-1 if gray level higher than local mean, 0 else """ return _core16(kernel_threshold,image,selem,mask,out,shift_x,shift_y,bitdepth) @@ -312,7 +312,7 @@ def tophat(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): + char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """top hat """ return _core16(kernel_tophat,image,selem,mask,out,shift_x,shift_y,bitdepth) From ae73da922f7293a24cad3c974bb83d05fb7960c8 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 14:45:25 +0200 Subject: [PATCH 55/86] remplace emask with is_in_mask function --- skimage/rank/_core8.pyx | 103 +++++++++++++++--------------- skimage/rank/tests/demo_single.py | 29 +++++++++ 2 files changed, 79 insertions(+), 53 deletions(-) create mode 100644 skimage/rank/tests/demo_single.py diff --git a/skimage/rank/_core8.pyx b/skimage/rank/_core8.pyx index 6dc59059..baedd67a 100644 --- a/skimage/rank/_core8.pyx +++ b/skimage/rank/_core8.pyx @@ -18,6 +18,15 @@ from libc.stdlib cimport malloc, free # 8 bit core kernel #--------------------------------------------------------------------------- +cdef inline Py_ssize_t is_in_mask(Py_ssize_t rows, Py_ssize_t cols,Py_ssize_t r, Py_ssize_t c,np.uint8_t* mask): + if r < 0 or r > rows - 1 or c < 0 or c > cols - 1: + return 0 + else: + if mask[r*cols+c]: + return 1 + else: + return 0 + cdef inline _core8(np.uint8_t kernel(Py_ssize_t*, float, np.uint8_t), np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -55,21 +64,9 @@ char shift_x, char shift_y): else: out = np.ascontiguousarray(out) - # create extended image and mask - cdef Py_ssize_t erows = rows+srows-1 - cdef Py_ssize_t ecols = cols+scols-1 - - cdef np.ndarray emask = np.zeros((erows, ecols), dtype=np.uint8) - cdef np.ndarray eimage = np.zeros((erows, ecols), dtype=np.uint8) - - eimage[centre_r:rows+centre_r,centre_c:cols+centre_c] = image - emask[centre_r:rows+centre_r,centre_c:cols+centre_c] = mask - mask = np.ascontiguousarray(mask) # define pointers to the data - cdef np.uint8_t* eimage_data = eimage.data - cdef np.uint8_t* emask_data = emask.data cdef np.uint8_t* out_data = out.data cdef np.uint8_t* image_data = image.data @@ -145,18 +142,18 @@ char shift_x, char shift_y): for r in range(srows): for c in range(scols): - rr = r - cc = c + rr = r - centre_r + cc = c - centre_c if selem[r, c]: - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] + if is_in_mask(rows,cols,rr,cc,mask_data): + value = image_data[rr * cols + cc] histo[value] += 1 pop += 1. r = 0 c = 0 # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) + out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c]) # kernel ------------------------------------------- # main loop @@ -165,22 +162,22 @@ char shift_x, char shift_y): # ---> west to east for c in range(1,cols): for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] + rr = r + se_e_r[s] + cc = c + se_e_c[s] + if is_in_mask(rows,cols,rr,cc,mask_data): + value = image_data[rr * cols + cc] histo[value] += 1 pop += 1. for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] + rr = r + se_w_r[s] + cc = c + se_w_c[s] - 1 + if is_in_mask(rows,cols,rr,cc,mask_data): + value = image_data[rr * cols + cc] histo[value] -= 1 pop -= 1. # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) + out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c]) # kernel ------------------------------------------- r += 1 # pass to the next row @@ -189,43 +186,43 @@ char shift_x, char shift_y): # ---> north to south for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] + rr = r + se_s_r[s] + cc = c + se_s_c[s] + if is_in_mask(rows,cols,rr,cc,mask_data): + value = image_data[rr * cols + cc] histo[value] += 1 pop += 1. for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] + rr = r + se_n_r[s] - 1 + cc = c + se_n_c[s] + if is_in_mask(rows,cols,rr,cc,mask_data): + value = image_data[rr * cols + cc] histo[value] -= 1 pop -= 1. # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) + out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c]) # kernel ------------------------------------------- # ---> east to west for c in range(cols-2,-1,-1): for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] + rr = r + se_w_r[s] + cc = c + se_w_c[s] + if is_in_mask(rows,cols,rr,cc,mask_data): + value = image_data[rr * cols + cc] histo[value] += 1 pop += 1. for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c + 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] + rr = r + se_e_r[s] + cc = c + se_e_c[s] + 1 + if is_in_mask(rows,cols,rr,cc,mask_data): + value = image_data[rr * cols + cc] histo[value] -= 1 pop -= 1. # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) + out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c]) # kernel ------------------------------------------- r += 1 # pass to the next row @@ -234,22 +231,22 @@ char shift_x, char shift_y): # ---> north to south for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] + rr = r + se_s_r[s] + cc = c + se_s_c[s] + if is_in_mask(rows,cols,rr,cc,mask_data): + value = image_data[rr * cols + cc] histo[value] += 1 pop += 1. for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] + rr = r + se_n_r[s] - 1 + cc = c + se_n_c[s] + if is_in_mask(rows,cols,rr,cc,mask_data): + value = image_data[rr * cols + cc] histo[value] -= 1 pop -= 1. # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c]) + out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c]) # kernel ------------------------------------------- # release memory allocated by malloc diff --git a/skimage/rank/tests/demo_single.py b/skimage/rank/tests/demo_single.py new file mode 100644 index 00000000..028f27b2 --- /dev/null +++ b/skimage/rank/tests/demo_single.py @@ -0,0 +1,29 @@ +import numpy as np +import matplotlib.pyplot as plt +from pprint import pprint + +from skimage import data +from skimage.morphology.selem import disk +import skimage.rank as rank + + +if __name__ == '__main__': + a8 = data.camera() + a16 = data.camera().astype(np.uint16) + selem = disk(10) + + f8= rank.mean(a8,selem) + f16= rank.mean(a16,selem) + + print f8==f16 + + plt.figure() + plt.subplot(1,2,1) + plt.imshow(a8) + plt.subplot(1,2,2) + plt.imshow(f8-f16) + plt.show() + + + + From aa131ce67b2cbb1869f9ce65436767d4fcc2606c Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 15:03:29 +0200 Subject: [PATCH 56/86] add comment --- skimage/rank/_core8.pyx | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/skimage/rank/_core8.pyx b/skimage/rank/_core8.pyx index baedd67a..72b0d6aa 100644 --- a/skimage/rank/_core8.pyx +++ b/skimage/rank/_core8.pyx @@ -18,7 +18,11 @@ from libc.stdlib cimport malloc, free # 8 bit core kernel #--------------------------------------------------------------------------- -cdef inline Py_ssize_t is_in_mask(Py_ssize_t rows, Py_ssize_t cols,Py_ssize_t r, Py_ssize_t c,np.uint8_t* mask): +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: @@ -134,7 +138,7 @@ char shift_x, char shift_y): se_s_c[num_se_s] = c - centre_c num_se_s += 1 - # initial population and histogram + # initial population and histogram (kernel is centered on the first row and column) for i in range(256): histo[i] = 0 @@ -152,9 +156,9 @@ char shift_x, char shift_y): r = 0 c = 0 - # kernel ------------------------------------------- + # kernel -------------------------------------------------------------------- out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c]) - # kernel ------------------------------------------- + # kernel -------------------------------------------------------------------- # main loop r = 0 @@ -176,9 +180,9 @@ char shift_x, char shift_y): histo[value] -= 1 pop -= 1. - # kernel ------------------------------------------- + # kernel -------------------------------------------------------------------- out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c]) - # kernel ------------------------------------------- + # kernel -------------------------------------------------------------------- r += 1 # pass to the next row if r>=rows: @@ -200,9 +204,9 @@ char shift_x, char shift_y): histo[value] -= 1 pop -= 1. - # kernel ------------------------------------------- + # kernel -------------------------------------------------------------------- out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c]) - # kernel ------------------------------------------- + # kernel -------------------------------------------------------------------- # ---> east to west for c in range(cols-2,-1,-1): @@ -221,9 +225,9 @@ char shift_x, char shift_y): histo[value] -= 1 pop -= 1. - # kernel ------------------------------------------- + # kernel -------------------------------------------------------------------- out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c]) - # kernel ------------------------------------------- + # kernel -------------------------------------------------------------------- r += 1 # pass to the next row if r>=rows: @@ -245,9 +249,9 @@ char shift_x, char shift_y): histo[value] -= 1 pop -= 1. - # kernel ------------------------------------------- + # kernel -------------------------------------------------------------------- out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c]) - # kernel ------------------------------------------- + # kernel -------------------------------------------------------------------- # release memory allocated by malloc From 3dd08d71d012700bd31bf71aa5bb8972b9ce7dcc Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 15:16:26 +0200 Subject: [PATCH 57/86] remplace emask with is_in_mask function in crank16 --- skimage/rank/_core16.pyx | 109 +++++++++++++++--------------- skimage/rank/tests/demo_single.py | 2 +- 2 files changed, 56 insertions(+), 55 deletions(-) diff --git a/skimage/rank/_core16.pyx b/skimage/rank/_core16.pyx index 00e229d9..6a004da7 100644 --- a/skimage/rank/_core16.pyx +++ b/skimage/rank/_core16.pyx @@ -18,6 +18,20 @@ from libc.stdlib cimport malloc, free # 16 bit core kernel receives extra information about data bitdepth #--------------------------------------------------------------------------- +cdef inline np.uint8_t is_in_mask(Py_ssize_t rows, Py_ssize_t cols,Py_ssize_t r, Py_ssize_t c,np.uint8_t* mask): + """ returns 1 if given(r,c) coordinate are within the image frame ([0-rows],[0-cols]) and + inside the given mask + returns 0 otherwise + """ + if r < 0 or r > rows - 1 or c < 0 or c > cols - 1: + return 0 + else: + if mask[r*cols+c]: + return 1 + else: + return 0 + + cdef inline _core16(np.uint16_t kernel(Py_ssize_t*, float, np.uint16_t, Py_ssize_t ,Py_ssize_t,Py_ssize_t ), np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -65,22 +79,9 @@ char shift_x, char shift_y,Py_ssize_t bitdepth): else: out = np.ascontiguousarray(out) - # create extended image and mask - cdef Py_ssize_t erows = rows+srows-1 - cdef Py_ssize_t ecols = cols+scols-1 - - cdef np.ndarray emask = np.zeros((erows, ecols), dtype=np.uint8) - cdef np.ndarray eimage = np.zeros((erows, ecols), dtype=np.uint16) - - eimage[centre_r:rows+centre_r,centre_c:cols+centre_c] = image - emask[centre_r:rows+centre_r,centre_c:cols+centre_c] = mask - mask = np.ascontiguousarray(mask) # define pointers to the data - cdef np.uint16_t* eimage_data = eimage.data - cdef np.uint8_t* emask_data = emask.data - cdef np.uint16_t* out_data = out.data cdef np.uint16_t* image_data = image.data cdef np.uint8_t* mask_data = mask.data @@ -155,18 +156,18 @@ char shift_x, char shift_y,Py_ssize_t bitdepth): for r in range(srows): for c in range(scols): - rr = r - cc = c + rr = r - centre_r + cc = c - centre_c if selem[r, c]: - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] + if is_in_mask(rows,cols,rr,cc,mask_data): + value = image_data[rr * cols + cc] histo[value] += 1 pop += 1. r = 0 c = 0 # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c], bitdepth,maxbin,midbin) # kernel ------------------------------------------- @@ -176,22 +177,22 @@ char shift_x, char shift_y,Py_ssize_t bitdepth): # ---> west to east for c in range(1,cols): for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] + rr = r + se_e_r[s] + cc = c + se_e_c[s] + if is_in_mask(rows,cols,rr,cc,mask_data): + value = image_data[rr * cols + cc] histo[value] += 1 pop += 1. for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] + rr = r + se_w_r[s] + cc = c + se_w_c[s] - 1 + if is_in_mask(rows,cols,rr,cc,mask_data): + value = image_data[rr * cols + cc] histo[value] -= 1 pop -= 1. # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c ], bitdepth,maxbin,midbin) # kernel ------------------------------------------- @@ -201,44 +202,44 @@ char shift_x, char shift_y,Py_ssize_t bitdepth): # ---> north to south for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] + rr = r + se_s_r[s] + cc = c + se_s_c[s] + if is_in_mask(rows,cols,rr,cc,mask_data): + value = image_data[rr * cols + cc] histo[value] += 1 pop += 1. for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] + rr = r + se_n_r[s] - 1 + cc = c + se_n_c[s] + if is_in_mask(rows,cols,rr,cc,mask_data): + value = image_data[rr * cols + cc] histo[value] -= 1 pop -= 1. # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c], bitdepth,maxbin,midbin) # kernel ------------------------------------------- # ---> east to west for c in range(cols-2,-1,-1): for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] + rr = r + se_w_r[s] + cc = c + se_w_c[s] + if is_in_mask(rows,cols,rr,cc,mask_data): + value = image_data[rr * cols + cc] histo[value] += 1 pop += 1. for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c + 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] + rr = r + se_e_r[s] + cc = c + se_e_c[s] + 1 + if is_in_mask(rows,cols,rr,cc,mask_data): + value = image_data[rr * cols + cc] histo[value] -= 1 pop -= 1. # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c ], bitdepth,maxbin,midbin) # kernel ------------------------------------------- @@ -248,22 +249,22 @@ char shift_x, char shift_y,Py_ssize_t bitdepth): # ---> north to south for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] + rr = r + se_s_r[s] + cc = c + se_s_c[s] + if is_in_mask(rows,cols,rr,cc,mask_data): + value = image_data[rr * cols + cc] histo[value] += 1 pop += 1. for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] + rr = r + se_n_r[s] - 1 + cc = c + se_n_c[s] + if is_in_mask(rows,cols,rr,cc,mask_data): + value = image_data[rr * cols + cc] histo[value] -= 1 pop -= 1. # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], + out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c ], bitdepth,maxbin,midbin) # kernel ------------------------------------------- diff --git a/skimage/rank/tests/demo_single.py b/skimage/rank/tests/demo_single.py index 028f27b2..5ec95d7b 100644 --- a/skimage/rank/tests/demo_single.py +++ b/skimage/rank/tests/demo_single.py @@ -19,7 +19,7 @@ if __name__ == '__main__': plt.figure() plt.subplot(1,2,1) - plt.imshow(a8) + plt.imshow(f16) plt.subplot(1,2,2) plt.imshow(f8-f16) plt.show() From f62b8d06d2aaecb9361c1831482339884b1b73ef Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 15:42:31 +0200 Subject: [PATCH 58/86] group core8,8p and 8b --- skimage/rank/_core8.pxd | 11 +++++--- skimage/rank/_core8.pyx | 25 +++++++++++------- skimage/rank/_crank8.pyx | 56 ++++++++++++++++++++-------------------- 3 files changed, 52 insertions(+), 40 deletions(-) diff --git a/skimage/rank/_core8.pxd b/skimage/rank/_core8.pxd index 6dca9f61..c0ac709d 100644 --- a/skimage/rank/_core8.pxd +++ b/skimage/rank/_core8.pxd @@ -1,12 +1,17 @@ cimport numpy as np +# generic cdef functions +cdef inline np.uint8_t uint8_max(np.uint8_t a, np.uint8_t b) +cdef inline np.uint8_t uint8_min(np.uint8_t a, np.uint8_t b) + #--------------------------------------------------------------------------- -# 8 bit core kernel +# 8 bit core kernel receives extra information about data inferior and superior percentiles #--------------------------------------------------------------------------- -cdef inline _core8(np.uint8_t kernel(Py_ssize_t*, float, np.uint8_t), +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) +char shift_x, char shift_y, float p0, float p1, Py_ssize_t s0, Py_ssize_t s1) + diff --git a/skimage/rank/_core8.pyx b/skimage/rank/_core8.pyx index 72b0d6aa..3ffbb5b9 100644 --- a/skimage/rank/_core8.pyx +++ b/skimage/rank/_core8.pyx @@ -14,6 +14,11 @@ 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 #--------------------------------------------------------------------------- @@ -31,12 +36,12 @@ 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), +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): +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 @@ -78,7 +83,9 @@ char shift_x, char shift_y): # 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 @@ -157,7 +164,7 @@ char shift_x, char shift_y): r = 0 c = 0 # kernel -------------------------------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c]) + out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c],p0,p1,s0,s1) # kernel -------------------------------------------------------------------- # main loop @@ -181,14 +188,14 @@ char shift_x, char shift_y): pop -= 1. # kernel -------------------------------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c]) + 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: break - # ---> north to south + # ---> north to south for s in range(num_se_s): rr = r + se_s_r[s] cc = c + se_s_c[s] @@ -205,7 +212,7 @@ char shift_x, char shift_y): pop -= 1. # kernel -------------------------------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c]) + out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c],p0,p1,s0,s1) # kernel -------------------------------------------------------------------- # ---> east to west @@ -226,7 +233,7 @@ char shift_x, char shift_y): pop -= 1. # kernel -------------------------------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c]) + 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 @@ -250,7 +257,7 @@ char shift_x, char shift_y): pop -= 1. # kernel -------------------------------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c]) + out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c],p0,p1,s0,s1) # kernel -------------------------------------------------------------------- # release memory allocated by malloc diff --git a/skimage/rank/_crank8.pyx b/skimage/rank/_crank8.pyx index 68fbfba8..600cb00d 100644 --- a/skimage/rank/_crank8.pyx +++ b/skimage/rank/_crank8.pyx @@ -21,7 +21,7 @@ from _core8 cimport _core8 # kernels uint8 # ----------------------------------------------------------------- -cdef inline np.uint8_t kernel_autolevel(Py_ssize_t* histo, float pop, np.uint8_t g): +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 if pop: @@ -41,7 +41,7 @@ cdef inline np.uint8_t kernel_autolevel(Py_ssize_t* histo, float pop, np.uint8_t else: return (0) -cdef inline np.uint8_t kernel_bottomhat(Py_ssize_t* histo, float pop, np.uint8_t g): +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 for i in range(256): @@ -51,7 +51,7 @@ cdef inline np.uint8_t kernel_bottomhat(Py_ssize_t* histo, float pop, np.uint8_t return (g-i) -cdef inline np.uint8_t kernel_equalize(Py_ssize_t* histo, float pop, np.uint8_t g): +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. @@ -65,7 +65,7 @@ cdef inline np.uint8_t kernel_equalize(Py_ssize_t* histo, float pop, np.uint8_t else: return (0) -cdef inline np.uint8_t kernel_gradient(Py_ssize_t* histo, float pop, np.uint8_t g): +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 @@ -82,7 +82,7 @@ cdef inline np.uint8_t kernel_gradient(Py_ssize_t* histo, float pop, np.uint8_t else: return (0) -cdef inline np.uint8_t kernel_maximum(Py_ssize_t* histo, float pop, np.uint8_t g): +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: @@ -92,7 +92,7 @@ cdef inline np.uint8_t kernel_maximum(Py_ssize_t* histo, float pop, np.uint8_t g return (0) -cdef inline np.uint8_t kernel_mean(Py_ssize_t* histo, float pop, np.uint8_t g): +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. @@ -103,7 +103,7 @@ cdef inline np.uint8_t kernel_mean(Py_ssize_t* histo, float pop, np.uint8_t g): else: return (0) -cdef inline np.uint8_t kernel_meansubstraction(Py_ssize_t* histo, float pop, np.uint8_t g): +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. @@ -114,7 +114,7 @@ cdef inline np.uint8_t kernel_meansubstraction(Py_ssize_t* histo, float pop, np. else: return (0) -cdef inline np.uint8_t kernel_median(Py_ssize_t* histo, float pop, np.uint8_t g): +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 @@ -127,7 +127,7 @@ cdef inline np.uint8_t kernel_median(Py_ssize_t* histo, float pop, np.uint8_t g) return (0) -cdef inline np.uint8_t kernel_minimum(Py_ssize_t* histo, float pop, np.uint8_t g): +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: @@ -137,7 +137,7 @@ cdef inline np.uint8_t kernel_minimum(Py_ssize_t* histo, float pop, np.uint8_t g return (0) -cdef inline np.uint8_t kernel_modal(Py_ssize_t* histo, float pop, np.uint8_t g): +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 if pop: @@ -149,7 +149,7 @@ cdef inline np.uint8_t kernel_modal(Py_ssize_t* histo, float pop, np.uint8_t g): return (0) -cdef inline np.uint8_t kernel_morph_contr_enh(Py_ssize_t* histo, float pop, np.uint8_t g): +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 if pop: @@ -168,10 +168,10 @@ cdef inline np.uint8_t kernel_morph_contr_enh(Py_ssize_t* histo, float pop, np.u else: return (0) -cdef inline np.uint8_t kernel_pop(Py_ssize_t* histo, float pop, np.uint8_t g): +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 (pop) -cdef inline np.uint8_t kernel_threshold(Py_ssize_t* histo, float pop, np.uint8_t g): +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. @@ -182,7 +182,7 @@ cdef inline np.uint8_t kernel_threshold(Py_ssize_t* histo, float pop, np.uint8_t else: return (0) -cdef inline np.uint8_t kernel_tophat(Py_ssize_t* histo, float pop, np.uint8_t g): +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 for i in range(255,-1,-1): @@ -201,7 +201,7 @@ def autolevel(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """bottom hat """ - return _core8(kernel_autolevel,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) def bottomhat(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -210,7 +210,7 @@ def bottomhat(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """bottom hat """ - return _core8(kernel_bottomhat,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_bottomhat,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) def equalize(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -219,7 +219,7 @@ def equalize(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """local egalisation of the gray level """ - return _core8(kernel_equalize,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_equalize,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) def gradient(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -228,7 +228,7 @@ def gradient(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """local maximum - local minimum gray level """ - return _core8(kernel_gradient,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_gradient,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) def maximum(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -237,7 +237,7 @@ def maximum(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """local maximum gray level """ - return _core8(kernel_maximum,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_maximum,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) def mean(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -246,7 +246,7 @@ def mean(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """average gray level (clipped on uint8) """ - return _core8(kernel_mean,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_mean,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) def meansubstraction(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -255,7 +255,7 @@ def meansubstraction(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """(g - average gray level)/2+127 (clipped on uint8) """ - return _core8(kernel_meansubstraction,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_meansubstraction,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) def median(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -264,7 +264,7 @@ def median(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """local median """ - return _core8(kernel_median,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_median,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) def minimum(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -273,7 +273,7 @@ def minimum(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """local minimum gray level """ - return _core8(kernel_minimum,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_minimum,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) def morph_contr_enh(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -282,7 +282,7 @@ def morph_contr_enh(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """morphological contrast enhancement """ - return _core8(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) def modal(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -291,7 +291,7 @@ def modal(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """local mode """ - return _core8(kernel_modal,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_modal,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) def pop(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -300,7 +300,7 @@ def pop(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """returns the number of actual pixels of the structuring element inside the mask """ - return _core8(kernel_pop,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_pop,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) def threshold(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -309,7 +309,7 @@ def threshold(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """returns 255 if gray level higher than local mean, 0 else """ - return _core8(kernel_threshold,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_threshold,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) def tophat(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -318,5 +318,5 @@ def tophat(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """top hat """ - return _core8(kernel_tophat,image,selem,mask,out,shift_x,shift_y) + return _core8(kernel_tophat,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) From e47ef3b38e49421c4b4d7be3a607032544826714 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 15:55:21 +0200 Subject: [PATCH 59/86] delete core8p --- skimage/rank/_core8p.pxd | 17 -- skimage/rank/_core8p.pyx | 266 --------------------------- skimage/rank/_crank8_percentiles.pyx | 34 ++-- skimage/rank/setup.py | 3 - skimage/rank/tests/demo_single.py | 6 +- 5 files changed, 20 insertions(+), 306 deletions(-) delete mode 100644 skimage/rank/_core8p.pxd delete mode 100644 skimage/rank/_core8p.pyx diff --git a/skimage/rank/_core8p.pxd b/skimage/rank/_core8p.pxd deleted file mode 100644 index 8d3181e8..00000000 --- a/skimage/rank/_core8p.pxd +++ /dev/null @@ -1,17 +0,0 @@ -cimport numpy as np - -# generic cdef functions -cdef inline np.uint8_t uint8_max(np.uint8_t a, np.uint8_t b) -cdef inline 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 inline _core8p(np.uint8_t kernel(int*, float, np.uint8_t, float, float), -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) - diff --git a/skimage/rank/_core8p.pyx b/skimage/rank/_core8p.pyx deleted file mode 100644 index b1adac70..00000000 --- a/skimage/rank/_core8p.pyx +++ /dev/null @@ -1,266 +0,0 @@ -#cython: cdivision=True -#cython: boundscheck=False -#cython: nonecheck=False -#cython: wraparound=False - -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 receives extra information about data inferior and superior percentiles -#--------------------------------------------------------------------------- - -cdef inline _core8p(np.uint8_t kernel(int*, float, np.uint8_t, float, float), -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): - """ Main loop, this function computes the histogram for each image point - - data is uint8 - - result is uint8 casted - """ - - cdef int rows = image.shape[0] - cdef int cols = image.shape[1] - cdef int srows = selem.shape[0] - cdef int scols = selem.shape[1] - - cdef int centre_r = int(selem.shape[0] / 2) + shift_y - cdef int centre_c = int(selem.shape[1] / 2) + shift_x - - # check that structuring element center is inside the element bounding box - assert centre_r >= 0 - assert centre_c >= 0 - 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 out is None: - out = np.zeros((rows, cols), dtype=np.uint8) - else: - out = np.ascontiguousarray(out) - - # create extended image and mask - cdef int erows = rows+srows-1 - cdef int ecols = cols+scols-1 - - cdef np.ndarray emask = np.zeros((erows, ecols), dtype=np.uint8) - cdef np.ndarray eimage = np.zeros((erows, ecols), dtype=np.uint8) - - eimage[centre_r:rows+centre_r,centre_c:cols+centre_c] = image - emask[centre_r:rows+centre_r,centre_c:cols+centre_c] = mask - - mask = np.ascontiguousarray(mask) - - # define pointers to the data - cdef np.uint8_t* eimage_data = eimage.data - cdef np.uint8_t* emask_data = emask.data - - cdef np.uint8_t* out_data = out.data - cdef np.uint8_t* image_data = image.data - cdef np.uint8_t* mask_data = mask.data - - # define local variable types - cdef int r, c, rr, cc, s, value, local_max, i, even_row - cdef float pop # number of pixels actually inside the neighborhood (float) - - # allocate memory with malloc - cdef int max_se = srows*scols - - # number of element in each attack border - cdef int num_se_n, num_se_s, num_se_e, num_se_w - - # the current local histogram distribution - cdef int* histo = malloc(256 * sizeof(int)) - - # 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 int* se_e_r = malloc(max_se * sizeof(int)) - cdef int* se_e_c = malloc(max_se * sizeof(int)) - cdef int* se_w_r = malloc(max_se * sizeof(int)) - cdef int* se_w_c = malloc(max_se * sizeof(int)) - cdef int* se_n_r = malloc(max_se * sizeof(int)) - cdef int* se_n_c = malloc(max_se * sizeof(int)) - cdef int* se_s_r = malloc(max_se * sizeof(int)) - cdef int* se_s_c = malloc(max_se * sizeof(int)) - - # 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 - - t = np.hstack((np.zeros((selem.shape[0],1)),selem)) - t_w = np.diff(t,axis=1)==1 - - t = np.vstack((selem,np.zeros((1,selem.shape[1])))) - t_s = np.diff(t,axis=0)==-1 - - t = np.vstack((np.zeros((1,selem.shape[1])),selem)) - t_n = np.diff(t,axis=0)==1 - - num_se_n = num_se_s = num_se_e = num_se_w = 0 - - for r in range(srows): - for c in range(scols): - if t_e[r,c]: - se_e_r[num_se_e] = r - centre_r - se_e_c[num_se_e] = c - centre_c - num_se_e += 1 - if t_w[r,c]: - se_w_r[num_se_w] = r - centre_r - se_w_c[num_se_w] = c - centre_c - num_se_w += 1 - if t_n[r,c]: - se_n_r[num_se_n] = r - centre_r - se_n_c[num_se_n] = c - centre_c - num_se_n += 1 - if t_s[r,c]: - se_s_r[num_se_s] = r - centre_r - se_s_c[num_se_s] = c - centre_c - num_se_s += 1 - - # initial population and histogram - for i in range(256): - histo[i] = 0 - - pop = 0 - - for r in range(srows): - for c in range(scols): - rr = r - cc = c - if selem[r, c]: - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - - r = 0 - c = 0 - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) - # kernel ------------------------------------------- - - # main loop - r = 0 - for even_row in range(0,rows,2): - # ---> west to east - for c in range(1,cols): - for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) - # kernel ------------------------------------------- - - # ---> east to west - for c in range(cols-2,-1,-1): - for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c + 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c],p0,p1) - # kernel ------------------------------------------- - - # release memory allocated by malloc - - free(se_e_r) - free(se_e_c) - free(se_w_r) - free(se_w_c) - free(se_n_r) - free(se_n_c) - free(se_s_r) - free(se_s_c) - - free(histo) - - return out - diff --git a/skimage/rank/_crank8_percentiles.pyx b/skimage/rank/_crank8_percentiles.pyx index 2299f04a..16ad49d5 100644 --- a/skimage/rank/_crank8_percentiles.pyx +++ b/skimage/rank/_crank8_percentiles.pyx @@ -7,13 +7,13 @@ import numpy as np cimport numpy as np # import main loop -from _core8p cimport _core8p,uint8_max,uint8_min +from _core8 cimport _core8,uint8_max,uint8_min # ----------------------------------------------------------------- # kernels uint8 (SOFT version using percentiles) # ----------------------------------------------------------------- -cdef inline np.uint8_t kernel_autolevel(int* histo, float pop, np.uint8_t g, float p0, float p1): +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: @@ -42,7 +42,7 @@ cdef inline np.uint8_t kernel_autolevel(int* histo, float pop, np.uint8_t g, flo return (128) -cdef inline np.uint8_t kernel_gradient(int* histo, float pop, np.uint8_t g, float p0, float p1): +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: @@ -65,7 +65,7 @@ cdef inline np.uint8_t kernel_gradient(int* histo, float pop, np.uint8_t g, floa return (0) -cdef inline np.uint8_t kernel_mean(int* histo, float pop, np.uint8_t g, float p0, float p1): +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,7 +84,7 @@ cdef inline np.uint8_t kernel_mean(int* histo, float pop, np.uint8_t g, float p0 else: return (0) -cdef inline np.uint8_t kernel_mean_substraction(int* histo, float pop, np.uint8_t g, float p0, float p1): +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: @@ -103,7 +103,7 @@ cdef inline np.uint8_t kernel_mean_substraction(int* histo, float pop, np.uint8_ else: return (0) -cdef inline np.uint8_t kernel_morph_contr_enh(int* histo, float pop, np.uint8_t g, float p0, float p1): +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,7 +131,7 @@ cdef inline np.uint8_t kernel_morph_contr_enh(int* histo, float pop, np.uint8_t else: return (0) -cdef inline np.uint8_t kernel_percentile(int* histo, float pop, np.uint8_t g, float p0, float p1): +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. @@ -145,7 +145,7 @@ cdef inline np.uint8_t kernel_percentile(int* histo, float pop, np.uint8_t g, fl else: return (0) -cdef inline np.uint8_t kernel_pop(int* histo, float pop, np.uint8_t g, float p0, float p1): +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: @@ -159,7 +159,7 @@ cdef inline np.uint8_t kernel_pop(int* histo, float pop, np.uint8_t g, float p0, else: return (0) -cdef inline np.uint8_t kernel_threshold(int* histo, float pop, np.uint8_t g, float p0, float p1): +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. @@ -183,7 +183,7 @@ 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 _core8p(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,p0,p1) + return _core8(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,p0,p1,0,0) def gradient(np.ndarray[np.uint8_t, ndim=2] image, @@ -193,7 +193,7 @@ 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 _core8p(kernel_gradient,image,selem,mask,out,shift_x,shift_y,p0,p1) + return _core8(kernel_gradient,image,selem,mask,out,shift_x,shift_y,p0,p1,0,0) def mean(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -202,7 +202,7 @@ 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 _core8p(kernel_mean,image,selem,mask,out,shift_x,shift_y,p0,p1) + return _core8(kernel_mean,image,selem,mask,out,shift_x,shift_y,p0,p1,0,0) def mean_substraction(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -211,7 +211,7 @@ 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 _core8p(kernel_mean_substraction,image,selem,mask,out,shift_x,shift_y,p0,p1) + return _core8(kernel_mean_substraction,image,selem,mask,out,shift_x,shift_y,p0,p1,0,0) def morph_contr_enh(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -220,7 +220,7 @@ 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 _core8p(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y,p0,p1) + return _core8(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y,p0,p1,0,0) def percentile(np.ndarray[np.uint8_t, ndim=2] image, @@ -230,7 +230,7 @@ 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 _core8p(kernel_percentile,image,selem,mask,out,shift_x,shift_y,p0,p1) + return _core8(kernel_percentile,image,selem,mask,out,shift_x,shift_y,p0,p1,0,0) def pop(np.ndarray[np.uint8_t, ndim=2] image, @@ -240,7 +240,7 @@ 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 _core8p(kernel_pop,image,selem,mask,out,shift_x,shift_y,p0,p1) + return _core8(kernel_pop,image,selem,mask,out,shift_x,shift_y,p0,p1,0,0) def threshold(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -249,4 +249,4 @@ 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 _core8p(kernel_threshold,image,selem,mask,out,shift_x,shift_y,p0,p1) + return _core8(kernel_threshold,image,selem,mask,out,shift_x,shift_y,p0,p1,0,0) diff --git a/skimage/rank/setup.py b/skimage/rank/setup.py index 207ff18f..854748b8 100644 --- a/skimage/rank/setup.py +++ b/skimage/rank/setup.py @@ -13,7 +13,6 @@ def configuration(parent_package='', top_path=None): cython(['_core8.pyx'], working_path=base_path) - cython(['_core8p.pyx'], working_path=base_path) cython(['_core16.pyx'], working_path=base_path) cython(['_core16p.pyx'], working_path=base_path) cython(['_core16b.pyx'], working_path=base_path) @@ -25,8 +24,6 @@ def configuration(parent_package='', top_path=None): config.add_extension('_core8', sources=['_core8.c'], include_dirs=[get_numpy_include_dirs()]) - config.add_extension('_core8p', sources=['_core8p.c'], - include_dirs=[get_numpy_include_dirs()]) config.add_extension('_core16', sources=['_core16.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('_core16p', sources=['_core16p.c'], diff --git a/skimage/rank/tests/demo_single.py b/skimage/rank/tests/demo_single.py index 5ec95d7b..7ff12b28 100644 --- a/skimage/rank/tests/demo_single.py +++ b/skimage/rank/tests/demo_single.py @@ -12,8 +12,8 @@ if __name__ == '__main__': a16 = data.camera().astype(np.uint16) selem = disk(10) - f8= rank.mean(a8,selem) - f16= rank.mean(a16,selem) + f8= rank.percentile_autolevel(a8,selem,p0=.0,p1=1.) + f16= rank.autolevel(a16,selem) print f8==f16 @@ -21,7 +21,7 @@ if __name__ == '__main__': plt.subplot(1,2,1) plt.imshow(f16) plt.subplot(1,2,2) - plt.imshow(f8-f16) + plt.imshow(f8) plt.show() From 3ba95a77af73761995249b020b25e18321f683cc Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 16:35:11 +0200 Subject: [PATCH 60/86] group crank16 and crank16p --- skimage/rank/_core16.pxd | 17 ++++-- skimage/rank/_core16.pyx | 27 +++++---- skimage/rank/_core8.pxd | 10 ++-- skimage/rank/_core8.pyx | 10 ++-- skimage/rank/_crank16.pyx | 84 ++++++++++++++++++--------- skimage/rank/_crank16_percentiles.pyx | 34 +++++------ skimage/rank/_crank8.pyx | 42 +++++++++----- 7 files changed, 138 insertions(+), 86 deletions(-) diff --git a/skimage/rank/_core16.pxd b/skimage/rank/_core16.pxd index 0efd4e04..f9bb47b3 100644 --- a/skimage/rank/_core16.pxd +++ b/skimage/rank/_core16.pxd @@ -4,9 +4,14 @@ cimport numpy as np # 16 bit core kernel receives extra information about data bitdepth #--------------------------------------------------------------------------- -cdef inline _core16(np.uint16_t kernel(Py_ssize_t*, float, np.uint16_t, Py_ssize_t ,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) \ No newline at end of file +# generic cdef functions +cdef inline int int_max(int a, int b) +cdef inline int int_min(int a, int b) + +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) \ No newline at end of file diff --git a/skimage/rank/_core16.pyx b/skimage/rank/_core16.pyx index 6a004da7..2e55aa8b 100644 --- a/skimage/rank/_core16.pyx +++ b/skimage/rank/_core16.pyx @@ -18,6 +18,10 @@ from libc.stdlib cimport malloc, free # 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 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 @@ -32,12 +36,13 @@ cdef inline np.uint8_t is_in_mask(Py_ssize_t rows, Py_ssize_t cols,Py_ssize_t r, return 0 -cdef inline _core16(np.uint16_t kernel(Py_ssize_t*, float, np.uint16_t, Py_ssize_t ,Py_ssize_t,Py_ssize_t ), -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): +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 @@ -168,7 +173,7 @@ char shift_x, char shift_y,Py_ssize_t bitdepth): c = 0 # kernel ------------------------------------------- out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c], - bitdepth,maxbin,midbin) + bitdepth,maxbin,midbin,p0,p1,s0,s1) # kernel ------------------------------------------- # main loop @@ -193,7 +198,7 @@ char shift_x, char shift_y,Py_ssize_t bitdepth): # kernel ------------------------------------------- out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c ], - bitdepth,maxbin,midbin) + bitdepth,maxbin,midbin,p0,p1,s0,s1) # kernel ------------------------------------------- r += 1 # pass to the next row @@ -218,7 +223,7 @@ char shift_x, char shift_y,Py_ssize_t bitdepth): # kernel ------------------------------------------- out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c], - bitdepth,maxbin,midbin) + bitdepth,maxbin,midbin,p0,p1,s0,s1) # kernel ------------------------------------------- # ---> east to west @@ -240,7 +245,7 @@ char shift_x, char shift_y,Py_ssize_t bitdepth): # kernel ------------------------------------------- out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c ], - bitdepth,maxbin,midbin) + bitdepth,maxbin,midbin,p0,p1,s0,s1) # kernel ------------------------------------------- r += 1 # pass to the next row @@ -265,7 +270,7 @@ char shift_x, char shift_y,Py_ssize_t bitdepth): # kernel ------------------------------------------- out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c ], - bitdepth,maxbin,midbin) + bitdepth,maxbin,midbin,p0,p1,s0,s1) # kernel ------------------------------------------- # release memory allocated by malloc diff --git a/skimage/rank/_core8.pxd b/skimage/rank/_core8.pxd index c0ac709d..a677e915 100644 --- a/skimage/rank/_core8.pxd +++ b/skimage/rank/_core8.pxd @@ -9,9 +9,9 @@ cdef inline np.uint8_t uint8_min(np.uint8_t a, np.uint8_t b) #--------------------------------------------------------------------------- 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) + np.ndarray[np.uint8_t, ndim=2] image, + np.ndarray[np.uint8_t, ndim=2] selem, + np.ndarray[np.uint8_t, ndim=2] mask, + np.ndarray[np.uint8_t, ndim=2] out, + char shift_x, char shift_y, float p0, float p1, Py_ssize_t s0, Py_ssize_t s1) diff --git a/skimage/rank/_core8.pyx b/skimage/rank/_core8.pyx index 3ffbb5b9..87588813 100644 --- a/skimage/rank/_core8.pyx +++ b/skimage/rank/_core8.pyx @@ -37,11 +37,11 @@ cdef inline np.uint8_t is_in_mask(Py_ssize_t rows, Py_ssize_t cols,Py_ssize_t r, 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): + 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 diff --git a/skimage/rank/_crank16.pyx b/skimage/rank/_crank16.pyx index eb08326b..2fdda1e3 100644 --- a/skimage/rank/_crank16.pyx +++ b/skimage/rank/_crank16.pyx @@ -21,7 +21,9 @@ from _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): +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: @@ -39,7 +41,9 @@ cdef inline np.uint16_t kernel_autolevel(Py_ssize_t* histo, float pop, np.uint16 else: return (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): +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): @@ -49,7 +53,9 @@ cdef inline np.uint16_t kernel_bottomhat(Py_ssize_t* histo, float pop, np.uint16 return (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): +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. @@ -63,7 +69,9 @@ cdef inline np.uint16_t kernel_equalize(Py_ssize_t* histo, float pop, np.uint16_ else: return (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): +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: @@ -79,7 +87,9 @@ cdef inline np.uint16_t kernel_gradient(Py_ssize_t* histo, float pop, np.uint16_ else: return (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): +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: @@ -89,7 +99,9 @@ cdef inline np.uint16_t kernel_maximum(Py_ssize_t* histo, float pop, np.uint16_t return (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): +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. @@ -100,7 +112,9 @@ cdef inline np.uint16_t kernel_mean(Py_ssize_t* histo, float pop, np.uint16_t g, else: return (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): +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. @@ -111,7 +125,9 @@ cdef inline np.uint16_t kernel_meansubstraction(Py_ssize_t* histo, float pop, np else: return (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): +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 @@ -124,7 +140,9 @@ cdef inline np.uint16_t kernel_median(Py_ssize_t* histo, float pop, np.uint16_t return (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): +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: @@ -134,7 +152,9 @@ cdef inline np.uint16_t kernel_minimum(Py_ssize_t* histo, float pop, np.uint16_t return (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): +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: @@ -146,7 +166,9 @@ cdef inline np.uint16_t kernel_modal(Py_ssize_t* histo, float pop, np.uint16_t g return (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): +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: @@ -165,10 +187,14 @@ cdef inline np.uint16_t kernel_morph_contr_enh(Py_ssize_t* histo, float pop, np. else: return (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): +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 (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): +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. @@ -179,7 +205,9 @@ cdef inline np.uint16_t kernel_threshold(Py_ssize_t* histo, float pop, np.uint16 else: return (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): +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): @@ -198,7 +226,7 @@ def autolevel(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """bottom hat """ - return _core16(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) def bottomhat(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -207,7 +235,7 @@ def bottomhat(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """bottom hat """ - return _core16(kernel_bottomhat,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_bottomhat,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) def equalize(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -216,7 +244,7 @@ def equalize(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """local egalisation of the gray level """ - return _core16(kernel_equalize,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_equalize,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) def gradient(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -225,7 +253,7 @@ def gradient(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """local maximum - local minimum gray level """ - return _core16(kernel_gradient,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_gradient,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) def maximum(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -234,7 +262,7 @@ def maximum(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """local maximum gray level """ - return _core16(kernel_maximum,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_maximum,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) def mean(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -243,7 +271,7 @@ def mean(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """average gray level (clipped on uint8) """ - return _core16(kernel_mean,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_mean,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) def meansubstraction(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -252,7 +280,7 @@ def meansubstraction(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """(g - average gray level)/2+midbin (clipped on uint8) """ - return _core16(kernel_meansubstraction,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_meansubstraction,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) def median(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -261,7 +289,7 @@ def median(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """local median """ - return _core16(kernel_median,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_median,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) def minimum(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -270,7 +298,7 @@ def minimum(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """local minimum gray level """ - return _core16(kernel_minimum,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_minimum,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) def morph_contr_enh(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -279,7 +307,7 @@ def morph_contr_enh(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """morphological contrast enhancement """ - return _core16(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) def modal(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -288,7 +316,7 @@ def modal(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """local mode """ - return _core16(kernel_modal,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_modal,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) def pop(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -297,7 +325,7 @@ def pop(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """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) + return _core16(kernel_pop,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) def threshold(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -306,7 +334,7 @@ def threshold(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """returns maxbin-1 if gray level higher than local mean, 0 else """ - return _core16(kernel_threshold,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_threshold,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) def tophat(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -315,4 +343,4 @@ def tophat(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """top hat """ - return _core16(kernel_tophat,image,selem,mask,out,shift_x,shift_y,bitdepth) + return _core16(kernel_tophat,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) diff --git a/skimage/rank/_crank16_percentiles.pyx b/skimage/rank/_crank16_percentiles.pyx index 0f07196e..b270965b 100644 --- a/skimage/rank/_crank16_percentiles.pyx +++ b/skimage/rank/_crank16_percentiles.pyx @@ -7,13 +7,13 @@ import numpy as np cimport numpy as np # import main loop -from _core16p cimport _core16p,int_min,int_max +from _core16 cimport _core16,int_min,int_max # ----------------------------------------------------------------- # kernels uint16 (SOFT version using percentiles) # ----------------------------------------------------------------- -cdef inline np.uint16_t kernel_autolevel(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin, float p0, float p1): +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 if pop: @@ -40,7 +40,7 @@ cdef inline np.uint16_t kernel_autolevel(int* histo, float pop, np.uint16_t g,in return (0) -cdef inline np.uint16_t kernel_gradient(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin, float p0, float p1): +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 if pop: @@ -63,7 +63,7 @@ cdef inline np.uint16_t kernel_gradient(int* histo, float pop, np.uint16_t g,int return (0) -cdef inline np.uint16_t kernel_mean(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin, float p0, float p1): +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 if pop: @@ -83,7 +83,7 @@ cdef inline np.uint16_t kernel_mean(int* histo, float pop, np.uint16_t g,int bit else: return (0) -cdef inline np.uint16_t kernel_mean_substraction(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin, float p0, float p1): +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 if pop: @@ -102,7 +102,7 @@ cdef inline np.uint16_t kernel_mean_substraction(int* histo, float pop, np.uint1 else: return (0) -cdef inline np.uint16_t kernel_morph_contr_enh(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin, float p0, float p1): +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 if pop: @@ -130,7 +130,7 @@ cdef inline np.uint16_t kernel_morph_contr_enh(int* histo, float pop, np.uint16_ else: return (0) -cdef inline np.uint16_t kernel_percentile(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin, float p0, float p1): +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. @@ -144,7 +144,7 @@ cdef inline np.uint16_t kernel_percentile(int* histo, float pop, np.uint16_t g,i else: return (0) -cdef inline np.uint16_t kernel_pop(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin, float p0, float p1): +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 if pop: @@ -158,7 +158,7 @@ cdef inline np.uint16_t kernel_pop(int* histo, float pop, np.uint16_t g,int bitd else: return (0) -cdef inline np.uint16_t kernel_threshold(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin, float p0, float p1): +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. @@ -182,7 +182,7 @@ def autolevel(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8, float p0=0., float p1=0.): """bottom hat """ - return _core16p(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) + return _core16(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1,0,0) def gradient(np.ndarray[np.uint16_t, ndim=2] image, @@ -192,7 +192,7 @@ def gradient(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8, float p0=0., float p1=0.): """return p0,p1 percentile gradient """ - return _core16p(kernel_gradient,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) + return _core16(kernel_gradient,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1,0,0) def mean(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -201,7 +201,7 @@ def mean(np.ndarray[np.uint16_t, ndim=2] image, 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 _core16p(kernel_mean,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) + return _core16(kernel_mean,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1,0,0) def mean_substraction(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -210,7 +210,7 @@ def mean_substraction(np.ndarray[np.uint16_t, ndim=2] image, 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 _core16p(kernel_mean_substraction,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) + return _core16(kernel_mean_substraction,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1,0,0) def morph_contr_enh(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -219,7 +219,7 @@ def morph_contr_enh(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8, float p0=0., float p1=0.): """reforce contrast using percentiles """ - return _core16p(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) + return _core16(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1,0,0) def percentile(np.ndarray[np.uint16_t, ndim=2] image, @@ -229,7 +229,7 @@ def percentile(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8, float p0=0., float p1=0.): """return p0 percentile """ - return _core16p(kernel_percentile,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) + return _core16(kernel_percentile,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1,0,0) def pop(np.ndarray[np.uint16_t, ndim=2] image, @@ -239,7 +239,7 @@ def pop(np.ndarray[np.uint16_t, ndim=2] image, 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 _core16p(kernel_pop,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) + return _core16(kernel_pop,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1,0,0) def threshold(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] selem, @@ -248,4 +248,4 @@ def threshold(np.ndarray[np.uint16_t, ndim=2] image, 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 _core16p(kernel_threshold,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) + return _core16(kernel_threshold,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1,0,0) diff --git a/skimage/rank/_crank8.pyx b/skimage/rank/_crank8.pyx index 600cb00d..a0b20073 100644 --- a/skimage/rank/_crank8.pyx +++ b/skimage/rank/_crank8.pyx @@ -21,7 +21,8 @@ from _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 if pop: @@ -41,7 +42,8 @@ cdef inline np.uint8_t kernel_autolevel(Py_ssize_t* histo, float pop, np.uint8_t else: return (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 for i in range(256): @@ -51,7 +53,8 @@ cdef inline np.uint8_t kernel_bottomhat(Py_ssize_t* histo, float pop, np.uint8_t return (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. @@ -65,7 +68,8 @@ cdef inline np.uint8_t kernel_equalize(Py_ssize_t* histo, float pop, np.uint8_t else: return (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 @@ -82,7 +86,8 @@ cdef inline np.uint8_t kernel_gradient(Py_ssize_t* histo, float pop, np.uint8_t else: return (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: @@ -92,7 +97,8 @@ cdef inline np.uint8_t kernel_maximum(Py_ssize_t* histo, float pop, np.uint8_t g return (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. @@ -103,7 +109,8 @@ cdef inline np.uint8_t kernel_mean(Py_ssize_t* histo, float pop, np.uint8_t g,fl else: return (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. @@ -114,7 +121,8 @@ cdef inline np.uint8_t kernel_meansubstraction(Py_ssize_t* histo, float pop, np. else: return (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 @@ -127,7 +135,8 @@ cdef inline np.uint8_t kernel_median(Py_ssize_t* histo, float pop, np.uint8_t g, return (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: @@ -137,7 +146,8 @@ cdef inline np.uint8_t kernel_minimum(Py_ssize_t* histo, float pop, np.uint8_t g return (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 if pop: @@ -149,7 +159,8 @@ cdef inline np.uint8_t kernel_modal(Py_ssize_t* histo, float pop, np.uint8_t g,f return (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 if pop: @@ -168,10 +179,12 @@ cdef inline np.uint8_t kernel_morph_contr_enh(Py_ssize_t* histo, float pop, np.u else: return (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): return (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 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. @@ -182,7 +195,8 @@ cdef inline np.uint8_t kernel_threshold(Py_ssize_t* histo, float pop, np.uint8_t else: return (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 for i in range(255,-1,-1): From 4fd0857b87c3b74179605b48879547fb3d8bf5d2 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 16:36:08 +0200 Subject: [PATCH 61/86] delete core16p --- skimage/rank/_core16p.pxd | 16 --- skimage/rank/_core16p.pyx | 282 -------------------------------------- skimage/rank/setup.py | 3 - 3 files changed, 301 deletions(-) delete mode 100644 skimage/rank/_core16p.pxd delete mode 100644 skimage/rank/_core16p.pyx diff --git a/skimage/rank/_core16p.pxd b/skimage/rank/_core16p.pxd deleted file mode 100644 index d162540c..00000000 --- a/skimage/rank/_core16p.pxd +++ /dev/null @@ -1,16 +0,0 @@ -cimport numpy as np - -# generic cdef functions -cdef inline int int_max(int a, int b) -cdef inline int int_min(int a, int b) - -#--------------------------------------------------------------------------- -# 16 bit core kernel receives extra information about data inferior and superior percentiles -#--------------------------------------------------------------------------- - -cdef inline _core16p(np.uint16_t kernel(int*, float, np.uint16_t,int,int,int, float, float), -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,int bitdepth, float p0, float p1) \ No newline at end of file diff --git a/skimage/rank/_core16p.pyx b/skimage/rank/_core16p.pyx deleted file mode 100644 index 9e992b6b..00000000 --- a/skimage/rank/_core16p.pyx +++ /dev/null @@ -1,282 +0,0 @@ -#cython: cdivision=True -#cython: boundscheck=False -#cython: nonecheck=False -#cython: wraparound=False - -import numpy as np -cimport numpy as np -from libc.stdlib cimport malloc, free - -# 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 - -#--------------------------------------------------------------------------- -# 16 bit core kernel receives extra information about data inferior and superior percentiles -#--------------------------------------------------------------------------- - -cdef inline _core16p(np.uint16_t kernel(int*, float, np.uint16_t,int,int,int, float, float), -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,int bitdepth, float p0, float p1): - """ Main loop, this function computes the histogram for each image point - - data is uint16 - - result is uint16 casted - """ - - cdef int rows = image.shape[0] - cdef int cols = image.shape[1] - cdef int srows = selem.shape[0] - cdef int scols = selem.shape[1] - - cdef int centre_r = int(selem.shape[0] / 2) + shift_y - cdef int centre_c = int(selem.shape[1] / 2) + shift_x - - # check that structuring element center is inside the element bounding box - assert centre_r >= 0 - assert centre_c >= 0 - assert centre_r < srows - assert centre_c < scols - - assert bitdepth in range(2,13) - - 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 int maxbin=maxbin_list[bitdepth],midbin=midbin_list[bitdepth] - - assert (imageeimage.data - cdef np.uint8_t* emask_data = emask.data - - cdef np.uint16_t* out_data = out.data - cdef np.uint16_t* image_data = image.data - cdef np.uint8_t* mask_data = mask.data - - # define local variable types - cdef int r, c, rr, cc, s, value, local_max, i, even_row - cdef float pop # number of pixels actually inside the neighborhood (float) - - # allocate memory with malloc - cdef int max_se = srows*scols - - # number of element in each attack border - cdef int num_se_n, num_se_s, num_se_e, num_se_w - - # the current local histogram distribution - cdef int* histo = malloc(maxbin * sizeof(int)) - - # 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 int* se_e_r = malloc(max_se * sizeof(int)) - cdef int* se_e_c = malloc(max_se * sizeof(int)) - cdef int* se_w_r = malloc(max_se * sizeof(int)) - cdef int* se_w_c = malloc(max_se * sizeof(int)) - cdef int* se_n_r = malloc(max_se * sizeof(int)) - cdef int* se_n_c = malloc(max_se * sizeof(int)) - cdef int* se_s_r = malloc(max_se * sizeof(int)) - cdef int* se_s_c = malloc(max_se * sizeof(int)) - - # 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 - - t = np.hstack((np.zeros((selem.shape[0],1)),selem)) - t_w = np.diff(t,axis=1)==1 - - t = np.vstack((selem,np.zeros((1,selem.shape[1])))) - t_s = np.diff(t,axis=0)==-1 - - t = np.vstack((np.zeros((1,selem.shape[1])),selem)) - t_n = np.diff(t,axis=0)==1 - - num_se_n = num_se_s = num_se_e = num_se_w = 0 - - for r in range(srows): - for c in range(scols): - if t_e[r,c]: - se_e_r[num_se_e] = r - centre_r - se_e_c[num_se_e] = c - centre_c - num_se_e += 1 - if t_w[r,c]: - se_w_r[num_se_w] = r - centre_r - se_w_c[num_se_w] = c - centre_c - num_se_w += 1 - if t_n[r,c]: - se_n_r[num_se_n] = r - centre_r - se_n_c[num_se_n] = c - centre_c - num_se_n += 1 - if t_s[r,c]: - se_s_r[num_se_s] = r - centre_r - se_s_c[num_se_s] = c - centre_c - num_se_s += 1 - - # initial population and histogram - for i in range(maxbin): - histo[i] = 0 - - pop = 0 - - for r in range(srows): - for c in range(scols): - rr = r - cc = c - if selem[r, c]: - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - - r = 0 - c = 0 - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,p0,p1) - # kernel ------------------------------------------- - - # main loop - r = 0 - for even_row in range(0,rows,2): - # ---> west to east - for c in range(1,cols): - for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,p0,p1) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,p0,p1) - # kernel ------------------------------------------- - - # ---> east to west - for c in range(cols-2,-1,-1): - for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c + 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,p0,p1) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,p0,p1) - # kernel ------------------------------------------- - - # release memory allocated by malloc - - free(se_e_r) - free(se_e_c) - free(se_w_r) - free(se_w_c) - free(se_n_r) - free(se_n_c) - free(se_s_r) - free(se_s_c) - - free(histo) - - return out - - diff --git a/skimage/rank/setup.py b/skimage/rank/setup.py index 854748b8..b7cac4dc 100644 --- a/skimage/rank/setup.py +++ b/skimage/rank/setup.py @@ -14,7 +14,6 @@ def configuration(parent_package='', top_path=None): cython(['_core8.pyx'], working_path=base_path) cython(['_core16.pyx'], working_path=base_path) - cython(['_core16p.pyx'], working_path=base_path) cython(['_core16b.pyx'], working_path=base_path) cython(['_crank8.pyx'], working_path=base_path) cython(['_crank8_percentiles.pyx'], working_path=base_path) @@ -26,8 +25,6 @@ def configuration(parent_package='', top_path=None): include_dirs=[get_numpy_include_dirs()]) config.add_extension('_core16', sources=['_core16.c'], include_dirs=[get_numpy_include_dirs()]) - config.add_extension('_core16p', sources=['_core16p.c'], - include_dirs=[get_numpy_include_dirs()]) config.add_extension('_core16b', sources=['_core16b.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('_crank8', sources=['_crank8.c'], From 9079d004bbd55058546e2f3c76337c2ff6fb9131 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 16:46:41 +0200 Subject: [PATCH 62/86] grou rank16 and rank16b, remove core16b --- skimage/rank/_core16b.pxd | 12 -- skimage/rank/_core16b.pyx | 284 ---------------------------- skimage/rank/_crank16_bilateral.pyx | 10 +- skimage/rank/setup.py | 3 - skimage/rank/tests/test_suite.py | 9 + 5 files changed, 14 insertions(+), 304 deletions(-) delete mode 100644 skimage/rank/_core16b.pxd delete mode 100644 skimage/rank/_core16b.pyx diff --git a/skimage/rank/_core16b.pxd b/skimage/rank/_core16b.pxd deleted file mode 100644 index b972ae9a..00000000 --- a/skimage/rank/_core16b.pxd +++ /dev/null @@ -1,12 +0,0 @@ -cimport numpy as np - -#--------------------------------------------------------------------------- -# 16 bit core kernel receives extra information about data bitdepth and bilateral interval -#--------------------------------------------------------------------------- - -cdef inline _core16b(np.uint16_t kernel(int*, float, np.uint16_t, int ,int,int,int,int), -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,int bitdepth, int s0, int s1) \ No newline at end of file diff --git a/skimage/rank/_core16b.pyx b/skimage/rank/_core16b.pyx deleted file mode 100644 index 163662b5..00000000 --- a/skimage/rank/_core16b.pyx +++ /dev/null @@ -1,284 +0,0 @@ -""" to compile this use: ->>> python setup.py build_ext --inplace - -to generate html report use: ->>> cython -a core16b.pxd -""" - -#cython: cdivision=True -#cython: boundscheck=False -#cython: nonecheck=False -#cython: wraparound=False - -import numpy as np -cimport numpy as np -from libc.stdlib cimport malloc, free - -#--------------------------------------------------------------------------- -# 16 bit core kernel receives extra information about data bitdepth and bilateral interval -#--------------------------------------------------------------------------- - -cdef inline _core16b(np.uint16_t kernel(int*, float, np.uint16_t, int ,int,int,int,int), -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,int bitdepth, int s0, int s1): - """ Main loop, this function computes the histogram for each image point - - data is uint8 - - result is uint8 casted - - only pixel inside [s0,s1] centered on g are taken into account - """ - - cdef int rows = image.shape[0] - cdef int cols = image.shape[1] - cdef int srows = selem.shape[0] - cdef int scols = selem.shape[1] - - cdef int centre_r = int(selem.shape[0] / 2) + shift_y - cdef int centre_c = int(selem.shape[1] / 2) + shift_x - - # check that structuring element center is inside the element bounding box - assert centre_r >= 0 - assert centre_c >= 0 - assert centre_r < srows - assert centre_c < scols - assert bitdepth in range(2,13) - - 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 int maxbin=maxbin_list[bitdepth],midbin=midbin_list[bitdepth] - - assert (imageeimage.data - cdef np.uint8_t* emask_data = emask.data - - cdef np.uint16_t* out_data = out.data - cdef np.uint16_t* image_data = image.data - cdef np.uint8_t* mask_data = mask.data - - # define local variable types - cdef int r, c, rr, cc, s, value, local_max, i, even_row - cdef float pop # number of pixels actually inside the neighborhood (float) - - # allocate memory with malloc - cdef int max_se = srows*scols - - # number of element in each attack border - cdef int num_se_n, num_se_s, num_se_e, num_se_w - - # the current local histogram distribution - cdef int* histo = malloc(maxbin * sizeof(int)) - - # 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 int* se_e_r = malloc(max_se * sizeof(int)) - cdef int* se_e_c = malloc(max_se * sizeof(int)) - cdef int* se_w_r = malloc(max_se * sizeof(int)) - cdef int* se_w_c = malloc(max_se * sizeof(int)) - cdef int* se_n_r = malloc(max_se * sizeof(int)) - cdef int* se_n_c = malloc(max_se * sizeof(int)) - cdef int* se_s_r = malloc(max_se * sizeof(int)) - cdef int* se_s_c = malloc(max_se * sizeof(int)) - - # 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 - - t = np.hstack((np.zeros((selem.shape[0],1)),selem)) - t_w = np.diff(t,axis=1)==1 - - t = np.vstack((selem,np.zeros((1,selem.shape[1])))) - t_s = np.diff(t,axis=0)==-1 - - t = np.vstack((np.zeros((1,selem.shape[1])),selem)) - t_n = np.diff(t,axis=0)==1 - - num_se_n = num_se_s = num_se_e = num_se_w = 0 - - for r in range(srows): - for c in range(scols): - if t_e[r,c]: - se_e_r[num_se_e] = r - centre_r - se_e_c[num_se_e] = c - centre_c - num_se_e += 1 - if t_w[r,c]: - se_w_r[num_se_w] = r - centre_r - se_w_c[num_se_w] = c - centre_c - num_se_w += 1 - if t_n[r,c]: - se_n_r[num_se_n] = r - centre_r - se_n_c[num_se_n] = c - centre_c - num_se_n += 1 - if t_s[r,c]: - se_s_r[num_se_s] = r - centre_r - se_s_c[num_se_s] = c - centre_c - num_se_s += 1 - - # initial population and histogram - for i in range(maxbin): - histo[i] = 0 - - pop = 0 - - for r in range(srows): - for c in range(scols): - rr = r - cc = c - if selem[r, c]: - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - - r = 0 - c = 0 - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,s0,s1) - # kernel ------------------------------------------- - - # main loop - r = 0 - for even_row in range(0,rows,2): - # ---> west to east - for c in range(1,cols): - for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,s0,s1) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,s0,s1) - # kernel ------------------------------------------- - - # ---> east to west - for c in range(cols-2,-1,-1): - for s in range(num_se_w): - rr = r + se_w_r[s] + centre_r - cc = c + se_w_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_e): - rr = r + se_e_r[s] + centre_r - cc = c + se_e_c[s] + centre_c + 1 - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,s0,s1) - # kernel ------------------------------------------- - - r += 1 # pass to the next row - if r>=rows: - break - - # ---> north to south - for s in range(num_se_s): - rr = r + se_s_r[s] + centre_r - cc = c + se_s_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] += 1 - pop += 1. - for s in range(num_se_n): - rr = r + se_n_r[s] + centre_r - 1 - cc = c + se_n_c[s] + centre_c - if emask_data[rr * ecols + cc]: - value = eimage_data[rr * ecols + cc] - histo[value] -= 1 - pop -= 1. - - # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,eimage_data[(r+centre_r) * ecols + c + centre_c], - bitdepth,maxbin,midbin,s0,s1) - # kernel ------------------------------------------- - - # release memory allocated by malloc - - free(se_e_r) - free(se_e_c) - free(se_w_r) - free(se_w_c) - free(se_n_r) - free(se_n_c) - free(se_s_r) - free(se_s_c) - - free(histo) - - return out diff --git a/skimage/rank/_crank16_bilateral.pyx b/skimage/rank/_crank16_bilateral.pyx index e783d7ea..46028ad3 100644 --- a/skimage/rank/_crank16_bilateral.pyx +++ b/skimage/rank/_crank16_bilateral.pyx @@ -15,14 +15,14 @@ import numpy as np cimport numpy as np # import main loop -from _core16b cimport _core16b +from _core16 cimport _core16 # ----------------------------------------------------------------- # kernels uint16 take extra parameter for defining the bitdepth # ----------------------------------------------------------------- -cdef inline np.uint16_t kernel_mean(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin, int s0, int 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. @@ -39,7 +39,7 @@ cdef inline np.uint16_t kernel_mean(int* histo, float pop, np.uint16_t g,int bit return (0) -cdef inline np.uint16_t kernel_pop(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin, int s0, int 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 if pop: @@ -61,7 +61,7 @@ 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 _core16b(kernel_mean,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) + return _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, @@ -71,5 +71,5 @@ def pop(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, int bitdepth=8, int s0=1, int s1=1): """returns the number of actual pixels of the structuring element inside the mask """ - return _core16b(kernel_pop,image,selem,mask,out,shift_x,shift_y,bitdepth,s0,s1) + return _core16(kernel_pop,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,s0,s1) diff --git a/skimage/rank/setup.py b/skimage/rank/setup.py index b7cac4dc..e1f996f7 100644 --- a/skimage/rank/setup.py +++ b/skimage/rank/setup.py @@ -14,7 +14,6 @@ def configuration(parent_package='', top_path=None): cython(['_core8.pyx'], working_path=base_path) cython(['_core16.pyx'], working_path=base_path) - cython(['_core16b.pyx'], working_path=base_path) cython(['_crank8.pyx'], working_path=base_path) cython(['_crank8_percentiles.pyx'], working_path=base_path) cython(['_crank16.pyx'], working_path=base_path) @@ -25,8 +24,6 @@ def configuration(parent_package='', top_path=None): include_dirs=[get_numpy_include_dirs()]) config.add_extension('_core16', sources=['_core16.c'], include_dirs=[get_numpy_include_dirs()]) - config.add_extension('_core16b', sources=['_core16b.c'], - include_dirs=[get_numpy_include_dirs()]) config.add_extension('_crank8', sources=['_crank8.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('_crank8_percentiles', sources=['_crank8_percentiles.c'], diff --git a/skimage/rank/tests/test_suite.py b/skimage/rank/tests/test_suite.py index 0887fa8f..e7d2436b 100644 --- a/skimage/rank/tests/test_suite.py +++ b/skimage/rank/tests/test_suite.py @@ -104,6 +104,15 @@ class TestSequenceFunctions(unittest.TestCase): assert (loc_autolevel==loc_perc_autolevel).all() + def test_compare_autolevels_16bit(self): + image = data.camera().astype(np.uint16) + + 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() From de164ce72611eb60328ce77c635e51b8040398a6 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 16:56:36 +0200 Subject: [PATCH 63/86] find error in autolevel and percentile autolevel (16bit) --- skimage/rank/tests/demo_single.py | 5 +++-- skimage/rank/tests/test_suite.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/skimage/rank/tests/demo_single.py b/skimage/rank/tests/demo_single.py index 7ff12b28..96f1fbeb 100644 --- a/skimage/rank/tests/demo_single.py +++ b/skimage/rank/tests/demo_single.py @@ -9,11 +9,12 @@ import skimage.rank as rank if __name__ == '__main__': a8 = data.camera() - a16 = data.camera().astype(np.uint16) + a16 = data.camera().astype(np.uint16)*4 selem = disk(10) f8= rank.percentile_autolevel(a8,selem,p0=.0,p1=1.) f16= rank.autolevel(a16,selem) + f16p= rank.percentile_autolevel(a16,selem,p0=.0,p1=1.) print f8==f16 @@ -21,7 +22,7 @@ if __name__ == '__main__': plt.subplot(1,2,1) plt.imshow(f16) plt.subplot(1,2,2) - plt.imshow(f8) + plt.imshow(f16p-f16) plt.show() diff --git a/skimage/rank/tests/test_suite.py b/skimage/rank/tests/test_suite.py index e7d2436b..9ed39956 100644 --- a/skimage/rank/tests/test_suite.py +++ b/skimage/rank/tests/test_suite.py @@ -105,7 +105,7 @@ class TestSequenceFunctions(unittest.TestCase): assert (loc_autolevel==loc_perc_autolevel).all() def test_compare_autolevels_16bit(self): - image = data.camera().astype(np.uint16) + image = data.camera().astype(np.uint16)*4 selem = disk(20) loc_autolevel = rank.autolevel(image,selem=selem) From 2ce1a029245e1189861a07bb2aa5789788b6124f Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Tue, 16 Oct 2012 11:13:09 +0200 Subject: [PATCH 64/86] fix error in autolevel and percentile autolevel (16bit) --- skimage/rank/_crank16_percentiles.pyx | 2 +- skimage/rank/tests/demo_single.py | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/skimage/rank/_crank16_percentiles.pyx b/skimage/rank/_crank16_percentiles.pyx index b270965b..4fa3661c 100644 --- a/skimage/rank/_crank16_percentiles.pyx +++ b/skimage/rank/_crank16_percentiles.pyx @@ -33,7 +33,7 @@ cdef inline np.uint16_t kernel_autolevel(Py_ssize_t* histo, float pop, np.uint16 delta = imax-imin if delta>0: - return (255*(int_min(int_max(imin,g),imax)-imin)/delta) + return (1.0*(maxbin-1)*(int_min(int_max(imin,g),imax)-imin)/delta) else: return (imax-imin) else: diff --git a/skimage/rank/tests/demo_single.py b/skimage/rank/tests/demo_single.py index 96f1fbeb..b601b226 100644 --- a/skimage/rank/tests/demo_single.py +++ b/skimage/rank/tests/demo_single.py @@ -16,15 +16,22 @@ if __name__ == '__main__': f16= rank.autolevel(a16,selem) f16p= rank.percentile_autolevel(a16,selem,p0=.0,p1=1.) - print f8==f16 + print f16==f16p plt.figure() - plt.subplot(1,2,1) + plt.subplot(1,3,1) plt.imshow(f16) - plt.subplot(1,2,2) + plt.colorbar() + plt.subplot(1,3,2) + plt.imshow(f16p) + plt.colorbar() + plt.subplot(1,3,3) plt.imshow(f16p-f16) + plt.colorbar() plt.show() + print f16 + print f16p From 516cb8ffa9ced3059fedd0dd1d67f819aa8f6076 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Tue, 16 Oct 2012 12:12:28 +0200 Subject: [PATCH 65/86] add histogram_increment and decrement to core8 --- skimage/rank/_core8.pyx | 48 ++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/skimage/rank/_core8.pyx b/skimage/rank/_core8.pyx index 87588813..19e09aec 100644 --- a/skimage/rank/_core8.pyx +++ b/skimage/rank/_core8.pyx @@ -23,6 +23,14 @@ cdef inline np.uint8_t uint8_min(np.uint8_t a, np.uint8_t b): return a if a <= b # 8 bit core kernel #--------------------------------------------------------------------------- +cdef inline void histogram_increment(Py_ssize_t* histo,float *pop,np.uint8_t value): + histo[value] += 1 + pop[0] += 1. + +cdef inline void histogram_decrement(Py_ssize_t* histo,float *pop,np.uint8_t value): + 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 @@ -157,9 +165,7 @@ cdef inline _core8(np.uint8_t kernel(Py_ssize_t*, float, np.uint8_t, float, floa cc = c - centre_c if selem[r, c]: if is_in_mask(rows,cols,rr,cc,mask_data): - value = image_data[rr * cols + cc] - histo[value] += 1 - pop += 1. + histogram_increment(histo,&pop,image_data[rr * cols + cc]) r = 0 c = 0 @@ -176,16 +182,13 @@ cdef inline _core8(np.uint8_t kernel(Py_ssize_t*, float, np.uint8_t, float, floa rr = r + se_e_r[s] cc = c + se_e_c[s] if is_in_mask(rows,cols,rr,cc,mask_data): - value = image_data[rr * cols + cc] - histo[value] += 1 - pop += 1. + 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): - value = image_data[rr * cols + cc] - histo[value] -= 1 - pop -= 1. + 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) @@ -200,16 +203,13 @@ cdef inline _core8(np.uint8_t kernel(Py_ssize_t*, float, np.uint8_t, float, floa rr = r + se_s_r[s] cc = c + se_s_c[s] if is_in_mask(rows,cols,rr,cc,mask_data): - value = image_data[rr * cols + cc] - histo[value] += 1 - pop += 1. + 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): - value = image_data[rr * cols + cc] - histo[value] -= 1 - pop -= 1. + 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) @@ -221,16 +221,13 @@ cdef inline _core8(np.uint8_t kernel(Py_ssize_t*, float, np.uint8_t, float, floa rr = r + se_w_r[s] cc = c + se_w_c[s] if is_in_mask(rows,cols,rr,cc,mask_data): - value = image_data[rr * cols + cc] - histo[value] += 1 - pop += 1. + 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): - value = image_data[rr * cols + cc] - histo[value] -= 1 - pop -= 1. + 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) @@ -245,16 +242,13 @@ cdef inline _core8(np.uint8_t kernel(Py_ssize_t*, float, np.uint8_t, float, floa rr = r + se_s_r[s] cc = c + se_s_c[s] if is_in_mask(rows,cols,rr,cc,mask_data): - value = image_data[rr * cols + cc] - histo[value] += 1 - pop += 1. + 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): - value = image_data[rr * cols + cc] - histo[value] -= 1 - pop -= 1. + 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) From b35c4a6633312c3d956d059325b4805544aa8e0b Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Tue, 16 Oct 2012 12:36:05 +0200 Subject: [PATCH 66/86] add histogram_increment and decrement to core16 --- skimage/rank/_core16.pyx | 51 ++++++++++++++--------------- skimage/rank/_core8.pyx | 5 ++- skimage/rank/tests/test_suite.py | 55 ++++++++++++++++++++++++++++++-- 3 files changed, 81 insertions(+), 30 deletions(-) diff --git a/skimage/rank/_core16.pyx b/skimage/rank/_core16.pyx index 2e55aa8b..edef264b 100644 --- a/skimage/rank/_core16.pyx +++ b/skimage/rank/_core16.pyx @@ -22,6 +22,14 @@ from libc.stdlib cimport malloc, free 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): + histo[value] += 1 + pop[0] += 1. + +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 @@ -79,6 +87,9 @@ cdef inline _core16(np.uint16_t kernel(Py_ssize_t*, float, np.uint16_t,Py_ssize_ 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: @@ -165,9 +176,7 @@ cdef inline _core16(np.uint16_t kernel(Py_ssize_t*, float, np.uint16_t,Py_ssize_ cc = c - centre_c if selem[r, c]: if is_in_mask(rows,cols,rr,cc,mask_data): - value = image_data[rr * cols + cc] - histo[value] += 1 - pop += 1. + histogram_increment(histo,&pop,image_data[rr * cols + cc]) r = 0 c = 0 @@ -185,16 +194,13 @@ cdef inline _core16(np.uint16_t kernel(Py_ssize_t*, float, np.uint16_t,Py_ssize_ rr = r + se_e_r[s] cc = c + se_e_c[s] if is_in_mask(rows,cols,rr,cc,mask_data): - value = image_data[rr * cols + cc] - histo[value] += 1 - pop += 1. + 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): - value = image_data[rr * cols + cc] - histo[value] -= 1 - pop -= 1. + histogram_decrement(histo,&pop,image_data[rr * cols + cc]) # kernel ------------------------------------------- out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c ], @@ -210,16 +216,13 @@ cdef inline _core16(np.uint16_t kernel(Py_ssize_t*, float, np.uint16_t,Py_ssize_ rr = r + se_s_r[s] cc = c + se_s_c[s] if is_in_mask(rows,cols,rr,cc,mask_data): - value = image_data[rr * cols + cc] - histo[value] += 1 - pop += 1. + 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): - value = image_data[rr * cols + cc] - histo[value] -= 1 - pop -= 1. + histogram_decrement(histo,&pop,image_data[rr * cols + cc]) # kernel ------------------------------------------- out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c], @@ -232,16 +235,13 @@ cdef inline _core16(np.uint16_t kernel(Py_ssize_t*, float, np.uint16_t,Py_ssize_ rr = r + se_w_r[s] cc = c + se_w_c[s] if is_in_mask(rows,cols,rr,cc,mask_data): - value = image_data[rr * cols + cc] - histo[value] += 1 - pop += 1. + 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): - value = image_data[rr * cols + cc] - histo[value] -= 1 - pop -= 1. + histogram_decrement(histo,&pop,image_data[rr * cols + cc]) # kernel ------------------------------------------- out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c ], @@ -257,16 +257,13 @@ cdef inline _core16(np.uint16_t kernel(Py_ssize_t*, float, np.uint16_t,Py_ssize_ rr = r + se_s_r[s] cc = c + se_s_c[s] if is_in_mask(rows,cols,rr,cc,mask_data): - value = image_data[rr * cols + cc] - histo[value] += 1 - pop += 1. + 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): - value = image_data[rr * cols + cc] - histo[value] -= 1 - pop -= 1. + histogram_decrement(histo,&pop,image_data[rr * cols + cc]) # kernel ------------------------------------------- out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c ], diff --git a/skimage/rank/_core8.pyx b/skimage/rank/_core8.pyx index 19e09aec..86c40a6d 100644 --- a/skimage/rank/_core8.pyx +++ b/skimage/rank/_core8.pyx @@ -76,6 +76,9 @@ cdef inline _core8(np.uint8_t kernel(Py_ssize_t*, float, np.uint8_t, float, floa 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: @@ -183,7 +186,7 @@ cdef inline _core8(np.uint8_t kernel(Py_ssize_t*, float, np.uint8_t, float, floa 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]) - + for s in range(num_se_w): rr = r + se_w_r[s] cc = c + se_w_c[s] - 1 diff --git a/skimage/rank/tests/test_suite.py b/skimage/rank/tests/test_suite.py index 9ed39956..d0e2c319 100644 --- a/skimage/rank/tests/test_suite.py +++ b/skimage/rank/tests/test_suite.py @@ -16,6 +16,7 @@ class TestSequenceFunctions(unittest.TestCase): 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)): @@ -39,8 +40,9 @@ class TestSequenceFunctions(unittest.TestCase): 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(self): + 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): @@ -50,7 +52,21 @@ class TestSequenceFunctions(unittest.TestCase): 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) @@ -64,6 +80,8 @@ class TestSequenceFunctions(unittest.TestCase): 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) @@ -75,6 +93,8 @@ class TestSequenceFunctions(unittest.TestCase): 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') @@ -91,11 +111,37 @@ class TestSequenceFunctions(unittest.TestCase): @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) @@ -105,6 +151,9 @@ class TestSequenceFunctions(unittest.TestCase): 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) @@ -114,7 +163,9 @@ class TestSequenceFunctions(unittest.TestCase): 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 + # 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() From 64c37c4e0ca43644cda9103efb0721a9386e783e Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Tue, 16 Oct 2012 14:40:42 +0200 Subject: [PATCH 67/86] keep true test in /test, move temporary tests in local --- skimage/rank/local/__init__.py | 1 + skimage/rank/{tests => local}/demo_16bitbilateral.py | 0 skimage/rank/{tests => local}/demo_all.py | 0 skimage/rank/{tests => local}/demo_benchmark.py | 2 +- skimage/rank/{tests => local}/demo_single.py | 0 skimage/rank/{tests => local}/test_morph_contr_enh.py | 0 skimage/rank/{tests => local}/test_rank.py | 0 skimage/rank/{tests => local}/tools.py | 0 skimage/rank/tests/test_suite.py | 2 +- 9 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 skimage/rank/local/__init__.py rename skimage/rank/{tests => local}/demo_16bitbilateral.py (100%) rename skimage/rank/{tests => local}/demo_all.py (100%) rename skimage/rank/{tests => local}/demo_benchmark.py (98%) rename skimage/rank/{tests => local}/demo_single.py (100%) rename skimage/rank/{tests => local}/test_morph_contr_enh.py (100%) rename skimage/rank/{tests => local}/test_rank.py (100%) rename skimage/rank/{tests => local}/tools.py (100%) diff --git a/skimage/rank/local/__init__.py b/skimage/rank/local/__init__.py new file mode 100644 index 00000000..10b6fb15 --- /dev/null +++ b/skimage/rank/local/__init__.py @@ -0,0 +1 @@ +__author__ = 'olivier' diff --git a/skimage/rank/tests/demo_16bitbilateral.py b/skimage/rank/local/demo_16bitbilateral.py similarity index 100% rename from skimage/rank/tests/demo_16bitbilateral.py rename to skimage/rank/local/demo_16bitbilateral.py diff --git a/skimage/rank/tests/demo_all.py b/skimage/rank/local/demo_all.py similarity index 100% rename from skimage/rank/tests/demo_all.py rename to skimage/rank/local/demo_all.py diff --git a/skimage/rank/tests/demo_benchmark.py b/skimage/rank/local/demo_benchmark.py similarity index 98% rename from skimage/rank/tests/demo_benchmark.py rename to skimage/rank/local/demo_benchmark.py index c3046083..feae3a8b 100644 --- a/skimage/rank/tests/demo_benchmark.py +++ b/skimage/rank/local/demo_benchmark.py @@ -6,7 +6,7 @@ from skimage.morphology import dilation import skimage.rank as rank from skimage.filter import median_filter -from tools import log_timing +from skimage.rank.local.tools import log_timing @log_timing def cr_max(image,selem): diff --git a/skimage/rank/tests/demo_single.py b/skimage/rank/local/demo_single.py similarity index 100% rename from skimage/rank/tests/demo_single.py rename to skimage/rank/local/demo_single.py diff --git a/skimage/rank/tests/test_morph_contr_enh.py b/skimage/rank/local/test_morph_contr_enh.py similarity index 100% rename from skimage/rank/tests/test_morph_contr_enh.py rename to skimage/rank/local/test_morph_contr_enh.py diff --git a/skimage/rank/tests/test_rank.py b/skimage/rank/local/test_rank.py similarity index 100% rename from skimage/rank/tests/test_rank.py rename to skimage/rank/local/test_rank.py diff --git a/skimage/rank/tests/tools.py b/skimage/rank/local/tools.py similarity index 100% rename from skimage/rank/tests/tools.py rename to skimage/rank/local/tools.py diff --git a/skimage/rank/tests/test_suite.py b/skimage/rank/tests/test_suite.py index d0e2c319..9d2bcfea 100644 --- a/skimage/rank/tests/test_suite.py +++ b/skimage/rank/tests/test_suite.py @@ -66,7 +66,7 @@ class TestSequenceFunctions(unittest.TestCase): 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) From 6e396f8598c9ad620297aeb75aeef26cc8cc0409 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Tue, 16 Oct 2012 15:03:34 +0200 Subject: [PATCH 68/86] clean up --- doc/examples/plot_local_equalize.py | 9 +-- doc/examples/plot_local_threshold.py | 9 ++- doc/examples/plot_watershed.py | 2 +- skimage/rank/bilateral_rank.py | 14 ++-- skimage/rank/percentile_rank.py | 56 +++++++--------- skimage/rank/rank.py | 98 ++++++++++++---------------- 6 files changed, 82 insertions(+), 106 deletions(-) diff --git a/doc/examples/plot_local_equalize.py b/doc/examples/plot_local_equalize.py index ec28067d..897989f0 100644 --- a/doc/examples/plot_local_equalize.py +++ b/doc/examples/plot_local_equalize.py @@ -5,11 +5,9 @@ Local Histogram Equalization This examples enhances an image with low contrast, using a method called *local histogram equalization*, which "spreads out the most frequent intensity -values" in an image . The equalized image [1]_ has a roughly linear cumulative -distribution function for each pixel neighborhood. The local version [2]_ of the histogram -equalization emphasized every local graylevel variations. - -to be adjusted... +values" in an image . +The equalized image [1]_ has a roughly linear cumulative distribution function for each pixel neighborhood. +The local version [2]_ of the histogram equalization emphasized every local graylevel variations. .. [1] http://en.wikipedia.org/wiki/Histogram_equalization .. [2] http://en.wikipedia.org/wiki/Adaptive_histogram_equalization @@ -22,7 +20,6 @@ from skimage import exposure from skimage import rank from skimage.morphology import disk - import matplotlib.pyplot as plt import numpy as np diff --git a/doc/examples/plot_local_threshold.py b/doc/examples/plot_local_threshold.py index 01077571..c5810156 100644 --- a/doc/examples/plot_local_threshold.py +++ b/doc/examples/plot_local_threshold.py @@ -14,9 +14,12 @@ calculates thresholds in regions of size `block_size` surrounding each pixel (i.e. local neighborhoods). Each threshold value is the weighted mean of the local neighborhood minus an offset value. -Added local threshold using rank filter +An other approach is to binarize locally the image using local histogram distribution. -to be adjusted ... +rank.threshold function set pixels higher than the local mean to 1, to 0 otherwize +rank.morph_contr_enh replaces each pixel by the local minimum (or local maximum) if the +pixel gray level is more close to the local minimum (resp. by the local maximum +if the pixel gray level is more close to the local maximum). """ import matplotlib.pyplot as plt @@ -36,7 +39,7 @@ binary_global = image > global_thresh block_size = 40 binary_adaptive = threshold_adaptive(image, block_size, offset=10) -selem = disk(10) +selem = disk(20) loc_thresh = threshold(image,selem=selem) loc_morph_contr_enh = morph_contr_enh(image,selem=selem) diff --git a/doc/examples/plot_watershed.py b/doc/examples/plot_watershed.py index 9fce196f..50857b2c 100644 --- a/doc/examples/plot_watershed.py +++ b/doc/examples/plot_watershed.py @@ -26,7 +26,7 @@ See Wikipedia_ for more details on the algorithm. """ import numpy as np -e + import matplotlib.pyplot as plt from skimage.morphology import watershed, is_local_maximum diff --git a/skimage/rank/bilateral_rank.py b/skimage/rank/bilateral_rank.py index a76133a6..cde9e736 100644 --- a/skimage/rank/bilateral_rank.py +++ b/skimage/rank/bilateral_rank.py @@ -35,10 +35,9 @@ def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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). s0, s1 : int define the [s0,s1] interval to be considered for computing the value. @@ -110,10 +109,9 @@ def bilateral_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fals 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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). s0, s1 : int define the [s0,s1] interval to be considered for computing the value. diff --git a/skimage/rank/percentile_rank.py b/skimage/rank/percentile_rank.py index 6cc273e3..64f76bcb 100644 --- a/skimage/rank/percentile_rank.py +++ b/skimage/rank/percentile_rank.py @@ -47,10 +47,9 @@ def percentile_autolevel(image, selem, out=None, mask=None, shift_x=False, shift 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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. @@ -120,10 +119,9 @@ def percentile_gradient(image, selem, out=None, mask=None, shift_x=False, shift_ 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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. @@ -194,10 +192,9 @@ def percentile_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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. @@ -267,10 +264,9 @@ def percentile_mean_substraction(image, selem, out=None, mask=None, shift_x=Fals 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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. @@ -341,10 +337,9 @@ def percentile_morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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. @@ -414,10 +409,9 @@ def percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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. @@ -488,10 +482,9 @@ def percentile_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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. @@ -561,10 +554,9 @@ def percentile_threshold(image, selem, out=None, mask=None, shift_x=False, shift 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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. diff --git a/skimage/rank/rank.py b/skimage/rank/rank.py index dafe0715..9d841d76 100644 --- a/skimage/rank/rank.py +++ b/skimage/rank/rank.py @@ -44,10 +44,9 @@ def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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 ------- @@ -116,10 +115,9 @@ def bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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 ------- @@ -187,10 +185,9 @@ def equalize(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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 ------- @@ -258,10 +255,9 @@ def gradient(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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,10 +327,9 @@ def maximum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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 ------- @@ -403,10 +398,9 @@ def mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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 ------- @@ -475,10 +469,9 @@ def meansubstraction(image, selem, out=None, mask=None, shift_x=False, shift_y=F 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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 ------- @@ -547,10 +540,9 @@ def median(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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 ------- @@ -619,10 +611,9 @@ def minimum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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 ------- @@ -692,10 +683,9 @@ def modal(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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 ------- @@ -765,10 +755,9 @@ def morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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 ------- @@ -837,10 +826,9 @@ def pop(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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 ------- @@ -909,10 +897,9 @@ def threshold(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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 ------- @@ -982,10 +969,9 @@ def tophat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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 : bool - shift structuring element about center point. This only affects - eccentric structuring elements (i.e. selem with even numbered sides). - Shift is bounded to the structuring element sizes. + 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 ------- From 35ebb64c3fa5f119bbce6534d72bd9d216020985 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Tue, 16 Oct 2012 16:20:12 +0200 Subject: [PATCH 69/86] compare ndimage.percentile in demo --- skimage/rank/local/demo_benchmark.py | 75 ++++++++++++++++------------ 1 file changed, 44 insertions(+), 31 deletions(-) diff --git a/skimage/rank/local/demo_benchmark.py b/skimage/rank/local/demo_benchmark.py index feae3a8b..d3c3d00a 100644 --- a/skimage/rank/local/demo_benchmark.py +++ b/skimage/rank/local/demo_benchmark.py @@ -1,44 +1,53 @@ import numpy as np import matplotlib.pyplot as plt +import time from skimage import data -from skimage.morphology import dilation -import skimage.rank as rank +from skimage.morphology import dilation,disk from skimage.filter import median_filter +from scipy.ndimage.filters import percentile_filter +import skimage.rank as rank -from skimage.rank.local.tools import log_timing +def log_timing(func): + """ Decorator that returns both function results and execution time + (result, ms) + """ + def wrapper(*arg): + t1 = time.time() + res = func(*arg) + t2 = time.time() + ms = (t2-t1)*1000.0 + print '%s took %0.3f ms' % (func.func_name, ms) + return (res,ms) + return wrapper -@log_timing -def cr_max(image,selem): - return rank.maximum(image=image,selem = selem) @log_timing def cr_med(image,selem): return rank.median(image=image,selem = selem) -@log_timing -def cm_dil(image,selem): - return dilation(image=image,selem = selem) - @log_timing def ctmf_med(image,radius): return median_filter(image=image,radius=radius) +@log_timing +def ndi_med(image,n): + return percentile_filter(image,50,size=n*2-1) def compare_dilate(): - """comparison between + """ Comparison between - crank.maximum rankfilter implementation - cmorph.dilate cython implementation on increasing structuring element size and increasing image size """ -# a = (np.random.random((500,500))*256).astype('uint8') a = data.camera() rec = [] e_range = range(1,20,1) for r in e_range: - elem = np.ones((r,r),dtype='uint8') +# elem = np.ones((r,r),dtype='uint8') + elem = disk(r+1) # elem = (np.random.random((r,r))>.5).astype('uint8') rc,ms_rc = cr_max(a,elem) rcm,ms_rcm = cm_dil(a,elem) @@ -56,7 +65,8 @@ def compare_dilate(): plt.imshow(np.hstack((rc,rcm))) r = 9 - elem = np.ones((r,r),dtype='uint8') +# elem = np.ones((r,r),dtype='uint8') + elem = disk(r+1) rec = [] s_range = range(100,1000,100) @@ -79,7 +89,7 @@ def compare_dilate(): plt.show() def compare_median(): - """comparison between + """ Comparison between - crank.median rankfilter implementation - ctmf.median_filter filter @@ -88,47 +98,50 @@ def compare_median(): a = data.camera() rec = [] - e_range = range(2,40,4) + e_range = range(2,30,4) for r in e_range: - elem = np.ones((2*r+1,2*r+1),dtype='uint8') - # elem = (np.random.random((r,r))>.5).astype('uint8') + elem = disk(r+1) rc,ms_rc = cr_med(a,elem) rctmf,ms_rctmf = ctmf_med(a,r) - rec.append((ms_rc,ms_rctmf)) + rndi,ms_ndi = ndi_med(a,r) + rec.append((ms_rc,ms_rctmf,ms_ndi)) # check if results are identical -# assert (rc==rctmf).all() + # obviously they cannot be identical since structuring element are different (octagon<>disk) + # assert (rc==rctmf).all() rec = np.asarray(rec) plt.figure() plt.title('increasing element size') plt.plot(e_range,rec) - plt.legend(['rank.median','ctmf.median_filter']) - plt.figure() - plt.imshow(np.hstack((rc,rctmf))) + plt.legend(['rank.median','ctmf.median_filter','ndimage.percentile']) plt.ylabel('time (ms)') plt.xlabel('element radius') + plt.figure() + plt.imshow(np.hstack((rc,rctmf,rndi))) + plt.xlabel('rank.median vs ctmf.median_filter vs ndimage.percentile') r = 9 - elem = np.ones((r*2+1,r*2+1),dtype='uint8') + elem = disk(r+1) rec = [] - s_range = range(100,1000,100) + s_range = [100,200,500,1000,2000] for s in s_range: a = (np.random.random((s,s))*256).astype('uint8') - (rc,ms_rc) = cr_max(a,elem) + (rc,ms_rc) = cr_med(a,elem) rctmf,ms_rctmf = ctmf_med(a,r) - rec.append((ms_rc,ms_rctmf)) -# assert (rc==rcm).all() + rndi,ms_ndi = ndi_med(a,r) + rec.append((ms_rc,ms_rctmf,ms_ndi)) + # check if results are identical + # obviously they cannot be identical since structuring element are different (octagon<>disk) + # assert (rc==rctmf).all() rec = np.asarray(rec) plt.figure() plt.title('increasing image size') plt.plot(s_range,rec) - plt.legend(['rank.median','ctmf.median_filter']) - plt.figure() - plt.imshow(np.hstack((rc,rctmf))) + plt.legend(['rank.median','ctmf.median_filter','ndimage.percentile']) plt.ylabel('time (ms)') plt.xlabel('image size') From a9dac3689515a4ee74b6d7f088bab7bf46ef6cda Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Tue, 16 Oct 2012 17:03:22 +0200 Subject: [PATCH 70/86] add _apply(func8,func16,...) helper function --- skimage/rank/bilateral_rank.py | 47 ++++--- skimage/rank/percentile_rank.py | 123 +++++-------------- skimage/rank/rank.py | 209 +++++++------------------------- 3 files changed, 89 insertions(+), 290 deletions(-) diff --git a/skimage/rank/bilateral_rank.py b/skimage/rank/bilateral_rank.py index cde9e736..5fd66e21 100644 --- a/skimage/rank/bilateral_rank.py +++ b/skimage/rank/bilateral_rank.py @@ -1,4 +1,7 @@ """ + +note: 8 bit images are casted into 16 bit image here + :author: Olivier Debeir, 2012 :license: modified BSD """ @@ -16,6 +19,21 @@ import _crank16_bilateral __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 + 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) + def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False, s0=10, s1=10): """Return greyscale local bilateral_mean of an image. @@ -76,19 +94,8 @@ def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal [ 0, 0, 0, 0, 0]], dtype=uint16) """ - 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 - 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 _crank16_bilateral.mean(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,bitdepth=bitdepth+1,out=out,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): @@ -150,18 +157,6 @@ def bilateral_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fals [3, 4, 3, 4, 3]], dtype=uint16) """ - 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 - 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 _crank16_bilateral.pop(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,bitdepth=bitdepth+1,out=out,s0=s0,s1=s1) + return _apply(None, _crank16_bilateral.pop, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, s0=s0, s1=s1) diff --git a/skimage/rank/percentile_rank.py b/skimage/rank/percentile_rank.py index 64f76bcb..e7d760da 100644 --- a/skimage/rank/percentile_rank.py +++ b/skimage/rank/percentile_rank.py @@ -29,6 +29,20 @@ __all__ = ['percentile_autolevel','percentile_gradient', 'percentile_mean','percentile_mean_substraction', 'percentile_morph_contr_enh','percentile_pop'] +def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y, p0, p1): + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return func8(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) + elif image.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) + else: + raise TypeError("only uint8 and uint16 image supported!") + 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. @@ -88,18 +102,8 @@ def percentile_autolevel(image, selem, out=None, mask=None, shift_x=False, shift [ 0, 0, 0, 0, 0]], dtype=uint16) """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8_percentiles.autolevel(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16_percentiles.autolevel(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!") + + 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.): """Return greyscale local percentile_gradient of an image. @@ -160,19 +164,8 @@ def percentile_gradient(image, selem, out=None, mask=None, shift_x=False, shift_ [4095, 4095, 4095, 4095, 4095]], dtype=uint16) """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8_percentiles.gradient(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16_percentiles.gradient(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!") + 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.): """Return greyscale local mean of an image. @@ -233,18 +226,8 @@ def percentile_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa [1023, 1365, 2047, 1365, 1023]], dtype=uint16) """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8_percentiles.mean(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16_percentiles.mean(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!") + + 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.): """Return greyscale local mean_substraction of an image. @@ -305,19 +288,8 @@ def percentile_mean_substraction(image, selem, out=None, mask=None, shift_x=Fals [1536, 1365, 1024, 1365, 1536]], dtype=uint16) """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8_percentiles.mean_substraction(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16_percentiles.mean_substraction(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!") + 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.): """Return greyscale local morph_contr_enh of an image. @@ -378,18 +350,8 @@ def percentile_morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, [ 0, 0, 0, 0, 0]], dtype=uint16) """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8_percentiles.morph_contr_enh(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16_percentiles.morph_contr_enh(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!") + + 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.): """Return greyscale local percentile of an image. @@ -451,18 +413,8 @@ def percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8_percentiles.percentile(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16_percentiles.percentile(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!") + + 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.): """Return greyscale local pop of an image. @@ -523,18 +475,8 @@ def percentile_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal [4, 6, 6, 6, 4]], dtype=uint16) """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8_percentiles.pop(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16_percentiles.pop(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!") + + 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.): """Return greyscale local threshold of an image. @@ -596,16 +538,5 @@ def percentile_threshold(image, selem, out=None, mask=None, shift_x=False, shift """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8_percentiles.threshold(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16_percentiles.threshold(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!") + 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) \ No newline at end of file diff --git a/skimage/rank/rank.py b/skimage/rank/rank.py index 9d841d76..c080c291 100644 --- a/skimage/rank/rank.py +++ b/skimage/rank/rank.py @@ -26,6 +26,20 @@ import _crank16,_crank8 __all__ = ['autolevel','bottomhat','equalize','gradient','maximum','mean' ,'meansubstraction','median','minimum','modal','morph_contr_enh','pop','threshold', 'tophat'] +def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y): + selem = img_as_ubyte(selem) + if mask is not None: + mask = img_as_ubyte(mask) + if image.dtype == np.uint8: + return func8(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) + elif image.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) + else: + raise TypeError("only uint8 and uint16 image supported!") + def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Return greyscale local autolevel of an image. @@ -84,18 +98,8 @@ def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): [ 0, 0, 0, 0, 0]], dtype=uint16) """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8.autolevel(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16.autolevel(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!") + + 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): """Return greyscale local bottomhat of an image. @@ -154,18 +158,8 @@ def bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): [ 0, 4095, 4095, 4095, 0], [ 0, 0, 0, 0, 0]], dtype=uint16) """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8.bottomhat(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16.bottomhat(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!") + + 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): """Return greyscale local equalize of an image. @@ -224,18 +218,8 @@ def equalize(image, selem, out=None, mask=None, shift_x=False, shift_y=False): [2730, 4095, 4095, 4095, 2730], [3071, 2730, 2047, 2730, 3071]], dtype=uint16) """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8.equalize(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16.equalize(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!") + + 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. @@ -295,19 +279,8 @@ def gradient(image, selem, out=None, mask=None, shift_x=False, shift_y=False): [4095, 4095, 4095, 4095, 4095]], dtype=uint16) """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8.gradient(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16.gradient(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!") + 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): """Return greyscale local maximum of an image. @@ -367,18 +340,8 @@ def maximum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): [ 0, 0, 0, 0, 0]], dtype=uint16) """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8.maximum(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16.maximum(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!") + + 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): """Return greyscale local mean of an image. @@ -438,18 +401,8 @@ def mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False): [1023, 1365, 2047, 1365, 1023]], dtype=uint16) """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8.mean(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16.mean(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!") + + 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): """Return greyscale local meansubstraction of an image. @@ -509,18 +462,8 @@ def meansubstraction(image, selem, out=None, mask=None, shift_x=False, shift_y=F [1535, 1364, 1023, 1364, 1535]], dtype=uint16) """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8.meansubstraction(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16.meansubstraction(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!") + + 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. @@ -580,18 +523,8 @@ def median(image, selem, out=None, mask=None, shift_x=False, shift_y=False): [ 0, 0, 4095, 0, 0]], dtype=uint16) """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8.median(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16.median(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!") + + 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): """Return greyscale local minimum of an image. @@ -652,18 +585,8 @@ def minimum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): [ 0, 0, 0, 0, 0]], dtype=uint16) """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8.minimum(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16.minimum(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!") + + 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): """Return greyscale local modal of an image. @@ -724,18 +647,8 @@ def modal(image, selem, out=None, mask=None, shift_x=False, shift_y=False): [ 0, 0, 500, 0, 0]], dtype=uint16) """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8.modal(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16.modal(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!") + + 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): """Return greyscale local morph_contr_enh of an image. @@ -795,18 +708,8 @@ def morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa [ 0, 0, 0, 0, 0]], dtype=uint16) """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8.morph_contr_enh(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16.morph_contr_enh(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!") + + 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 greyscale local pop of an image. @@ -866,18 +769,8 @@ def pop(image, selem, out=None, mask=None, shift_x=False, shift_y=False): [4, 6, 6, 6, 4]], dtype=uint16) """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8.pop(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16.pop(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!") + + 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): """Return greyscale local threshold of an image. @@ -938,18 +831,8 @@ def threshold(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8.threshold(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16.threshold(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!") + + 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): """Return greyscale local tophat of an image. @@ -1008,18 +891,8 @@ def tophat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): [4095, 0, 0, 0, 4095], [4095, 4095, 4095, 4095, 4095]], dtype=uint16) """ - selem = img_as_ubyte(selem) - if mask is not None: - mask = img_as_ubyte(mask) - if image.dtype == np.uint8: - return _crank8.tophat(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) - elif image.dtype == np.uint16: - bitdepth = find_bitdepth(image) - if bitdepth>11: - raise ValueError("only uint16 <4096 image (12bit) supported!") - return _crank16.tophat(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!") + + return _apply(_crank8.tophat, _crank16.tophat, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) if __name__ == "__main__": import sys From b2da237e1455fa92e029a3cf164b1ee4ab3cad1f Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 17 Oct 2012 12:07:20 +0200 Subject: [PATCH 71/86] autopep8 sources --- skimage/rank/__init__.py | 2 +- skimage/rank/_core16.pxd | 7 +- skimage/rank/_core16.pyx | 150 ++++++------ skimage/rank/_core8.pxd | 4 +- skimage/rank/_core8.pyx | 131 ++++++----- skimage/rank/_crank16.pyx | 327 ++++++++++++++------------ skimage/rank/_crank16_bilateral.pyx | 45 ++-- skimage/rank/_crank16_percentiles.pyx | 212 +++++++++-------- skimage/rank/_crank8.pyx | 301 +++++++++++++----------- skimage/rank/_crank8_percentiles.pyx | 212 +++++++++-------- skimage/rank/bilateral_rank.py | 23 +- skimage/rank/generic.py | 3 +- skimage/rank/percentile_rank.py | 78 ++++-- skimage/rank/rank.py | 29 ++- skimage/rank/setup.py | 33 +-- 15 files changed, 844 insertions(+), 713 deletions(-) diff --git a/skimage/rank/__init__.py b/skimage/rank/__init__.py index 09812649..30d936db 100644 --- a/skimage/rank/__init__.py +++ b/skimage/rank/__init__.py @@ -1,3 +1,3 @@ from .rank import * from .percentile_rank import * -from .bilateral_rank import * \ No newline at end of file +from .bilateral_rank import * diff --git a/skimage/rank/_core16.pxd b/skimage/rank/_core16.pxd index f9bb47b3..a2843f76 100644 --- a/skimage/rank/_core16.pxd +++ b/skimage/rank/_core16.pxd @@ -8,10 +8,11 @@ cimport numpy as np cdef inline int int_max(int a, int b) cdef inline int int_min(int a, int b) -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), +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) \ No newline at end of file + char shift_x, char shift_y, Py_ssize_t bitdepth, + float p0, float p1, Py_ssize_t s0, Py_ssize_t s1) diff --git a/skimage/rank/_core16.pyx b/skimage/rank/_core16.pyx index edef264b..81fab0b4 100644 --- a/skimage/rank/_core16.pyx +++ b/skimage/rank/_core16.pyx @@ -19,18 +19,20 @@ from libc.stdlib cimport malloc, free #--------------------------------------------------------------------------- # 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 int int_max(int a, int b): + return a if a >= b else b +cdef inline int int_min(int a, int b): + return a if a <= b else b -cdef inline void histogram_increment(Py_ssize_t* histo,float *pop,np.uint16_t value): +cdef inline void histogram_increment(Py_ssize_t * histo, float * pop, np.uint16_t value): histo[value] += 1 pop[0] += 1. -cdef inline void histogram_decrement(Py_ssize_t* histo,float *pop,np.uint16_t value): +cdef inline void histogram_decrement(Py_ssize_t * histo, float * pop, np.uint16_t value): histo[value] -= 1 pop[0] -= 1. -cdef inline np.uint8_t is_in_mask(Py_ssize_t rows, Py_ssize_t cols,Py_ssize_t r, Py_ssize_t c,np.uint8_t* mask): +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 @@ -38,19 +40,20 @@ cdef inline np.uint8_t is_in_mask(Py_ssize_t rows, Py_ssize_t cols,Py_ssize_t r, if r < 0 or r > rows - 1 or c < 0 or c > cols - 1: return 0 else: - if mask[r*cols+c]: + if mask[r * cols + c]: return 1 else: return 0 -cdef inline _core16(np.uint16_t kernel(Py_ssize_t*, float, np.uint16_t,Py_ssize_t,Py_ssize_t,Py_ssize_t, float, float, Py_ssize_t, Py_ssize_t), +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): + 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 @@ -69,16 +72,15 @@ cdef inline _core16(np.uint16_t kernel(Py_ssize_t*, float, np.uint16_t,Py_ssize_ assert centre_c >= 0 assert centre_r < srows assert centre_c < scols - assert bitdepth in range(2,13) - - 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] + assert bitdepth in range(2, 13) + 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] + cdef Py_ssize_t maxbin = maxbin_list[bitdepth], midbin = midbin_list[bitdepth] - assert (imageout.data - cdef np.uint16_t* image_data = image.data - cdef np.uint8_t* mask_data = mask.data + cdef np.uint16_t * out_data = out.data + cdef np.uint16_t * image_data = image.data + cdef np.uint8_t * mask_data = mask.data # define local variable types cdef Py_ssize_t r, c, rr, cc, s, value, local_max, i, even_row cdef float pop # number of pixels actually inside the neighborhood (float) # allocate memory with malloc - cdef Py_ssize_t max_se = srows*scols + cdef Py_ssize_t max_se = srows * scols # number of element in each attack border cdef Py_ssize_t num_se_n, num_se_s, num_se_e, num_se_w # the current local histogram distribution - cdef Py_ssize_t* histo = malloc(maxbin * sizeof(Py_ssize_t)) + cdef Py_ssize_t * histo = malloc(maxbin * sizeof(Py_ssize_t)) # these lists contain the relative pixel row and column for each of the 4 attack borders # east, west, north and south # e.g. se_e_r lists the rows of the east structuring element border - cdef Py_ssize_t* se_e_r = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t* se_e_c = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t* se_w_r = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t* se_w_c = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t* se_n_r = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t* se_n_c = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t* se_s_r = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t* se_s_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_e_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_e_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_w_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_w_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_n_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_n_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_s_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_s_c = malloc(max_se * sizeof(Py_ssize_t)) # build attack and release borders # by using difference along axis - t = np.hstack((selem,np.zeros((selem.shape[0],1)))) - t_e = np.diff(t,axis=1)==-1 + t = np.hstack((selem, np.zeros((selem.shape[0], 1)))) + t_e = np.diff(t, axis=1) == -1 - t = np.hstack((np.zeros((selem.shape[0],1)),selem)) - t_w = np.diff(t,axis=1)==1 + t = np.hstack((np.zeros((selem.shape[0], 1)), selem)) + t_w = np.diff(t, axis=1) == 1 - t = np.vstack((selem,np.zeros((1,selem.shape[1])))) - t_s = np.diff(t,axis=0)==-1 + t = np.vstack((selem, np.zeros((1, selem.shape[1])))) + t_s = np.diff(t, axis=0) == -1 - t = np.vstack((np.zeros((1,selem.shape[1])),selem)) - t_n = np.diff(t,axis=0)==1 + t = np.vstack((np.zeros((1, selem.shape[1])), selem)) + t_n = np.diff(t, axis=0) == 1 num_se_n = num_se_s = num_se_e = num_se_w = 0 for r in range(srows): for c in range(scols): - if t_e[r,c]: + if t_e[r, c]: se_e_r[num_se_e] = r - centre_r se_e_c[num_se_e] = c - centre_c num_se_e += 1 - if t_w[r,c]: + if t_w[r, c]: se_w_r[num_se_w] = r - centre_r se_w_c[num_se_w] = c - centre_c num_se_w += 1 - if t_n[r,c]: + if t_n[r, c]: se_n_r[num_se_n] = r - centre_r se_n_c[num_se_n] = c - centre_c num_se_n += 1 - if t_s[r,c]: + if t_s[r, c]: se_s_r[num_se_s] = r - centre_r se_s_c[num_se_s] = c - centre_c num_se_s += 1 @@ -175,99 +177,101 @@ cdef inline _core16(np.uint16_t kernel(Py_ssize_t*, float, np.uint16_t,Py_ssize_ rr = r - centre_r cc = c - centre_c if selem[r, c]: - if is_in_mask(rows,cols,rr,cc,mask_data): - histogram_increment(histo,&pop,image_data[rr * cols + cc]) + if is_in_mask(rows, cols, rr, cc, mask_data): + 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], - bitdepth,maxbin,midbin,p0,p1,s0,s1) + out_data[r * cols + c] = kernel(histo, pop, image_data[r * cols + c], + bitdepth, maxbin, midbin, p0, p1, s0, s1) # kernel ------------------------------------------- # main loop r = 0 - for even_row in range(0,rows,2): + for even_row in range(0, rows, 2): # ---> west to east - for c in range(1,cols): + for c in range(1, cols): for s in range(num_se_e): rr = r + se_e_r[s] cc = c + se_e_c[s] - if is_in_mask(rows,cols,rr,cc,mask_data): - histogram_increment(histo,&pop,image_data[rr * cols + cc]) + if is_in_mask(rows, cols, rr, cc, mask_data): + 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]) + if is_in_mask(rows, cols, rr, cc, mask_data): + histogram_decrement(histo, & pop, image_data[rr * cols + cc]) # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c ], - bitdepth,maxbin,midbin,p0,p1,s0,s1) + out_data[r * cols + c] = kernel( + histo, pop, image_data[r * cols + c], + bitdepth, maxbin, midbin, p0, p1, s0, s1) # kernel ------------------------------------------- r += 1 # pass to the next row - if r>=rows: + if r >= rows: break # ---> north to south for s in range(num_se_s): rr = r + se_s_r[s] cc = c + se_s_c[s] - if is_in_mask(rows,cols,rr,cc,mask_data): - histogram_increment(histo,&pop,image_data[rr * cols + cc]) + if is_in_mask(rows, cols, rr, cc, mask_data): + 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]) + if is_in_mask(rows, cols, rr, cc, mask_data): + histogram_decrement(histo, & pop, image_data[rr * cols + cc]) # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c], - bitdepth,maxbin,midbin,p0,p1,s0,s1) + out_data[r * cols + c] = kernel(histo, pop, image_data[r * cols + c], + bitdepth, maxbin, midbin, p0, p1, s0, s1) # kernel ------------------------------------------- # ---> east to west - for c in range(cols-2,-1,-1): + for c in range(cols - 2, -1, -1): for s in range(num_se_w): rr = r + se_w_r[s] cc = c + se_w_c[s] - if is_in_mask(rows,cols,rr,cc,mask_data): - histogram_increment(histo,&pop,image_data[rr * cols + cc]) + if is_in_mask(rows, cols, rr, cc, mask_data): + 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]) + if is_in_mask(rows, cols, rr, cc, mask_data): + histogram_decrement(histo, & pop, image_data[rr * cols + cc]) # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c ], - bitdepth,maxbin,midbin,p0,p1,s0,s1) + out_data[r * cols + c] = kernel( + histo, pop, image_data[r * cols + c], + bitdepth, maxbin, midbin, p0, p1, s0, s1) # kernel ------------------------------------------- r += 1 # pass to the next row - if r>=rows: + if r >= rows: break # ---> north to south for s in range(num_se_s): rr = r + se_s_r[s] cc = c + se_s_c[s] - if is_in_mask(rows,cols,rr,cc,mask_data): - histogram_increment(histo,&pop,image_data[rr * cols + cc]) + if is_in_mask(rows, cols, rr, cc, mask_data): + 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]) + if is_in_mask(rows, cols, rr, cc, mask_data): + histogram_decrement(histo, & pop, image_data[rr * cols + cc]) # kernel ------------------------------------------- - out_data[r * cols + c] = kernel(histo,pop,image_data[r * cols + c ], - bitdepth,maxbin,midbin,p0,p1,s0,s1) + out_data[r * cols + c] = kernel(histo, pop, image_data[r * cols + c], + bitdepth, maxbin, midbin, p0, p1, s0, s1) # kernel ------------------------------------------- # release memory allocated by malloc diff --git a/skimage/rank/_core8.pxd b/skimage/rank/_core8.pxd index a677e915..1a170500 100644 --- a/skimage/rank/_core8.pxd +++ b/skimage/rank/_core8.pxd @@ -8,10 +8,10 @@ cdef inline 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 inline _core8(np.uint8_t kernel(Py_ssize_t*, float, np.uint8_t, float, float, Py_ssize_t, Py_ssize_t), +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) - diff --git a/skimage/rank/_core8.pyx b/skimage/rank/_core8.pyx index 86c40a6d..7851388d 100644 --- a/skimage/rank/_core8.pyx +++ b/skimage/rank/_core8.pyx @@ -15,23 +15,25 @@ 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 +cdef inline np.uint8_t uint8_max(np.uint8_t a, np.uint8_t b): + return a if a >= b else b +cdef inline np.uint8_t uint8_min(np.uint8_t a, np.uint8_t b): + return a if a <= b else b #--------------------------------------------------------------------------- # 8 bit core kernel #--------------------------------------------------------------------------- -cdef inline void histogram_increment(Py_ssize_t* histo,float *pop,np.uint8_t value): +cdef inline void histogram_increment(Py_ssize_t * histo, float * pop, np.uint8_t value): histo[value] += 1 pop[0] += 1. -cdef inline void histogram_decrement(Py_ssize_t* histo,float *pop,np.uint8_t value): +cdef inline void histogram_decrement(Py_ssize_t * histo, float * pop, np.uint8_t value): histo[value] -= 1 pop[0] -= 1. -cdef inline np.uint8_t is_in_mask(Py_ssize_t rows, Py_ssize_t cols,Py_ssize_t r, Py_ssize_t c,np.uint8_t* mask): +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 @@ -39,17 +41,18 @@ cdef inline np.uint8_t is_in_mask(Py_ssize_t rows, Py_ssize_t cols,Py_ssize_t r, if r < 0 or r > rows - 1 or c < 0 or c > cols - 1: return 0 else: - if mask[r*cols+c]: + if mask[r * cols + c]: return 1 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), +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): + 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 @@ -88,9 +91,9 @@ cdef inline _core8(np.uint8_t kernel(Py_ssize_t*, float, np.uint8_t, float, floa # define pointers to the data - cdef np.uint8_t* out_data = out.data - cdef np.uint8_t* image_data = image.data - cdef np.uint8_t* mask_data = mask.data + cdef np.uint8_t * out_data = out.data + cdef np.uint8_t * image_data = image.data + cdef np.uint8_t * mask_data = mask.data # define local variable types cdef Py_ssize_t r, c, rr, cc, s, value, local_max, i, even_row @@ -99,59 +102,59 @@ cdef inline _core8(np.uint8_t kernel(Py_ssize_t*, float, np.uint8_t, float, floa cdef float pop # allocate memory with malloc - cdef Py_ssize_t max_se = srows*scols + cdef Py_ssize_t max_se = srows * scols # number of element in each attack border cdef Py_ssize_t num_se_n, num_se_s, num_se_e, num_se_w # the current local histogram distribution - cdef Py_ssize_t* histo = malloc(256 * sizeof(Py_ssize_t)) + cdef Py_ssize_t * histo = malloc(256 * sizeof(Py_ssize_t)) # these lists contain the relative pixel row and column for each of the 4 attack borders # east, west, north and south # e.g. se_e_r lists the rows of the east structuring element border - cdef Py_ssize_t* se_e_r = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t* se_e_c = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t* se_w_r = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t* se_w_c = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t* se_n_r = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t* se_n_c = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t* se_s_r = malloc(max_se * sizeof(Py_ssize_t)) - cdef Py_ssize_t* se_s_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_e_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_e_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_w_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_w_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_n_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_n_c = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_s_r = malloc(max_se * sizeof(Py_ssize_t)) + cdef Py_ssize_t * se_s_c = malloc(max_se * sizeof(Py_ssize_t)) # build attack and release borders # by using difference along axis - t = np.hstack((selem,np.zeros((selem.shape[0],1)))) - t_e = np.diff(t,axis=1)==-1 + t = np.hstack((selem, np.zeros((selem.shape[0], 1)))) + t_e = np.diff(t, axis=1) == -1 - t = np.hstack((np.zeros((selem.shape[0],1)),selem)) - t_w = np.diff(t,axis=1)==1 + t = np.hstack((np.zeros((selem.shape[0], 1)), selem)) + t_w = np.diff(t, axis=1) == 1 - t = np.vstack((selem,np.zeros((1,selem.shape[1])))) - t_s = np.diff(t,axis=0)==-1 + t = np.vstack((selem, np.zeros((1, selem.shape[1])))) + t_s = np.diff(t, axis=0) == -1 - t = np.vstack((np.zeros((1,selem.shape[1])),selem)) - t_n = np.diff(t,axis=0)==1 + t = np.vstack((np.zeros((1, selem.shape[1])), selem)) + t_n = np.diff(t, axis=0) == 1 num_se_n = num_se_s = num_se_e = num_se_w = 0 for r in range(srows): for c in range(scols): - if t_e[r,c]: + if t_e[r, c]: se_e_r[num_se_e] = r - centre_r se_e_c[num_se_e] = c - centre_c num_se_e += 1 - if t_w[r,c]: + if t_w[r, c]: se_w_r[num_se_w] = r - centre_r se_w_c[num_se_w] = c - centre_c num_se_w += 1 - if t_n[r,c]: + if t_n[r, c]: se_n_r[num_se_n] = r - centre_r se_n_c[num_se_n] = c - centre_c num_se_n += 1 - if t_s[r,c]: + if t_s[r, c]: se_s_r[num_se_s] = r - centre_r se_s_c[num_se_s] = c - centre_c num_se_s += 1 @@ -167,94 +170,99 @@ cdef inline _core8(np.uint8_t kernel(Py_ssize_t*, float, np.uint8_t, float, floa rr = r - centre_r cc = c - centre_c if selem[r, c]: - if is_in_mask(rows,cols,rr,cc,mask_data): - histogram_increment(histo,&pop,image_data[rr * cols + cc]) + if is_in_mask(rows, cols, rr, cc, mask_data): + 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) + out_data[r * cols + c] = kernel(histo, pop, image_data[r * cols + + c], p0, p1, s0, s1) # kernel -------------------------------------------------------------------- # main loop r = 0 - for even_row in range(0,rows,2): + for even_row in range(0, rows, 2): # ---> west to east - for c in range(1,cols): + for c in range(1, cols): for s in range(num_se_e): rr = r + se_e_r[s] cc = c + se_e_c[s] - if is_in_mask(rows,cols,rr,cc,mask_data): - histogram_increment(histo,&pop,image_data[rr * cols + cc]) + if is_in_mask(rows, cols, rr, cc, mask_data): + 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]) + if is_in_mask(rows, cols, rr, cc, mask_data): + 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) + 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: + if r >= rows: break # ---> north to south for s in range(num_se_s): rr = r + se_s_r[s] cc = c + se_s_c[s] - if is_in_mask(rows,cols,rr,cc,mask_data): - histogram_increment(histo,&pop,image_data[rr * cols + cc]) + if is_in_mask(rows, cols, rr, cc, mask_data): + 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]) + if is_in_mask(rows, cols, rr, cc, mask_data): + 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) + 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): + for c in range(cols - 2, -1, -1): for s in range(num_se_w): rr = r + se_w_r[s] cc = c + se_w_c[s] - if is_in_mask(rows,cols,rr,cc,mask_data): - histogram_increment(histo,&pop,image_data[rr * cols + cc]) + if is_in_mask(rows, cols, rr, cc, mask_data): + 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]) + if is_in_mask(rows, cols, rr, cc, mask_data): + 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) + 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: + if r >= rows: break # ---> north to south for s in range(num_se_s): rr = r + se_s_r[s] cc = c + se_s_c[s] - if is_in_mask(rows,cols,rr,cc,mask_data): - histogram_increment(histo,&pop,image_data[rr * cols + cc]) + if is_in_mask(rows, cols, rr, cc, mask_data): + 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]) + if is_in_mask(rows, cols, rr, cc, mask_data): + 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) + out_data[r * cols + c] = kernel(histo, pop, image_data[r * + cols + c], p0, p1, s0, s1) # kernel -------------------------------------------------------------------- # release memory allocated by malloc @@ -271,4 +279,3 @@ cdef inline _core8(np.uint8_t kernel(Py_ssize_t*, float, np.uint8_t, float, floa free(histo) return out - diff --git a/skimage/rank/_crank16.pyx b/skimage/rank/_crank16.pyx index 2fdda1e3..ce8510db 100644 --- a/skimage/rank/_crank16.pyx +++ b/skimage/rank/_crank16.pyx @@ -21,13 +21,14 @@ from _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 Py_ssize_t i,imin,imax,delta +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: - for i in range(maxbin-1,-1,-1): + for i in range(maxbin - 1, -1, -1): if histo[i]: imax = i break @@ -35,47 +36,50 @@ float p0, float p1, Py_ssize_t s0, Py_ssize_t s1): if histo[i]: imin = i break - delta = imax-imin - if delta>0: - return (1.*(maxbin-1)*(g-imin)/delta) + delta = imax - imin + if delta > 0: + return < np.uint16_t > (1. * (maxbin - 1) * (g - imin) / delta) else: - return (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 (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. if pop: for i in range(maxbin): sum += histo[i] - if i>=g: + if i >= g: break - return (((maxbin-1)*sum)/pop) + return < np.uint16_t > (((maxbin - 1) * sum) / pop) else: - return (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 Py_ssize_t i,imin,imax +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: - for i in range(maxbin-1,-1,-1): + for i in range(maxbin - 1, -1, -1): if histo[i]: imax = i break @@ -83,96 +87,103 @@ float p0, float p1, Py_ssize_t s0, Py_ssize_t s1): if histo[i]: imin = i break - return (imax-imin) + return < np.uint16_t > (imax - imin) else: - return (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): + for i in range(maxbin - 1, -1, -1): if histo[i]: - return (i) + return < np.uint16_t > (i) - return (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 (mean/pop) + mean += histo[i] * i + return < np.uint16_t > (mean / pop) else: - return (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 ((g-mean/pop)/2.+(midbin-1)) + mean += histo[i] * i + return < np.uint16_t > ((g - mean / pop) / 2. + (midbin - 1)) else: - return (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 + cdef float sum = pop / 2.0 if pop: for i in range(maxbin): if histo[i]: sum -= histo[i] - if sum<0: - return (i) + if sum < 0: + return < np.uint16_t > (i) - return (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 (i) + return < np.uint16_t > (i) - return (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 Py_ssize_t hmax=0,imax=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 Py_ssize_t hmax = 0, imax = 0 if pop: for i in range(maxbin): - if histo[i]>hmax: + if histo[i] > hmax: hmax = histo[i] imax = i - return (imax) + return < np.uint16_t > (imax) - return (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 Py_ssize_t i,imin,imax +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: - for i in range(maxbin-1,-1,-1): + for i in range(maxbin - 1, -1, -1): if histo[i]: imax = i break @@ -180,80 +191,89 @@ float p0, float p1, Py_ssize_t s0, Py_ssize_t s1): if histo[i]: imin = i break - if imax-g < g-imin: - return (imax) + if imax - g < g - imin: + return < np.uint16_t > (imax) else: - return (imin) + return < np.uint16_t > (imin) else: - return (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 (pop) +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_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 (g>(mean/pop)) + mean += histo[i] * i + return < np.uint16_t > (g > (mean / pop)) else: - return (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): + for i in range(maxbin - 1, -1, -1): if histo[i]: break - return (i-g) + return < np.uint16_t > (i - g) # ----------------------------------------------------------------- # python wrappers # ----------------------------------------------------------------- + + 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, Py_ssize_t bitdepth=8): + 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): """bottom hat """ - return _core16(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) + return _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, - 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): + 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): """bottom hat """ - return _core16(kernel_bottomhat,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) + return _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, - 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): + 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): """local egalisation of the gray level """ - return _core16(kernel_equalize,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) + return _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, - 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): + 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): """local maximum - local minimum gray level """ - return _core16(kernel_gradient,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) + return _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, np.ndarray[np.uint8_t, ndim=2] selem, @@ -262,34 +282,38 @@ def maximum(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """local maximum gray level """ - return _core16(kernel_maximum,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) + return _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, - 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): + 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): """average gray level (clipped on uint8) """ - return _core16(kernel_mean,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) + return _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, - 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): + 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): """(g - average gray level)/2+midbin (clipped on uint8) """ - return _core16(kernel_meansubstraction,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) + return _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, - 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): + 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): """local median """ - return _core16(kernel_median,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) + return _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, np.ndarray[np.uint8_t, ndim=2] selem, @@ -298,49 +322,54 @@ def minimum(np.ndarray[np.uint16_t, ndim=2] image, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): """local minimum gray level """ - return _core16(kernel_minimum,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) + return _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, - 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): + 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): """morphological contrast enhancement """ - return _core16(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) + 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) + def modal(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): + 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): """local mode """ - return _core16(kernel_modal,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) + return _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, - 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): + 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): """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,0,0) + return _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, - 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): + 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): """returns maxbin-1 if gray level higher than local mean, 0 else """ - return _core16(kernel_threshold,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) + return _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, - 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): + 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): """top hat """ - return _core16(kernel_tophat,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,0,0) + return _core16(kernel_tophat, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) diff --git a/skimage/rank/_crank16_bilateral.pyx b/skimage/rank/_crank16_bilateral.pyx index 46028ad3..b5103be4 100644 --- a/skimage/rank/_crank16_bilateral.pyx +++ b/skimage/rank/_crank16_bilateral.pyx @@ -22,54 +22,53 @@ from _core16 cimport _core16 # ----------------------------------------------------------------- -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 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. if pop: for i in range(maxbin): - if (g>(i-s0)) and (g<(i+s1)): + if (g > (i - s0)) and (g < (i + s1)): bilat_pop += histo[i] - mean += histo[i]*i + mean += histo[i] * i if bilat_pop: - return (mean/bilat_pop) + return < np.uint16_t > (mean / bilat_pop) else: - return (0) + return < np.uint16_t > (0) else: - return (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 int i,bilat_pop=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 int i, bilat_pop = 0 if pop: for i in range(maxbin): - if (g>(i-s0)) and (g<(i+s1)): + if (g > (i - s0)) and (g < (i + s1)): bilat_pop += histo[i] - return (bilat_pop) + return < np.uint16_t > (bilat_pop) else: - return (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, - 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): + 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, 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) + return _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, - 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, int s0=1, int s1=1): + 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, int s0=1, int s1=1): """returns the number of actual pixels of the structuring element inside the mask """ - return _core16(kernel_pop,image,selem,mask,out,shift_x,shift_y,bitdepth,.0,.0,s0,s1) - + return _core16(kernel_pop, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, s0, s1) diff --git a/skimage/rank/_crank16_percentiles.pyx b/skimage/rank/_crank16_percentiles.pyx index 4fa3661c..527d2aed 100644 --- a/skimage/rank/_crank16_percentiles.pyx +++ b/skimage/rank/_crank16_percentiles.pyx @@ -7,64 +7,64 @@ import numpy as np cimport numpy as np # import main loop -from _core16 cimport _core16,int_min,int_max +from _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 int i,imin,imax,sum,delta +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 if pop: sum = 0 - p1 = 1.0-p1 + p1 = 1.0 - p1 for i in range(maxbin): sum += histo[i] - if sum>p0*pop: + if sum > p0 * pop: imin = i break sum = 0 - for i in range(maxbin-1,-1,-1): + for i in range(maxbin - 1, -1, -1): sum += histo[i] - if sum>p1*pop: + if sum > p1 * pop: imax = i break - delta = imax-imin - if delta>0: - return (1.0*(maxbin-1)*(int_min(int_max(imin,g),imax)-imin)/delta) + delta = imax - imin + if delta > 0: + return < np.uint16_t > (1.0 * (maxbin - 1) * (int_min(int_max(imin, g), imax) - imin) / delta) else: - return (imax-imin) + return < np.uint16_t > (imax - imin) else: - return (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 int i,imin,imax,sum,delta +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 if pop: sum = 0 - p1 = 1.0-p1 + p1 = 1.0 - p1 for i in range(maxbin): sum += histo[i] - if sum>=p0*pop: + if sum >= p0 * pop: imin = i break sum = 0 - for i in range((maxbin-1),-1,-1): + for i in range((maxbin - 1), -1, -1): sum += histo[i] - if sum>=p1*pop: + if sum >= p1 * pop: imax = i break - return (imax-imin) + return < np.uint16_t > (imax - imin) else: - return (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 int i,sum,mean,n +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 if pop: sum = 0 @@ -72,19 +72,19 @@ cdef inline np.uint16_t kernel_mean(Py_ssize_t* histo, float pop, np.uint16_t g, n = 0 for i in range(maxbin): sum += histo[i] - if (sum>=p0*pop) and (sum<=p1*pop): + if (sum >= p0 * pop) and (sum <= p1 * pop): n += histo[i] - mean += histo[i]*i + mean += histo[i] * i - if n>0: - return (1.0*mean/n) + if n > 0: + return < np.uint16_t > (1.0 * mean / n) else: - return (0) + return < np.uint16_t > (0) else: - return (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 int i,sum,mean,n +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 if pop: sum = 0 @@ -92,160 +92,166 @@ cdef inline np.uint16_t kernel_mean_substraction(Py_ssize_t* histo, float pop, n n = 0 for i in range(maxbin): sum += histo[i] - if (sum>=p0*pop) and (sum<=p1*pop): + if (sum >= p0 * pop) and (sum <= p1 * pop): n += histo[i] - mean += histo[i]*i - if n>0: - return ((g-(mean/n))*.5+midbin) + mean += histo[i] * i + if n > 0: + return < np.uint16_t > ((g - (mean / n)) * .5 + midbin) else: - return (0) + return < np.uint16_t > (0) else: - return (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 int i,imin,imax,sum,delta +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 if pop: sum = 0 - p1 = 1.0-p1 + p1 = 1.0 - p1 for i in range(maxbin): sum += histo[i] - if sum>p0*pop: + if sum > p0 * pop: imin = i break sum = 0 - for i in range((maxbin-1),-1,-1): + for i in range((maxbin - 1), -1, -1): sum += histo[i] - if sum>p1*pop: + if sum > p1 * pop: imax = i break - if g>imax: - return imax - if gimin - if imax-g < g-imin: - return imax + if g > imax: + return < np.uint16_t > imax + if g < imin: + return < np.uint16_t > imin + if imax - g < g - imin: + return < np.uint16_t > imax else: - return imin + return < np.uint16_t > imin else: - return (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. if pop: for i in range(maxbin): sum += histo[i] - if sum>=p0*pop: + if sum >= p0 * pop: break - return (i) + return < np.uint16_t > (i) else: - return (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 int i,sum,n +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 if pop: sum = 0 n = 0 for i in range(maxbin): sum += histo[i] - if (sum>=p0*pop) and (sum<=p1*pop): + if (sum >= p0 * pop) and (sum <= p1 * pop): n += histo[i] - return (n) + return < np.uint16_t > (n) else: - return (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. if pop: for i in range(maxbin): sum += histo[i] - if sum>=p0*pop: + if sum >= p0 * pop: break - return ((maxbin-1)*(g>=i)) + return < np.uint16_t > ((maxbin - 1) * (g >= i)) else: - return (0) + return < np.uint16_t > (0) # ----------------------------------------------------------------- # python wrappers # ----------------------------------------------------------------- + + 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.): + 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.): """bottom hat """ - return _core16(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1,0,0) + return _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.): + 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.): """return p0,p1 percentile gradient """ - return _core16(kernel_gradient,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1,0,0) + return _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.): + 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.): """return mean between [p0 and p1] percentiles """ - return _core16(kernel_mean,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1,0,0) + return _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.): + 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.): """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,0,0) + return _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.): + 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.): """reforce contrast using percentiles """ - return _core16(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1,0,0) + 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) 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.): + 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.): """return p0 percentile """ - return _core16(kernel_percentile,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1,0,0) + return _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.): + 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.): """return nb of pixels between [p0 and p1] """ - return _core16(kernel_pop,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1,0,0) + return _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.): + 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.): """return (maxbin-1) if g > percentile p0 """ - return _core16(kernel_threshold,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1,0,0) + return _core16(kernel_threshold, image, selem, mask, out, shift_x, shift_y, bitdepth, p0, p1, < Py_ssize_t > 0, < Py_ssize_t > 0) diff --git a/skimage/rank/_crank8.pyx b/skimage/rank/_crank8.pyx index a0b20073..94124cf7 100644 --- a/skimage/rank/_crank8.pyx +++ b/skimage/rank/_crank8.pyx @@ -21,12 +21,13 @@ from _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 Py_ssize_t i,imin,imax,delta +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 if pop: - for i in range(255,-1,-1): + for i in range(255, -1, -1): if histo[i]: imax = i break @@ -34,47 +35,49 @@ float p0, float p1, Py_ssize_t s0, Py_ssize_t s1): if histo[i]: imin = i break - delta = imax-imin - if delta>0: - return (255.*(g-imin)/delta) + delta = imax - imin + if delta > 0: + return < np.uint8_t > (255. * (g - imin) / delta) else: - return (imax-imin) + return < np.uint8_t > (imax - imin) else: - return (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 for i in range(256): if histo[i]: break - return (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. if pop: for i in range(256): sum += histo[i] - if i>=g: + if i >= g: break - return ((255*sum)/pop) + return < np.uint8_t > ((255 * sum) / pop) else: - return (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 Py_ssize_t i,imin,imax + 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 Py_ssize_t i, imin, imax if pop: - for i in range(255,-1,-1): + for i in range(255, -1, -1): if histo[i]: imax = i break @@ -82,89 +85,95 @@ float p0, float p1, Py_ssize_t s0, Py_ssize_t s1): if histo[i]: imin = i break - return (imax-imin) + return < np.uint8_t > (imax - imin) else: - return (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): + for i in range(255, -1, -1): if histo[i]: - return (i) + return < np.uint8_t > (i) - return (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. if pop: for i in range(256): - mean += histo[i]*i - return (mean/pop) + mean += histo[i] * i + return < np.uint8_t > (mean / pop) else: - return (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. if pop: for i in range(256): - mean += histo[i]*i - return ((g-mean/pop)/2.+127) + mean += histo[i] * i + return < np.uint8_t > ((g - mean / pop) / 2. + 127) else: - return (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 + cdef float sum = pop / 2.0 if pop: for i in range(256): if histo[i]: sum -= histo[i] - if sum<0: - return (i) + if sum < 0: + return < np.uint8_t > (i) - return (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 (i) + return < np.uint8_t > (i) - return (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 Py_ssize_t hmax=0,imax=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 Py_ssize_t hmax = 0, imax = 0 if pop: for i in range(256): - if histo[i]>hmax: + if histo[i] > hmax: hmax = histo[i] imax = i - return (imax) + return < np.uint8_t > (imax) - return (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 Py_ssize_t i,imin,imax +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 if pop: - for i in range(255,-1,-1): + for i in range(255, -1, -1): if histo[i]: imax = i break @@ -172,77 +181,85 @@ float p0, float p1, Py_ssize_t s0, Py_ssize_t s1): if histo[i]: imin = i break - if imax-g < g-imin: - return (imax) + if imax - g < g - imin: + return < np.uint8_t > (imax) else: - return (imin) + return < np.uint8_t > (imin) else: - return (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 (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): + 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 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. if pop: for i in range(256): - mean += histo[i]*i - return (g>(mean/pop)) + mean += histo[i] * i + return < np.uint8_t > (g > (mean / pop)) else: - return (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 - for i in range(255,-1,-1): + for i in range(255, -1, -1): if histo[i]: break - return (i-g) + return < np.uint8_t > (i - g) # ----------------------------------------------------------------- # python wrappers # ----------------------------------------------------------------- + + def autolevel(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): + 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): """bottom hat """ - return _core8(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) + return _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, - 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): + 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): """bottom hat """ - return _core8(kernel_bottomhat,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) + return _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, - 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): + 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): """local egalisation of the gray level """ - return _core8(kernel_equalize,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) + return _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, - 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): + 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): """local maximum - local minimum gray level """ - return _core8(kernel_gradient,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) + return _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, np.ndarray[np.uint8_t, ndim=2] selem, @@ -251,34 +268,38 @@ def maximum(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """local maximum gray level """ - return _core8(kernel_maximum,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) + return _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, - 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): + 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): """average gray level (clipped on uint8) """ - return _core8(kernel_mean,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) + return _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, - 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): + 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): """(g - average gray level)/2+127 (clipped on uint8) """ - return _core8(kernel_meansubstraction,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) + return _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, - 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): + 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): """local median """ - return _core8(kernel_median,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) + return _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, np.ndarray[np.uint8_t, ndim=2] selem, @@ -287,50 +308,54 @@ def minimum(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """local minimum gray level """ - return _core8(kernel_minimum,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) + return _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, - 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): + 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): """morphological contrast enhancement """ - return _core8(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y,.0,.0,0,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) + def modal(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): + 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): """local mode """ - return _core8(kernel_modal,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) + return _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, - 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): + 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): """returns the number of actual pixels of the structuring element inside the mask """ - return _core8(kernel_pop,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) + return _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, - 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): + 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): """returns 255 if gray level higher than local mean, 0 else """ - return _core8(kernel_threshold,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) + return _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, - 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): + 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): """top hat """ - return _core8(kernel_tophat,image,selem,mask,out,shift_x,shift_y,.0,.0,0,0) - + return _core8(kernel_tophat, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) diff --git a/skimage/rank/_crank8_percentiles.pyx b/skimage/rank/_crank8_percentiles.pyx index 16ad49d5..5441eac7 100644 --- a/skimage/rank/_crank8_percentiles.pyx +++ b/skimage/rank/_crank8_percentiles.pyx @@ -7,66 +7,66 @@ import numpy as np cimport numpy as np # import main loop -from _core8 cimport _core8,uint8_max,uint8_min +from _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 int i,imin,imax,sum,delta +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: sum = 0 - p1 = 1.0-p1 + p1 = 1.0 - p1 imin = 0 imax = 255 for i in range(256): sum += histo[i] - if sum>(p0*pop): + if sum > (p0 * pop): imin = i break sum = 0 - for i in range(255,-1,-1): + for i in range(255, -1, -1): sum += histo[i] - if sum>(p1*pop): + if sum > (p1 * pop): imax = i break - delta = imax-imin - if delta>0: - return (255*(uint8_min(uint8_max(imin,g),imax)-imin)/delta) + delta = imax - imin + if delta > 0: + return < np.uint8_t > (255 * (uint8_min(uint8_max(imin, g), imax) - imin) / delta) else: - return (imax-imin) + return < np.uint8_t > (imax - imin) else: - return (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 int i,imin,imax,sum,delta +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: sum = 0 - p1 = 1.0-p1 + p1 = 1.0 - p1 for i in range(256): sum += histo[i] - if sum>=p0*pop: + if sum >= p0 * pop: imin = i break sum = 0 - for i in range(255,-1,-1): + for i in range(255, -1, -1): sum += histo[i] - if sum>=p1*pop: + if sum >= p1 * pop: imax = i break - return (imax-imin) + return < np.uint8_t > (imax - imin) else: - return (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 int i,sum,mean,n +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: sum = 0 @@ -74,18 +74,18 @@ cdef inline np.uint8_t kernel_mean(Py_ssize_t* histo, float pop, np.uint8_t g, f n = 0 for i in range(256): sum += histo[i] - if (sum>=p0*pop) and (sum<=p1*pop): + if (sum >= p0 * pop) and (sum <= p1 * pop): n += histo[i] - mean += histo[i]*i - if n>0: - return (1.0*mean/n) + mean += histo[i] * i + if n > 0: + return < np.uint8_t > (1.0 * mean / n) else: - return (0) + return < np.uint8_t > (0) else: - return (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 int i,sum,mean,n +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: sum = 0 @@ -93,160 +93,166 @@ cdef inline np.uint8_t kernel_mean_substraction(Py_ssize_t* histo, float pop, np n = 0 for i in range(256): sum += histo[i] - if (sum>=p0*pop) and (sum<=p1*pop): + if (sum >= p0 * pop) and (sum <= p1 * pop): n += histo[i] - mean += histo[i]*i - if n>0: - return ((g-(mean/n))*.5+127) + mean += histo[i] * i + if n > 0: + return < np.uint8_t > ((g - (mean / n)) * .5 + 127) else: - return (0) + return < np.uint8_t > (0) else: - return (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 int i,imin,imax,sum,delta +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: sum = 0 - p1 = 1.0-p1 + p1 = 1.0 - p1 for i in range(256): sum += histo[i] - if sum>=p0*pop: + if sum >= p0 * pop: imin = i break sum = 0 - for i in range(255,-1,-1): + for i in range(255, -1, -1): sum += histo[i] - if sum>=p1*pop: + if sum >= p1 * pop: imax = i break - if g>imax: - return imax - if gimin - if imax-g < g-imin: - return imax + if g > imax: + return < np.uint8_t > imax + if g < imin: + return < np.uint8_t > imin + if imax - g < g - imin: + return < np.uint8_t > imax else: - return imin + return < np.uint8_t > imin else: - return (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. if pop: for i in range(256): sum += histo[i] - if sum>=p0*pop: + if sum >= p0 * pop: break - return (i) + return < np.uint8_t > (i) else: - return (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 int i,sum,n +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: sum = 0 n = 0 for i in range(256): sum += histo[i] - if (sum>=p0*pop) and (sum<=p1*pop): + if (sum >= p0 * pop) and (sum <= p1 * pop): n += histo[i] - return (n) + return < np.uint8_t > (n) else: - return (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. if pop: for i in range(256): sum += histo[i] - if sum>=p0*pop: + if sum >= p0 * pop: break - return (255*(g>=i)) + return < np.uint8_t > (255 * (g >= i)) else: - return (0) + return < np.uint8_t > (0) # ----------------------------------------------------------------- # python wrappers # ----------------------------------------------------------------- + + def autolevel(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, float p0=0., float p1=0.): + 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, float p0=0., float p1=0.): """autolevel """ - return _core8(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,p0,p1,0,0) + return _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, - 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, float p0=0., float p1=0.): + 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, 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,0,0) + return _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, - 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, float p0=0., float p1=0.): + 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, 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,0,0) + return _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, - 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, float p0=0., float p1=0.): + 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, 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,0,0) + return _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, - 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, float p0=0., float p1=0.): + 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, 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,0,0) + return _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, - 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, float p0=0., float p1=0.): + 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, float p0=0., float p1=0.): """return p0 percentile """ - return _core8(kernel_percentile,image,selem,mask,out,shift_x,shift_y,p0,p1,0,0) + return _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, - 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, float p0=0., float p1=0.): + 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, 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,0,0) + return _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, - 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, float p0=0., float p1=0.): + 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, 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,0,0) + return _core8(kernel_threshold, image, selem, mask, out, shift_x, shift_y, p0, p1, < Py_ssize_t > 0, < Py_ssize_t > 0) diff --git a/skimage/rank/bilateral_rank.py b/skimage/rank/bilateral_rank.py index 5fd66e21..97db8f99 100644 --- a/skimage/rank/bilateral_rank.py +++ b/skimage/rank/bilateral_rank.py @@ -17,7 +17,8 @@ from generic import find_bitdepth import _crank16_bilateral -__all__ = ['bilateral_mean','bilateral_pop'] +__all__ = ['bilateral_mean', 'bilateral_pop'] + def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y, s0, s1): selem = img_as_ubyte(selem) @@ -30,9 +31,9 @@ def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y, s0, s1): else: raise TypeError("only uint8 and uint16 image supported!") bitdepth = find_bitdepth(image) - if bitdepth>11: + 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) + return func16(image, selem, shift_x=shift_x, shift_y=shift_y, mask=mask, bitdepth=bitdepth + 1, out=out, s0=s0, s1=s1) def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False, s0=10, s1=10): @@ -69,12 +70,13 @@ def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal to be updated >>> # Local mean >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*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) - >>> bilateral_mean(ima8, square(3), s0=10,s1=10) + >>> rank.bilateral_mean(ima8, square(3), s0=10,s1=10) array([[ 0, 0, 0, 0, 0], [ 0, 255, 255, 255, 0], [ 0, 255, 255, 255, 0], @@ -86,7 +88,7 @@ def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> bilateral_mean(ima16, square(3), s0=10,s1=10) + >>> rank.bilateral_mean(ima16, square(3), s0=10,s1=10) array([[ 0, 0, 0, 0, 0], [ 0, 4095, 4095, 4095, 0], [ 0, 4095, 4095, 4095, 0], @@ -132,12 +134,13 @@ def bilateral_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fals to be updated >>> # Local mean >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*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) - >>> bilateral_pop(ima8, square(3), s0=10,s1=10) + >>> rank.bilateral_pop(ima8, square(3), s0=10,s1=10) array([[3, 4, 3, 4, 3], [4, 4, 6, 4, 4], [3, 6, 9, 6, 3], @@ -149,7 +152,7 @@ def bilateral_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fals ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> bilateral_pop(ima16, square(3), s0=10,s1=10) + >>> rank.bilateral_pop(ima16, square(3), s0=10,s1=10) array([[3, 4, 3, 4, 3], [4, 4, 6, 4, 4], [3, 6, 9, 6, 3], @@ -160,3 +163,9 @@ 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) +if __name__ == "__main__": + import sys + sys.path.append('.') + + import doctest + doctest.testmod(verbose=True) diff --git a/skimage/rank/generic.py b/skimage/rank/generic.py index e8808e5e..94fc3130 100644 --- a/skimage/rank/generic.py +++ b/skimage/rank/generic.py @@ -1,10 +1,11 @@ import numpy as np + def find_bitdepth(image): """returns the max bith depth of a uint16 image """ umax = np.max(image) - if umax>2: + if umax > 2: return int(np.log2(umax)) else: return 1 diff --git a/skimage/rank/percentile_rank.py b/skimage/rank/percentile_rank.py index e7d760da..6ceb503d 100644 --- a/skimage/rank/percentile_rank.py +++ b/skimage/rank/percentile_rank.py @@ -23,26 +23,29 @@ from skimage import img_as_ubyte import numpy as np from generic import find_bitdepth -import _crank16_percentiles,_crank8_percentiles +import _crank16_percentiles +import _crank8_percentiles + +__all__ = ['percentile_autolevel', 'percentile_gradient', + 'percentile_mean', 'percentile_mean_substraction', + 'percentile_morph_contr_enh', 'percentile', 'percentile_pop', 'percentile_threshold'] -__all__ = ['percentile_autolevel','percentile_gradient', - 'percentile_mean','percentile_mean_substraction', - 'percentile_morph_contr_enh','percentile_pop'] def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y, p0, p1): selem = img_as_ubyte(selem) if mask is not None: mask = img_as_ubyte(mask) if image.dtype == np.uint8: - return func8(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out,p0=p0,p1=p1) + return func8(image, selem, shift_x=shift_x, shift_y=shift_y, mask=mask, out=out, p0=p0, p1=p1) elif image.dtype == np.uint16: bitdepth = find_bitdepth(image) - if bitdepth>11: + 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) + return 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!") + 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. @@ -77,15 +80,16 @@ def percentile_autolevel(image, selem, out=None, mask=None, shift_x=False, shift to be updated >>> # Local mean >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*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) - >>> percentile_autolevel(ima8, square(3), p0=0.,p1=1.) + >>> rank.percentile_autolevel(ima8, square(3), p0=0.,p1=1.) array([[ 0, 0, 0, 0, 0], [ 0, 255, 255, 255, 0], - [ 0, 255, 255, 255, 0], + [ 0, 255, 0, 255, 0], [ 0, 255, 255, 255, 0], [ 0, 0, 0, 0, 0]], dtype=uint8) @@ -94,10 +98,10 @@ def percentile_autolevel(image, selem, out=None, mask=None, shift_x=False, shift ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> percentile_autolevel(ima16, square(3), p0=0.,p1=1.) + >>> rank.percentile_autolevel(ima16, square(3), p0=0.,p1=1.) array([[ 0, 0, 0, 0, 0], [ 0, 4095, 4095, 4095, 0], - [ 0, 4095, 4095, 4095, 0], + [ 0, 4095, 0, 4095, 0], [ 0, 4095, 4095, 4095, 0], [ 0, 0, 0, 0, 0]], dtype=uint16) @@ -105,6 +109,7 @@ def percentile_autolevel(image, selem, out=None, mask=None, shift_x=False, shift 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.): """Return greyscale local percentile_gradient of an image. @@ -139,12 +144,13 @@ def percentile_gradient(image, selem, out=None, mask=None, shift_x=False, shift_ to be updated >>> # Local gradient >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*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) - >>> percentile_gradient(ima8, square(3), p0=0.,p1=1.) + >>> rank.percentile_gradient(ima8, square(3), p0=0.,p1=1.) array([[255, 255, 255, 255, 255], [255, 255, 255, 255, 255], [255, 255, 255, 255, 255], @@ -156,7 +162,7 @@ def percentile_gradient(image, selem, out=None, mask=None, shift_x=False, shift_ ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> percentile_gradient(ima16, square(3), p0=0.,p1=1.) + >>> rank.percentile_gradient(ima16, square(3), p0=0.,p1=1.) array([[4095, 4095, 4095, 4095, 4095], [4095, 4095, 4095, 4095, 4095], [4095, 4095, 4095, 4095, 4095], @@ -167,6 +173,7 @@ def percentile_gradient(image, selem, out=None, mask=None, shift_x=False, shift_ 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.): """Return greyscale local mean of an image. @@ -201,12 +208,13 @@ def percentile_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa to be updated >>> # Local mean >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*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) - >>> percentile_mean(ima8, square(3),p0=0.,p1=1.) + >>> rank.percentile_mean(ima8, square(3),p0=0.,p1=1.) array([[ 63, 85, 127, 85, 63], [ 85, 113, 170, 113, 85], [127, 170, 255, 170, 127], @@ -218,7 +226,7 @@ def percentile_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> percentile_mean(ima16, square(3),p0=0.,p1=1.) + >>> rank.percentile_mean(ima16, square(3),p0=0.,p1=1.) array([[1023, 1365, 2047, 1365, 1023], [1365, 1820, 2730, 1820, 1365], [2047, 2730, 4095, 2730, 2047], @@ -229,6 +237,7 @@ def percentile_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa 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.): """Return greyscale local mean_substraction of an image. @@ -263,12 +272,13 @@ def percentile_mean_substraction(image, selem, out=None, mask=None, shift_x=Fals to be updated >>> # Local mean_substraction >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*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) - >>> percentile_mean_substraction(ima8, square(3), p0=0.,p1=1.) + >>> rank.percentile_mean_substraction(ima8, square(3), p0=0.,p1=1.) array([[ 95, 84, 63, 84, 95], [ 84, 198, 169, 198, 84], [ 63, 169, 127, 169, 63], @@ -280,7 +290,7 @@ def percentile_mean_substraction(image, selem, out=None, mask=None, shift_x=Fals ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> percentile_mean_substraction(ima16, square(3), p0=0.,p1=1.) + >>> rank.percentile_mean_substraction(ima16, square(3), p0=0.,p1=1.) array([[1536, 1365, 1024, 1365, 1536], [1365, 3185, 2730, 3185, 1365], [1024, 2730, 2048, 2730, 1024], @@ -291,6 +301,7 @@ def percentile_mean_substraction(image, selem, out=None, mask=None, shift_x=Fals 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.): """Return greyscale local morph_contr_enh of an image. @@ -325,12 +336,13 @@ def percentile_morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, to be updated >>> # Local mean >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*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) - >>> percentile_morph_contr_enh(ima8, square(3), p0=0.,p1=1.) + >>> rank.percentile_morph_contr_enh(ima8, square(3), p0=0.,p1=1.) array([[ 0, 0, 0, 0, 0], [ 0, 255, 255, 255, 0], [ 0, 255, 255, 255, 0], @@ -342,7 +354,7 @@ def percentile_morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> percentile_morph_contr_enh(ima16, square(3), p0=0.,p1=1.) + >>> rank.percentile_morph_contr_enh(ima16, square(3), p0=0.,p1=1.) array([[ 0, 0, 0, 0, 0], [ 0, 4095, 4095, 4095, 0], [ 0, 4095, 4095, 4095, 0], @@ -353,6 +365,7 @@ def percentile_morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, 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.): """Return greyscale local percentile of an image. @@ -387,12 +400,13 @@ def percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, to be updated >>> # Local mean >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 128*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) - >>> percentile(ima8, square(3), p0=0.,p1=1.) + >>> rank.percentile(ima8, square(3), p0=0.,p1=1.) array([[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], @@ -404,7 +418,7 @@ def percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> percentile(ima16, square(3), p0=0.,p1=1.) + >>> rank.percentile(ima16, square(3), p0=0.,p1=1.) array([[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], @@ -416,6 +430,7 @@ def percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, 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.): """Return greyscale local pop of an image. @@ -450,12 +465,13 @@ def percentile_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal to be updated >>> # Local mean >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*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) - >>> percentile_pop(ima8, square(3), p0=0.,p1=1.) + >>> rank.percentile_pop(ima8, square(3), p0=0.,p1=1.) array([[4, 6, 6, 6, 4], [6, 9, 9, 9, 6], [6, 9, 9, 9, 6], @@ -467,7 +483,7 @@ def percentile_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> percentile_pop(ima16, square(3), p0=0.,p1=1.) + >>> rank.percentile_pop(ima16, square(3), p0=0.,p1=1.) array([[4, 6, 6, 6, 4], [6, 9, 9, 9, 6], [6, 9, 9, 9, 6], @@ -478,6 +494,7 @@ def percentile_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal 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.): """Return greyscale local threshold of an image. @@ -512,12 +529,13 @@ def percentile_threshold(image, selem, out=None, mask=None, shift_x=False, shift to be updated >>> # Local mean >>> from skimage.morphology import square + >>> import skimage.rank as rank >>> ima8 = 255*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) - >>> percentile_threshold(ima8, square(3), p0=0.,p1=1.) + >>> rank.percentile_threshold(ima8, square(3), p0=0.,p1=1.) array([[255, 255, 255, 255, 255], [255, 255, 255, 255, 255], [255, 255, 255, 255, 255], @@ -529,7 +547,7 @@ def percentile_threshold(image, selem, out=None, mask=None, shift_x=False, shift ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], ... [0, 0, 0, 0, 0]], dtype=np.uint16) - >>> percentile_threshold(ima16, square(3), p0=0.,p1=1.) + >>> rank.percentile_threshold(ima16, square(3), p0=0.,p1=1.) array([[4095, 4095, 4095, 4095, 4095], [4095, 4095, 4095, 4095, 4095], [4095, 4095, 4095, 4095, 4095], @@ -539,4 +557,12 @@ def percentile_threshold(image, selem, out=None, mask=None, shift_x=False, shift """ - 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) \ No newline at end of file + 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) + + +if __name__ == "__main__": + import sys + sys.path.append('.') + + import doctest + doctest.testmod(verbose=True) diff --git a/skimage/rank/rank.py b/skimage/rank/rank.py index c080c291..d07c9037 100644 --- a/skimage/rank/rank.py +++ b/skimage/rank/rank.py @@ -21,25 +21,27 @@ from skimage import img_as_ubyte import numpy as np from generic import find_bitdepth -import _crank16,_crank8 +import _crank16 +import _crank8 + +__all__ = ['autolevel', 'bottomhat', 'equalize', 'gradient', 'maximum', 'mean', 'meansubstraction', 'median', 'minimum', 'modal', 'morph_contr_enh', 'pop', 'threshold', 'tophat'] -__all__ = ['autolevel','bottomhat','equalize','gradient','maximum','mean' - ,'meansubstraction','median','minimum','modal','morph_contr_enh','pop','threshold', 'tophat'] def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y): selem = img_as_ubyte(selem) if mask is not None: mask = img_as_ubyte(mask) if image.dtype == np.uint8: - return func8(image,selem,shift_x=shift_x,shift_y=shift_y,mask=mask,out=out) + return func8(image, selem, shift_x=shift_x, shift_y=shift_y, mask=mask, out=out) elif image.dtype == np.uint16: bitdepth = find_bitdepth(image) - if bitdepth>11: + 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) + return 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!") + def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Return greyscale local autolevel of an image. @@ -101,6 +103,7 @@ 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) + def bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Return greyscale local bottomhat of an image. @@ -161,6 +164,7 @@ def bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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): """Return greyscale local equalize of an image. @@ -221,6 +225,7 @@ def equalize(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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. @@ -282,6 +287,7 @@ 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) + def maximum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Return greyscale local maximum of an image. @@ -343,6 +349,7 @@ def maximum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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): """Return greyscale local mean of an image. @@ -404,6 +411,7 @@ def mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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): """Return greyscale local meansubstraction of an image. @@ -465,6 +473,7 @@ def meansubstraction(image, selem, out=None, mask=None, shift_x=False, shift_y=F 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. @@ -526,6 +535,7 @@ def median(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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): """Return greyscale local minimum of an image. @@ -588,6 +598,7 @@ def minimum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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): """Return greyscale local modal of an image. @@ -650,6 +661,7 @@ def modal(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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): """Return greyscale local morph_contr_enh of an image. @@ -711,6 +723,7 @@ def morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa 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 greyscale local pop of an image. @@ -772,6 +785,7 @@ def pop(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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): """Return greyscale local threshold of an image. @@ -834,6 +848,7 @@ def threshold(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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): """Return greyscale local tophat of an image. @@ -899,4 +914,4 @@ if __name__ == "__main__": sys.path.append('.') import doctest - doctest.testmod(verbose=True) \ No newline at end of file + doctest.testmod(verbose=True) diff --git a/skimage/rank/setup.py b/skimage/rank/setup.py index e1f996f7..c6a3dbb9 100644 --- a/skimage/rank/setup.py +++ b/skimage/rank/setup.py @@ -5,13 +5,13 @@ from skimage._build import cython base_path = os.path.abspath(os.path.dirname(__file__)) + def configuration(parent_package='', top_path=None): from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs config = Configuration('rank', parent_package, top_path) # config.add_data_dir('tests') - cython(['_core8.pyx'], working_path=base_path) cython(['_core16.pyx'], working_path=base_path) cython(['_crank8.pyx'], working_path=base_path) @@ -21,18 +21,21 @@ def configuration(parent_package='', top_path=None): cython(['_crank16_bilateral.pyx'], working_path=base_path) config.add_extension('_core8', sources=['_core8.c'], - include_dirs=[get_numpy_include_dirs()]) + include_dirs=[get_numpy_include_dirs()]) config.add_extension('_core16', sources=['_core16.c'], - include_dirs=[get_numpy_include_dirs()]) + include_dirs=[get_numpy_include_dirs()]) config.add_extension('_crank8', sources=['_crank8.c'], - include_dirs=[get_numpy_include_dirs()]) - config.add_extension('_crank8_percentiles', sources=['_crank8_percentiles.c'], + include_dirs=[get_numpy_include_dirs()]) + config.add_extension( + '_crank8_percentiles', sources=['_crank8_percentiles.c'], include_dirs=[get_numpy_include_dirs()]) config.add_extension('_crank16', sources=['_crank16.c'], + include_dirs=[get_numpy_include_dirs()]) + config.add_extension( + '_crank16_percentiles', sources=['_crank16_percentiles.c'], include_dirs=[get_numpy_include_dirs()]) - config.add_extension('_crank16_percentiles', sources=['_crank16_percentiles.c'], - include_dirs=[get_numpy_include_dirs()]) - config.add_extension('_crank16_bilateral', sources=['_crank16_bilateral.c'], + config.add_extension( + '_crank16_bilateral', sources=['_crank16_bilateral.c'], include_dirs=[get_numpy_include_dirs()]) return config @@ -40,10 +43,10 @@ def configuration(parent_package='', top_path=None): if __name__ == '__main__': from numpy.distutils.core import setup setup(maintainer='scikits-image Developers', - author='Olivier Debeir', - maintainer_email='scikits-image@googlegroups.com', - description='Rank filters', - url='https://github.com/scikits-image/scikits-image', - license='SciPy License (BSD Style)', - **(configuration(top_path='').todict()) - ) + author='Olivier Debeir', + maintainer_email='scikits-image@googlegroups.com', + description='Rank filters', + url='https://github.com/scikits-image/scikits-image', + license='SciPy License (BSD Style)', + **(configuration(top_path='').todict()) + ) From 82d20ca694c0ceb4b6ad3bbc0fb0856acbf629b9 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 18 Oct 2012 09:18:01 +0200 Subject: [PATCH 72/86] moved example to doc --- doc/examples/plot_16bitbilateral.py | 33 +++++++++++++++ .../examples/plot_benchmark_rank.py | 41 +++++++++++++++---- skimage/rank/local/demo_16bitbilateral.py | 31 -------------- 3 files changed, 65 insertions(+), 40 deletions(-) create mode 100644 doc/examples/plot_16bitbilateral.py rename skimage/rank/local/demo_benchmark.py => doc/examples/plot_benchmark_rank.py (85%) delete mode 100644 skimage/rank/local/demo_16bitbilateral.py diff --git a/doc/examples/plot_16bitbilateral.py b/doc/examples/plot_16bitbilateral.py new file mode 100644 index 00000000..f61f3c55 --- /dev/null +++ b/doc/examples/plot_16bitbilateral.py @@ -0,0 +1,33 @@ +""" +============================== +Simplified bilateral filtering +============================== + +to complete + +""" +import numpy as np +import matplotlib.pyplot as plt + +from skimage import data +from skimage.morphology import disk +import skimage.rank as rank + +a8 = (data.coins()).astype('uint8') + +a16 = (data.coins()).astype('uint16')*16 +selem = np.ones((20,20),dtype='uint8') +f1 = rank.percentile_mean(a8,selem = selem,p0=.1,p1=.9) +f2 = rank.bilateral_mean(a16,selem = selem,s0=500,s1=500) +selem = disk(50) +f3 = rank.equalize(a16,selem = selem) + +# display results +fig, axes = plt.subplots(nrows=3, figsize=(15,5)) +ax0, ax1, ax2 = axes + +ax0.imshow(np.hstack((a8,f1))) +ax1.imshow(np.hstack((a16,f2))) +ax2.imshow(np.hstack((a16,f3))) + +plt.show() diff --git a/skimage/rank/local/demo_benchmark.py b/doc/examples/plot_benchmark_rank.py similarity index 85% rename from skimage/rank/local/demo_benchmark.py rename to doc/examples/plot_benchmark_rank.py index d3c3d00a..dab2f8d4 100644 --- a/skimage/rank/local/demo_benchmark.py +++ b/doc/examples/plot_benchmark_rank.py @@ -1,3 +1,20 @@ +""" +============================== +Compare execution time for + - skimage.rank.median, + - skimage.filter import median_filter + - scipy.ndimage.filters import percentile_filter, + + and + + - skimage.cmorph.dilate + - skimage.rank.maximum + +============================== + +to complete + +""" import numpy as np import matplotlib.pyplot as plt import time @@ -17,7 +34,6 @@ def log_timing(func): res = func(*arg) t2 = time.time() ms = (t2-t1)*1000.0 - print '%s took %0.3f ms' % (func.func_name, ms) return (res,ms) return wrapper @@ -26,6 +42,14 @@ def log_timing(func): def cr_med(image,selem): return rank.median(image=image,selem = selem) +@log_timing +def cr_max(image,selem): + return rank.maximum(image=image,selem = selem) + +@log_timing +def cm_dil(image,selem): + return dilation(image=image,selem = selem) + @log_timing def ctmf_med(image,radius): return median_filter(image=image,radius=radius) @@ -46,13 +70,12 @@ def compare_dilate(): rec = [] e_range = range(1,20,1) for r in e_range: -# elem = np.ones((r,r),dtype='uint8') elem = disk(r+1) # elem = (np.random.random((r,r))>.5).astype('uint8') rc,ms_rc = cr_max(a,elem) rcm,ms_rcm = cm_dil(a,elem) rec.append((ms_rc,ms_rcm)) - # check if results are identical + # same structuring element, the results must match assert (rc==rcm).all() rec = np.asarray(rec) @@ -65,7 +88,6 @@ def compare_dilate(): plt.imshow(np.hstack((rc,rcm))) r = 9 -# elem = np.ones((r,r),dtype='uint8') elem = disk(r+1) rec = [] @@ -75,6 +97,7 @@ def compare_dilate(): (rc,ms_rc) = cr_max(a,elem) (rcm,ms_rcm) = cm_dil(a,elem) rec.append((ms_rc,ms_rcm)) + # same structuring element, the results must match assert (rc==rcm).all() rec = np.asarray(rec) @@ -86,7 +109,6 @@ def compare_dilate(): plt.figure() plt.imshow(np.hstack((rc,rcm))) - plt.show() def compare_median(): """ Comparison between @@ -145,7 +167,8 @@ def compare_median(): plt.ylabel('time (ms)') plt.xlabel('image size') - plt.show() -if __name__ == '__main__': -# compare_dilate() - compare_median() \ No newline at end of file + + +compare_dilate() +compare_median() +plt.show() diff --git a/skimage/rank/local/demo_16bitbilateral.py b/skimage/rank/local/demo_16bitbilateral.py deleted file mode 100644 index 85fd510c..00000000 --- a/skimage/rank/local/demo_16bitbilateral.py +++ /dev/null @@ -1,31 +0,0 @@ -import numpy as np -import matplotlib.pyplot as plt - -from skimage import data -from skimage.morphology import disk -import skimage.rank as rank - -if __name__ == '__main__': - a8 = (data.coins()).astype('uint8') - - a16 = (data.coins()).astype('uint16')*16 - selem = np.ones((20,20),dtype='uint8') - f1 = rank.percentile_mean(a8,selem = selem,p0=.1,p1=.9) - f2 = rank.bilateral_mean(a16,selem = selem,s0=500,s1=500) - - selem = disk(50) - f3 = rank.equalize(a16,selem = selem) - - plt.figure() - plt.imshow(np.hstack((a8,f1))) - plt.colorbar() - - plt.figure() - plt.imshow(np.hstack((a16,f2))) - plt.colorbar() - - plt.figure() - plt.imshow(np.hstack((a16,f3))) - plt.colorbar() - - plt.show() From 491f53aaa7bb5f767b872ae6afdd7b0783483431 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 18 Oct 2012 09:19:45 +0200 Subject: [PATCH 73/86] removed useless tools.py --- skimage/rank/local/tools.py | 42 ------------------------------------- 1 file changed, 42 deletions(-) delete mode 100644 skimage/rank/local/tools.py diff --git a/skimage/rank/local/tools.py b/skimage/rank/local/tools.py deleted file mode 100644 index 2fba4798..00000000 --- a/skimage/rank/local/tools.py +++ /dev/null @@ -1,42 +0,0 @@ -__author__ = 'Olivier Debeir 2021' - -import logging -import time - -def init_logger(logfilename = 'myapp.log'): - """add logger capabilities - """ - FORMAT = '%(asctime)-15s %(processName)s %(process)d %(message)s' - logging.basicConfig(filename=logfilename,format=FORMAT,filemode='wt') - logger = logging.getLogger() - logger.setLevel(logging.DEBUG) - - # create console handler and set level to debug - ch = logging.StreamHandler() - ch.setLevel(logging.DEBUG) - - # add ch to logger - logger.addHandler(ch) - logger.info('start logging in %s' % logfilename) - return logger - - -logger = logging.getLogger() - -def log_timing(func): - - def wrapper(*arg): - log_timing.level += 1 - t1 = time.time() - res = func(*arg) - t2 = time.time() - ms = (t2-t1)*1000.0 - logger.info('%s%s took %0.3f ms' % (log_timing.level*'-',func.func_name, ms)) - log_timing.level -= 1 - return (res,ms) - - return wrapper - -log_timing.level = 0 - - From 381fdf92795bf76cf4acc68d0ae5b56d0bc29f8d Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 18 Oct 2012 09:23:41 +0200 Subject: [PATCH 74/86] modify CONTRIBUTORS.txt --- CONTRIBUTORS.txt | 3 +++ skimage/rank/bilateral_rank.py | 3 --- skimage/rank/local/__init__.py | 1 - skimage/rank/percentile_rank.py | 2 -- skimage/rank/rank.py | 2 -- 5 files changed, 3 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 5f18e821..de933cfc 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -117,3 +117,6 @@ - Petter Strandmark Perimeter calculation in regionprops. + +- Olivier Debeir + Rank filters (8- and 16-bits) using sliding window. \ No newline at end of file diff --git a/skimage/rank/bilateral_rank.py b/skimage/rank/bilateral_rank.py index 97db8f99..24ccbcd0 100644 --- a/skimage/rank/bilateral_rank.py +++ b/skimage/rank/bilateral_rank.py @@ -2,11 +2,8 @@ note: 8 bit images are casted into 16 bit image here -:author: Olivier Debeir, 2012 -:license: modified BSD """ -__docformat__ = 'restructuredtext en' import warnings from skimage import img_as_ubyte diff --git a/skimage/rank/local/__init__.py b/skimage/rank/local/__init__.py index 10b6fb15..e69de29b 100644 --- a/skimage/rank/local/__init__.py +++ b/skimage/rank/local/__init__.py @@ -1 +0,0 @@ -__author__ = 'olivier' diff --git a/skimage/rank/percentile_rank.py b/skimage/rank/percentile_rank.py index 6ceb503d..2ed6f011 100644 --- a/skimage/rank/percentile_rank.py +++ b/skimage/rank/percentile_rank.py @@ -12,8 +12,6 @@ for 16 bit input images, the number of histogram bins is determined from the max result image is 8 or 16 bit with respect to the input image -:author: Olivier Debeir, 2012 -:license: modified BSD """ __docformat__ = 'restructuredtext en' diff --git a/skimage/rank/rank.py b/skimage/rank/rank.py index d07c9037..012c046f 100644 --- a/skimage/rank/rank.py +++ b/skimage/rank/rank.py @@ -10,8 +10,6 @@ for 16 bit input images, the number of histogram bins is determined from the max result image is 8 or 16 bit with respect to the input image -:author: Olivier Debeir, 2012 -:license: modified BSD """ __docformat__ = 'restructuredtext en' From 8d219d1427c5447d63f7d0145192f574701eb2df Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 18 Oct 2012 09:25:18 +0200 Subject: [PATCH 75/86] __docformat__ removed --- skimage/rank/percentile_rank.py | 1 - skimage/rank/rank.py | 1 - 2 files changed, 2 deletions(-) diff --git a/skimage/rank/percentile_rank.py b/skimage/rank/percentile_rank.py index 2ed6f011..ac19ccd6 100644 --- a/skimage/rank/percentile_rank.py +++ b/skimage/rank/percentile_rank.py @@ -14,7 +14,6 @@ result image is 8 or 16 bit with respect to the input image """ -__docformat__ = 'restructuredtext en' import warnings from skimage import img_as_ubyte diff --git a/skimage/rank/rank.py b/skimage/rank/rank.py index 012c046f..51854128 100644 --- a/skimage/rank/rank.py +++ b/skimage/rank/rank.py @@ -12,7 +12,6 @@ result image is 8 or 16 bit with respect to the input image """ -__docformat__ = 'restructuredtext en' import warnings from skimage import img_as_ubyte From e618c1d4548977efa17cc6d6353dde456a7d4f92 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 18 Oct 2012 10:00:10 +0200 Subject: [PATCH 76/86] move rank/ into filter/ --- doc/__init__.py | 1 + .../{ => applications}/plot_benchmark_rank.py | 19 +++++----- doc/examples/plot_16bitbilateral.py | 8 ++-- doc/examples/plot_lena_bilateral_denoise.py | 2 +- doc/examples/plot_local_autolevels.py | 2 +- doc/examples/plot_local_equalize.py | 2 +- doc/examples/plot_local_threshold.py | 2 +- doc/examples/plot_marked_watershed.py | 5 +-- skimage/{ => filter}/rank/README.rst | 0 skimage/{ => filter}/rank/__init__.py | 0 skimage/{ => filter}/rank/_core16.pxd | 0 skimage/{ => filter}/rank/_core16.pyx | 0 skimage/{ => filter}/rank/_core8.pxd | 0 skimage/{ => filter}/rank/_core8.pyx | 0 skimage/{ => filter}/rank/_crank16.pyx | 2 +- .../{ => filter}/rank/_crank16_bilateral.pyx | 2 +- .../rank/_crank16_percentiles.pyx | 2 +- skimage/{ => filter}/rank/_crank8.pyx | 2 +- .../{ => filter}/rank/_crank8_percentiles.pyx | 2 +- skimage/{ => filter}/rank/bilateral_rank.py | 31 ++++++++++++---- skimage/{ => filter}/rank/generic.py | 0 skimage/{ => filter}/rank/local/demo_all.py | 3 +- .../{ => filter}/rank/local/demo_single.py | 3 +- skimage/filter/rank/local/iko_pan_Ja1.tif | Bin 0 -> 129176 bytes .../rank/local/test_morph_contr_enh.py | 2 +- skimage/{ => filter}/rank/local/test_rank.py | 2 +- skimage/{ => filter}/rank/percentile_rank.py | 23 +++++------- skimage/{ => filter}/rank/rank.py | 35 ++++++++---------- skimage/{ => filter}/rank/setup.py | 0 skimage/{ => filter}/rank/tests/test_suite.py | 8 ++-- skimage/rank/local/__init__.py | 0 31 files changed, 83 insertions(+), 75 deletions(-) create mode 100644 doc/__init__.py rename doc/examples/{ => applications}/plot_benchmark_rank.py (96%) rename skimage/{ => filter}/rank/README.rst (100%) rename skimage/{ => filter}/rank/__init__.py (100%) rename skimage/{ => filter}/rank/_core16.pxd (100%) rename skimage/{ => filter}/rank/_core16.pyx (100%) rename skimage/{ => filter}/rank/_core8.pxd (100%) rename skimage/{ => filter}/rank/_core8.pyx (100%) rename skimage/{ => filter}/rank/_crank16.pyx (99%) rename skimage/{ => filter}/rank/_crank16_bilateral.pyx (98%) rename skimage/{ => filter}/rank/_crank16_percentiles.pyx (99%) rename skimage/{ => filter}/rank/_crank8.pyx (99%) rename skimage/{ => filter}/rank/_crank8_percentiles.pyx (99%) rename skimage/{ => filter}/rank/bilateral_rank.py (85%) rename skimage/{ => filter}/rank/generic.py (100%) rename skimage/{ => filter}/rank/local/demo_all.py (98%) rename skimage/{ => filter}/rank/local/demo_single.py (92%) create mode 100644 skimage/filter/rank/local/iko_pan_Ja1.tif rename skimage/{ => filter}/rank/local/test_morph_contr_enh.py (93%) rename skimage/{ => filter}/rank/local/test_rank.py (95%) rename skimage/{ => filter}/rank/percentile_rank.py (98%) rename skimage/{ => filter}/rank/rank.py (98%) rename skimage/{ => filter}/rank/setup.py (100%) rename skimage/{ => filter}/rank/tests/test_suite.py (97%) delete mode 100644 skimage/rank/local/__init__.py diff --git a/doc/__init__.py b/doc/__init__.py new file mode 100644 index 00000000..10b6fb15 --- /dev/null +++ b/doc/__init__.py @@ -0,0 +1 @@ +__author__ = 'olivier' diff --git a/doc/examples/plot_benchmark_rank.py b/doc/examples/applications/plot_benchmark_rank.py similarity index 96% rename from doc/examples/plot_benchmark_rank.py rename to doc/examples/applications/plot_benchmark_rank.py index dab2f8d4..79357768 100644 --- a/doc/examples/plot_benchmark_rank.py +++ b/doc/examples/applications/plot_benchmark_rank.py @@ -19,13 +19,14 @@ import numpy as np import matplotlib.pyplot as plt import time +from scipy.ndimage.filters import percentile_filter + from skimage import data from skimage.morphology import dilation,disk from skimage.filter import median_filter -from scipy.ndimage.filters import percentile_filter -import skimage.rank as rank +import skimage.filter.rank as rank -def log_timing(func): +def exec_and_timeit(func): """ Decorator that returns both function results and execution time (result, ms) """ @@ -38,23 +39,23 @@ def log_timing(func): return wrapper -@log_timing +@exec_and_timeit def cr_med(image,selem): return rank.median(image=image,selem = selem) -@log_timing +@exec_and_timeit def cr_max(image,selem): return rank.maximum(image=image,selem = selem) -@log_timing +@exec_and_timeit def cm_dil(image,selem): return dilation(image=image,selem = selem) -@log_timing +@exec_and_timeit def ctmf_med(image,radius): return median_filter(image=image,radius=radius) -@log_timing +@exec_and_timeit def ndi_med(image,n): return percentile_filter(image,50,size=n*2-1) @@ -84,8 +85,6 @@ def compare_dilate(): plt.title('increasing element size') plt.plot(e_range,rec) plt.legend(['crank.maximum','cmorph.dilate']) - plt.figure() - plt.imshow(np.hstack((rc,rcm))) r = 9 elem = disk(r+1) diff --git a/doc/examples/plot_16bitbilateral.py b/doc/examples/plot_16bitbilateral.py index f61f3c55..076d03c4 100644 --- a/doc/examples/plot_16bitbilateral.py +++ b/doc/examples/plot_16bitbilateral.py @@ -11,7 +11,7 @@ import matplotlib.pyplot as plt from skimage import data from skimage.morphology import disk -import skimage.rank as rank +import skimage.filter.rank as rank a8 = (data.coins()).astype('uint8') @@ -23,11 +23,13 @@ selem = disk(50) f3 = rank.equalize(a16,selem = selem) # display results -fig, axes = plt.subplots(nrows=3, figsize=(15,5)) +fig, axes = plt.subplots(nrows=3, figsize=(15,15)) ax0, ax1, ax2 = axes ax0.imshow(np.hstack((a8,f1))) +ax0.set_title('percentile mean') ax1.imshow(np.hstack((a16,f2))) +ax1.set_title('bilateral mean') ax2.imshow(np.hstack((a16,f3))) - +ax2.set_title('local equalization') plt.show() diff --git a/doc/examples/plot_lena_bilateral_denoise.py b/doc/examples/plot_lena_bilateral_denoise.py index 57593867..969403d0 100644 --- a/doc/examples/plot_lena_bilateral_denoise.py +++ b/doc/examples/plot_lena_bilateral_denoise.py @@ -18,7 +18,7 @@ import numpy as np import matplotlib.pyplot as plt from skimage import data, color, img_as_ubyte -from skimage.rank import bilateral_mean +from skimage.filter.rank import bilateral_mean from skimage.morphology import disk l = img_as_ubyte(color.rgb2gray(data.lena())) diff --git a/doc/examples/plot_local_autolevels.py b/doc/examples/plot_local_autolevels.py index 842215d5..7c750141 100644 --- a/doc/examples/plot_local_autolevels.py +++ b/doc/examples/plot_local_autolevels.py @@ -13,7 +13,7 @@ import numpy as np from skimage import data -from skimage.rank import percentile_autolevel,autolevel +from skimage.filter.rank import percentile_autolevel,autolevel from skimage.morphology import disk diff --git a/doc/examples/plot_local_equalize.py b/doc/examples/plot_local_equalize.py index 897989f0..1a431f5c 100644 --- a/doc/examples/plot_local_equalize.py +++ b/doc/examples/plot_local_equalize.py @@ -17,12 +17,12 @@ The local version [2]_ of the histogram equalization emphasized every local gray from skimage import data from skimage.util.dtype import dtype_range from skimage import exposure -from skimage import rank from skimage.morphology import disk import matplotlib.pyplot as plt import numpy as np +from skimage.filter import rank def plot_img_and_hist(img, axes, bins=256): """Plot an image along with its histogram and cumulative histogram. diff --git a/doc/examples/plot_local_threshold.py b/doc/examples/plot_local_threshold.py index c5810156..8bc79b30 100644 --- a/doc/examples/plot_local_threshold.py +++ b/doc/examples/plot_local_threshold.py @@ -27,7 +27,7 @@ import matplotlib.pyplot as plt from skimage import data from skimage.filter import threshold_otsu, threshold_adaptive -from skimage.rank import threshold,morph_contr_enh +from skimage.filter.rank import threshold,morph_contr_enh from skimage.morphology import disk diff --git a/doc/examples/plot_marked_watershed.py b/doc/examples/plot_marked_watershed.py index 0be25007..738a3d24 100644 --- a/doc/examples/plot_marked_watershed.py +++ b/doc/examples/plot_marked_watershed.py @@ -14,15 +14,14 @@ See Wikipedia_ for more details on the algorithm. """ -import numpy as np from scipy import ndimage import matplotlib.pyplot as plt from skimage.morphology import watershed,disk -from skimage import rank from skimage import data -from scipy import ndimage # original data +from skimage.filter import rank + image = data.camera() # denoise image diff --git a/skimage/rank/README.rst b/skimage/filter/rank/README.rst similarity index 100% rename from skimage/rank/README.rst rename to skimage/filter/rank/README.rst diff --git a/skimage/rank/__init__.py b/skimage/filter/rank/__init__.py similarity index 100% rename from skimage/rank/__init__.py rename to skimage/filter/rank/__init__.py diff --git a/skimage/rank/_core16.pxd b/skimage/filter/rank/_core16.pxd similarity index 100% rename from skimage/rank/_core16.pxd rename to skimage/filter/rank/_core16.pxd diff --git a/skimage/rank/_core16.pyx b/skimage/filter/rank/_core16.pyx similarity index 100% rename from skimage/rank/_core16.pyx rename to skimage/filter/rank/_core16.pyx diff --git a/skimage/rank/_core8.pxd b/skimage/filter/rank/_core8.pxd similarity index 100% rename from skimage/rank/_core8.pxd rename to skimage/filter/rank/_core8.pxd diff --git a/skimage/rank/_core8.pyx b/skimage/filter/rank/_core8.pyx similarity index 100% rename from skimage/rank/_core8.pyx rename to skimage/filter/rank/_core8.pyx diff --git a/skimage/rank/_crank16.pyx b/skimage/filter/rank/_crank16.pyx similarity index 99% rename from skimage/rank/_crank16.pyx rename to skimage/filter/rank/_crank16.pyx index ce8510db..57d41563 100644 --- a/skimage/rank/_crank16.pyx +++ b/skimage/filter/rank/_crank16.pyx @@ -15,7 +15,7 @@ import numpy as np cimport numpy as np # import main loop -from _core16 cimport _core16 +from skimage.filter.rank._core16 cimport _core16 # ----------------------------------------------------------------- # kernels uint16 take extra parameter for defining the bitdepth diff --git a/skimage/rank/_crank16_bilateral.pyx b/skimage/filter/rank/_crank16_bilateral.pyx similarity index 98% rename from skimage/rank/_crank16_bilateral.pyx rename to skimage/filter/rank/_crank16_bilateral.pyx index b5103be4..24016bbf 100644 --- a/skimage/rank/_crank16_bilateral.pyx +++ b/skimage/filter/rank/_crank16_bilateral.pyx @@ -15,7 +15,7 @@ import numpy as np cimport numpy as np # import main loop -from _core16 cimport _core16 +from skimage.filter.rank._core16 cimport _core16 # ----------------------------------------------------------------- # kernels uint16 take extra parameter for defining the bitdepth diff --git a/skimage/rank/_crank16_percentiles.pyx b/skimage/filter/rank/_crank16_percentiles.pyx similarity index 99% rename from skimage/rank/_crank16_percentiles.pyx rename to skimage/filter/rank/_crank16_percentiles.pyx index 527d2aed..73ccde68 100644 --- a/skimage/rank/_crank16_percentiles.pyx +++ b/skimage/filter/rank/_crank16_percentiles.pyx @@ -7,7 +7,7 @@ import numpy as np cimport numpy as np # import main loop -from _core16 cimport _core16, int_min, int_max +from skimage.filter.rank._core16 cimport _core16, int_min, int_max # ----------------------------------------------------------------- # kernels uint16 (SOFT version using percentiles) diff --git a/skimage/rank/_crank8.pyx b/skimage/filter/rank/_crank8.pyx similarity index 99% rename from skimage/rank/_crank8.pyx rename to skimage/filter/rank/_crank8.pyx index 94124cf7..045e3645 100644 --- a/skimage/rank/_crank8.pyx +++ b/skimage/filter/rank/_crank8.pyx @@ -15,7 +15,7 @@ import numpy as np cimport numpy as np # import main loop -from _core8 cimport _core8 +from skimage.filter.rank._core8 cimport _core8 # ----------------------------------------------------------------- # kernels uint8 diff --git a/skimage/rank/_crank8_percentiles.pyx b/skimage/filter/rank/_crank8_percentiles.pyx similarity index 99% rename from skimage/rank/_crank8_percentiles.pyx rename to skimage/filter/rank/_crank8_percentiles.pyx index 5441eac7..f882961a 100644 --- a/skimage/rank/_crank8_percentiles.pyx +++ b/skimage/filter/rank/_crank8_percentiles.pyx @@ -7,7 +7,7 @@ import numpy as np cimport numpy as np # import main loop -from _core8 cimport _core8, uint8_max, uint8_min +from skimage.filter.rank._core8 cimport _core8, uint8_max, uint8_min # ----------------------------------------------------------------- # kernels uint8 (SOFT version using percentiles) diff --git a/skimage/rank/bilateral_rank.py b/skimage/filter/rank/bilateral_rank.py similarity index 85% rename from skimage/rank/bilateral_rank.py rename to skimage/filter/rank/bilateral_rank.py index 24ccbcd0..1dc7552d 100644 --- a/skimage/rank/bilateral_rank.py +++ b/skimage/filter/rank/bilateral_rank.py @@ -1,17 +1,32 @@ -""" +"""bilateral_rank.py - approximate bilateral rankfilter for local (custom kernel) mean -note: 8 bit images are casted into 16 bit image here +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. + +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) + +result image is 16 bit with respect to the input image """ - -import warnings from skimage import img_as_ubyte import numpy as np +from skimage.filter.rank import _crank16_bilateral -from generic import find_bitdepth -import _crank16_bilateral +from skimage.filter.rank.generic import find_bitdepth __all__ = ['bilateral_mean', 'bilateral_pop'] @@ -67,7 +82,7 @@ def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal to be updated >>> # Local mean >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], @@ -131,7 +146,7 @@ def bilateral_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fals to be updated >>> # Local mean >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], diff --git a/skimage/rank/generic.py b/skimage/filter/rank/generic.py similarity index 100% rename from skimage/rank/generic.py rename to skimage/filter/rank/generic.py diff --git a/skimage/rank/local/demo_all.py b/skimage/filter/rank/local/demo_all.py similarity index 98% rename from skimage/rank/local/demo_all.py rename to skimage/filter/rank/local/demo_all.py index 8df5c3e7..038c749b 100644 --- a/skimage/rank/local/demo_all.py +++ b/skimage/filter/rank/local/demo_all.py @@ -1,10 +1,9 @@ -import numpy as np import matplotlib.pyplot as plt from pprint import pprint from skimage import data from skimage.morphology.selem import disk -import skimage.rank as rank +import skimage.filter.rank as rank def plot_all(): a8 = data.camera() diff --git a/skimage/rank/local/demo_single.py b/skimage/filter/rank/local/demo_single.py similarity index 92% rename from skimage/rank/local/demo_single.py rename to skimage/filter/rank/local/demo_single.py index b601b226..39b9acc0 100644 --- a/skimage/rank/local/demo_single.py +++ b/skimage/filter/rank/local/demo_single.py @@ -1,10 +1,9 @@ import numpy as np import matplotlib.pyplot as plt -from pprint import pprint from skimage import data from skimage.morphology.selem import disk -import skimage.rank as rank +import skimage.filter.rank as rank if __name__ == '__main__': diff --git a/skimage/filter/rank/local/iko_pan_Ja1.tif b/skimage/filter/rank/local/iko_pan_Ja1.tif new file mode 100644 index 0000000000000000000000000000000000000000..47201695755a73086ba6d598f3441063ecdf1068 GIT binary patch literal 129176 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 *mQA#EEoq#Nt zA=BBE)dEzT!$sAc(MJ!!S4-2F&r`Y97+p}Cx=x8M=YN~16@1eNl)Ccz9?kv{`n(&u zZz6R5JATa-@cwIfF0Uff~c;^#p^@s`n@*KK8ej(3i@Y7=i!U4hmPrJpjJ@EE(5nZWuTSeJ?m@2n8JzNw%?5aKjbrI(#+a>j zcp~<_9eVwEWckV1P9%WVQn)Y!nHb7AYZ%<~HF({R*LV&1UIy})parI(-&X|L*ou#_ z1&_cJw}R#=(UsAOQ2{(S7vFFO?`h!Gm3DqY>3K-~YA{&L=Mq}I0m|!5<#1&s9B~L* zI0AC~oQo_bqsQK-Ye_VO<0dlN=tyFsEp=p9BMp9Bwx zpZ2d$9lJb!jD1cYr`3oRT0bxeqxk%2Bp71EjzES zb}`?kQT9@flKCuv18TIpeq1(m*$90KVok6Wr0PYTL9{(+{)h~}MlG+y$^VUdcXZGo zxVj@edp0_0IF_h8bRLXtNd=e1*q0RkFG0T~(y!%kO&Oz)qTttX01{FV+m_wXzv$nR zUV>!pWkhVGPPx;sJ^%)et;^|M!1$~V=8Z^s;az@j#I z>DlLUhok)i@wiYca+rFmcolMGAFq6_Y~aocbb;6Fp*2s$p0|vy0`)5R!+6j_%9z7z z5%t%PmcZY0;DW`-dw=x(VCefch+Tj+KMkbw@M&v-d2`-v@pErO`~L^?x}5(T68R;5 zph&Gk?~X!K3_>UVgg)5DD7`)&-3uT-o_I`Ke1;1++XoxJICvFY<;#YVet07Ml7`8W9)17Gace!>u{!1s?`UKoD4t`r3qdWubt!)7kKLhMX5wBPq z><^wpA|}Jx8)7unw`JH`$8Otc!$Htf|2k4DMl<2k@Zuc+>6k5DBR*GX)?Ss0DIaWJ1{4x4qD?0>_x`+ z@U4LF8|gs~^05($?}cC9q&5G-pZJz`eT$sGAEVxhQnm9xqm{;D)qkR$z3?K>;rd7L z?iutT8*ZISJLX`gmSVAHQ>T%F%i;Em&rdyKvw<;(?0v)p0~-Y7vMUTwg>Hu_~b+?+%!wC8K+|F_uE3!^kj$VQsp0=*>U z{XS4?g*CqjIiJrc`x>ZmGf2OW4$KcOhCVNHM(_Peto#n7_cE;WyGUnWXxIf=7!P9O zxN8@q`=-S5#uJ0v6Hgr15Q9oKZ3FJSblo$Blmoxo9eK_7} z0=V`@o*feoKtFwgZhr)gW;FU?y!g&=)pRJmgc^;}q#+Bl@o=tZjMpB&zZLDDfL}13 zHe^wAE*eLFtb{hyippa&Y*jXRRMS33QhT}L_^lFDnj-VY;^l@aa5G{fUmQZ}1MWJE zHmHf^Itr;1X|0RVado0ilvU0%1!$QKquKQEN2odl`Fsb-xDjNo=cVudXSn?XzRr zl+wF$a82ZCV@#j${|oT{me&_>K|l1!3~Cxf-$!!aOl19ITKWw9^$HyKDw^#zYS~B~ zMtU6?>O(lHe3Yj?L4&*u_hg~%XK^ht=Dcm_)`L+00C*TxQP((crj6bUx(C4gaEyKl z{GsPT-VTs--o>%IW5W&TnNl#Tpud&eVN|Y?=kx)0hZjX> zBhN*YsCM7Or+jam!l=F+@FZ9t9~ryMgxW742Z>1Uo7lM7(0Lw`@GH{(4Yj<&KM2w3H-p~Q@WBO);F}=(*~I8xF?3XO3Cy1!}I zkC;q3W23XM1LyI?wb1S*5WNjuc`tUgH&QzU>7LC0iOALz*&?cjI|l3@(C6T0RT#^qB%zANuO;Hp*cNvj6I0fQ)S8VD|; z*AwA`Z?W>PBER>;^Pl6p_Mo1H@K!pg+nNPX<_St%2B&tXm(!7s|6raAeRHW*zx)VT z*al;$^^p1_vDU5?IWuFVkZ={qs*`JGS?eP4^|9Y-gTq*M=j9yP>7yBgb>3_XsOM0k z)=W-uoMt4ZkSAIr$15qhPL#*lqp@$1&U5?WpsS#VuYr4BU?lZ4uQQSxcqC7zY8t(Iy(Fkyn!{Kox*D-cg=_DbD&r%wPztM%Ru}K zXgQc#orO(BzKp&*_ZESd{`6s_(e|jJxANS6yu-3smK`xWr=nGMEMMcbIVN*-?ktg` z>m%H;jx){|ZsuGeeRq7egR-4j(Ff2UJV=d31NU*xsF2>k7V0^`IPLQ2Al&&QR4t~r zUt>{QgXR@jvIfMPpMqQVpjR_^b%(k?!};G~k3XUJ-9hq!c!u>J?EB>)e-n}#FkZcw z_{@3CQ5+0bF%Mo!wC&mOgXq!dt>{*8?-q><-(XH{3USxc;C5uZHBYxjy8p>I?QQga zS#S}W;04Chzk&G}q^UO=cM!)DK;;Ga-nrFy$ zgCibCN_&y$FX-W~e9lK>_XgwsyvCr*M}nlU5>o}1qokItJcB88gw3;*LIWwGFSQ3+egWTf!T!95&H56=halnoz^*$;e#iF_=#=>!XQ7qG zqvfYk{|Nf|2X^ibTK5Cm?Mi5z$vu-neiU~v;JzfK$$h-lCOLX_1&7 z;#eR47-*^8tK;t?U<^&q*%=_McWsWHP2b5gWwES^ts}V-{;SQZ>4_f8!MM*Al&GIr z$o=Jf>?f;DK=2 z$IwD8st2PVWgIkv_UW$|g6}$dy@D1if0=0FHMCma#aZZqJaZ*{_Ac%3h|XG$e(wnv z{!ZEBL46GPrSfDtNG=7#`EY7KytyyX4d2t(hiFR|%9u`_lVbg_kUOTKANBrn!FvKa zzZ>_|#tyuWclS0=I+E7bHj7H3<}qY{H=J;kBW-yp*UCBH2w5~c!szP}5Hx1%TuE+x z)+oAjbw*dU-c{hS7tHq2wYjZbxnv)M<`m|4LoxMPc9#s8%dw! zwyDG*p1~VmPu#mRc=n?YL~5FW*(LaPZ}Ptu z5`G~z+DL2@;x&!Y`41o;=OQHwh`5a+8)h>3M+=#MJ%h6+!(S)!`2unM$IzY~!X?Om zEhOs?C^!{angHhGsq1A98*-^y!HYQ3|c@ z2c2(`stKSym(TIk{2QNdPdMx$7!JmDQ?Y3Bfr}0kG7^_xdOxr^tqZ6qhV75y!?;^0)Q&aouWvQXHAd)xil!_I+^r$>{m(uoLINM@z_j*~MJxF|wYnM#?q?51{)xK#dfxosEn; zhjl*p=W=Iluy_p$j)AkxQy2*nHk(Y3EeUaZukQZ zsfi?;Ep$Kns4K104;V`+qvQ7&?(D?)<1V=M#Bed$p>v2&Y$2EPY@%2vBU{Vp$6jcd z4hGurVsNbHcpvE2M|(Gnjv}La_3ExF`eV+_Za8HR?b!$VW<{vWDxtlj06i7;_ICd3 zrR&Az!5?P6H347cHHef~=YI|$-R;P;9m(?}u)w8csINa7sVuRYebsu$jYV?wVeknN4O+m?!02*&%vThD_CujJcRSr>3=q4UkQ$BApQ+FkHu;`F8`MQqv-iB z{O>}K&7__Qdb7CG@yTlXrv*#qtv@%E7WCn%Z_xGMBkNBxX8DEl#%~94?ndTXn!@MT z(Y8b|&j9aq`m>oiVspnTgOliKVT^MTcT|Q&9bwl*kL8a|^k6eR zbrf#S+eT!q5DdlGsD!?|-i#W;xM~G2z5A{7H6M<2PFF9nkTXZ1#b?m!M<{$+Sb~(_ zh`vija<(G-=2)6-TMh-XIX0%W77Es6bZ7Eii7V$`$0x&~zdctwUqnXP-xv|y57%p_ zuZ1cdiSNvW=MP}54+f7Q=NE#y*%p=Nof$5Is=1)Q4Eaq5xzE9EHYE+B^zkvC&ddJJ zw{JK*9gS}O)jURk&W|tS%xqqhKz|C?on7pVX7~^0AHxa#Kt2JjwVnLv+rj)Jo}LYl zuK{gi69>`ld*NiQ-mB17J-iDnjzK{qYYoxD&ZxSoK^w1USCbP_iC=E^L=MOn@;373 z+~_WjYQ}SBdlqo5n3rCG5g2o?4sm@uJh2Ks&P1Q*@lwN^J@N24D7cX#W8{ zkOx~t>!D%_oacCN9h5c>adRA_(_XhBgYqO$zYWZv1npv%bn?Pz*6qs245tAp*DCZoN82M7H5*- zfWgRrB3G2?BydYWr#UXjhUXlM8SC$X|M4YSVIc3j&|sHCuZ3Ls9B$3QPyGlVvlr)n zh2z(OvbnxSr&^-_>LXQmFb>&)_RWsvE<&QU>v|#1rqyKH)a2BdtFE?h1cEEzK6O_f zPl>PdvD=_U9prI2J+1~PV|d%(qq>n+-`RBMcFg!*LECrmir}7>(KpO)r69?h@nb%~ z%YGXUSRY=9kH3>rR?>RcU^t6!_DN0DV;fZ14poh9nw7Gd|LL6j1uOOm()kXQ`JRyt znZe+A6@2gwuLR`ybf~f?XbiXS;gwIs=P1~>#}j@DO>jOM;U=(ug6}_2(tDsj5L(Zt zR|6^Ycj!6@`ez{7M%bO}HS>5Yn69Kn=6b9IdwpCZUgn7p2ZZ3yo!raw>6$L-4_Y;50mzo51~Oa3TJU_ZQL5QtB?HmF7Y=XU3x% zq?`ve=gE08GbT!Ce>FI(*VAcRF1%s(^FjKP3rA+h8sQ-4%(&E&8}T{JNKJ0ivtLbb z#`1qPG?>6Dhgo=9H_-dB$l%|R#EI0e<*%l<6X2!s)TBOWU z=Z+1rL?kel`VOkR43&C<;{){cab%ze8var!(2UvD=DZG|->cAe`FQY$@bS+505efJaB5g}Q;syR@PlnN9)8bm~v#({Zok&a4tm1(a9LU3v6C?dqILCH>vay<0h(k8C=IE(Q7h;B1Um zE71VYuU=Hfedf#Ql^SOq19C_3%D+dm{uwU45-NA5oO<{YGvSOiNWL7CkCbaYj0L(v zPR*`8%H>RH+z#h=3b=nIGVwL~aR8G25qj?;uzLWU?!!mx1nQSlN5lx`MB=hxc#zDg zVqW_gy$&Qo+Yzn)D)F3~!TSwbG8vlngzCfLzUd&a2-zA&i<4t}yN=I%&Y1~O(HGrcb1N-58o z8LuVZ1os@HhXL`na>_A}N^js8Z==0Qv~nu#Urd|VK${G>{wXBvY;T~FC?tw1KxAJBzR&Q?^GG;s>4^A3J`Mu!ce}dlIu}yEueCY}3l2?$F z%ZaTW4(cG+#YFn5@ZS%BcqaL-?P)<{tm7?6`ghpN&Y(RI&)Qh~INsWg$Kbhq+Pj37 zERJh7KSDiYPN31(CEQUCCCZ?l>KiQEXUq^j3Vp4;`Bu)$1CA@yrOsj*-K(G#zaobdvFcaR!w<+TGxPBB+-zg4qn>yNSFU38rG>t_ur-bJ2h1ln+2lda?w@=}9z zf+J^Ai@9|h&_orylW2#QDxJ3Efb}j~QZrK1GUg)Hjw@%t5ymyt2nld>TeL|Th>ZhX z^Fh{Q-}Q;K_6f1?&;x|0@|)8fk7Si{ z)?7))*?F{OIoJ+@CVwF1uIv38nhfLHI~*^7X3N0Ih==P-&6IIW?fl3-_+T^F^tR2| zwQr^1v4XQ}`7Q#kRo%!vLFCx1l033zWJs7{+dLix)B*ikMBA^4Bdw$0$<5T6#l5NY zx&t(5jmABda&qFDexX0VL2@k( zL0u1bE?LS=_56a5hW9RgQx}ax~oL>WOJ!?YD8U?iz{yzJgI#3$&K< zFa;@hrG=xr-XQZKeI5f{&7{~u%jU*%J^?S~DW3cod-X5y?}7H{gk3+KQL3v_w?Va< zH5i$+PLF*jSeX@}HaC)D?rH_?)OQyf&l>}GthOI&dyjh_)QcQryQayNFRl203M;Hn z*44pnC1jmpeW+E@-6Mne*k` zA+3y1uI5`hcTAg{Em;lG8Q11d-F^#rNLZ$~H4L@Uz zpQN>}ZkS2?rqGh*JfB2+v_wCm<7d&rrL-*wD@4?WFqbKGPe#MW4UWO2p_%!U{b<1>!XTp!^qtuyPj znJsS|ogdwTjGI-lmwp@9E1*}d0We0f3l9GjAL_4+vRt9^CgnL(;jEpWkmHF;DCuZ% z57%7NYZS)WIXyeq&=qn$ZlHcSa2IXU@~BY@ zLHPidaS1I+hn8F6hHUP1jc0=>8wnl*dY{tsxg5>r|8(kG2KJLEWh>|U#BU>Tj?4#8 z>u8R1IrBm_JCIcR6X5`(^+_P;n!#SQWGMRdCcLCE#N(TT z{_Akf7_R5?wDZ8uyOhUt_nCqisVLe`+Y7m?1byZzyh`}nc&q-(0kACQ?Ksao`3lN1 z3*H@0nt*rP=!VEOOe^WR-ii@SV^<|S<0_lgXrCwH({IqCCosA&vrgZk5J@*fK-``C zbzW^HbgYRVde)JnQCau8$mdmrB<|!~4t%QLUk%N3sP$Tq9*$-=KcWG$elv1k2kn9p z!jf+cf2q|Rx_-sDY&f0G*In>CxF( zvlAKD%z>XK)7C<2cFeVkV|Dj-T4_e3BQU+XqfpP4d3vY%PtKZ}6=yE2nU$4%)7Li^ zWBk=zs0*WeqH9?nVgBKCgn?%!GR-9$j3_7-j_}@1+&ylK#ql z8#&V6IFDgOBokU1aotX9@?%@$+>d^|_i7)^IZcETyYbkUvF?0E(1vk&C9#+T!By1d zy!tJ8!G9rg)0T1T_fSbo*%z8lrakka?=bXhXL`E<%IdS4mzafS&O|pA@y+;~E78hbaE-)L2&T@Q523CBaASY&{DFGXph^<8bVqWu3yJWUaRenyi>eQ~mC~MJ z_N6`^^P@bw5SmYfK8xwWO8&3oa~=Iu`n8tE>daJiKOF73GayGOXB(2L77vNLRAI{< zskxJo65JB`ZW~<}Ib*6dK8ja&kSti&vqsp*jg+KCcCDPV&#oBhgs;&FPwEodxsvm) zZXU&*2jddeDOyN1r*l2>WiE6oq~*?Dy1siS*NuZ`(*D=z|Ag>2a$J*{Wg3G0?t;a> z8ZCbfI_?2x(r$@I<0HV+x!Trwqpkdd3rJzZ7)6yfb3s;bV1_^IS@}D-iYA_Hj*=b2xUV1LMqU zQ)99XqG}Mnkk>iU321vGy2mIX4@^q%>s|Yt%M%$$h3g=k3tvRbN8n{XgV%H>I$p`q zVmo)`sw<;1uD#T6H^0^_>k9fJ4{K|juQM9D3;M3*-4S{++O{Ud z=I`dJK3)pfC&Zde`KW-C%(BSBr|JpXQz*s!fMjYL#9c;r90P9#fgfpu5%UqT9@WOU zrt%NkHj=AfaP%Y3yBf#H>=asSUWcnW&48W_rxalguB4^=;JX~kQk$q}R@2HQ`0(D-n!NQoj8r6}f5m)!4FdM|(Luz91`c$q`Jb*;&XX(W`x8TZ% z6VT=t;6t4Yy5?Gz@^ZbJBYyWWFnXs{Xq)%LJ4T}P45z};7cuv80~WV37)p8O-f0cZ zqcetG1z+uqC0Y40x7Jm%u9-7-;|g54)2x59_s$EyVE%YIJAsW2=J8q{bfBl-GUB

^6aIu$oeZt#fR-x@raAH%hcaHlJbU1y^$HwL6cnhB!!>locw z+D7nL2#P`ED8?x9bgq^1TsC;>BhCf0KcKO>uHVsPvy?aS)M(0I4rK=YpO{akh2wZ; zT3kYRKF83q0obG79H&xCG0&+LR%7=cqYW9HUx~b~qQ%*8#56dh2Yq^gXST6MXFYRC z+tCJ}Qp!A9S(1pVm{Cnt3xwjRuW!JnFNFljH}dgS8Ra{ZPX(gtdyY z<8tTb-8aeEe^Hm~f@mXr=*))^&9PxGEcr}wC1$f?H-XRfK_jS=3avY$E&tB{XOQ=9 zjLQ2%(f-h72y|V*|7l@YIG{l^2o6%uxYL`qIwd|@0k(y-$F{4(-B}8xs*Ev z+5DM15_oszj#NsWL#yY3{&=p>=6>g~65!Nn*md(gj8E?ZbrD<&Jr?lfTReX;QfmIT zdUGE3?rU&gLhI6Ki|c}wcztj)yxbwG0xG);g<9M=tFfCc^i%YW&6ZK(EyUd_p}Ucb znl(}8-UY=18i{iahB>ES{?X9c~G?dicX@a13#I-&VnW7*Q4w%X+mqT3N1!vEpm%X5&D~84* zcN3wDwsI1bReK(S&dwsP;_hs4H~OP(*H@Q*>v+4fqq+P>nT&C-h8ps8I%f)@xRGIX zrV)4ddRqa`NnA~XE6rlx4#I`>(49lv?Mlg=NUOB6iLsw$bk{wme&d<$v~LWUPXbL> zPtJsg=J4sNM!o+Ow90m_j--vf8L8N{xFR<@j- zH;Uv8wX^!`Xroz&sd(yhd1VC6m_0cX9FNvm$NH5i!8CR*DvcwAXGiPN<9bCyk!&rb zQT72Gy$LN{XS^F6v=s~Dx{dPXLP6L5>EX)N<`=m(Q%;l@ykd+fn!!H%EwUGG-OrOXz0G{y5eS&fseuw#NRtbL(dAIRbT8 zv@M)9Lu&!_KOyWB+wq0O)lZ@~4T-=UBgdZzWAHW{loFoFY(NmLM4o?#$3BLV${vd{qFjn@&{jJFGls7R zXSUoVur6TIWf6th~@tH!z4Ae}kzS6ecLx01hF4rSdnK^tps zv@>k(KI*uqLfcX~MZ>)U__ie%VamG>0WmIT8 ze6W^28@t#5P7^?3BuJXqo6Pko;QbqI-Ux+Uv*ud0Szxh=kz_^i1V^c8u~b@=MV;;r zt3^+zRkOj(U2VqjnMPTOJf{yallLO78$)!wXyj)wpY8F`+$~`)_Yb1oOW|oV1I(fQ zoVi5T{x`vf?g#B-}|H0Cqi0W z!sqRjZAMUDj7q==y=I34_pWn|rm||3$6ch{0oWaP9PzmCu~A*KAV$!->9K$PHGXI- zEOaTQIm_lwXq!O7tQ5;K%hFv|3+S)eTGhcDO`4sV?J(Bk=X* z;b~|eXRn;a>I-#T2WlKVji}8G`sI$Tj--!5$#t|Vg->yGk3-`=HEZpS4Vt;5{w?La zv43X;9Q9Pu8t0)hDB~w&aR4*l(dJxi&>e_Z7%?3EmG|#`CI&q`4m8S}g2W)aZ=DYUrQ^Gw0_%vd->D zqW;GJR*bN#@Rjr?n_%nowZ;AbRLMrJ^|SQf9AlaDrfx5TQf3nA%^1Zp^T=6RcWU?- z+Wmd%J&U@kIA`?F8GHAyb-yw*sEq@-V$(P~J4=A~BxXss1?CwXPc~dF^!w-Rq3pcZ zaw2`Jp~gsf{C7CGKeRB%)ZHv5K=~JF=Uk{Xlh;nD@9NK4^wg1;-k+ltcV}4#|GJ-q zdHrVQ>20Oc16SF2zk5u~<+T>h)!z0+Z@V|rFiIT8@o1iOHg-I?ECQbq&`T84`M;QQ z7V@bayO)mR@^zL)Gp$`)C33o5yzWG?q zHuy;ABmd^c8-2JLE7}^ls3I@4HZv2op;ukd51?H`jxOW#pFHb|dNo)II`&m0=sa@n z{!DgOd+hM*SoUUE)K_>dLjv8a#N9-9V{Z?^^Ul#b^3vZiJH80C9j}>HrhKf2=EYn$ zzG`mDe5B+lZ0v{NHW^)Mo`$g^qXE9u?v4d)lXITGqSfbs`2@y$XT!rrn49tcBzCZI zZN{f?QLShcRFMXwpr(HGP-r)Y|F6-nVvgLu)eN^)(8WDk)V)ivzOL_A+lzJWD2vaH zF}h~I?dMt=PpjYLixhBl1}&XFIm57>Qe2rNzv-PzbvVxwSR(>_k`LRurH>e4&O=B7yoJ0nr=bidN)I7h|DAe8}VRfsUfBk3&PYK-R7xcJ)5gxr<0yU*u^u zI-v|*-kEY=rTnqz`CKy2tfm$Mef5;v*yh;ht92%LM0MkrP}G&*QgH(GHShd0C~0hUDWC3$vJxu0mSG;PtC>GF55V2h{WS{X zSdI;|c^NUtr62n82hj*-`fdX$^CUJy*$gnZrWr_M3e+EmmNh>mk8{q~J2GAmN_sI` z*{M7;o7Rqo|3-uRGD=wlH#%=({BJI`>37cOtoNkGmZc`XzLGK7px8?pMtRfV<6jsF z-U~jh!7?XspPkj@inW6Vzo3oJV{~=~(oqVITk+!dF#~ysd**@qwTzw$$tA0eZOvsZ z&{W1|hw<<3VpMk?wCq9s`WkP7x^c8yIC_d+n-M(&T5RP=J?=cbyT-dRz*Ua_v(n3X zOXIob6*+HO6I0s(LaXVk+1;Pfy4Fa1Iy5zB-f{6Zq}vrEzfx8hts?U&k#WcI@LLnS zk)!x==b+yr;zZ75Jb`9Rr%h%PPem3cL9glP&mpwk{r+5I=r3)|2X9v_)MTWjf~}*o z3b<5zVx-vIDChEAo4AcT=W<<-O}WnoFEbg^`PLAAH-f!_KJ=qJE%taMWEA%=L|d3C z<%**eP&5}@=}qM>XHwPp3E(yu4wy-+htkgNl)MEU*!lsq@j*rz-LOFK@cJAcxQX|r#I&D9AM}Dci$L0agI(iZv+CWb zp8J$KqBSDye4cY>dcw}QIES_xOq8<~^r0q7{Q)Jmg2T)lckUpE=e46b&}V3Pb#!6) z6?13>!HM*uF1}~$Fe7-JS-#rDlByZ|_JPt1kb)1OxgMOm_bx!bx`En&7`+VIY7}xC zdeZqOXQquYx>KHWXnJ$b**ap;e={!US~_DdTJC)AUd8o!d~n+d#2f4BlM9X82 zIKo{;+|v{uSdZMh&-6K1{bnG48c&R%mTt^by#XD6NAEYrH-3Uqg8TdgM0K9UUUY$G z#vt{&_Ch1=_&z9V7L=jTY@;8>f)~P7@6*at@XN;2%MEbF zGOoG@!a4lbOXG;VZ(4jDcQi(?tJ%+iV#aUEDeX1NS_1CBhu1~DkRbQ!nFZBdCHgEB zI{>Ae`E+&CDoU2y7Q>Iu=ezFM+z)fYjLGcajAN=~zL~dI$vv*WFv?_RzT@jmS~&;q zT?}Fip}(GYGIhDPWC1+8hPInAvx@uN)56$^_E%)xw`2@=INEkbZ3agpL2f+PXVNxD zapvtz;CwPXG&!!t{p`Hkxy2#8+>zpYbofx-H-u?ey}9^md(hg|Nc2f){Lka8f;Ld} z7;{kOfS-tEKMLB7xZV&->Jha;dTs_uckOV0V&`QXNk2fnKl8eQe6zn(-!1rb_n|o+ zX0F~io-t|ntk6$$FG1rS#v#nX*odrVK?nDyaviGkIoTk(98Ne4jpp!-b~OQxdV?CT zppCt-oS9JVYh=y63{L{}t&BDn1s9RsSr==5VR$I`gt54}oaKxpS3>{a7;WZ;xjF`Eq+3ps;)=8jYe$56-N@V3_Ia=J=Pj{6x^H=@xAI#m!#Bui=B-~k3b@hCx>YnifY3E|D zjNmvO8mJH4zed?NLOh#RY6;A-ONx1F5|T2Wqv3FOcaDF=?lM*-XD9ddj;xhpv~kc;8iYdyGCfsWkh z{&?DWHN2T|t^!GeE0)30W@S1f@gXgkii~st0rQr=q2*=`e@Bl};ROBgEbw;xH4c7R z2(rdi%zh|_cM?D}jVprwy&rVjIWO?wNICWZrp7*UGqp+h49SBgbDhDCX@< zkdXG%>}?IOx_XMcB&>55%z8o9E>J^NP1h`aVkf5}n0Ssvw-;jEBxLidJCq6cZT z%~-!Ypwz1I9pPot_8iLojpvpy;m9QNg#na!JM)qGkx z4c(zP-isC(OP$LT`g#50I^0Fnv4+_l6QRp8{<}AY{@*MlK!4s`ZKJw_Dd$o!djg4k z16e+Xe|8bL)d7!ZdHn)@9l-2dM%>$xd{I9m%p=#Nf;p}exvM4CxfP!`f^|Rq+)ijK zf7z-R{&_n%_bzDt4AkiZ_KWCyZaho#5F^13X!xb@wL5~8Ky62E`rezk+g%m1pq-Sv zESeZo$o&fo=*bd#?3{r!e@l4Uj1Ff6yWxesODs5~Jrm*Q9jtXdj(Oa=(J|)D+C(X6 z|Fz7oRMPi>Xk;UvnMis9)Eh^Iz5_)bQ;Z_0LAm+KJ%~2 zh~yljP44h(p1nJYq{cm1O6`t6wh(`C9i=NP+&?Uzxdrpk%<*!*+BN0<;Dlkc!e8nb z!JRufb}rXdJpK~I2;^2jVGHdY8Mn(d>h4#jPd1p=cZsEJ7Uere8Vt|7#@Uhn0<^7p za5Fe#w82l$kqLLaeMI6 zYojSoCaQHJs9#5X)fn3d+As?a{SLXm6%Y9|o|qh5fPH@+-P#yU@GaC@i*A3MvLA|L z0*Uav{<$mF-EYG9bRdWM3JzlLB$Yct&8>O^<*?+otG zGhR3xd_z0dU>BOBvmo&w zGF#O>1*)lEZZpE}YEyj=|I^Tu3U2_5(9_STS2-497Eh(rhi;IUW9<2WRM~xf`Xw z-1r?O=^dsjuz1&j$(?*R7CZv2?C)AN zLelqR!OuX}>!Br^BK_`Ia699#noP1!(H8Gx2ft%2Ogg%t8sEMFEq(>;TO#>GXvgnJ z*a|Gc{UGlzs{DgqI-1pX8;vyLY7Tuq6m`duOj_A>?%vWk<+j9Z>fd!a9VTg7=WhBhYIIC3eO?GR{4a|5Kp$FkXMq zUTw59+}dzwbJv32YFf33wydLl+9F4ea>H`g;mJc=x#q6j%i#ti#byXOQ1T|#MdXm=uXoe4h}eK(g% zP1P6Lj-hQyv_A`8HtsVjwmRC57sEmPKIB~DEAz=hIUCK~0k7V8#2wi32$sM3dq6X;94EfQdvYhC!F5e4heOUQL@^ zXKXf`dGTf|x_5;wFrQ4F>xwH^!@K%Z&NQ>oIW+Z@Yt3EH?W&br?l4^n6;elCtLUc`r1dMcZc+$>_s~+zg>%#3#EUEob3>KY*0KhqOBH za~I#(yNWZ`^>N_axGOFP8rzEcGKu@cFDLJ|kWkb1GbM z2YTu=>R*QR_JR6Yj1a#^qEgT-??4s3G5vOZo!xxu^O`Yjj+~M$jorEAFvsqIkjMRw zN}a#n09EAs>6~|MVi7#*JmH)4?m%EXU_80a-=J|CF;cI~^>sY`HB{>jjVB;Ulc9va zK{|l;-Hg=l;hMj3pg-(>3i-6$%z!l7RkM0Zf72{oe^bd7ih7-ExmR!AbpS>c&3DoB zG~(?}Qu4KNgEi28CbGe=G}7{s;QlFemOIU|b(aYIpP$m^+uxAoHt6@dcuO}T!*5dhi*Ur{oNWWn?UD3*(GAbX zQQHgg8JaT|=u3Zh5(oGj(s2|D~{VG2j z;RT~|?(mz(Q|=+Q0@RX0A%$|xXEEb+9(?*Oqql=#y@cp%3BQdvlG)U^D1Qu6wg4Tb zzwFpox-F&lbE7ZelNmfcBG!qHc=YVXQ@7(sGqH;B>0Gbi&RFhxTCI?Dp_RiNUYcspZ@J{C&u3Z@~8&Yl}xaYkz}{TRXbsqpYjkX%mN5|Clz zZmx?k1KC|={EZ0hnVQJeiE}_qy|9FH%W3TZ^w-zm_Zr&lMeg_awxw7W<+z${F)}`y zd67}Xq}K;+iN8LEFZUI?{a;wchlyb9KG3>!@}zV1FQ>o_)dV?N)_J2t0AjpZJ-i_t-MF*0KG1F{3qD`J!ba;~13 zMXPG|Ew0IQbEQHeypc#tTn+6$zcp)~=D-~T;at5qcjifgL;SVo@znDi+HD}R&=XAL zkeVpqJbai@^lk^-KNf2~fegVtLAx-MNXsKwjaRV4HzBis!Bej$0$;_v%URgEQ_%z$ zpsUa0vmO5T%V>j_ko4BPTA}|hg@fI}L%V-An70J;<0$1~{LgXdf`rh>m>!yQYI*3O z9<<{x@aaPO-p!?L=!Y6<8{d4D5sF;6)E;%KI3pE}nS zxSR5CJUM}xo-$&u&De+INN^?^%5}CsLXlxm(pl>fNQeIMY{n%r?^Ih4`67)?8SGrk?mRijYD!PnpXNWx;QgkOK94E5kL z?sSA^&Yimy7Qk7~rH!IK$MhTMWolg4wfM1rV9Dp=yU!=@`!f34nmmYh^!rLMYl)|J za+rn1uO^~Cmk8aZpnVzF{I&7Ff&I(KuH&@x;fJYIkR@TybHZl+ltjdjBm{YsphfX!rZ@O=l=~W@JA22oN#f`!}>udo0n{Ncy>W ztJ%yZZ3pubBGJ!N!y3w2N`3C3XC}LAxcn7&{WyQi!kv$u57_wa0wP+^PnGTN+=FT~A zY7%WR2S$(0d>&&t?rGreu+yl`*w%bX(|(xCsnv6?X1;Ue*t(HH3Yc%?Rf3OmfD!e} z@Zz0dcn;Ef5;RyJYzR(7j{WU$_tR{PcKQ-OTVUn4lYz85IF1P2 zHH^VOqt!n%GWh}xHU+9Uy8ah_i)$WinKL3E)32APrz)5Zg`6oc&(HknYNXutUj^tp z*RC$*oLQ6l&{|A)_wYBaTtm5lCzC199UELvmybMFfk%_b-3TY3uP4xk<@YJBUV|<&a zX25kd_CgEeFR>Y?N#pJvv}+=g@)X>E1LYP6!$HfvN@jz0Kjc%3?b;S2=l84owKRV&P|7gX*{_Is(cBe&JQhw+ixKv zvyQR(8e}{PX6y6+q~ zC7(Q~_vlSuP;xiS0{CzkRCZ&OB@;{q$- zAy?nJ`^sM0V&9C#`s*ZSO4R)RxT_qLX?K(|^6pMsdudG`6wkt2J{j7ygI>L%ig}Dm zxn9|FaOy{!7J;tZV0Ni7R)3RcAhi3Ry#+jPjK|zrGvv*$a{a6E?uGEgWN4B?>)dzA zG2T$Tc6XReqo@DC^WK83Ucp#qBYoQh&7We-^)xN&gIwIi$lBkOKN4({LOlFm9Z<792Ki8lso+;t$_IxuJm1ooH)Pg zyq3G27+Zh$BxjyQmoMd+H9VTxBGHx*E!e1CS|1S&5x|i%WP<7n11MjOG zs=LFpBVB*>VJmlL(RZ!E5_rJf*wlD4K_i!5i~x7{eE5MgN09SZXvq|GPJggUhV#Bd z!w*I3yD(1uJDgbx&lVyFdEg$Qk#^z7oPeLXFGku-e0T9x%Nt)Yli%4heUBm*$Qe zLdueA`N;k&w6O~%t)g|V&7ML_zX#dlnaSxzk5~Gmy(xcvp3!VmNLC z=!Iw8x1tw!o9paOOmpbdAh36yB^90L zt~+aKsWI-6L?dUR+e^`@zN_(CZi6$uIsguM7-@cjv0kfi1#$TaXt}mn>1JfqY(@F5BJGbbUJIXPl6~_XyBUf-$20FPbOUHUcLIpufpM77_+!qqlmG5ZTeD=eqRU| zoD6TjjE;C14mk!^?)m2arCF4sKc~0ujyG#S-(0Ds^eB}!8)G^?%Ap=ts=SZClETQR zD!3G%H;t!Gjz_A$f~fxOH2O3Qc@*W|;9N$#dw}g2uDU|j*$OlLweilZ4dclCHe*I+ zMY%(%^Dg~3JDMYB4r+D_TL}(1$VECWb|1G_u;}i)Fq84(T4EQQz;Yzs(vQqd)k3r1 zj?aAy{(25}XdYIe7Nfga#B0}Z|0!_n5p45KyxPLUJDG2DMR#L3pdD2D7d5{_e#Lt1 z{~*vWK%eE~rRh^@i5-o&>yc}SM>CGP97?yvs^0bIB>U6&0XDFqfNPr$=Xhji7e+OoRpyO~#@RzH#o^zpZcaZ-I zZ}fUbA1%=CbDd;M(@hoY9}uw)lHz z>nUFjFiN0x&!BBzLW$OtbOQbB2x`o)Qd2KRK7;xH18vn8Q^uV+8cDyME7eCEMl02C zDd6sm*OzE;cb86}2eaUnsoYWXd#R}$rSt4mv}RiH0W`_vj@js0_c5{^dbV@1&w1dv z5AS^nI93q1@HZ*jgXTHV|3XGGx1x=!u|)gPyw&L5y0pG5xF;M6mlOqeA`#}w`KxAC zoN0;OehJi1V^rcUinl;ZGYy@~PseUw2x7DFX1?Wf9~4nS^61-(i~wGtE>|Hw57qAj zLGz2%jP4I_o?%{WCEcUP`6{!@ccGV;ATLWew}%>xv!x?tj`G!?{*ppxdOV9>8MSnk z{vx!1b0_;KBMJF%Po-OF+1>Q{Tr7Ac+}o61mD3l;rTz}ngP>jq&*on0aF$e0-ThHr zYcH?q*O`IoK2~NrJ3nBXUEO2kxCp&{KKAeeIQwmSYo4dJ{W)yP_vo9Rpye;Bjln{X zrW|d$Ge+7U*DSbCm0YTyH<>#IgTI_V7JQe3`&@Y45nD~>bSG@~K;&--ZE#HPZaTKi z-51S$Z-CBOf=_Y)M^E>nj@!Yl6MFql_^LgzxQ4X#26({Vy?P1?d;vb`?9DP8 zJ}^&e8eHSA9vld|B4tnE<=ujY=nBVl#a5b`H3*3^gK!Ca_zS##Ikl*>{e1ugsN_`|%;laR|3;oes8#GBao z^U-`$Da|!jYv3niEza}0M#)&i5-@Q@UbC9WyhXDa&4XA(?@ohvnqw^o^1OS$W+6F$ z0r8>mgR4eelhg;U?8mo6p4!59GgY;M^UxlSznnEq0CRu6&sD4Xct2rb&3@6cbS1Jf z4$S-|srz_-5p8px!nm)i1YC8ql^R=xX1Ok9Tv{vEuI6QoL>CTWH0FxZ$DzW-wD=rw z{*bo27w}7Hyz}ryjuEq+$!MGz1AMn*K~Jvz%oE=br8D=fJ)E;W=2^4vljvzVE%}lb zUXLeGvp&0K*RZ4bSo!dWdC<#{i4V~5S3uYQho-xLx~k0j0DkU$5xcu{>=|mRtIw?DYq)RaQ>iY0 zLp=8^d6NGuZ$Yj<%45t7O)oj@sii@RlsHjm26ICBvR3w|as8Tdtp3FK<=OQm)0l&FRFOX}W`0a$CCozU1B4 zW{vhkEnC6=AwH8?boZ0$b!qWCaL4g>Jl(nm;=E)tjj*#jt?Ff0xfM)eRsM{UC+Z)V z%)oE;Y&6}TuGoTKm#)PFeI|Ws7o*u^O(nCey1!C#;eJI+$%agCmPDZjxgxCdATeiN)Z@tW8osb5G>m#?ii zRR);`*vo2jp70&$b)-X*4gVT^e+c8r0{w!9sqg-+K;RFY{hD2!Snf}z9FCU%WrwN7 z+nZiV)!jxU`_A@p9R9!Gw|27g%v(==OS)55SHz~`{5L;|#Yb|b+sep_9G&8ooCYV3 z{;WOT;ch=w_A}C||IRKdIn}t-`kLaVx52&zsQiZnN*|ikOn%~Ta-U||Pe1hE-+Rfo zZv&3Wd>UZ?vG_i-zI}Mo3+d|_wT>s9z@BC^`rYIAb64D=E+PE=`yt29A}H`q;G z*I4Ar$;nF2aH=dGf|;!MQu1Is7R_FuaRP2QidL>o*Y{(|cR^nd%a`7W&N_x&m_8tP zvH&`QM$Q7#wJ}|ma?aD26mLcHU&~@%U39aK6UBhn7w_8HWV>j90{4}5_Xlk;(+N-} zjEBlo&z8D@$nol~x~bNVcN5Jy9yO$vBOZTFMOu@l>%8+g*riimb60NeyY=8dagMs= z$wuWn;9?SabCFLS1*cEpQ@0@)1==YgqZymG}A3k|-L+xl!XMKMb7xRU0rUheGT>a;#!ia%*JZ&WMq;`g+{dPdKT8eVlVu( z3MVC2kQ3o#XeSe8omHgc#240=+MsX1<_vpJw&a%V;-^sm#dz~Wxp@4ROro0zbIFAqj@oB{O8lnk{I8rP4#DGd z{CyQ%TKd0vg=)Hh?2Dd%4dZpt#Ho7AKjYiGx?X7Q7~1Uv*2q2ZkVzi9h(&B+oyYO; z&n6YNC!cq=zO$|J7T-(1ly&eOzWJVQkY24hK~DyID$*iLzk|8dDZa=rc+@9Wg1}7N zI*^>-2cA+Ha2jv%1GE^vev4EKJ*CDh{#okFQ-_|s?DRQFW$F{CK9RjtHl)W_KU(Wa z+_p_=q6kUbBD3SBi@T)aG}#Zk+jBZ1FOgrCbHVD`?L=#0-=+U+X2gs{lSiZJQ{ZJw z^t~VNX?StJyyWrtS?g_{pD6;;azYon`Vt*G{Npd}pLd{p8`IW5I4MF83QtxutTLRk2Tu=7xU+_G_9+N-& zofYNeC!K3Y`7d4F>)La7QZIE6@m9NA-Ra6xA49TJ$P4+xaQq%;a`F2(t-7Jy2)|fZY zRE}OR|FyvH(_sHiYmE;!65c-sf5J@RPciSaO~1Idsz1ic_aB!z823;zV;VCFCTtpoGPeM18^4{EbX0e+Px-{HcL&HS?{J?9q7Jhn1Im_ip_PuXc_9&|8UYPl1c|#VPE( z`|#k+uJLcUzaGX9hwZgRdadkY-MgclR6`^V@B_T0UtPN2#BWGff<(7_qQPnQd9BVHmpD?sb5W}zV9lyPn}TYV)D3u zAi=-Gq5H6;0{8APxUSg5%AO|~Gif_H#L2j9>HKV=M_;n!ZV`^JN#)7KX&_URS09bs zyZE3uyfm)Z8=Q0Ya~(SQ4@h1|MjVZcX7G|8=lP}6+Oc`KOPljHdT6RTu9>oRctR_^BtToD|ST{`*}TC zUFmrf4CkaizEe6Lr7!A_o+YPaWF@9JvDgcB&O-m`FOZtY#0ic-Lzi0HFc#s#FumH9 zp7A`<;Z`U&6R#7&8Vhbc?Im7WI=Cl4BB#4Uyq+G;P1ux=vyaYTY3xP5Plc@^^xt^O6_vI0_Y2tX?7smtOmc2>rZB|1d$XgDM!i>o+hHiEqrJxm zO%+00`Kz7KPggvhdBf?8`a8X}AE=KmomRfMd{KF*HQr+S_BAE}_4RHtejl{HS8;iA zPj6;ZjI_H$K`}X;JJMNeX}5W7%k@R9_v1yU(l`8DKV$r!0o&6n{F^-8)PqmQ`+f1} z4y@>@?$F#T>B2e;4iiN1qm$=w;q|P8d%$-)*GdM<1~kz^5rHaDx`}O)>V@>;%GAkZ6DE2+ zOME7$O_@uWPAeneBOSsP6%&gx4&01hIL$Q&dFMW`zLECL$=P^onSk2!Xb)o3L47?* zypH{TIBV`eT=YH(Fx#`_)XazDB7gvH%rYWblb~{)68TKEsjt}_^E#R*exwj1UwC4+- zP(DYj_1f|keN89}XWv zwNqF>tBNWxeb(ADy*d>~$$M!6OYulXxbAaaN$kCoeRYPp$l5PJF>{;WN3-X$F?!+5 zHRR%fRvnM}2s`)(OQbrYcnWw7clUYL7>hq0`O-5XnOiw0n&B#wE8RqXtZ4JeIR0et z9ZNQS!0yKP!z6-CZ9d1egpUjOHgmDw^jj*Ey1}a$@<&a_#bU<;%+#mhUPbQI^$EY>MJm z75%OJS5on;($VEh%Ki8(4_o!&Y>f@^dI>kKcJA^We&2)iKN8&y=BK5XW~x_{^E?#w zXVzFw+eX092UdAVX=YK&N>=++e~^l$pE%k`5Ii0PSCazY;;e__r2FR{U!l`8X@@&$-kZSxHS4~JopdOjbh_0aXbs6e-hqCt zfoGG+In^5CO~fDk!Mf95E%w|r9_3bGP-VB9(Vi!=U#~%5FL_)=cWes=|3byr;@EUr znd*_M`PkFngZMtBAMNHiSg+y#MQHjU-s5@ZvXi*3(^^+htSm$SFc< z32(p+XSm+IaF#5&uW`b=WJ_I?d8WH$N@)5%ZNlG*pA*TEjwzw1f&Ne4{bJORe&@+) z4W;Ikvl(rY3g~~47$?Bux%hT-P&pj_x}d<+Y)tdr&`WHUyYW|5X-KiNJs(^t)@_x&yv*JoNQ;k#+YY$9Elu7O*4yCsjy$y`#ddgMM^txj>8z^#2v558-?q+wwb-`8bmO*z)<# zRSwmW;PCQke1*4Zk|FN@k-z(qA0ME;OF{AzHqjy)YT= zIm6#=aKYJN{+3;(^JIFHCmSqXYftgbhgoQIVEtxPvK5-%4YmDFyPfDN|8>Q5RN04Y z?ZHaR{K79PHv6X_-x!a##Nj*Qu2e9 zjHk=-Ti}$ulg9p6LoYJipDdXSy3^TBfUhTw3xN*($OB*i$K)7K+0-Tc?hz5c&@T|+$ekiC83 z^B?%Rp7ebb%+L4A-Kby)+z;@LL#*}JVsrM$9&Ddmaqr%sl)iD}d}bK#PA|jMKF>uf zo0U`XJsfObByn=)^98wZI*Z_aT)z=YxC=Ipqm}BhqwWWx!LE~eq3L=#nC!XPRqn!} zLvi*$tZEY);&Jlx zxvPeh2hzx^i{u8qg@(3gbKU2z$x8SD9i{X%IJK2bl(Jzx3$=OP-^i;a3diGzY*ZhPca}JzNRhj>syIxD;wO}(J zk5g|h9VlbyMwD|g+;2vwWIx}C^DIE`Klyx4zwY5Rbi&7*t50rl|&nM+ul96-i@m*zbOoQ*GY=)mnle@t4#IjCQba*@VV@q+q-N5E| z(cUwx<-c}21z*%J_ASl8@7szQ9tm!HxaVK~+XVNg59WOS zjl~&4K71x>7_E8==qHn^3A)>#X59;g9PjlzNas4_ z&k&f-DP_8sRbxDzQj=x;ql~$9NKUpzqJYT;Xyz`-oH@l+_8>))MR78mA514TcBiZ> zebOQ^a>k#0*P3jk=Jqy_T+h6;WD0z2^|OkNQA#uWy$n|W;nkf=Z?o8weYhnW*%Xbg z=dTSb{)SdMu`uprU1i4CmU^x4j9>og?hR2x3s-AvWhU5aLVSHWy_ro8b=Sjuq6vyj zOe#^SgHS>ppIayXGX)j&z-{}xPcrv^!}Iskm~G)_IGSmS3l|roSQ+Dadb^WHq1=mE zryH>9k}Gy*B|0z|WX6JHPC19b?o9l+inOi?I$yHm*O8&=%$<2gGePB3e5TF;c9T#2 zC)}^X>xpCi&3;GlmJSjN`LC6}Y#qr1t*&8DUx8+z6q_y6s7|$(+RhDH(e_k3ky+bbr*oaIHv~Pm3rrRMZ4jXhfs1; z`&omZ-$tA7u(3Wa&I6U6u(-9|Z&-ou!DQo~@G_;y2~Ikmb$7?!IHx1M*^Z6)B<%FY zY3arMAuRVKnT{)G*7sl-8iZ4CvYM}8W+zuYfHiqMI2}y#G^M@!y6@`Z0PO)42FQ)Rw55VoKNa9GI?Z~%u%&YEvdLs_}zLGbw7!*@OITQz- z33u_8?s2tbd}O-GEEr4gr><6>oWmNu%uYkBc^kV`Mvu4G4Y z--6l9*f^b4T90nN0>9r5n>VAd>Pp-9+0)1PRBP7dr!e!P$0uNYF+H@ecTQ(_o`6Fy z!LJ>yXbKPV_ewl2RsA_@O-J>d3Z(mHW+yJeX&?K0vE5eT!zWSYspzS@tA7C(nf7*) z-R5y5eoSrnBzt@kPbIQ505xw0T4$oOXME#zR5P4~5&b=&xDqAQbB#8xwlDhM9Nae- zA($$HJdRDftNpccxAdFtZ0D&!N{5C{c9r>O^}XBPqdu;W5C0eWu&%hx=lilm-$gUm z+U=F_dbXdh+_MKNTnwA(dAScO=PWe44vpXLJYv_XqpCKq`o8=>(ZQN5j#08Ny-T}7$Mn@&fbs;$PCmFlL=1A+jnGU%Hp33D+Ge{S~)3KXvE8fC=X6o2@sE;G6THLAQ&mDQUe`A5) zmomPkLlEAl2&nd$;{RLpOD#F>1hOVpePgXw?+K=cx;KY{nt9^_)3C8s^- zxXF}=UHt+ZD?RUWTAfOl_>yBQo>y}CzHx>9NuFEq-ae%ImZVZD4A!IWjZ5G1G^Ud( zhlsBC^t=b&Y5)>VU_4crvq^>nNu{5P#L9c4!~fx? zRNP^$&b}l^~v5%Hp=P>1thO8b7wKacC>=EMf{vYaQW^i@Mf~57Ws3Yeb=?x^v-)6{1T1nCKmSt zitj8#us`el^WuB5{l{WwRFY_PZQAJvpL)%Hp7yP$NSHS6n>k5|#?)v1)M0P;bjOSE zKzq7A8E6ae-Ye)P)IFFkZAs=Ff%>;cK?i|-ZM^~~l-HJbt=gmN)pEJ&ysDAq9x(ng z7-bg7P9XJLu>lVJy+|B>A5go+`X8k;Q>UDq{U6*vnV9JV-Q2w!;FzC4F`fOBIWfr! zBl{95Ujc5{R^;>5Fqa-H-=&y1nB zSbdlI+$p@;)BOBa{EMDF7u|J&&-_0ebTeA-WH0ey+WMPrI}O2lop??Qw31xq-AJBxsH&6o-R9jUe$qE;2NBUD z{oV~F?v2lDm7XlmlQpwP)%5ZsPV86J`BpNOWXl2`3q zGd@*gIN7bdVR=0|OD+Gm@4(l1Uzg+YGkf;dTgiiDjhv?%C-=t%)}*Qies#_ zGtcK#Qtm9Wcyn6qPBQZad{mtkGS~_)r1_2^QQ!7$UZ`u0$6L?h(Q~c)GPcA_vOX3; zA~VmxSSa>f(XVtZn~IilZmHW37))gSu0;Jg<=B*jdKR9V6pw-6FnfI)WShWw`dp^Y z>lrwx!L#myMwa@{1vJ`k#VhpJL#mNqL%$u-U>|(Gywtr&mhX;sf1uC3B*r(YJhpsz zRsZtVaQj`k2|S#GC-#PuM%H-;t~m|`TvFQ5V{g=cn4P|?Z);uJVk3A-1UqrkC2*SB zkza67;xLKXEP(Btv@P^JXRpb^zZHJoAg^!24Lg(Pso;&c}(7Yc;ZY8^B z!)E$S-b1R@x2`SF>&~uzu=R&4Zg-bG>^nYsWLsBQ|H;m4l+!~hCs4^&Pkb_wl2Ir& zm5yiO)8p{--5%*Sy|;bW1l?n-s-_(;E;gnU`?3F@qmv#*W7~n=PTs%RcaQK|a*`9D zOP2Bm<-eR2rs^XT1^;9_rcQ2&3eBB$s^3k=<6U&fn~1xTA9^u*`59@+@9Y-`yGZ^%)$bdVHk6|MYm+9pd*7 zLl^CFTMII(hVR{sUS}6akn@?aab2lR`ASjo{Za2p_Pe9qXX@Qt`n@Iy#3sDJUDChq zAh_MK{1F=J;*l)hbUEz`BOSfhn5OSRE}RR7TcDmjQP?Tgd=KdE!An?BoB=+sgUO2` zCHwKHt|{GFzLbr=N7d4Dm-4fAI91Qc`*F_*aBPEPe??E}))p-_0ql2Slcd)Ee7ZHg z7dFL1ulwG?teQkIo3MrBb*4r+-HDR-+Xbdaqs(-QOTFe`FghGf{lQl}6nnPB=Xihcq_52D>$kv31TaqnS=)uQQJJ1^W!&&%yZtI|^~ zwY)2=ek~9CAYG0l-4kuzzWl2lEVH*8-7nRo>shexla8&?${g}2ooK#8HLo}+*#a$m zglkSjUt4=zWRLga(bK*1Z+lILi_GvF2|9hjrjK202tJRxV)`eJqT4bhZIJz)h+b0R zetBs$?EHe7ZYW(-?tqFj@#h3EO;u=muFPSxPbvOI9zDcbX<(1%`d)MQNi}CDzgt&4 zwVaW^Z&me+cko3uFJFx&&ji;aP*G~%M05BI(TDHTQ}uBDi{+ckcb6V4?^Ly{yp&uY zSpFO&`-9aP<=HUT#{QGpnp3jOns3L8JPE~bhR$n}!hgbg{Gk@GxN*5Hd$I>ubwJ;l zm5~aubQDi^OcxxN?9D#-t}p9o6bOB1CA*R6Q%JH$*~K@}ANN{c;ui&aU0u`whrdMr zRu((5+cJZ70!SPS28~Jj`{{)feRdP@??9?-Sx#St8t88gjK{m)Mqlecte~cx?(J~< zrk-!2-}Ub0ro7fo+#&sf{wi)~o9qWF>DZGD>tqBxWPdH~|4lr4HR-&RzkE8{_ypwc zaPK!!d1~nHA*-*q+f2h*Ox`Ul(vS3A`Xbdz>7O|h{8FdU8AOwdIFnXSKJliwbT+Fi zXLtvqqpi^3@9fqQWY4tX1`v71PLt7;4#w&7_`ZFn@9|e?u{|HCaRiPz zf{k(v9(;u_b2@H61I2twj&DJptt!$pIo;TfF27M;Ri0SxQ10q1{giTRw$GC=v#N9t zDcQw;Q{nTI$_{$7{;nr~4~6q&_H0=i2WF{kJQFQ!SYB44y9T%=_1~#t9B8MQ}7%KeK)De6p=_a+%DlM&$F;;CmJh z*@5IO;m565B{^r=%gS1V(NCbz8g3JV%`Di|V0MJvbS{klmYR%qs6Kt6I^l}+*V@{5 zPXy1CNX1*}(7IN=C#?TjY=Z8Wi|=OAzy+=~2j^~Fp6PQZy2HL7BRP&Gxi`kq znNyr;b&U$KPBhNmyqnr6@^0`; z*MW3l$y}h<@#ZsjJ;uKJIL%B?osylO2$o0Fj3fBx>xyl0(?+oMn%%|c%30zoz8xGi zs;p*cMbqt|E;?u5EPKVprqlZOf_l z?opBHnYfmW*fHSvr5z{Nb-Jsh4k>-d`di^ja^f(u^WWh4cYjkUw=If4!{0JaiLbtq z{lu2J2;{cGp|Q-n;lyV^`(FF{5$$FQ#D>lvGLigGbWug0%(9QnEu3hl>%3dW-2<-Ym~b!ihF?cnp3=iB0G|c=|!Ck@G(B|KM?6aS`N0eOn-RY zzP}~!UZj~mB27{~mYymd$+mB-H}g2o##MiSU@N*Hb%c@bKRMB^DULgW<#jsy`8YAo z@#OPo?DcgZlIT=??909L94tkbcY@9I`x%bfCc0lcdbBH#eP}VHIIQ#!a!I_@O5-~& zq-oNZ_i9kxhc$OK*|G$EHTC+Ju9ke#0lc`UV10p=XMWBDdcMDGb$K@vlDqg!Z@TFp zu5dZsFkj?kL9rVPYfD(Vz|L>QE44xENqn6AmhSeP{@$s9o(EE0tbB<3^@s6lTW1&= zP|sClcF8485;zrUgk?}L(y{3re0yfq!?sO!)+=KGc&1M}g-oD(IKEDX&zu<@c zj{oPfGfS|(DNZi2MbcLyxi6VXxyEA?n!F}VZ(2_O&24D?oy&Wbr-EVw7R(D)eLM`M zbIt@jo_z4Z;Fi3UOmM6|DGT%;^(<%RlThwFa`Aq&dOn==_KgnUl)fVIOwzS*2s|9X z(tQ@b8j&_Mda>Sa{v%qpP#m|tQ|dNFxD0@3i><$tQS9aTQWU0Cu7_-+?5)p#Dm&;_D|CP67anncRUDw>9YK71vi;0 ze;C=m5i4wR=|0f89mX5OU^6>z1Y=)X??qO#0#%o3u=Uow*4_5Es`t^sLr$FHNB$R& z{|Z9MZjHy5=w-ScBtPMI@W_f{AB+LdLHHrl2lKr;fe)%vqaRd zir$S^dU~Qu+zn{c$>L8-C5?;vZJ@IQ*qjBvX}BIg`mBi83bR@ICiWl&PC{ zUZmNp(B(Vs-Wfj9MQZ>FlKvgZQo0J%dKb0v!HKM`H*sc1r>38Zn7szy14IXUz;(LR z+yxRxvn$SK$!DHzJy6=H{0YdX`noxplMX;_-Tf`kV91Wq3WZi9LAIX_QV z*B9*X9Q^$}`FaSv9*cK#zSNZcnXbCq(NTN*ZyT^U1%^LHKe35sxyN|dNM*hAWcXVv z!n6Sn&Xk!{&ZVDptmp-NlVo0x6OBEb^xC>Iy`=> zICEmE<6Of@(Gj4PUg=qXdQoMrZ}NJx!vSomk7(#w#fuevm3a`!yci2EcfnjLR_`sf zV`)9dZfh%cJEeHviDq;9e3G-2FWs?MaRqsCG!1rJMRz_-`h3F+NsYq0FgU>PbURE1 zPh#tR(ZhQ7{vSB-Z)}n~a6+dLEGoXqQVzg$MkuOxHsbV{|o=){5c zdrN#czoEI+R-f~fwm$nB z&G;;7(v=h$B*K?&PU&-am8-l*3$;ZjP2nN>zJphW;*J-+(j1rOw7L%rq~Alb9KW=Z zQ)!3f>)uGq+~ubZe$JHP#`tvxN&h(Mbd_~?gpp+1e@y}=dpMBE)Y?p7P6b5bR&S!$ zui^MjtDnQqUqH(JRh%O>ktuYixYFCGwvN>viq~t=_qo$zbejm*L~Bi#!Qr0&0b}vU z6Xl(a@5itttNA@uDVvgQ-NF4`>-vSCRwCDHR&ZUA53%;r89hA_KEY{Aae2A4f%`q+ z{=M9(ddhM#sFIsi-SHxwSvuQ8Tl@ZqoJdw;Dtg6HeJ9mT$zS=Rw77hJsZLSHN$GPq zypvP1S@1lPFFhUhd&^Gw2A|Ktue0nwQyOO5itp}edeMH}f zxuvDE%b&pWB`}_Ob&+LX`THOC;eSw9J5ik(qSo~b9S}*V+fl;$;yJuIl+Si23i{S6 zlS!DX#`|pQ`6!sneA2$CJ+@*)*Wb+*kHdZcaqpY#^E@&p9ot^B+JnLA3HUn8^=W_Y zq7&AkkW7NiiCUsD&y#$KeeQrW&$YHE=*G;8Nhi9Ys5ocTecZoig-_l`;|q)9;UiN} zUqM%AIxlzvp8AtdkCqpZG5-hZt>nvg0J?IWP5O!E6-T+L;90-E_?5XybFxOO^H_Fz!#rc9PxrDSv$^|81<3 zn&dY<3Ag_xhkp~5`BhBrbdu@6?((u-r~hL5%BAOGDrI`PP8Y9!Si$-2to7xh2d9$h ziS4|B-qP`>7u=<9=y|yRQT||Ucz?t?k~dJ@Z#cI5H~3_*S2A@o5y~;J`MQ0jzUy#U zKE&@M;JG%da1lS|cKc~!Rn>B%wn$Jsq?~f5vqh>1G8uV<*vn&9yLUO0!{VteBIl}O zu76s=?yl0(%8us?K1r?|fkHBYJkz3fAlWyE`5K-r@SSDoX)w)O19bK#UpHaB{GG&U zg10jxq7%GU*Slw?Uut|Cp!A9S-mTF_YV%s6{o{G|^=Pd6#haz}#qHqVipSjTdi z)|7TCukqQ9$@zG5=`r)YJzs-I6OrAP##zdue$SmE%R566L&3 zF5LyQcyWO~?tPEp#Cv9H5{Tqt}R33#5!^nN((i1L3}9#8Xlhq8sZNk{-ns_VlVQp0~u2;eaV8@yOb)qZ}<;=it}iu%$WMY{^E^~#T%#F&1Irt^Tb9j zr+uHV$jSSystp__diw&tPXDlUxW0r=t7G36lQPZV`W5stj?5kCTFC;>tfov=&XnEY z>><=Q(uy+k;8J@zn5Mc4Pd;lWnX8x_tutAU$C7!ExL)d=$ANuLYQlM4(A7-1d<-2e za-Vg0B>s2ihbK0FD;Qo0=X3DUyy80en8%x63Daf%S`EJ1rlNAI(Z_~<7v%}A`WCG3 zQCe=l+mkqJi%bUpxPt3GWJ`2)CcVWk`hfJgw&J-A^6H7=rkO(cBKrN@`DiaVPiETT zqu(dmW2G{k#`k7K+ zR{lYydA@Twj0}Xq%}ei*MPK_|PiGd-x?g{Ip2&6^0Q1Aq+XSCF$_lE;t>22B&{p_; zQ-1I~R>hwrLULH11@+V^z6BFIyY|7QZ>(-tufB!XKEOF=;^Mo=-G5uly>>dr6|eE` zTh?+ls=E^;uCw>}=5z4RAXJpe9m#EqZcncIApfl(9oLAcZ%Epl=9|~jp(o?;rtb5s zy=SgLx|F8ZMRM9R0p)YhA5Q7BU5eQLsAGK1ISy-P{FUvYU? zva=S=v03>~6tS9BT$Am-39o%i_^w&b{PqPNu@AeGSBJ4E68T+(D|+Fy)^L*wrpynG zl@q<*#a*u?kCMxA7A^8G&}~gq-U*_winn|&m-lzpdHv!U_-;zB5AgW9Qg_;e)E`-# z>eH8j^OY>w`_cD3xF8+T5}Qu{hi+bP2coISo(hM}(7^6sb_osiDSDj2JFm^cZCV;w zt|~nN*F#)&h{tz0eHi(+B|f~E+WWC>8 z_gd1Ywza%!m&1JGJea*!e5STf9zYH+FZO}$r@V6t9{(S{zaM?v=o9VmWO|;&E68-A z*u0}~>-Tsv9j6;xOKKf+=J!wgJ`2UyBP}MwRchdq>zW>tAA`l4?9)l#GKFy6S`Hy;MQx@71RXuP^Nd7^rmNiv#z z`;xq0;@io0$tmB(pth2BNH@b~pgFa8n%sU8j;F%-Q1_V1^Y2TC)P}87`E&cb{`O9+ zj-#>Cr+fxVP7j4-|DTLsZ}j>!_)Z;O4f1~#ng3*|A<5GS?;Yh-WqTU-BKN+~UN^@R z?}5xo@P9n4r#kvUcesZXc*MHXLAoCdeGbdPc;bHPm=M3`CbUu0^$zmwOUcMrJbG66 zZ7KPXPPpmmnyjAmpP5C*Jn3`o!6B2q=HUEfO=m*idb;&o7-))SKK7XxL1!HdZbNq8 zfDZ~j!TRC_T7PpmkF~x5evjw2g};gAB&w5HQOkX68hkc!rCs6saF)t}yp=ob=XxBs z7y3!YQ!+!+Tca0SYC3+7CU^z*{$P)l;p9u+ak|<}Bw-rUnU~bCrVH~Jmf+)L(_rsBN6zlUM*JETv_e-GqUTp> zj5)A9q=N4e_<1~f&GeWP;QKVPMqS{=IjKCi7P(vh`>*Q?y^ zui_DM@&{Cy3e8vHbwB4{SKxzmNxg>V{>Ak#bd3{f_A~J7J*f9;e;>ykGvRg$48;oV z0Y5#^L0=f@0zRkV>4QMDHabb}YO*rYNp^k(!->@o#_93;V*k&z(g~#a1=f(M$f+od zf079IFSz7nQZ`xZPm>4FyV7DYm$fE-Z&)5jSG07`gJC)yA=bfiO>#Zwa2xX1Gl@Fb zP9!JK)_69X2Dp*U_lH=?t!%;hMY{0bP9MIB<`Q>L7wHl9@j33^T-0J8a-=t%+JuCB z4Bxb8JFS5A(Ow+@|D)h!DBKUEDgP`k1-EO^`GX{AI>X*fN~BXrA}*cmZEoe-4M?&V zOT%EYuT>3#fpn1wls6`c_pz=?Y9d~9-HGto7d7?8>7!6XP1rk%ggX$$Hy3k!!5U}s zTkk-*N0k17Qm@D9`qJ!j{zKfF+ce)9srQ2sttN*~m zV_-d9O*7-KGpwffK>7{61lkQ?;C$Hq#=Gep-peC>P&aqITT2~jtDlQq@Jqi+q-HHS zp7_faJhM&6^5w2Rnj~4}-Nfxzd3QtaXGZBFP|Xa(W#W06K9XtHm!SG1UH3Kn*})F? zw9jGaA^ma_tNFt3_UJGWnG4=cDt_4~Fxn6{#udBEdhZU)k+%cL+pj%F;gANE^W$)K zbm61^=0v2spB5~t*^^(*$83BRY|z4q?% z46S@|>E~iUIBZ6y?~P6l_Ws3onoP0g{Js-#`YAAerK_FEGI)a2NL;lk4ozKWw0T>S z_$&Jv;`Jk3X(-&?fNyWWhv`4Cf~<{|mt2^19vY92GeIexn!m!$(X{>O(?m)dgUYw~ zJ^g%!vD}gux|>sneq`yNMJrdH411Xh_9q;carjzzOvZJ1Xh}t0Le6X73O!dy( zsCnM|gN*nC%{2n0E6BZ%V5Ytm&n$8}@FAHsl&#zczO$cn*L{wT>JHzj-0#U_nqC~} z)9qk;V#O053fJG_@tNRs0xaC;8kgbn`|SNOIDg7@I@!~Et`^H@G2ToMKeNzKNO~*A z$9c=A!Z%GpIWw8p6{q33omk~Ry6-|-W1PFsD~=`UjslPItg+vUS!+;qZv4No2f%cqeHwM&!vf=kfxZfNE) z9B>SK;Y60$nXrE-oImI@uj19Nv}2-KnR?mFT~BhIzU2BRB>jUVW-Rn?!F+H2@*Mn| z?pKlJnIAgRz5Ai}_I@X()7LdpQIcLQkr@3zs+aHNL@0UN<5BtF=<6FSO}>l>ux!(je0 zD`luXXVO3)aG2$H7cwyQ#CL<~OqBf&e58Zd=45IeT=Og_)?qcIf;aWhyP&x7WZdv# zXSTt)@Uy?X>$Z4*YH<^qJdcHToOM2j)8BTd&(T&+=GwY?Cl#1)DA$zw4MzHvF#S{wPD zX|%EH7l3??@=Ba>1x%#Y>RG#a%iexwp>6Dr?NMMlasCH&_s37+@1FdlNx1!cm~My$ z7Ql5ouZ^qd*nM!?ZE*E3k0X5RL94%;&GP~XCl>vg=b0s(Gn;qNz zsmS0P{eHl85=(i)H}-Lc`MNbshp(I-_VLLs*1IDMbtCj}dT9Zj*;!UjJJKv&tyUE0 zpvYR*b_`Dc6~0@6*8L>c`831(?B(aluhb8pV?TXK%Jk40>g1uGzv%??7v9>DJ++=L zokhAV!r|%A{|zklvx3OJ&hV9dg=7z0UHY@Qy+Q*G$ehfoT2O3h=Rb;q9Er}`fx|uU z{2>f4X4n5pzOTo_t4N%96Uo0!by|&bba)Namh;tLSo(i?brsx?FKxxTcpao}_UZdj z)tMEJ+8)(Ci~f4U-)$`2ejv~t^(VW0j3`S7GJL$=eslRWrP8-3A+gXaDwgfBWNID% z-D8F6|8WB>q(ekIRGf}H>HVFmyUf;Tfev>mzw9%g;PGus@1mmUh>pdD=<*|SY;%%l ze;7X%PA)0UDvqv5;3Lt;VKCI+3MP;`tBR(s`JmM{$8$q)SY|$FF5w&aDKiG{6KAMp zO^@NseLP-=y~j{^`Xg_JUM^;{r|Z`RrMJbJ63uVr>Vx=uC%RIo?4Nwe(@{!)^m(_v zr3X=c+!D|JIJ#pfE_n|{v=@tPRwQles!6EN}X?BYy#`>{w5(icm0#6BC+)O~2~ zft3i?_s+)`(&rnB-=+u8hPd!X$L(hZUfu#@eR|me>_hP0?i)nUrwsk~Lre<+08GZojI2nE}fQ36q+~hDV zW$A4QC&TRaWshMf{-2AVSWawCrxO#$A5S*U0>{1SuR65kPM%G5N^l}iH6H3d z;(+goG-bAMB8U@Q`vmts#@@E|H@U7&*(R6Zgc~Xn?OoJ+F%0Ac@@8_lndnsVMOKql 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%0Dj>cHoCdbk<7Z)+88SP*ZboD)IzS=a1>L$W7t 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 L&V3s<8XWu!riJvI literal 0 HcmV?d00001 diff --git a/skimage/rank/local/test_morph_contr_enh.py b/skimage/filter/rank/local/test_morph_contr_enh.py similarity index 93% rename from skimage/rank/local/test_morph_contr_enh.py rename to skimage/filter/rank/local/test_morph_contr_enh.py index 812e81c5..f2f0f7c9 100644 --- a/skimage/rank/local/test_morph_contr_enh.py +++ b/skimage/filter/rank/local/test_morph_contr_enh.py @@ -3,7 +3,7 @@ import matplotlib.pyplot as plt import gdal from skimage.morphology import disk -import skimage.rank as rank +import skimage.filter.rank as rank filename = 'iko_pan_Ja1.tif' im16 = gdal.Open(filename).ReadAsArray().astype(np.uint16) diff --git a/skimage/rank/local/test_rank.py b/skimage/filter/rank/local/test_rank.py similarity index 95% rename from skimage/rank/local/test_rank.py rename to skimage/filter/rank/local/test_rank.py index 75dd7f65..09cfdcd5 100644 --- a/skimage/rank/local/test_rank.py +++ b/skimage/filter/rank/local/test_rank.py @@ -3,7 +3,7 @@ import matplotlib.pyplot as plt from skimage import data from skimage.morphology.selem import disk -import skimage.rank as rank +import skimage.filter.rank as rank print dir(rank) diff --git a/skimage/rank/percentile_rank.py b/skimage/filter/rank/percentile_rank.py similarity index 98% rename from skimage/rank/percentile_rank.py rename to skimage/filter/rank/percentile_rank.py index ac19ccd6..7908f5ac 100644 --- a/skimage/rank/percentile_rank.py +++ b/skimage/filter/rank/percentile_rank.py @@ -14,14 +14,11 @@ result image is 8 or 16 bit with respect to the input image """ - -import warnings from skimage import img_as_ubyte import numpy as np -from generic import find_bitdepth -import _crank16_percentiles -import _crank8_percentiles +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', @@ -77,7 +74,7 @@ def percentile_autolevel(image, selem, out=None, mask=None, shift_x=False, shift to be updated >>> # Local mean >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], @@ -141,7 +138,7 @@ def percentile_gradient(image, selem, out=None, mask=None, shift_x=False, shift_ to be updated >>> # Local gradient >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], @@ -205,7 +202,7 @@ def percentile_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa to be updated >>> # Local mean >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], @@ -269,7 +266,7 @@ def percentile_mean_substraction(image, selem, out=None, mask=None, shift_x=Fals to be updated >>> # Local mean_substraction >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], @@ -333,7 +330,7 @@ def percentile_morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, to be updated >>> # Local mean >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], @@ -397,7 +394,7 @@ def percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, to be updated >>> # Local mean >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 128*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], @@ -462,7 +459,7 @@ def percentile_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal to be updated >>> # Local mean >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], @@ -526,7 +523,7 @@ def percentile_threshold(image, selem, out=None, mask=None, shift_x=False, shift to be updated >>> # Local mean >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], diff --git a/skimage/rank/rank.py b/skimage/filter/rank/rank.py similarity index 98% rename from skimage/rank/rank.py rename to skimage/filter/rank/rank.py index 51854128..0a9dee27 100644 --- a/skimage/rank/rank.py +++ b/skimage/filter/rank/rank.py @@ -12,14 +12,11 @@ result image is 8 or 16 bit with respect to the input image """ - -import warnings from skimage import img_as_ubyte import numpy as np +from skimage.filter.rank import _crank8, _crank16 -from generic import find_bitdepth -import _crank16 -import _crank8 +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'] @@ -71,7 +68,7 @@ def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local mean >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], @@ -133,7 +130,7 @@ def bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local mean >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], @@ -194,7 +191,7 @@ def equalize(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local mean >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], @@ -255,7 +252,7 @@ def gradient(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local gradient >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], @@ -317,7 +314,7 @@ def maximum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local maximum >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 0, 0, 0, 0], ... [0, 0, 1, 0, 0], @@ -379,7 +376,7 @@ def mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local mean >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], @@ -441,7 +438,7 @@ def meansubstraction(image, selem, out=None, mask=None, shift_x=False, shift_y=F to be updated >>> # Local meansubstraction >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], @@ -503,7 +500,7 @@ def median(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local median >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 0, 1, 0], @@ -565,7 +562,7 @@ def minimum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local minimum >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], @@ -628,7 +625,7 @@ def modal(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local modal >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 5, 6, 0], @@ -691,7 +688,7 @@ def morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa to be updated >>> # Local mean >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], @@ -753,7 +750,7 @@ def pop(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local mean >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], @@ -815,7 +812,7 @@ def threshold(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local mean >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], @@ -878,7 +875,7 @@ def tophat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): to be updated >>> # Local mean >>> from skimage.morphology import square - >>> import skimage.rank as rank + >>> import skimage.filter.rank as rank >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], ... [0, 1, 1, 1, 0], ... [0, 1, 1, 1, 0], diff --git a/skimage/rank/setup.py b/skimage/filter/rank/setup.py similarity index 100% rename from skimage/rank/setup.py rename to skimage/filter/rank/setup.py diff --git a/skimage/rank/tests/test_suite.py b/skimage/filter/rank/tests/test_suite.py similarity index 97% rename from skimage/rank/tests/test_suite.py rename to skimage/filter/rank/tests/test_suite.py index 9d2bcfea..4f1e6f81 100644 --- a/skimage/rank/tests/test_suite.py +++ b/skimage/filter/rank/tests/test_suite.py @@ -1,12 +1,12 @@ import unittest import numpy as np +from skimage.filter import rank -from skimage.rank import _crank8,_crank8_percentiles -from skimage.rank import _crank16,_crank16_bilateral,_crank16_percentiles -from skimage.morphology import cmorph,disk from skimage import data -from skimage import rank +from skimage.morphology import cmorph,disk +from skimage.filter.rank import _crank8, _crank16 +from skimage.filter.rank import _crank16_percentiles class TestSequenceFunctions(unittest.TestCase): diff --git a/skimage/rank/local/__init__.py b/skimage/rank/local/__init__.py deleted file mode 100644 index e69de29b..00000000 From 53deddf5e06616d10d481bb2f0e2fb7e9c22c220 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 18 Oct 2012 10:12:19 +0200 Subject: [PATCH 77/86] cut long lines --- skimage/filter/rank/bilateral_rank.py | 9 ++++++--- skimage/filter/rank/percentile_rank.py | 27 +++++++++++++++++--------- skimage/filter/rank/rank.py | 24 +++++++++++++++-------- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/skimage/filter/rank/bilateral_rank.py b/skimage/filter/rank/bilateral_rank.py index 1dc7552d..5ea92ed9 100644 --- a/skimage/filter/rank/bilateral_rank.py +++ b/skimage/filter/rank/bilateral_rank.py @@ -45,7 +45,8 @@ def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y, s0, s1): 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) + return func16(image, selem, shift_x=shift_x, shift_y=shift_y, mask=mask, bitdepth=bitdepth + 1, out=out, + s0=s0, s1=s1) def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False, s0=10, s1=10): @@ -109,7 +110,8 @@ def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal """ - 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): @@ -173,7 +175,8 @@ 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) if __name__ == "__main__": import sys diff --git a/skimage/filter/rank/percentile_rank.py b/skimage/filter/rank/percentile_rank.py index 7908f5ac..77858715 100644 --- a/skimage/filter/rank/percentile_rank.py +++ b/skimage/filter/rank/percentile_rank.py @@ -35,7 +35,8 @@ def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y, p0, p1): 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) + return 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!") @@ -101,7 +102,8 @@ def percentile_autolevel(image, selem, out=None, mask=None, shift_x=False, shift """ - 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.): @@ -165,7 +167,8 @@ def percentile_gradient(image, selem, out=None, mask=None, shift_x=False, shift_ """ - 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.): @@ -229,7 +232,8 @@ def percentile_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa """ - 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.): @@ -293,7 +297,8 @@ def percentile_mean_substraction(image, selem, out=None, mask=None, shift_x=Fals """ - 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.): @@ -357,7 +362,8 @@ def percentile_morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, """ - 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.): @@ -422,7 +428,8 @@ def percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, """ - 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.): @@ -486,7 +493,8 @@ def percentile_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal """ - 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.): @@ -551,7 +559,8 @@ def percentile_threshold(image, selem, out=None, mask=None, shift_x=False, shift """ - 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) if __name__ == "__main__": diff --git a/skimage/filter/rank/rank.py b/skimage/filter/rank/rank.py index 0a9dee27..d4df3aef 100644 --- a/skimage/filter/rank/rank.py +++ b/skimage/filter/rank/rank.py @@ -18,7 +18,8 @@ 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'] +__all__ = ['autolevel', 'bottomhat', 'equalize', 'gradient', 'maximum', 'mean', 'meansubstraction', 'median', 'minimum', + 'modal', 'morph_contr_enh', 'pop', 'threshold', 'tophat'] def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y): @@ -95,7 +96,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): @@ -156,7 +158,8 @@ def bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): [ 0, 0, 0, 0, 0]], dtype=uint16) """ - 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): @@ -217,7 +220,8 @@ def equalize(image, selem, out=None, mask=None, shift_x=False, shift_y=False): [3071, 2730, 2047, 2730, 3071]], dtype=uint16) """ - 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): @@ -279,7 +283,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): @@ -465,7 +470,8 @@ def meansubstraction(image, selem, out=None, mask=None, shift_x=False, shift_y=F """ - 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): @@ -715,7 +721,8 @@ def morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa """ - 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): @@ -840,7 +847,8 @@ def threshold(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """ - 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): From ce0a609579bdf35b641c223fea52f5b9ef8079cb Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 18 Oct 2012 10:21:34 +0200 Subject: [PATCH 78/86] autopep8 --- skimage/filter/rank/_core16.pyx | 2 +- skimage/filter/rank/_core8.pyx | 2 +- skimage/filter/rank/bilateral_rank.py | 9 ++++++--- skimage/filter/rank/percentile_rank.py | 27 +++++++++++++++++--------- skimage/filter/rank/rank.py | 21 +++++++++++++------- 5 files changed, 40 insertions(+), 21 deletions(-) diff --git a/skimage/filter/rank/_core16.pyx b/skimage/filter/rank/_core16.pyx index 81fab0b4..e60308ed 100644 --- a/skimage/filter/rank/_core16.pyx +++ b/skimage/filter/rank/_core16.pyx @@ -47,7 +47,7 @@ cdef inline np.uint8_t is_in_mask(Py_ssize_t rows, Py_ssize_t cols, Py_ssize_t r 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.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, diff --git a/skimage/filter/rank/_core8.pyx b/skimage/filter/rank/_core8.pyx index 7851388d..0d30045f 100644 --- a/skimage/filter/rank/_core8.pyx +++ b/skimage/filter/rank/_core8.pyx @@ -47,7 +47,7 @@ cdef inline np.uint8_t is_in_mask(Py_ssize_t rows, Py_ssize_t cols, Py_ssize_t r 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.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, diff --git a/skimage/filter/rank/bilateral_rank.py b/skimage/filter/rank/bilateral_rank.py index 5ea92ed9..ff4e7878 100644 --- a/skimage/filter/rank/bilateral_rank.py +++ b/skimage/filter/rank/bilateral_rank.py @@ -45,7 +45,8 @@ def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y, s0, s1): 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, + return func16( + image, selem, shift_x=shift_x, shift_y=shift_y, mask=mask, bitdepth=bitdepth + 1, out=out, s0=s0, s1=s1) @@ -110,7 +111,8 @@ def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal """ - return _apply(None, _crank16_bilateral.mean, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, + return _apply( + None, _crank16_bilateral.mean, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, s0=s0, s1=s1) @@ -175,7 +177,8 @@ 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, + return _apply( + None, _crank16_bilateral.pop, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, s0=s0, s1=s1) if __name__ == "__main__": diff --git a/skimage/filter/rank/percentile_rank.py b/skimage/filter/rank/percentile_rank.py index 77858715..5191bec4 100644 --- a/skimage/filter/rank/percentile_rank.py +++ b/skimage/filter/rank/percentile_rank.py @@ -35,7 +35,8 @@ def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y, p0, p1): 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, + return 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!") @@ -102,7 +103,8 @@ def percentile_autolevel(image, selem, out=None, mask=None, shift_x=False, shift """ - return _apply(_crank8_percentiles.autolevel, _crank16_percentiles.autolevel, image, selem, out=out, mask=mask, + 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) @@ -167,7 +169,8 @@ def percentile_gradient(image, selem, out=None, mask=None, shift_x=False, shift_ """ - return _apply(_crank8_percentiles.gradient, _crank16_percentiles.gradient, image, selem, out=out, mask=mask, + 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) @@ -232,7 +235,8 @@ def percentile_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa """ - return _apply(_crank8_percentiles.mean, _crank16_percentiles.mean, image, selem, out=out, mask=mask, + 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) @@ -297,7 +301,8 @@ def percentile_mean_substraction(image, selem, out=None, mask=None, shift_x=Fals """ - return _apply(_crank8_percentiles.mean_substraction, _crank16_percentiles.mean_substraction, image, selem, out=out, + 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) @@ -362,7 +367,8 @@ def percentile_morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, """ - return _apply(_crank8_percentiles.morph_contr_enh, _crank16_percentiles.morph_contr_enh, image, selem, out=out, + 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) @@ -428,7 +434,8 @@ def percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, """ - return _apply(_crank8_percentiles.percentile, _crank16_percentiles.percentile, image, selem, out=out, mask=mask, + 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) @@ -493,7 +500,8 @@ def percentile_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal """ - return _apply(_crank8_percentiles.pop, _crank16_percentiles.pop, image, selem, out=out, mask=mask, shift_x=shift_x, + 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) @@ -559,7 +567,8 @@ def percentile_threshold(image, selem, out=None, mask=None, shift_x=False, shift """ - return _apply(_crank8_percentiles.threshold, _crank16_percentiles.threshold, image, selem, out=out, mask=mask, + return _apply( + _crank8_percentiles.threshold, _crank16_percentiles.threshold, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, p0=p0, p1=p1) diff --git a/skimage/filter/rank/rank.py b/skimage/filter/rank/rank.py index d4df3aef..517ab2cf 100644 --- a/skimage/filter/rank/rank.py +++ b/skimage/filter/rank/rank.py @@ -96,7 +96,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, + return _apply( + _crank8.autolevel, _crank16.autolevel, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) @@ -158,7 +159,8 @@ def bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): [ 0, 0, 0, 0, 0]], dtype=uint16) """ - return _apply(_crank8.bottomhat, _crank16.bottomhat, image, selem, out=out, mask=mask, shift_x=shift_x, + return _apply( + _crank8.bottomhat, _crank16.bottomhat, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) @@ -220,7 +222,8 @@ def equalize(image, selem, out=None, mask=None, shift_x=False, shift_y=False): [3071, 2730, 2047, 2730, 3071]], dtype=uint16) """ - return _apply(_crank8.equalize, _crank16.equalize, image, selem, out=out, mask=mask, shift_x=shift_x, + return _apply( + _crank8.equalize, _crank16.equalize, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) @@ -283,7 +286,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, + return _apply( + _crank8.gradient, _crank16.gradient, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) @@ -470,7 +474,8 @@ def meansubstraction(image, selem, out=None, mask=None, shift_x=False, shift_y=F """ - return _apply(_crank8.meansubstraction, _crank16.meansubstraction, image, selem, out=out, mask=mask, + return _apply( + _crank8.meansubstraction, _crank16.meansubstraction, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) @@ -721,7 +726,8 @@ def morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa """ - return _apply(_crank8.morph_contr_enh, _crank16.morph_contr_enh, image, selem, out=out, mask=mask, shift_x=shift_x, + return _apply( + _crank8.morph_contr_enh, _crank16.morph_contr_enh, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) @@ -847,7 +853,8 @@ def threshold(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """ - return _apply(_crank8.threshold, _crank16.threshold, image, selem, out=out, mask=mask, shift_x=shift_x, + return _apply( + _crank8.threshold, _crank16.threshold, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) From 662ac3039ae0b5e4aecb3ca912ae9de3149945f3 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 18 Oct 2012 15:21:14 +0200 Subject: [PATCH 79/86] add example modal --- doc/examples/plot_modal_filter.py | 67 +++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 doc/examples/plot_modal_filter.py diff --git a/doc/examples/plot_modal_filter.py b/doc/examples/plot_modal_filter.py new file mode 100644 index 00000000..a66da0a1 --- /dev/null +++ b/doc/examples/plot_modal_filter.py @@ -0,0 +1,67 @@ +""" +=================== +Label image regions +=================== + +This example shows how to segment an image with image labelling. The following +steps are applied: + +1. Thresholding with automatic Otsu method +2. Close small holes with binary closing +3. Remove artifacts touching image border +4. Measure image regions to filter small objects + +""" + +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.patches as mpatches + +from skimage import data +from skimage.filter import threshold_otsu + +from skimage.filter.rank import modal + +from skimage.morphology import label, disk +from skimage.measure import find_contours + + +image = data.coins()[50:-50, 50:-50] + +# apply threshold +thresh = threshold_otsu(image) +bw = image > thresh + +# label image regions +label_image = label(bw) + +# filter obtained labels using model filter +mod_label_image = modal(label_image.astype(np.uint16),disk(5)) + +# the background is here 1 +contours = find_contours(mod_label_image==1,0, positive_orientation='low') + +fig, axes = plt.subplots(ncols=2, nrows=2, figsize=(6, 6)) + +print axes + +ax0, ax1, ax2, ax3 = axes.ravel() + +ax0.imshow(bw, cmap='gray') +ax0.set_title('Otsu threshold') +ax1.imshow(label_image, cmap='jet') +ax1.set_title('label image') +ax2.imshow(mod_label_image, cmap='jet') +ax2.set_title('filtered labels (modal)') +ax3.imshow(image, cmap='gray') +ax3.set_title('contour overlay') +ax3.set_xlim((0,image.shape[1])) +ax3.set_ylim((image.shape[0],0)) + + +for n, contour in enumerate(contours): + ax3.plot(contour[:, 1], contour[:, 0], linewidth=2) + + +plt.show() + From 8f7419a227f76f58d8affa30542f39ff6991b71a Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 18 Oct 2012 15:32:24 +0200 Subject: [PATCH 80/86] cut long line, autopep8 --- skimage/filter/rank/_core16.pxd | 2 +- skimage/filter/rank/_core16.pyx | 2 +- skimage/filter/rank/_core8.pxd | 2 +- skimage/filter/rank/_core8.pyx | 2 +- skimage/filter/rank/_crank16_bilateral.pyx | 10 +- skimage/filter/rank/_crank16_percentiles.pyx | 72 ++++++++++---- skimage/filter/rank/_crank8.pyx | 99 +++++++++++++------- skimage/filter/rank/_crank8_percentiles.pyx | 56 ++++++++--- 8 files changed, 174 insertions(+), 71 deletions(-) diff --git a/skimage/filter/rank/_core16.pxd b/skimage/filter/rank/_core16.pxd index a2843f76..a113f2b0 100644 --- a/skimage/filter/rank/_core16.pxd +++ b/skimage/filter/rank/_core16.pxd @@ -9,7 +9,7 @@ cdef inline int int_max(int a, int b) cdef inline int int_min(int a, int b) 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.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, diff --git a/skimage/filter/rank/_core16.pyx b/skimage/filter/rank/_core16.pyx index e60308ed..81fab0b4 100644 --- a/skimage/filter/rank/_core16.pyx +++ b/skimage/filter/rank/_core16.pyx @@ -47,7 +47,7 @@ cdef inline np.uint8_t is_in_mask(Py_ssize_t rows, Py_ssize_t cols, Py_ssize_t r 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.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, diff --git a/skimage/filter/rank/_core8.pxd b/skimage/filter/rank/_core8.pxd index 1a170500..8ecf7263 100644 --- a/skimage/filter/rank/_core8.pxd +++ b/skimage/filter/rank/_core8.pxd @@ -9,7 +9,7 @@ cdef inline np.uint8_t uint8_min(np.uint8_t a, np.uint8_t b) #--------------------------------------------------------------------------- cdef inline _core8( - np.uint8_t kernel(Py_ssize_t * , float, np.uint8_t, float, float, Py_ssize_t, Py_ssize_t), + 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, diff --git a/skimage/filter/rank/_core8.pyx b/skimage/filter/rank/_core8.pyx index 0d30045f..7851388d 100644 --- a/skimage/filter/rank/_core8.pyx +++ b/skimage/filter/rank/_core8.pyx @@ -47,7 +47,7 @@ cdef inline np.uint8_t is_in_mask(Py_ssize_t rows, Py_ssize_t cols, Py_ssize_t r 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.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, diff --git a/skimage/filter/rank/_crank16_bilateral.pyx b/skimage/filter/rank/_crank16_bilateral.pyx index 24016bbf..d6fb9c71 100644 --- a/skimage/filter/rank/_crank16_bilateral.pyx +++ b/skimage/filter/rank/_crank16_bilateral.pyx @@ -22,7 +22,10 @@ from skimage.filter.rank._core16 cimport _core16 # ----------------------------------------------------------------- -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. @@ -39,7 +42,10 @@ cdef inline np.uint16_t kernel_mean(Py_ssize_t * histo, float pop, np.uint16_t g 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 if pop: diff --git a/skimage/filter/rank/_crank16_percentiles.pyx b/skimage/filter/rank/_crank16_percentiles.pyx index 73ccde68..0d37b77c 100644 --- a/skimage/filter/rank/_crank16_percentiles.pyx +++ b/skimage/filter/rank/_crank16_percentiles.pyx @@ -13,7 +13,10 @@ 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 if pop: @@ -40,7 +43,10 @@ cdef inline np.uint16_t kernel_autolevel(Py_ssize_t * histo, float pop, np.uint1 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 if pop: @@ -63,7 +69,10 @@ cdef inline np.uint16_t kernel_gradient(Py_ssize_t * histo, float pop, np.uint16 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 if pop: @@ -83,7 +92,10 @@ cdef inline np.uint16_t kernel_mean(Py_ssize_t * histo, float pop, np.uint16_t g else: 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 if pop: @@ -102,7 +114,10 @@ cdef inline np.uint16_t kernel_mean_substraction(Py_ssize_t * histo, float pop, else: 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 if pop: @@ -130,7 +145,10 @@ cdef inline np.uint16_t kernel_morph_contr_enh(Py_ssize_t * histo, float pop, np else: 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. @@ -144,7 +162,10 @@ cdef inline np.uint16_t kernel_percentile(Py_ssize_t * histo, float pop, np.uint else: 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 if pop: @@ -158,7 +179,10 @@ cdef inline np.uint16_t kernel_pop(Py_ssize_t * histo, float pop, np.uint16_t g, else: 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. @@ -184,7 +208,9 @@ def autolevel(np.ndarray[np.uint16_t, ndim=2] image, 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) + return _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, @@ -194,7 +220,9 @@ def gradient(np.ndarray[np.uint16_t, ndim=2] image, 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) + return _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, @@ -204,7 +232,9 @@ def mean(np.ndarray[np.uint16_t, ndim=2] image, 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) + return _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, @@ -214,7 +244,9 @@ def mean_substraction(np.ndarray[np.uint16_t, ndim=2] image, 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) + return _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, @@ -224,7 +256,9 @@ def morph_contr_enh(np.ndarray[np.uint16_t, ndim=2] image, 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) + 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) def percentile(np.ndarray[np.uint16_t, ndim=2] image, @@ -234,7 +268,9 @@ def percentile(np.ndarray[np.uint16_t, ndim=2] image, 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) + return _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, @@ -244,7 +280,9 @@ def pop(np.ndarray[np.uint16_t, ndim=2] image, 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) + return _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, @@ -254,4 +292,6 @@ def threshold(np.ndarray[np.uint16_t, ndim=2] image, 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) + return _core16( + kernel_threshold, image, selem, mask, out, shift_x, shift_y, bitdepth, p0, p1, + < Py_ssize_t > 0, < Py_ssize_t > 0) diff --git a/skimage/filter/rank/_crank8.pyx b/skimage/filter/rank/_crank8.pyx index 045e3645..be00bf86 100644 --- a/skimage/filter/rank/_crank8.pyx +++ b/skimage/filter/rank/_crank8.pyx @@ -22,8 +22,9 @@ from skimage.filter.rank._core8 cimport _core8 # ----------------------------------------------------------------- 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): + 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 if pop: @@ -44,8 +45,9 @@ cdef inline np.uint8_t kernel_autolevel( 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): + 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 for i in range(256): @@ -56,8 +58,9 @@ cdef inline np.uint8_t kernel_bottomhat( 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): + 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. @@ -72,8 +75,9 @@ cdef inline np.uint8_t kernel_equalize( 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): + 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 if pop: @@ -90,8 +94,9 @@ cdef inline np.uint8_t kernel_gradient( 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): + 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: @@ -101,8 +106,10 @@ cdef inline np.uint8_t kernel_maximum( 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. @@ -114,8 +121,9 @@ cdef inline np.uint8_t kernel_mean(Py_ssize_t * histo, float pop, np.uint8_t g, 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): + 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. @@ -127,8 +135,9 @@ cdef inline np.uint8_t kernel_meansubstraction( 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): + 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 @@ -142,8 +151,9 @@ cdef inline np.uint8_t kernel_median( 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): + 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: @@ -154,8 +164,8 @@ cdef inline np.uint8_t kernel_minimum( 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): + 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 if pop: @@ -168,8 +178,9 @@ cdef inline np.uint8_t kernel_modal( 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): + 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 if pop: @@ -188,13 +199,16 @@ cdef inline np.uint8_t kernel_morph_contr_enh( else: 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): + 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): + 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. @@ -206,8 +220,9 @@ cdef inline np.uint8_t kernel_threshold( 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): + 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 for i in range(255, -1, -1): @@ -228,7 +243,9 @@ def autolevel(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """bottom hat """ - return _core8(kernel_autolevel, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + return _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, @@ -238,7 +255,9 @@ def bottomhat(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """bottom hat """ - return _core8(kernel_bottomhat, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + return _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, @@ -248,7 +267,9 @@ def equalize(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """local egalisation of the gray level """ - return _core8(kernel_equalize, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + return _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, @@ -258,7 +279,9 @@ def gradient(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """local maximum - local minimum gray level """ - return _core8(kernel_gradient, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + return _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, @@ -288,7 +311,9 @@ def meansubstraction(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """(g - average gray level)/2+127 (clipped on uint8) """ - return _core8(kernel_meansubstraction, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + return _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, @@ -318,7 +343,9 @@ def morph_contr_enh(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """morphological contrast enhancement """ - return _core8(kernel_morph_contr_enh, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 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) def modal(np.ndarray[np.uint8_t, ndim=2] image, @@ -348,7 +375,9 @@ def threshold(np.ndarray[np.uint8_t, ndim=2] image, char shift_x=0, char shift_y=0): """returns 255 if gray level higher than local mean, 0 else """ - return _core8(kernel_threshold, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + return _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, diff --git a/skimage/filter/rank/_crank8_percentiles.pyx b/skimage/filter/rank/_crank8_percentiles.pyx index f882961a..618a6452 100644 --- a/skimage/filter/rank/_crank8_percentiles.pyx +++ b/skimage/filter/rank/_crank8_percentiles.pyx @@ -13,7 +13,9 @@ 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: @@ -42,7 +44,9 @@ cdef inline np.uint8_t kernel_autolevel(Py_ssize_t * histo, float pop, np.uint8_ 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: @@ -65,7 +69,9 @@ cdef inline np.uint8_t kernel_gradient(Py_ssize_t * histo, float pop, np.uint8_t 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,7 +90,9 @@ cdef inline np.uint8_t kernel_mean(Py_ssize_t * histo, float pop, np.uint8_t g, else: 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: @@ -103,7 +111,9 @@ cdef inline np.uint8_t kernel_mean_substraction(Py_ssize_t * histo, float pop, n else: 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,7 +141,9 @@ cdef inline np.uint8_t kernel_morph_contr_enh(Py_ssize_t * histo, float pop, np. else: 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. @@ -145,7 +157,9 @@ cdef inline np.uint8_t kernel_percentile(Py_ssize_t * histo, float pop, np.uint8 else: 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: @@ -159,7 +173,9 @@ cdef inline np.uint8_t kernel_pop(Py_ssize_t * histo, float pop, np.uint8_t g, f else: 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,7 +201,9 @@ 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) + return _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, @@ -195,7 +213,9 @@ 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) + return _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, @@ -215,7 +235,9 @@ 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) + return _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, @@ -225,7 +247,9 @@ 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) + return _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, @@ -235,7 +259,9 @@ 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) + return _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, @@ -255,4 +281,6 @@ 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) + return _core8( + kernel_threshold, image, selem, mask, out, shift_x, shift_y, p0, p1, < Py_ssize_t > 0, + < Py_ssize_t > 0) From a9e05e5fd43859fece29db6542933d61fe43fec4 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 29 Oct 2012 09:14:50 +0100 Subject: [PATCH 81/86] remove inlines in pxd --- skimage/filter/rank/_core16.pxd | 6 +++--- skimage/filter/rank/_core8.pxd | 6 +++--- skimage/setup.py | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/skimage/filter/rank/_core16.pxd b/skimage/filter/rank/_core16.pxd index a113f2b0..9590e277 100644 --- a/skimage/filter/rank/_core16.pxd +++ b/skimage/filter/rank/_core16.pxd @@ -5,10 +5,10 @@ cimport numpy as np #--------------------------------------------------------------------------- # generic cdef functions -cdef inline int int_max(int a, int b) -cdef inline int int_min(int a, int b) +cdef int int_max(int a, int b) +cdef int int_min(int a, int b) -cdef inline _core16( +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, diff --git a/skimage/filter/rank/_core8.pxd b/skimage/filter/rank/_core8.pxd index 8ecf7263..9f898faa 100644 --- a/skimage/filter/rank/_core8.pxd +++ b/skimage/filter/rank/_core8.pxd @@ -1,14 +1,14 @@ cimport numpy as np # generic cdef functions -cdef inline np.uint8_t uint8_max(np.uint8_t a, np.uint8_t b) -cdef inline np.uint8_t uint8_min(np.uint8_t a, np.uint8_t b) +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 inline _core8( +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, diff --git a/skimage/setup.py b/skimage/setup.py index 7ed50b65..96497fa9 100644 --- a/skimage/setup.py +++ b/skimage/setup.py @@ -12,11 +12,11 @@ def configuration(parent_package='', top_path=None): config.add_subpackage('draw') config.add_subpackage('feature') config.add_subpackage('filter') + config.add_subpackage('filter/rank') config.add_subpackage('graph') config.add_subpackage('io') config.add_subpackage('measure') config.add_subpackage('morphology') - config.add_subpackage('rank') config.add_subpackage('transform') config.add_subpackage('util') config.add_subpackage('segmentation') From 42d46ad08766b3a1e0f577f2f193aa5789856f7e Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 29 Oct 2012 09:21:10 +0100 Subject: [PATCH 82/86] move setup from /filter/rank to /filter --- skimage/filter/rank/setup.py | 52 ------------------------------------ skimage/filter/setup.py | 27 ++++++++++++++++++- 2 files changed, 26 insertions(+), 53 deletions(-) delete mode 100644 skimage/filter/rank/setup.py diff --git a/skimage/filter/rank/setup.py b/skimage/filter/rank/setup.py deleted file mode 100644 index c6a3dbb9..00000000 --- a/skimage/filter/rank/setup.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python - -import os -from skimage._build import cython - -base_path = os.path.abspath(os.path.dirname(__file__)) - - -def configuration(parent_package='', top_path=None): - from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs - - config = Configuration('rank', parent_package, top_path) -# config.add_data_dir('tests') - - cython(['_core8.pyx'], working_path=base_path) - cython(['_core16.pyx'], working_path=base_path) - cython(['_crank8.pyx'], working_path=base_path) - cython(['_crank8_percentiles.pyx'], working_path=base_path) - cython(['_crank16.pyx'], working_path=base_path) - cython(['_crank16_percentiles.pyx'], working_path=base_path) - cython(['_crank16_bilateral.pyx'], working_path=base_path) - - config.add_extension('_core8', sources=['_core8.c'], - include_dirs=[get_numpy_include_dirs()]) - config.add_extension('_core16', sources=['_core16.c'], - include_dirs=[get_numpy_include_dirs()]) - config.add_extension('_crank8', sources=['_crank8.c'], - include_dirs=[get_numpy_include_dirs()]) - config.add_extension( - '_crank8_percentiles', sources=['_crank8_percentiles.c'], - include_dirs=[get_numpy_include_dirs()]) - config.add_extension('_crank16', sources=['_crank16.c'], - include_dirs=[get_numpy_include_dirs()]) - config.add_extension( - '_crank16_percentiles', sources=['_crank16_percentiles.c'], - include_dirs=[get_numpy_include_dirs()]) - config.add_extension( - '_crank16_bilateral', sources=['_crank16_bilateral.c'], - include_dirs=[get_numpy_include_dirs()]) - - return config - -if __name__ == '__main__': - from numpy.distutils.core import setup - setup(maintainer='scikits-image Developers', - author='Olivier Debeir', - maintainer_email='scikits-image@googlegroups.com', - description='Rank filters', - url='https://github.com/scikits-image/scikits-image', - license='SciPy License (BSD Style)', - **(configuration(top_path='').todict()) - ) diff --git a/skimage/filter/setup.py b/skimage/filter/setup.py index 03ea7def..34386e36 100644 --- a/skimage/filter/setup.py +++ b/skimage/filter/setup.py @@ -13,9 +13,34 @@ def configuration(parent_package='', top_path=None): config.add_data_dir('tests') cython(['_ctmf.pyx'], working_path=base_path) + cython(['rank/_core8.pyx'], working_path=base_path) + cython(['rank/_core16.pyx'], working_path=base_path) + cython(['rank/_crank8.pyx'], working_path=base_path) + cython(['rank/_crank8_percentiles.pyx'], working_path=base_path) + cython(['rank/_crank16.pyx'], working_path=base_path) + cython(['rank/_crank16_percentiles.pyx'], working_path=base_path) + cython(['rank/_crank16_bilateral.pyx'], working_path=base_path) config.add_extension('_ctmf', sources=['_ctmf.c'], - include_dirs=[get_numpy_include_dirs()]) + include_dirs=[get_numpy_include_dirs()]) + config.add_extension('rank/_core8', sources=['rank/_core8.c'], + include_dirs=[get_numpy_include_dirs()]) + config.add_extension('rank/_core16', sources=['rank/_core16.c'], + include_dirs=[get_numpy_include_dirs()]) + config.add_extension('rank/_crank8', sources=['rank/_crank8.c'], + include_dirs=[get_numpy_include_dirs()]) + config.add_extension( + 'rank/_crank8_percentiles', sources=['rank/_crank8_percentiles.c'], + include_dirs=[get_numpy_include_dirs()]) + config.add_extension('rank/_crank16', sources=['rank/_crank16.c'], + include_dirs=[get_numpy_include_dirs()]) + config.add_extension( + 'rank/_crank16_percentiles', sources=['rank/_crank16_percentiles.c'], + include_dirs=[get_numpy_include_dirs()]) + config.add_extension( + 'rank/_crank16_bilateral', sources=['rank/_crank16_bilateral.c'], + include_dirs=[get_numpy_include_dirs()]) + return config From 5ae4b4286cec5538e8897878aeb38673c87a9aac Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 29 Oct 2012 09:26:12 +0100 Subject: [PATCH 83/86] remove comments --- skimage/filter/rank/_core16.pyx | 7 ------- skimage/filter/rank/_core8.pyx | 7 ------- skimage/filter/rank/_crank16.pyx | 8 -------- skimage/filter/rank/_crank16_bilateral.pyx | 8 -------- skimage/filter/rank/_crank8.pyx | 8 -------- 5 files changed, 38 deletions(-) diff --git a/skimage/filter/rank/_core16.pyx b/skimage/filter/rank/_core16.pyx index 81fab0b4..4829792b 100644 --- a/skimage/filter/rank/_core16.pyx +++ b/skimage/filter/rank/_core16.pyx @@ -1,10 +1,3 @@ -""" to compile this use: ->>> python setup.py build_ext --inplace - -to generate html report use: ->>> cython -a core16.pxd -""" - #cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False diff --git a/skimage/filter/rank/_core8.pyx b/skimage/filter/rank/_core8.pyx index 7851388d..9955a1e1 100644 --- a/skimage/filter/rank/_core8.pyx +++ b/skimage/filter/rank/_core8.pyx @@ -1,10 +1,3 @@ -""" to compile this use: ->>> python setup.py build_ext --inplace - -to generate html report use: ->>> cython -a core8.pxd -""" - #cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False diff --git a/skimage/filter/rank/_crank16.pyx b/skimage/filter/rank/_crank16.pyx index 57d41563..f6ad10e4 100644 --- a/skimage/filter/rank/_crank16.pyx +++ b/skimage/filter/rank/_crank16.pyx @@ -1,11 +1,3 @@ -""" to compile this use: ->>> python setup.py build_ext --inplace - -to generate html report use: ->>> cython -a crank16.pxd - -""" - #cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False diff --git a/skimage/filter/rank/_crank16_bilateral.pyx b/skimage/filter/rank/_crank16_bilateral.pyx index d6fb9c71..c013b779 100644 --- a/skimage/filter/rank/_crank16_bilateral.pyx +++ b/skimage/filter/rank/_crank16_bilateral.pyx @@ -1,11 +1,3 @@ -""" to compile this use: ->>> python setup.py build_ext --inplace - -to generate html report use: ->>> cython -a crank16.pxd - -""" - #cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False diff --git a/skimage/filter/rank/_crank8.pyx b/skimage/filter/rank/_crank8.pyx index be00bf86..da716bd9 100644 --- a/skimage/filter/rank/_crank8.pyx +++ b/skimage/filter/rank/_crank8.pyx @@ -1,11 +1,3 @@ -""" to compile this use: ->>> python setup.py build_ext --inplace - -to generate html report use: ->>> cython -a crank.pxd - -""" - #cython: cdivision=True #cython: boundscheck=False #cython: nonecheck=False From e488e4b7bd30088b0335e853494f9a0a99fec0e1 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 29 Oct 2012 09:35:28 +0100 Subject: [PATCH 84/86] remove obsolete comments --- doc/__init__.py | 1 - skimage/filter/rank/bilateral_rank.py | 2 -- skimage/filter/rank/percentile_rank.py | 21 +++++++-------------- 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/doc/__init__.py b/doc/__init__.py index 10b6fb15..e69de29b 100644 --- a/doc/__init__.py +++ b/doc/__init__.py @@ -1 +0,0 @@ -__author__ = 'olivier' diff --git a/skimage/filter/rank/bilateral_rank.py b/skimage/filter/rank/bilateral_rank.py index ff4e7878..dd2942b4 100644 --- a/skimage/filter/rank/bilateral_rank.py +++ b/skimage/filter/rank/bilateral_rank.py @@ -81,7 +81,6 @@ def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal Examples -------- - to be updated >>> # Local mean >>> from skimage.morphology import square >>> import skimage.filter.rank as rank @@ -147,7 +146,6 @@ def bilateral_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fals Examples -------- - to be updated >>> # Local mean >>> from skimage.morphology import square >>> import skimage.filter.rank as rank diff --git a/skimage/filter/rank/percentile_rank.py b/skimage/filter/rank/percentile_rank.py index 5191bec4..3817e1cd 100644 --- a/skimage/filter/rank/percentile_rank.py +++ b/skimage/filter/rank/percentile_rank.py @@ -73,7 +73,6 @@ def percentile_autolevel(image, selem, out=None, mask=None, shift_x=False, shift Examples -------- - to be updated >>> # Local mean >>> from skimage.morphology import square >>> import skimage.filter.rank as rank @@ -139,7 +138,7 @@ def percentile_gradient(image, selem, out=None, mask=None, shift_x=False, shift_ Examples -------- - to be updated + >>> # Local gradient >>> from skimage.morphology import square >>> import skimage.filter.rank as rank @@ -205,7 +204,7 @@ def percentile_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa Examples -------- - to be updated + >>> # Local mean >>> from skimage.morphology import square >>> import skimage.filter.rank as rank @@ -271,7 +270,7 @@ def percentile_mean_substraction(image, selem, out=None, mask=None, shift_x=Fals Examples -------- - to be updated + >>> # Local mean_substraction >>> from skimage.morphology import square >>> import skimage.filter.rank as rank @@ -337,7 +336,7 @@ def percentile_morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, Examples -------- - to be updated + >>> # Local mean >>> from skimage.morphology import square >>> import skimage.filter.rank as rank @@ -403,7 +402,7 @@ def percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, Examples -------- - to be updated + >>> # Local mean >>> from skimage.morphology import square >>> import skimage.filter.rank as rank @@ -470,7 +469,7 @@ def percentile_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal Examples -------- - to be updated + >>> # Local mean >>> from skimage.morphology import square >>> import skimage.filter.rank as rank @@ -536,7 +535,7 @@ def percentile_threshold(image, selem, out=None, mask=None, shift_x=False, shift Examples -------- - to be updated + >>> # Local mean >>> from skimage.morphology import square >>> import skimage.filter.rank as rank @@ -572,9 +571,3 @@ def percentile_threshold(image, selem, out=None, mask=None, shift_x=False, shift shift_x=shift_x, shift_y=shift_y, p0=p0, p1=p1) -if __name__ == "__main__": - import sys - sys.path.append('.') - - import doctest - doctest.testmod(verbose=True) From 07f87d42d2d4b7573f4a1e596059cece73dc6812 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 29 Oct 2012 16:32:08 +0100 Subject: [PATCH 85/86] adjust setup --- doc/examples/plot_lena_bilateral_denoise.py | 9 ++++----- skimage/filter/rank/{local => demo}/demo_all.py | 0 skimage/filter/rank/{local => demo}/demo_single.py | 0 skimage/filter/rank/{local => demo}/iko_pan_Ja1.tif | Bin .../rank/{local => demo}/test_morph_contr_enh.py | 0 skimage/filter/rank/{local => demo}/test_rank.py | 0 skimage/setup.py | 1 - 7 files changed, 4 insertions(+), 6 deletions(-) rename skimage/filter/rank/{local => demo}/demo_all.py (100%) rename skimage/filter/rank/{local => demo}/demo_single.py (100%) rename skimage/filter/rank/{local => demo}/iko_pan_Ja1.tif (100%) rename skimage/filter/rank/{local => demo}/test_morph_contr_enh.py (100%) rename skimage/filter/rank/{local => demo}/test_rank.py (100%) diff --git a/doc/examples/plot_lena_bilateral_denoise.py b/doc/examples/plot_lena_bilateral_denoise.py index 969403d0..03fc61d0 100644 --- a/doc/examples/plot_lena_bilateral_denoise.py +++ b/doc/examples/plot_lena_bilateral_denoise.py @@ -1,4 +1,3 @@ - """ ==================================================== Denoising the picture of Lena using bilateral filter @@ -27,7 +26,7 @@ l = l[230:290, 220:320] noisy = l + 0.4 * l.std() * np.random.random(l.shape) selem = disk(30) -bilateral_denoised = bilateral_mean(noisy.astype(np.uint8), selem=selem,s0=10,s1=10) +approx_bilateral_denoised = bilateral_mean(noisy.astype(np.uint8), selem=selem,s0=10,s1=10) plt.figure(figsize=(8, 2)) @@ -36,14 +35,14 @@ plt.imshow(noisy, cmap=plt.cm.gray, vmin=40, vmax=220) plt.axis('off') plt.title('noisy', fontsize=20) plt.subplot(132) -plt.imshow(bilateral_denoised, cmap=plt.cm.gray, vmin=40, vmax=220) +plt.imshow(approx_bilateral_denoised, cmap=plt.cm.gray, vmin=40, vmax=220) plt.axis('off') plt.title('bilateral denoising', fontsize=20) selem = disk(30) -bilateral_denoised = bilateral_mean(noisy.astype(np.uint8), selem=selem,s0=40,s1=40) +approx_bilateral_denoised = bilateral_mean(noisy.astype(np.uint8), selem=selem,s0=40,s1=40) plt.subplot(133) -plt.imshow(bilateral_denoised, cmap=plt.cm.gray, vmin=40, vmax=220) +plt.imshow(approx_bilateral_denoised, cmap=plt.cm.gray, vmin=40, vmax=220) plt.axis('off') plt.title('(more) bilateral denoising', fontsize=20) diff --git a/skimage/filter/rank/local/demo_all.py b/skimage/filter/rank/demo/demo_all.py similarity index 100% rename from skimage/filter/rank/local/demo_all.py rename to skimage/filter/rank/demo/demo_all.py diff --git a/skimage/filter/rank/local/demo_single.py b/skimage/filter/rank/demo/demo_single.py similarity index 100% rename from skimage/filter/rank/local/demo_single.py rename to skimage/filter/rank/demo/demo_single.py diff --git a/skimage/filter/rank/local/iko_pan_Ja1.tif b/skimage/filter/rank/demo/iko_pan_Ja1.tif similarity index 100% rename from skimage/filter/rank/local/iko_pan_Ja1.tif rename to skimage/filter/rank/demo/iko_pan_Ja1.tif diff --git a/skimage/filter/rank/local/test_morph_contr_enh.py b/skimage/filter/rank/demo/test_morph_contr_enh.py similarity index 100% rename from skimage/filter/rank/local/test_morph_contr_enh.py rename to skimage/filter/rank/demo/test_morph_contr_enh.py diff --git a/skimage/filter/rank/local/test_rank.py b/skimage/filter/rank/demo/test_rank.py similarity index 100% rename from skimage/filter/rank/local/test_rank.py rename to skimage/filter/rank/demo/test_rank.py diff --git a/skimage/setup.py b/skimage/setup.py index 96497fa9..1082ba07 100644 --- a/skimage/setup.py +++ b/skimage/setup.py @@ -12,7 +12,6 @@ def configuration(parent_package='', top_path=None): config.add_subpackage('draw') config.add_subpackage('feature') config.add_subpackage('filter') - config.add_subpackage('filter/rank') config.add_subpackage('graph') config.add_subpackage('io') config.add_subpackage('measure') From 8b0613ff0946b9fbf8c3c8a74dea3cdf73024f03 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 29 Oct 2012 17:04:10 +0100 Subject: [PATCH 86/86] removed mains --- skimage/filter/rank/bilateral_rank.py | 6 ------ skimage/filter/rank/rank.py | 6 ------ 2 files changed, 12 deletions(-) diff --git a/skimage/filter/rank/bilateral_rank.py b/skimage/filter/rank/bilateral_rank.py index dd2942b4..69884e16 100644 --- a/skimage/filter/rank/bilateral_rank.py +++ b/skimage/filter/rank/bilateral_rank.py @@ -179,9 +179,3 @@ def bilateral_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fals None, _crank16_bilateral.pop, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y, s0=s0, s1=s1) -if __name__ == "__main__": - import sys - sys.path.append('.') - - import doctest - doctest.testmod(verbose=True) diff --git a/skimage/filter/rank/rank.py b/skimage/filter/rank/rank.py index 517ab2cf..fc06d48b 100644 --- a/skimage/filter/rank/rank.py +++ b/skimage/filter/rank/rank.py @@ -918,9 +918,3 @@ 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) -if __name__ == "__main__": - import sys - sys.path.append('.') - - import doctest - doctest.testmod(verbose=True)