From 0e1cc75a733fab981be9dc433cb3483f5e6b6750 Mon Sep 17 00:00:00 2001 From: odebeir Date: Wed, 3 Oct 2012 19:43:41 +0200 Subject: [PATCH 001/195] initial commit --- .gitignore | 2 +- skimage/rank/__init__.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 skimage/rank/__init__.py diff --git a/.gitignore b/.gitignore index 1bd4352c..925e5886 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,4 @@ doc/source/auto_examples/images/plot_*.png doc/source/auto_examples/images/thumb doc/source/auto_examples/applications/ doc/source/_static/random.js - +.idea/ diff --git a/skimage/rank/__init__.py b/skimage/rank/__init__.py new file mode 100644 index 00000000..bcc43cdc --- /dev/null +++ b/skimage/rank/__init__.py @@ -0,0 +1 @@ +from .rank import * From 26f9186bc945a6abb8181ec8c7c1cdbd0040d2ca Mon Sep 17 00:00:00 2001 From: odebeir Date: Wed, 3 Oct 2012 19:57:30 +0200 Subject: [PATCH 002/195] paste code --- skimage/rank/README.rst | 5 + skimage/rank/app.py | 171 +++++ skimage/rank/cmorph.pyx | 118 +++ skimage/rank/core.pxd | 1054 ++++++++++++++++++++++++++ skimage/rank/crank.pyx | 325 ++++++++ skimage/rank/crank16.pyx | 323 ++++++++ skimage/rank/crank16_percentiles.pyx | 268 +++++++ skimage/rank/crank_percentiles.pyx | 263 +++++++ skimage/rank/setup.py | 15 + skimage/rank/tools.py | 52 ++ 10 files changed, 2594 insertions(+) create mode 100644 skimage/rank/README.rst create mode 100644 skimage/rank/app.py create mode 100644 skimage/rank/cmorph.pyx create mode 100644 skimage/rank/core.pxd create mode 100644 skimage/rank/crank.pyx create mode 100644 skimage/rank/crank16.pyx create mode 100644 skimage/rank/crank16_percentiles.pyx create mode 100644 skimage/rank/crank_percentiles.pyx create mode 100644 skimage/rank/setup.py create mode 100644 skimage/rank/tools.py diff --git a/skimage/rank/README.rst b/skimage/rank/README.rst new file mode 100644 index 00000000..b15001e6 --- /dev/null +++ b/skimage/rank/README.rst @@ -0,0 +1,5 @@ +To use this to build your Cython file use the commandline options: + +.. sourcecode:: text + + $ python setup.py build_ext --inplace \ No newline at end of file diff --git a/skimage/rank/app.py b/skimage/rank/app.py new file mode 100644 index 00000000..acfc33ec --- /dev/null +++ b/skimage/rank/app.py @@ -0,0 +1,171 @@ +import numpy as np +from time import time +import matplotlib.pyplot as plt +from skimage import data + +from tools import log_timing,init_logger + +import crank +import crank16 +import crank_percentiles +import crank16_percentiles +from pyrankfilter import filter +from cmorph import dilate + + +@log_timing +def c_max(image,selem): + return crank.maximum(image=image,selem = selem) + +@log_timing +def w_max(image,selem): + return filter.maximum(image,struct_elem = 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) + (rw, ms_rw) = w_max(a,elem) + (rcm,ms_rcm) = cm_max(a,elem) + rec.append((ms_rc,ms_rw,ms_rcm)) + assert (rc==rw).all() + 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) + (rw, ms_rw) = w_max(a,elem) + (rcm,ms_rcm) = cm_max(a,elem) + rec.append((ms_rc,ms_rw,ms_rcm)) + assert (rc==rw).all() + 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,rw,rcm))) + + plt.show() + +def test_image_size(): + """try several image sizes to check bounds conditions + """ + 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)): + a = np.ones((m,n),dtype='uint8') + r = crank.mean(image=a,selem = elem,shift_x=0,shift_y=0) + assert a.shape == r.shape + r = crank.mean(image=a,selem = elem,shift_x=0,shift_y=-1) + assert a.shape == r.shape + r = crank.mean(image=a,selem = elem,shift_x=0,shift_y=+1) + assert a.shape == r.shape + r = crank.mean(image=a,selem = elem,shift_x=-1,shift_y=0) + assert a.shape == r.shape + r = crank.mean(image=a,selem = elem,shift_x=+1,shift_y=0) + assert a.shape == r.shape + r = crank.mean(image=a,selem = elem,shift_x=-1,shift_y=-1) + assert a.shape == r.shape + r = crank.mean(image=a,selem = elem,shift_x=+1,shift_y=+1) + assert a.shape == r.shape + + return True + + +if __name__ == '__main__': + + logger = init_logger('app.log') + a = np.zeros((10,10),dtype='uint8') + a[2,2] = 255 +# a[2,3] = 255 +# a[2,4] = 255 + + print a + + mask = np.ones_like(a) +# mask[:3,:3] = 0 + +# elem = np.asarray([[0,1,0],[1,1,1],[0,1,0]],dtype='uint8') + elem = np.asarray([[1,1,0],[1,1,1],[0,0,1]],dtype='uint8') + + niter = 1 + t0 = time() + + for iter in range(niter): + r = crank.mean(image=a,selem = elem,shift_x=0,shift_y=0,mask = mask) + p = crank.pop(image=a,selem = elem,shift_x=0,shift_y=0,mask = mask) + t1 = time() + print '%f msec'%(t1-t0) + + print 'cython mean' + print r + print p + + t0 = time() + for iter in range(niter): + r = filter.mean(a,struct_elem = elem,struct_elem_center=(1,1),mask = mask) + t1 = time() + print '%f msec'%(t1-t0) + + print 'filter.mean:' + print r + + print a + r = crank.maximum(image=a,selem = elem,shift_x=0,shift_y=0,mask = mask) + print r + + r = crank.gradient(image=r,selem = elem,shift_x=0,shift_y=0,mask = mask) + print r + im = np.zeros((10,10),dtype='uint8') + im[2:6,2:6] = 255 + elem = np.asarray([[1,1,1],[1,1,1],[1,1,1]],dtype='uint8') + f = crank.gradient(image=im,selem = elem) + print f + f = crank.egalise(image=im,selem = elem) + print f + +# compare() +# test_image_size() + +# 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) +# plt.imshow(f2) + plt.imshow(np.hstack((f1,f2))) + plt.colorbar() + plt.show() + + diff --git a/skimage/rank/cmorph.pyx b/skimage/rank/cmorph.pyx new file mode 100644 index 00000000..9b8b3a27 --- /dev/null +++ b/skimage/rank/cmorph.pyx @@ -0,0 +1,118 @@ +#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/core.pxd b/skimage/rank/core.pxd new file mode 100644 index 00000000..72facde3 --- /dev/null +++ b/skimage/rank/core.pxd @@ -0,0 +1,1054 @@ +""" 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 +#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 diff --git a/skimage/rank/crank.pyx b/skimage/rank/crank.pyx new file mode 100644 index 00000000..09048917 --- /dev/null +++ b/skimage/rank/crank.pyx @@ -0,0 +1,325 @@ +""" 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 +#cython: wraparound=False + +import numpy as np +cimport numpy as np + +# import main loop +from core cimport rank8 + +# todo +# - manage float output, +# - manage different bit depth input +# - add auxiliary parameters (spectral_interval, infSup) + +# ----------------------------------------------------------------- +# kernels uint8 +# ----------------------------------------------------------------- + +cdef inline np.uint8_t kernel_autolevel(int* histo, float pop, np.uint8_t g): + cdef int i,imin,imax,delta + + if pop: + for i in range(255,-1,-1): + if histo[i]: + imax = i + break + for i in range(256): + if histo[i]: + imin = i + break + delta = imax-imin + if delta>0: + return (255.*(g-imin)/delta) + else: + return (imax-imin) + +cdef inline np.uint8_t kernel_bottomhat(int* histo, float pop, np.uint8_t g): + cdef int i + + for i in range(256): + if histo[i]: + break + + return (g-i) + + +cdef inline np.uint8_t kernel_egalise(int* histo, float pop, np.uint8_t g): + cdef int i + cdef float sum = 0. + + if pop: + for i in range(256): + sum += histo[i] + if i>=g: + break + + return ((255*sum)/pop) + else: + return (0) + +cdef inline np.uint8_t kernel_gradient(int* histo, float pop, np.uint8_t g): + cdef int i,imin,imax + + + if pop: + for i in range(255,-1,-1): + if histo[i]: + imax = i + break + for i in range(256): + if histo[i]: + imin = i + break + return (imax-imin) + else: + return (0) + +cdef inline np.uint8_t kernel_maximum(int* histo, float pop, np.uint8_t g): + cdef int i + + if pop: + for i in range(255,-1,-1): + if histo[i]: + return (i) + + return (0) + +cdef inline np.uint8_t kernel_mean(int* histo, float pop, np.uint8_t g): + cdef int i + cdef float mean = 0. + + if pop: + for i in range(256): + mean += histo[i]*i + return (mean/pop) + else: + return (0) + +cdef inline np.uint8_t kernel_meansubstraction(int* histo, float pop, np.uint8_t g): + cdef int i + cdef float mean = 0. + + if pop: + for i in range(256): + mean += histo[i]*i + return ((g-mean/pop)/2.+127) + else: + return (0) + +cdef inline np.uint8_t kernel_median(int* histo, float pop, np.uint8_t g): + cdef int i + cdef float sum = pop/2.0 + + if pop: + for i in range(256): + if histo[i]: + sum -= histo[i] + if sum<0: + return (i) + + return (0) + +cdef inline np.uint8_t kernel_minimum(int* histo, float pop, np.uint8_t g): + cdef int i + + if pop: + for i in range(256): + if histo[i]: + return (i) + + return (0) + +cdef inline np.uint8_t kernel_modal(int* histo, float pop, np.uint8_t g): + cdef int hmax=0,imax=0 + + if pop: + for i in range(256): + if histo[i]>hmax: + hmax = histo[i] + imax = i + return (imax) + + return (0) + +cdef inline np.uint8_t kernel_morph_contr_enh(int* histo, float pop, np.uint8_t g): + cdef int i,imin,imax + + if pop: + for i in range(255,-1,-1): + if histo[i]: + imax = i + break + for i in range(256): + if histo[i]: + imin = i + break + if imax-g < g-imin: + return (imax) + else: + return (imin) + else: + return (0) + +cdef inline np.uint8_t kernel_pop(int* 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 float mean = 0. + + if pop: + for i in range(256): + mean += histo[i]*i + return (g>(mean/pop)) + else: + return (0) + +cdef inline np.uint8_t kernel_tophat(int* histo, float pop, np.uint8_t g): + cdef int i + + for i in range(255,-1,-1): + if histo[i]: + break + + return (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): + """bottom hat + """ + return rank8(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, + 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 rank8(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, + 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 rank8(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, + 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 rank8(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, + 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 gray level + """ + return rank8(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, + 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 rank8(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, + 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 rank8(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, + 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 rank8(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, + 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 minimum gray level + """ + return rank8(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, + 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 rank8(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, + 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 rank8(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, + 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 rank8(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, + 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 rank8(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, + 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 rank8(kernel_tophat,image,selem,mask,out,shift_x,shift_y) + diff --git a/skimage/rank/crank16.pyx b/skimage/rank/crank16.pyx new file mode 100644 index 00000000..78e5a2af --- /dev/null +++ b/skimage/rank/crank16.pyx @@ -0,0 +1,323 @@ +""" 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 +#cython: wraparound=False + +import numpy as np +cimport numpy as np + +# import main loop +from core cimport rank16 + +# todo +# - manage float output, +# - manage different bit depth input +# - add auxiliary parameters (spectral_interval, infSup) + +# ----------------------------------------------------------------- +# 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): + cdef int i + cdef float mean = 0. + + if pop: + for i in range(maxbin): + mean += histo[i]*i + return (mean/pop) + 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): + 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 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): + """bottom hat + """ + return rank16(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, + 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): + """bottom hat + """ + return rank16(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, + 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): + """local egalisation of the gray level + """ + return rank16(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, + 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): + """local maximum - local minimum gray level + """ + return rank16(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, + 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): + """local maximum gray level + """ + return rank16(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, + 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): + """average gray level (clipped on uint8) + """ + return rank16(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, + 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): + """(g - average gray level)/2+midbin (clipped on uint8) + """ + return rank16(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, + 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): + """local median + """ + return rank16(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, + 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): + """local minimum gray level + """ + return rank16(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, + 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): + """morphological contrast enhancement + """ + return rank16(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, + 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): + """local mode + """ + return rank16(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, + 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): + """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) + +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): + """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) + +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): + """top hat + """ + return rank16(kernel_tophat,image,selem,mask,out,shift_x,shift_y,bitdepth) diff --git a/skimage/rank/crank16_percentiles.pyx b/skimage/rank/crank16_percentiles.pyx new file mode 100644 index 00000000..b967c61a --- /dev/null +++ b/skimage/rank/crank16_percentiles.pyx @@ -0,0 +1,268 @@ +""" 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 +#cython: wraparound=False + +import numpy as np +cimport numpy as np + +# import main loop +from core cimport rank16_percentile + +# todo +# - manage float output, +# - manage different bit depth input +# - add auxiliary parameters (spectral_interval, infSup) + +# ----------------------------------------------------------------- +# kernels uint8 (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 int i,imin,imax,sum,delta + + if pop: + sum = 0 + p1 = 1.0-p1 + for i in range(maxbin): + sum += histo[i] + if sum>=p0*pop: + imin = i + break + sum = 0 + for i in range(maxbin-1,-1,-1): + sum += histo[i] + 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) + else: + return (0) + else: + 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 int i,imin,imax,sum,delta + + if pop: + sum = 0 + p1 = 1.0-p1 + for i in range(maxbin): + sum += histo[i] + if sum>=p0*pop: + imin = i + break + sum = 0 + for i in range((maxbin-1),-1,-1): + sum += histo[i] + if sum>=p1*pop: + imax = i + break + + return (imax-imin) + else: + 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 int i,sum,mean,n + + if pop: + sum = 0 + mean = 0 + n = 0 + for i in range(maxbin): + sum += histo[i] + if (sum>=p0*pop) and (sum<=p1*pop): + n += histo[i] + mean += histo[i]*i + + if n>0: + return (1.0*mean/n) + else: + return (0) + 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 int i,sum,mean,n + + if pop: + sum = 0 + mean = 0 + n = 0 + for i in range(maxbin): + sum += histo[i] + if (sum>=p0*pop) and (sum<=p1*pop): + n += histo[i] + mean += histo[i]*i + if n>0: + return ((g-(mean/n))*.5+midbin) + else: + return (0) + 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 int i,imin,imax,sum,delta + + if pop: + sum = 0 + p1 = 1.0-p1 + for i in range(maxbin): + sum += histo[i] + if sum>=p0*pop: + imin = i + break + sum = 0 + for i in range((maxbin-1),-1,-1): + sum += histo[i] + if sum>=p1*pop: + imax = i + break + if g>imax: + return imax + if gimin + if imax-g < g-imin: + return imax + else: + return imin + 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 int i + cdef float sum = 0. + + if pop: + for i in range(maxbin): + sum += histo[i] + if sum>=p0*pop: + break + + return (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 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): + n += histo[i] + return (n) + 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 int i + cdef float sum = 0. + + if pop: + for i in range(maxbin): + sum += histo[i] + if sum>=p0*pop: + break + + return ((maxbin-1)*(g>=i)) + else: + return (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.): + """bottom hat + """ + return rank16_percentile(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) + + +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.): + """return p0,p1 percentile gradient + """ + return rank16_percentile(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, + 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 rank16_percentile(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, + 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 rank16_percentile(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, + 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 rank16_percentile(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, + 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 rank16_percentile(kernel_percentile,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) + + +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.): + """return nb of pixels between [p0 and p1] + """ + return rank16_percentile(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, + 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 rank16_percentile(kernel_threshold,image,selem,mask,out,shift_x,shift_y,bitdepth,p0,p1) diff --git a/skimage/rank/crank_percentiles.pyx b/skimage/rank/crank_percentiles.pyx new file mode 100644 index 00000000..51a9e01f --- /dev/null +++ b/skimage/rank/crank_percentiles.pyx @@ -0,0 +1,263 @@ +""" 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 +#cython: wraparound=False + +import numpy as np +cimport numpy as np + +# import main loop +from core cimport rank8_percentile + +# todo +# - manage float output, +# - manage different bit depth input +# - add auxiliary parameters (spectral_interval, infSup) + +# ----------------------------------------------------------------- +# 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 int i,imin,imax,sum,delta + + if pop: + sum = 0 + p1 = 1.0-p1 + for i in range(256): + sum += histo[i] + if sum>=p0*pop: + imin = i + break + sum = 0 + for i in range(255,-1,-1): + sum += histo[i] + if sum>=p1*pop: + imax = i + break + + delta = imax-imin + if delta>0: + return (255.*(g-imin)/delta) + else: + return (0) + else: + return (0) + + +cdef inline np.uint8_t kernel_gradient(int* histo, float pop, np.uint8_t g, float p0, float p1): + cdef int i,imin,imax,sum,delta + + if pop: + sum = 0 + p1 = 1.0-p1 + for i in range(256): + sum += histo[i] + if sum>=p0*pop: + imin = i + break + sum = 0 + for i in range(255,-1,-1): + sum += histo[i] + if sum>=p1*pop: + imax = i + break + + return (imax-imin) + else: + return (0) + + +cdef inline np.uint8_t kernel_mean(int* histo, float pop, np.uint8_t g, float p0, float p1): + cdef int i,sum,mean,n + + if pop: + sum = 0 + mean = 0 + n = 0 + for i in range(256): + sum += histo[i] + if (sum>=p0*pop) and (sum<=p1*pop): + n += histo[i] + mean += histo[i]*i + if n>0: + return (1.0*mean/n) + else: + return (0) + else: + return (0) + +cdef inline np.uint8_t kernel_mean_substraction(int* histo, float pop, np.uint8_t g, float p0, float p1): + cdef int i,sum,mean,n + + if pop: + sum = 0 + mean = 0 + n = 0 + for i in range(256): + sum += histo[i] + if (sum>=p0*pop) and (sum<=p1*pop): + n += histo[i] + mean += histo[i]*i + if n>0: + return ((g-(mean/n))*.5+127) + else: + return (0) + 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 int i,imin,imax,sum,delta + + if pop: + sum = 0 + p1 = 1.0-p1 + for i in range(256): + sum += histo[i] + if sum>=p0*pop: + imin = i + break + sum = 0 + for i in range(255,-1,-1): + sum += histo[i] + if sum>=p1*pop: + imax = i + break + if g>imax: + return imax + if gimin + if imax-g < g-imin: + return imax + else: + return imin + else: + return (0) + +cdef inline np.uint8_t kernel_percentile(int* histo, float pop, np.uint8_t g, float p0, float p1): + cdef int i + cdef float sum = 0. + + if pop: + for i in range(256): + sum += histo[i] + if sum>=p0*pop: + break + + return (i) + else: + return (0) + +cdef inline np.uint8_t kernel_pop(int* histo, float pop, np.uint8_t g, float p0, float p1): + 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): + n += histo[i] + return (n) + else: + return (0) + +cdef inline np.uint8_t kernel_threshold(int* histo, float pop, np.uint8_t g, float p0, float p1): + cdef int i + cdef float sum = 0. + + if pop: + for i in range(256): + sum += histo[i] + if sum>=p0*pop: + break + + return (255*(g>=i)) + else: + return (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.): + """bottom hat + """ + return rank8_percentile(kernel_autolevel,image,selem,mask,out,shift_x,shift_y,p0,p1) + + +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.): + """return p0,p1 percentile gradient + """ + return rank8_percentile(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, + 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 rank8_percentile(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, + 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 rank8_percentile(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, + 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 rank8_percentile(kernel_morph_contr_enh,image,selem,mask,out,shift_x,shift_y,p0,p1) + + +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.): + """return p0 percentile + """ + return rank8_percentile(kernel_percentile,image,selem,mask,out,shift_x,shift_y,p0,p1) + + +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.): + """return nb of pixels between [p0 and p1] + """ + return rank8_percentile(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, + 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 rank8_percentile(kernel_threshold,image,selem,mask,out,shift_x,shift_y,p0,p1) diff --git a/skimage/rank/setup.py b/skimage/rank/setup.py new file mode 100644 index 00000000..6d18e27f --- /dev/null +++ b/skimage/rank/setup.py @@ -0,0 +1,15 @@ +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("helloworld", ["helloworld.pyx"]), + 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_percentiles", ["crank16_percentiles.pyx"], include_dirs=[np.get_include()])] +) \ No newline at end of file diff --git a/skimage/rank/tools.py b/skimage/rank/tools.py new file mode 100644 index 00000000..835a8884 --- /dev/null +++ b/skimage/rank/tools.py @@ -0,0 +1,52 @@ +__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 + +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 413db93d09d48d85d7b623e8199ab14e5ccdc7be Mon Sep 17 00:00:00 2001 From: odebeir Date: Thu, 4 Oct 2012 09:13:33 +0200 Subject: [PATCH 003/195] adjust code for new project --- skimage/rank/app.log | 1 + skimage/rank/app.py | 173 +++++++------- skimage/rank/core16.pxd | 285 +++++++++++++++++++++++ skimage/rank/core16b.pxd | 286 +++++++++++++++++++++++ skimage/rank/core16p.pxd | 287 +++++++++++++++++++++++ skimage/rank/core8.pxd | 271 ++++++++++++++++++++++ skimage/rank/core8p.pxd | 271 ++++++++++++++++++++++ skimage/rank/crank.pyx | 7 +- skimage/rank/crank16.pyx | 9 +- skimage/rank/crank16_bilateral.pyx | 332 +++++++++++++++++++++++++++ skimage/rank/crank16_percentiles.pyx | 7 +- skimage/rank/crank_percentiles.pyx | 7 +- skimage/rank/setup.py | 4 +- 13 files changed, 1832 insertions(+), 108 deletions(-) create mode 100644 skimage/rank/app.log create mode 100644 skimage/rank/core16.pxd create mode 100644 skimage/rank/core16b.pxd create mode 100644 skimage/rank/core16p.pxd create mode 100644 skimage/rank/core8.pxd create mode 100644 skimage/rank/core8p.pxd create mode 100644 skimage/rank/crank16_bilateral.pyx diff --git a/skimage/rank/app.log b/skimage/rank/app.log new file mode 100644 index 00000000..7eae20f5 --- /dev/null +++ b/skimage/rank/app.log @@ -0,0 +1 @@ +2012-10-04 09:12:19,785 MainProcess 5265 start logging in app.log diff --git a/skimage/rank/app.py b/skimage/rank/app.py index acfc33ec..0cf24408 100644 --- a/skimage/rank/app.py +++ b/skimage/rank/app.py @@ -1,3 +1,5 @@ +import unittest + import numpy as np from time import time import matplotlib.pyplot as plt @@ -9,7 +11,7 @@ import crank import crank16 import crank_percentiles import crank16_percentiles -from pyrankfilter import filter +import crank16_bilateral from cmorph import dilate @@ -17,10 +19,6 @@ from cmorph import dilate def c_max(image,selem): return crank.maximum(image=image,selem = selem) -@log_timing -def w_max(image,selem): - return filter.maximum(image,struct_elem = selem) - @log_timing def cm_max(image,selem): return dilate(image=image,selem = selem) @@ -39,10 +37,8 @@ def compare(): elem = np.ones((r,r),dtype='uint8') # elem = (np.random.random((r,r))>.5).astype('uint8') (rc,ms_rc) = c_max(a,elem) - (rw, ms_rw) = w_max(a,elem) (rcm,ms_rcm) = cm_max(a,elem) rec.append((ms_rc,ms_rw,ms_rcm)) - assert (rc==rw).all() assert (rc==rcm).all() rec = np.asarray(rec) @@ -59,10 +55,8 @@ def compare(): for s in range(100,1000,100): a = (np.random.random((s,s))*256).astype('uint8') (rc,ms_rc) = c_max(a,elem) - (rw, ms_rw) = w_max(a,elem) (rcm,ms_rcm) = cm_max(a,elem) rec.append((ms_rc,ms_rw,ms_rcm)) - assert (rc==rw).all() assert (rc==rcm).all() rec = np.asarray(rec) @@ -71,89 +65,105 @@ def compare(): plt.plot(rec) plt.legend(['sliding cython','sliding weaves','cmorph']) plt.figure() - plt.imshow(np.hstack((rc,rw,rcm))) + plt.imshow(np.hstack((rc,rcm))) plt.show() +class TestSequenceFunctions(unittest.TestCase): -def test_image_size(): - """try several image sizes to check bounds conditions - """ - 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)): - a = np.ones((m,n),dtype='uint8') - r = crank.mean(image=a,selem = elem,shift_x=0,shift_y=0) - assert a.shape == r.shape - r = crank.mean(image=a,selem = elem,shift_x=0,shift_y=-1) - assert a.shape == r.shape - r = crank.mean(image=a,selem = elem,shift_x=0,shift_y=+1) - assert a.shape == r.shape - r = crank.mean(image=a,selem = elem,shift_x=-1,shift_y=0) - assert a.shape == r.shape - r = crank.mean(image=a,selem = elem,shift_x=+1,shift_y=0) - assert a.shape == r.shape - r = crank.mean(image=a,selem = elem,shift_x=-1,shift_y=-1) - assert a.shape == r.shape - r = crank.mean(image=a,selem = elem,shift_x=+1,shift_y=+1) - assert a.shape == r.shape + def setUp(self): + pass - return True + def test_random_sizes(self): + # make sure the size is not a problem + niter = 10 + elem = np.asarray([[1,1,1],[1,1,1],[1,1,1]],dtype='uint8') + for m,n in np.random.random_integers(1,100,size=(10,2)): + a8 = np.ones((m,n),dtype='uint8') + r = crank.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) + self.assertTrue(a8.shape == r.shape) + for m,n in np.random.random_integers(1,100,size=(10,2)): + a16 = np.ones((m,n),dtype='uint16') + r = crank16.mean(image=a16,selem = elem,shift_x=0,shift_y=0) + self.assertTrue(a16.shape == r.shape) + r = crank16.mean(image=a16,selem = elem,shift_x=+1,shift_y=+1) + self.assertTrue(a16.shape == r.shape) + + for m,n in np.random.random_integers(1,100,size=(10,2)): + a16 = np.ones((m,n),dtype='uint16') + r = crank16_percentiles.mean(image=a16,selem = elem,shift_x=0,shift_y=0,p0=.1,p1=.9) + self.assertTrue(a16.shape == r.shape) + r = crank16_percentiles.mean(image=a16,selem = elem,shift_x=+1,shift_y=+1,p0=.1,p1=.9) + self.assertTrue(a16.shape == r.shape) + + def test_compare_with_cmorph(self): + #compare the result of maximum filter with dilate + a = (np.random.random((500,500))*256).astype('uint8') + + for r in range(1,20,1): + elem = np.ones((r,r),dtype='uint8') + # elem = (np.random.random((r,r))>.5).astype('uint8') + rc = crank.maximum(image=a,selem = elem) + cm = 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) + a16 = np.ones((100,100),dtype='uint16')*255*2 + r = crank16_percentiles.mean(image=a16,selem = elem,shift_x=0,shift_y=0,p0=.1,p1=.9,bitdepth=9) + a16 = np.ones((100,100),dtype='uint16')*255*4 + r = crank16_percentiles.mean(image=a16,selem = elem,shift_x=0,shift_y=0,p0=.1,p1=.9,bitdepth=10) + a16 = np.ones((100,100),dtype='uint16')*255*8 + r = crank16_percentiles.mean(image=a16,selem = elem,shift_x=0,shift_y=0,p0=.1,p1=.9,bitdepth=11) + a16 = np.ones((100,100),dtype='uint16')*255*16 + r = crank16_percentiles.mean(image=a16,selem = elem,shift_x=0,shift_y=0,p0=.1,p1=.9,bitdepth=12) + + def test_population(self): + a = np.zeros((5,5),dtype='uint8') + elem = np.ones((3,3),dtype='uint8') + p = crank.pop(image=a,selem = elem) + r = np.asarray([[4, 6, 6, 6, 4], + [6, 9, 9, 9, 6], + [6, 9, 9, 9, 6], + [6, 9, 9, 9, 6], + [4, 6, 6, 6, 4]]) + np.testing.assert_array_equal(r,p) + + def test_structuring_element(self): + 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) + r = np.asarray([[ 0, 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0, 0], + [ 0, 0, 255, 0, 0, 0], + [ 0, 0, 255, 255, 255, 0], + [ 0, 0, 0, 255, 255, 0], + [ 0, 0, 0, 0, 0, 0]]) + np.testing.assert_array_equal(r,f) + + + @unittest.expectedFailure + def test_fail_on_bitdepth(self): + # should fail because data bitdepth is too high for the function + a16 = np.ones((100,100),dtype='uint16')*255 + elem = np.ones((3,3),dtype='uint8') + f = crank16_percentiles.mean(image=a16,selem = elem,shift_x=0,shift_y=0,p0=.1,p1=.9,bitdepth=4) if __name__ == '__main__': logger = init_logger('app.log') - a = np.zeros((10,10),dtype='uint8') - a[2,2] = 255 -# a[2,3] = 255 -# a[2,4] = 255 - print a +# unittest.main() + suite = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions) + unittest.TextTestRunner(verbosity=2).run(suite) - mask = np.ones_like(a) -# mask[:3,:3] = 0 - -# elem = np.asarray([[0,1,0],[1,1,1],[0,1,0]],dtype='uint8') - elem = np.asarray([[1,1,0],[1,1,1],[0,0,1]],dtype='uint8') - - niter = 1 - t0 = time() - - for iter in range(niter): - r = crank.mean(image=a,selem = elem,shift_x=0,shift_y=0,mask = mask) - p = crank.pop(image=a,selem = elem,shift_x=0,shift_y=0,mask = mask) - t1 = time() - print '%f msec'%(t1-t0) - - print 'cython mean' - print r - print p - - t0 = time() - for iter in range(niter): - r = filter.mean(a,struct_elem = elem,struct_elem_center=(1,1),mask = mask) - t1 = time() - print '%f msec'%(t1-t0) - - print 'filter.mean:' - print r - - print a - r = crank.maximum(image=a,selem = elem,shift_x=0,shift_y=0,mask = mask) - print r - - r = crank.gradient(image=r,selem = elem,shift_x=0,shift_y=0,mask = mask) - print r - im = np.zeros((10,10),dtype='uint8') - im[2:6,2:6] = 255 - elem = np.asarray([[1,1,1],[1,1,1],[1,1,1]],dtype='uint8') - f = crank.gradient(image=im,selem = elem) - print f - f = crank.egalise(image=im,selem = elem) - print f # compare() -# test_image_size() # a = (data.coins()).astype('uint8') a8 = (data.coins()).astype('uint8') @@ -162,9 +172,10 @@ if __name__ == '__main__': # 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_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((f1,f2))) + plt.imshow(np.hstack((a,f2))) plt.colorbar() plt.show() diff --git a/skimage/rank/core16.pxd b/skimage/rank/core16.pxd new file mode 100644 index 00000000..9973025f --- /dev/null +++ b/skimage/rank/core16.pxd @@ -0,0 +1,285 @@ +""" 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 + +# 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 +#--------------------------------------------------------------------------- + +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 diff --git a/skimage/rank/core16b.pxd b/skimage/rank/core16b.pxd new file mode 100644 index 00000000..38832c11 --- /dev/null +++ b/skimage/rank/core16b.pxd @@ -0,0 +1,286 @@ +""" 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 + +# 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 +#--------------------------------------------------------------------------- + +cdef inline rank16b(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 + 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,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(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,s0,s1) + # 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,s0,s1) + # 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,s0,s1) + # 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,s0,s1) + # 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 diff --git a/skimage/rank/core16p.pxd b/skimage/rank/core16p.pxd new file mode 100644 index 00000000..dbf51c54 --- /dev/null +++ b/skimage/rank/core16p.pxd @@ -0,0 +1,287 @@ +""" 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 +#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 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 + + diff --git a/skimage/rank/core8.pxd b/skimage/rank/core8.pxd new file mode 100644 index 00000000..0c901c8b --- /dev/null +++ b/skimage/rank/core8.pxd @@ -0,0 +1,271 @@ +""" 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 + +# 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 + diff --git a/skimage/rank/core8p.pxd b/skimage/rank/core8p.pxd new file mode 100644 index 00000000..25e3ffcf --- /dev/null +++ b/skimage/rank/core8p.pxd @@ -0,0 +1,271 @@ +""" 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 +#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 receives 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 + diff --git a/skimage/rank/crank.pyx b/skimage/rank/crank.pyx index 09048917..59016eed 100644 --- a/skimage/rank/crank.pyx +++ b/skimage/rank/crank.pyx @@ -15,12 +15,7 @@ import numpy as np cimport numpy as np # import main loop -from core cimport rank8 - -# todo -# - manage float output, -# - manage different bit depth input -# - add auxiliary parameters (spectral_interval, infSup) +from core8 cimport rank8 # ----------------------------------------------------------------- # kernels uint8 diff --git a/skimage/rank/crank16.pyx b/skimage/rank/crank16.pyx index 78e5a2af..cd0bacd4 100644 --- a/skimage/rank/crank16.pyx +++ b/skimage/rank/crank16.pyx @@ -2,7 +2,7 @@ >>> python setup.py build_ext --inplace to generate html report use: ->>> cython -a crank.pxd +>>> cython -a crank16.pxd """ @@ -15,12 +15,7 @@ import numpy as np cimport numpy as np # import main loop -from core cimport rank16 - -# todo -# - manage float output, -# - manage different bit depth input -# - add auxiliary parameters (spectral_interval, infSup) +from core16 cimport rank16 # ----------------------------------------------------------------- # kernels uint16 take extra parameter for defining the bitdepth diff --git a/skimage/rank/crank16_bilateral.pyx b/skimage/rank/crank16_bilateral.pyx new file mode 100644 index 00000000..313b83d6 --- /dev/null +++ b/skimage/rank/crank16_bilateral.pyx @@ -0,0 +1,332 @@ +""" 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 +#cython: wraparound=False + +import numpy as np +cimport numpy as np + +# import main loop +from core16b cimport rank16b + +# ----------------------------------------------------------------- +# 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 + cdef float mean = 0. + + if pop: + for i in range(maxbin): + if (g>(i-s0)) and (g<(i+s1)): + bilat_pop += histo[i] + mean += histo[i]*i + if bilat_pop: + return (mean/bilat_pop) + else: + return (0) + 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 + + if pop: + for i in range(maxbin): + if (g>(i-s0)) and (g<(i+s1)): + bilat_pop += histo[i] + return (bilat_pop) + 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, + 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 rank16b(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, + 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 rank16b(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) diff --git a/skimage/rank/crank16_percentiles.pyx b/skimage/rank/crank16_percentiles.pyx index b967c61a..7756bc19 100644 --- a/skimage/rank/crank16_percentiles.pyx +++ b/skimage/rank/crank16_percentiles.pyx @@ -15,12 +15,7 @@ import numpy as np cimport numpy as np # import main loop -from core cimport rank16_percentile - -# todo -# - manage float output, -# - manage different bit depth input -# - add auxiliary parameters (spectral_interval, infSup) +from core16p cimport rank16_percentile # ----------------------------------------------------------------- # kernels uint8 (SOFT version using percentiles) diff --git a/skimage/rank/crank_percentiles.pyx b/skimage/rank/crank_percentiles.pyx index 51a9e01f..d4d6312f 100644 --- a/skimage/rank/crank_percentiles.pyx +++ b/skimage/rank/crank_percentiles.pyx @@ -15,12 +15,7 @@ import numpy as np cimport numpy as np # import main loop -from core cimport rank8_percentile - -# todo -# - manage float output, -# - manage different bit depth input -# - add auxiliary parameters (spectral_interval, infSup) +from core8p cimport rank8_percentile # ----------------------------------------------------------------- # kernels uint8 (SOFT version using percentiles) diff --git a/skimage/rank/setup.py b/skimage/rank/setup.py index 6d18e27f..e9af9446 100644 --- a/skimage/rank/setup.py +++ b/skimage/rank/setup.py @@ -6,10 +6,10 @@ from Cython.Distutils import build_ext setup( cmdclass = {'build_ext': build_ext}, - ext_modules = [Extension("helloworld", ["helloworld.pyx"]), - Extension("cmorph", ["cmorph.pyx"], include_dirs=[np.get_include()]), + 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()])] ) \ No newline at end of file From f3c89c5364cced2311ba9f724c83d7bfa7a7b1bc Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 11:32:33 +0200 Subject: [PATCH 004/195] 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 005/195] 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 006/195] 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 007/195] 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 008/195] 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 009/195] 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 010/195] 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 011/195] 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 012/195] 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 013/195] 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 014/195] 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 015/195] 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 016/195] 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 017/195] 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 018/195] 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 019/195] 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 020/195] 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 021/195] =?UTF-8?q?add=20bilateral=20filters=20pop=20and?= =?UTF-8?q?=20mean=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 022/195] 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 023/195] 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 024/195] 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 025/195] 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 026/195] 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 027/195] 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 028/195] 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 029/195] 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 030/195] 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 031/195] 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 032/195] 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 033/195] 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 034/195] 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 035/195] 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 036/195] 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 037/195] 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 038/195] 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 039/195] 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 040/195] 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 041/195] 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 042/195] 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 043/195] 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 044/195] 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 045/195] 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 046/195] 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 047/195] 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 048/195] 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 049/195] 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 050/195] 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 051/195] 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 052/195] 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 053/195] 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 054/195] 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 055/195] 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 056/195] 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 057/195] 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 058/195] 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 059/195] 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 060/195] 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 061/195] 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 062/195] 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 063/195] 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 064/195] 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 065/195] 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 066/195] 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 067/195] 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 068/195] 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 069/195] 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 070/195] 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 071/195] 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 072/195] 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 073/195] 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 074/195] 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 075/195] 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 076/195] 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 077/195] 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 078/195] __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 079/195] 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 080/195] 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 081/195] 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 082/195] 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 083/195] 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 084/195] 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 085/195] 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 086/195] 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 087/195] 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 088/195] 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 089/195] 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) From 9a7d9cd161caef4e0cbc1d632746fb5b27080fc4 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 11:32:33 +0200 Subject: [PATCH 090/195] 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 9788400f1f2f5c0de69c7f40e877ef01a809171c Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 16:09:56 +0200 Subject: [PATCH 091/195] 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 a309a354fc74626f607b06fdb5ee4d040a4d7624 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 16:12:08 +0200 Subject: [PATCH 092/195] 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 9eadcdf77493ba68c24ed7745ca48c0df43c906f Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 16:35:06 +0200 Subject: [PATCH 093/195] 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 2d6014e3566ee110658cfd09e7af38e6b1f85848 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 17:15:10 +0200 Subject: [PATCH 094/195] 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 969a8f6e6c2fdc69dee4af926eb035d8d9db4333 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 17:30:21 +0200 Subject: [PATCH 095/195] 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 5e0960275c7fa2fe3141b577aef826524304d50b Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 17:59:03 +0200 Subject: [PATCH 096/195] 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 1f5c2b9bfeac022009649d91a3214135127014c6 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 18:02:54 +0200 Subject: [PATCH 097/195] 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 27d028e2e99d32fa603a677c581e2a896e83a51a Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 18:03:08 +0200 Subject: [PATCH 098/195] 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 243c8bfabb12563bc3af5fd93cb9694b06aa0a2f Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 4 Oct 2012 18:23:33 +0200 Subject: [PATCH 099/195] 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 d4e01c2287c01824cf6394837916d9cd53f10cf3 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 10:56:05 +0200 Subject: [PATCH 100/195] 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 0c8b4157ed639b7a9735fffbcf760b3ff6f75e6e Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 11:26:14 +0200 Subject: [PATCH 101/195] 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 87db4ee5907d8c5288bd04673555a9381cbfc0eb Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 11:28:27 +0200 Subject: [PATCH 102/195] 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 3f476703f848860f3eb15eb75225d3a8f6e0b6b6 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 12:09:03 +0200 Subject: [PATCH 103/195] 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 54e22e08020317fbea459ef639b5e9f0aa7122b6 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 14:46:48 +0200 Subject: [PATCH 104/195] 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 10155e2e4d4cce8e1b655cc64afb158e04b7591b Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 15:22:59 +0200 Subject: [PATCH 105/195] 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 304cac7ecdef50bba63188316236b912f784bf4b Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 16:08:30 +0200 Subject: [PATCH 106/195] 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 8222a58ec8261516abeaf3c3a935cfc3fa270ee8 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 16:19:04 +0200 Subject: [PATCH 107/195] =?UTF-8?q?add=20bilateral=20filters=20pop=20and?= =?UTF-8?q?=20mean=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 c633fb895398031d1b7451b769bd433900f4cb30 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 17:00:26 +0200 Subject: [PATCH 108/195] 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 866ea40fbbed2d3c860b8a34f41fee65b81b5a48 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 17:15:33 +0200 Subject: [PATCH 109/195] 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 b83ae7086272c98715c326e7e7fc129686332bc2 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 17:48:15 +0200 Subject: [PATCH 110/195] 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 60e5dc7fe39b89a27d094a9b0d7eada3a7da35d2 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 5 Oct 2012 18:05:48 +0200 Subject: [PATCH 111/195] 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 a7ff15188fabda230abfb681cf8cd2f92123ac09 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 11:13:58 +0200 Subject: [PATCH 112/195] 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 d13517035fa1cdb4e29374b699b731d03ffbf031 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 11:29:28 +0200 Subject: [PATCH 113/195] 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 dc838a690f4d572fff2179b34bb489e7da56e1e4 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 11:37:22 +0200 Subject: [PATCH 114/195] 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 9f33242679e449cc2b3c5fc74c1b095f0c5538a6 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 11:41:18 +0200 Subject: [PATCH 115/195] 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 ad0c59f2dbd922e65a8eb762602c8748f8f4e557 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 11:44:03 +0200 Subject: [PATCH 116/195] 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 86449613e4c2a707864f311d4ae5b08051296ca4 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 14:14:13 +0200 Subject: [PATCH 117/195] 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 a07d0f64bbbef874c1a361341acf29bc587e10a4 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 14:30:29 +0200 Subject: [PATCH 118/195] 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 11566ced34b36355921a63b2f0b1c2bd21be6b13 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 15:34:54 +0200 Subject: [PATCH 119/195] 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 936b7d5d21bac67ba59aa032a7cf35d3b8979480 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 15:40:05 +0200 Subject: [PATCH 120/195] 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 633f30e23fbb949a429868f68cb711fda3085b7e Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 15:45:43 +0200 Subject: [PATCH 121/195] 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 175658e677b127ea583fb7385d47699a402878fa Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 15:48:36 +0200 Subject: [PATCH 122/195] 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 7ef083e5a67560d37730f12c4b44b9f79c598ea2 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 15:50:50 +0200 Subject: [PATCH 123/195] 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 c4dc33a27d3ba268daea32416cdd3a1b38a5ef4f Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 15:53:00 +0200 Subject: [PATCH 124/195] 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 7aae3ac6b68592ce99b97cf0ba8e84ea4f6e48c5 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 15:54:55 +0200 Subject: [PATCH 125/195] 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 c26d57dcfa246f907244a7f4c1db6f63073bbed7 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 16:46:37 +0200 Subject: [PATCH 126/195] 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 0a73260d5de6a87eeb88bab597a22374f20a9fa3 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 16:47:34 +0200 Subject: [PATCH 127/195] 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 ebfe4b8b95ca14344d461a9a4df4c0f24d9cf135 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 16:47:57 +0200 Subject: [PATCH 128/195] 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 cc5e23ef8a0fe41ebc13c02d4d908bd3c5223458 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 10 Oct 2012 17:32:35 +0200 Subject: [PATCH 129/195] 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 90351170d707298fe8c879a9eac52d66ef1ac6c7 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 11 Oct 2012 11:41:37 +0200 Subject: [PATCH 130/195] 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 42feb70a31cf0ef6f9cf23b82f6b44bf424a67e6 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 11 Oct 2012 12:03:34 +0200 Subject: [PATCH 131/195] 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 b208060cdf96948894f6b2993b88e772ea019bf2 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 11 Oct 2012 12:13:01 +0200 Subject: [PATCH 132/195] 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 0992ff6db72f688d64cfdec1f79a77d2877cb96f Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 11 Oct 2012 12:19:45 +0200 Subject: [PATCH 133/195] 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 9d9a7492bf76ef6fd6b67136fd7d3169587d36f9 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 12 Oct 2012 17:03:03 +0200 Subject: [PATCH 134/195] 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 3ccec228254cba8053062066d1fd209e1fc59a5d Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 12 Oct 2012 17:13:35 +0200 Subject: [PATCH 135/195] 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 23c8768cfad8f2bcafa32a1dc5c759a228c428b9 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 12 Oct 2012 17:19:38 +0200 Subject: [PATCH 136/195] 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 1c4e17a4351e97bb8089bdd95be9dbe3ab26f6eb Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 12 Oct 2012 17:34:04 +0200 Subject: [PATCH 137/195] 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 3d973a192e95691d3a8b70c734d6c36f851295c8 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Fri, 12 Oct 2012 17:47:51 +0200 Subject: [PATCH 138/195] 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 85b552230d8d7845515936495bc6f170bd32acc7 Mon Sep 17 00:00:00 2001 From: odebeir Date: Sat, 13 Oct 2012 09:47:25 +0200 Subject: [PATCH 139/195] 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 388bb7fc29a2972d51d3fba07ce23b3ba443b065 Mon Sep 17 00:00:00 2001 From: odebeir Date: Sat, 13 Oct 2012 10:09:06 +0200 Subject: [PATCH 140/195] 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 43cd63b133946735cf63f138af06a3d0fc5ee912 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 13:21:33 +0200 Subject: [PATCH 141/195] 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 c3a3f39bbc834e4a4f35f7c5c727c3f18f77d179 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 13:26:28 +0200 Subject: [PATCH 142/195] 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 b78a0460fbb43bcc942742b3a6b41f8d315977c8 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 13:36:41 +0200 Subject: [PATCH 143/195] 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 8b3b42bc02a9db778a13a8d9a824cdd7ff74769e Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 14:45:25 +0200 Subject: [PATCH 144/195] 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 b9c52e02961098b4ea9b0ae9c25a0d2193929551 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 15:03:29 +0200 Subject: [PATCH 145/195] 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 7df19d2810cad63cd550aa786a64dcc52cd06130 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 15:16:26 +0200 Subject: [PATCH 146/195] 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 ef768b22a86f78bf703794b52fea5e718e1a1114 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 15:42:31 +0200 Subject: [PATCH 147/195] 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 7862b971be98c8408b121bb5b596360f0c71ceb7 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 15:55:21 +0200 Subject: [PATCH 148/195] 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 e29ce3dba02931e0ae88b2cce29504895e59400f Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 16:35:11 +0200 Subject: [PATCH 149/195] 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 096fa018777338c046dca970a211694101395bc6 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 16:36:08 +0200 Subject: [PATCH 150/195] 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 a13d1bb4ac525b63f411d60af2a87635132d8883 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 16:46:41 +0200 Subject: [PATCH 151/195] 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 0e7271bfb4eff629ff73278a969c663cbcd5d337 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 15 Oct 2012 16:56:36 +0200 Subject: [PATCH 152/195] 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 f35cd7aa3af8ab35f6fbc598c32682b86b3fd9c7 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Tue, 16 Oct 2012 11:13:09 +0200 Subject: [PATCH 153/195] 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 8f70a1d01ce315a44b9c65c5b516f125c60ace03 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Tue, 16 Oct 2012 12:12:28 +0200 Subject: [PATCH 154/195] 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 b6b202ae7bbb1efcc88ccb86317903e0bb370fe3 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Tue, 16 Oct 2012 12:36:05 +0200 Subject: [PATCH 155/195] 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 e7e60a6cdb8f11c460b4a6507986ebf7dc3ab028 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Tue, 16 Oct 2012 14:40:42 +0200 Subject: [PATCH 156/195] 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 f730a644640685a62195b20ddc5027b7b3041254 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Tue, 16 Oct 2012 15:03:34 +0200 Subject: [PATCH 157/195] 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 c42fabc53f1615ac150dab551e08d0d5f651d86c Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Tue, 16 Oct 2012 16:20:12 +0200 Subject: [PATCH 158/195] 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 1e72afdb8bd79cb44fb77a2a25070f729a4aaaac Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Tue, 16 Oct 2012 17:03:22 +0200 Subject: [PATCH 159/195] 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 5b169f2a5e1b459e192256035e156fd0197e1f70 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 17 Oct 2012 12:07:20 +0200 Subject: [PATCH 160/195] 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 32b9cba23c79e17a486550d113c3f72386c13188 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 18 Oct 2012 09:18:01 +0200 Subject: [PATCH 161/195] 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 6814f5945488a1c8ffe2a883b9806134a22f16b5 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 18 Oct 2012 09:19:45 +0200 Subject: [PATCH 162/195] 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 9546c344a0317e3696382459e3bf250b0c4fb3fc Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 18 Oct 2012 09:23:41 +0200 Subject: [PATCH 163/195] 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 c73b14e2..8ba62e0b 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 f2f8b68a1a11afd982e5f167defe492bf62f2057 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 18 Oct 2012 09:25:18 +0200 Subject: [PATCH 164/195] __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 117b6d187bbdd34c02042ecbadaae6af0df7c465 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 18 Oct 2012 10:00:10 +0200 Subject: [PATCH 165/195] 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 zcmd44cXU-%`p13Fp%te0trb7kc7_r`JBve&HUE;TkHMz&0RP5+*5XWzE9iFe)hh1-+g|twK5DE z2SHdX2!kLv$UFS6_{9I$ zqa7al>#ZFw{ohYsd};jm@&$aHe)+|hUU>}%e!JrIOXJt&S6y}bzu*5;%MF+O?*<1; z!%bm!m>3QW$Amq@55lLzW?}pAgz$~J>e)w_NH#{x;F31bs4%dWB!)4*haBjGm zCuW4b!&kx%VfXOc@QQGG7)IN}s&H?Z6PAX1!YJAm9v2-AkA?@r!mw7fk87o2QCK@F z=iBbEVN@J$3+qSw!yTO6O)J8vlzVoEB|O_a3VHS*Pk1(n4sh2|o~skprrbT@{;(q4 z7dD7?hMU7W@x42#xj|GnY8fSSe_?oxr}y#HuCSaEef9t?*&kMOre1WA>nBoLHQ&9y zFFZb~;ormA;jD0M_+r>LEDu%$vx410oA8XV3dXG$W(MPfF}zcP2H`J! zt`0s5pA07ly@P?l#9&;|kI(5`%?xsbZNc{7)bMY-o&cXEVR1M(92L$9hldlwdEw~r z$MF5|R}k12Hi{O5&>E0P0-G7(mT($0*%Gb=kt|-@d6k7n!hA}}0?C!!yEa@9{t@;H z`-i`U1Hwfi%V-xzcW6N5Ry=wMCo4W%WAX<=%Z60YD{QaCyMEbIdEk3of{U|SgO zgo10~q5`N~LHP$kU=J;=g#L$OidRG5ePDJJ+6N$b7>vtkjc62e*M3T=9aZtU3vMW< zm8INU&h1D)xCF z$45ZCNpx0pn5W9AOa5pG{!!E+EDBBz{~Er=>pgmPL-;5?d@+13yfeHutc^6>8a~gJ z=fWGqKZTov6T&v(C7ioBJS(gK?Oa}~gUaBoa1oT8AAT3U9G;659SzP3PYzolJ$HoX zQ^!oWU>dki3i<|vf{~Q-r|{Qc1bEL1#suzC?efh6}@q zP<>iB4z5Z8r*2_a@G1*iMr){ZIoIcaL>joR<=ax;nQ&hYvQY>!S^Qtc*(|QFM1FI_ zjBpC245j2hM>j^_hlfD@<8W8dIP4D(R|Sc|<6$26tmXb>o*aafe~un_0^WNwyq+^f z;W{Y46I{f84;VxszK+jKcwj&0>PAPPzfxQuXpP<6u?ub}i#1IZwbY?b^+GZK3u(jYaLG>Y zKSrr#e1=hDN;?V{HsClDRD$rh@FOVv4|?<=y?+gT_bO+e49`Q-9|Exl(S^^24MXMn z_^?IT9L~5FjkrE23`&D_!TO*++_EK{1RaMU>wg2!8^deD2<)E;FXd=WP>ep<7}VyO zX~A%iP7P)U-8jmGU)BT(@WJX}ZLl273xgxUQ{n63b+l$A=nSCD6_j05`tRu4F37!d zwvh8Hz-0-j&qEWh1gj$WA{#l_2xT{e?+#?G5Nc$E>0tux+Zv7!|B05k6a6(2-ThkF z64XDW%xA+5!HsCN%fstkuL{lF@8tZajC0F-?Z3SqC zlx3NlDg7AFY8h&Qd2Q~Nn>Ru2O3FWk?ADIzA-!8EeJ5vj@qGq$)Qc9vAuZsdMp4uF zjwU*-)ZvLK;ScEFX;A7bxaK)*K^rh{z`Ge5p=r1SbRVM3=3&=hFw!(K z=oyR(CInk3p%QJeAlSrvCzxN3_HIv&BhbB{hChMrd?a@$Qavo}jAnkFwibZ-MqUfS zat_F6((8@TV_z&oYtRroq3s@MwgnoM#Pt3StF@N0#v;4-V82GhDx6C}7kTA`Y2`)TbF3n_mOz1ETIPh-dHV9`&8N*6=F-C%woI0Ryi(BR#8 z`irn1zR!HH8Oq)FglC3nAlWJ`43;9xqk;=KGbi{FZ9WjhM+8a1P~?Aikb`XRL%VJa z3W5mh(g8}3hThZQ=&|8U5Fdg(FNB-EpyXGeZ3#MH9_RA;zZ~jsN4Mtk-Ush}31~XZ`iKSpz||W_AYpH zw?dot_-PM-*`ImuWms}Ucxt#G&Atb}>{PBi2v)aZALc^gG^o`NX?y^EIS`8wA@jR~ zWq}gkozEoj9uo9N#<#)|*+Ck*zaiS=GEl!3?z#r~&ZG^?L1{c1cruzj3C#Y0Bm2OQ zo53v!+1nL+*QrS4D*CHb6o6C~$7;nA-g;b{k@!{c!g@;R2LIlPR_YdZqStT1MW29r zYH(}#4V-=>GH^Xoa55gq?;x~)gz88xbqmTJcj0|jg%jPPxiwPJ3y%d48{K-Xz$=2?Z8$_s^;k( zlvd1@QnWzRXdCuGYrYfw_wxJ_`dLoDlc3Qt5Y{iO#P>T!{f(%<4r795@J|(7b}8EZ zCM^2Hp!xxFun2wL75WZ>j$gsYpJ1cUMW0<7o{rQ#&igrR+n>5Mh~3pKq8Rr`bR4y?{-N=$(6^Wnv>K>QOt?>uBbHTJCau9t)ACZv2dcrW32 zJ=82k4$F|8BCPuwo?J=)rh?l8VEP7B=^tydZ^B>T=1&+|RAF~Ip}%j%e>nqR*!Z|?9&g}z<25ECZu{d*zADrg_PPf+5kS4oKyPiV$=6yU-m=& z3O?)b-Em$eQofh(Cm?e>;gkJ5vzL3yC}R)U>SZh0`s*Q@pbEqt *mQA#EEoq#Nt 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%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 2c1bed000d192b6b081cb53bed8ebb0cd7d55365 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 18 Oct 2012 10:12:19 +0200 Subject: [PATCH 166/195] 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 c5fb9b4b7222eab63276711411340e48a60f7761 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 18 Oct 2012 10:21:34 +0200 Subject: [PATCH 167/195] 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 2844db6025d551a228347982e12da83d8992d926 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 18 Oct 2012 15:21:14 +0200 Subject: [PATCH 168/195] 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 b8d9227d85e9c723805d5dc16eaacd3bab707335 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 18 Oct 2012 15:32:24 +0200 Subject: [PATCH 169/195] 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 27793ddecc97cc62326347408cea906afbdbbe34 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 29 Oct 2012 09:14:50 +0100 Subject: [PATCH 170/195] 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 cdfa2a6d90befbb84c38af013f0f25960d45043c Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 29 Oct 2012 09:21:10 +0100 Subject: [PATCH 171/195] move setup from /filter/rank to /filter --- skimage/filter/rank/setup.py | 52 ------------------------------------ skimage/filter/setup.py | 28 +++++++++++++++++-- 2 files changed, 26 insertions(+), 54 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 b996055b..79755e87 100644 --- a/skimage/filter/setup.py +++ b/skimage/filter/setup.py @@ -14,11 +14,35 @@ def configuration(parent_package='', top_path=None): cython(['_ctmf.pyx'], working_path=base_path) cython(['_denoise.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('_denoise', sources=['_denoise.c'], - include_dirs=[get_numpy_include_dirs(), '../_shared']) + include_dirs=[get_numpy_include_dirs(), '../_shared']) + 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 4ec4174b44ab10140e911e2a7ea890c95371dce2 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 29 Oct 2012 09:26:12 +0100 Subject: [PATCH 172/195] 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 b6527080751e16922be9f7b02f18a9c14b1f77ad Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 29 Oct 2012 09:35:28 +0100 Subject: [PATCH 173/195] 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 1d1696f11d1da6ee52071e5ba333b53c0b8e5d3f Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 29 Oct 2012 16:32:08 +0100 Subject: [PATCH 174/195] 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 528718bb6d2ff45bf34560fe43b7b460aba15f87 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 29 Oct 2012 17:04:10 +0100 Subject: [PATCH 175/195] 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) From 262e7f78f4ffe9145be2e1fcd8717cd4dde8da5d Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Mon, 29 Oct 2012 18:29:48 +0100 Subject: [PATCH 176/195] small comparison with denoise_bilateral --- skimage/filter/rank/demo/demo_single.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/skimage/filter/rank/demo/demo_single.py b/skimage/filter/rank/demo/demo_single.py index 39b9acc0..652f2cc8 100644 --- a/skimage/filter/rank/demo/demo_single.py +++ b/skimage/filter/rank/demo/demo_single.py @@ -5,6 +5,7 @@ from skimage import data from skimage.morphology.selem import disk import skimage.filter.rank as rank +from skimage.filter import denoise_bilateral if __name__ == '__main__': a8 = data.camera() @@ -15,6 +16,16 @@ if __name__ == '__main__': f16= rank.autolevel(a16,selem) f16p= rank.percentile_autolevel(a16,selem,p0=.0,p1=1.) + den = denoise_bilateral(a8,win_size=10,sigma_range=10,sigma_spatial=2)[:,:,0] + f16b= rank.bilateral_mean(a8.astype(np.uint16),disk(10),s0=10,s1=10) + + plt.figure() + plt.subplot(1,2,1) + plt.imshow(den) + plt.subplot(1,2,2) + plt.imshow(f16b) + plt.show() + print f16==f16p plt.figure() From 1460d7f1b1f1a66b90f3c35e9db52c957eef42b1 Mon Sep 17 00:00:00 2001 From: odebeir Date: Tue, 30 Oct 2012 16:55:05 +0100 Subject: [PATCH 177/195] compare bilateral --- doc/examples/plot_16bitbilateral.py | 34 +++++++++----- doc/examples/plot_compare_bilateral.py | 63 ++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 11 deletions(-) create mode 100644 doc/examples/plot_compare_bilateral.py diff --git a/doc/examples/plot_16bitbilateral.py b/doc/examples/plot_16bitbilateral.py index 076d03c4..fc30aa6b 100644 --- a/doc/examples/plot_16bitbilateral.py +++ b/doc/examples/plot_16bitbilateral.py @@ -1,9 +1,23 @@ """ ============================== -Simplified bilateral filtering +Bilateral mean ============================== +This example compares -to complete +* local mean +* percentile mean +* bilateral mean + +build on the local histogram distribution +local mean uses all pixels belonging to the structuring element to compute average gray level, +percentile mean uses only values between percentiles p0 and p1 (here 10% and 90%), +whereas bilateral mean uses only pixels of the structuring element having a gray level situated inside +g-s0 and g+s1 (here g-500 and g+500). +The filters are applied on a 16 bit image (actual bitdepth is 12bit). + +Percentile and usual mean give here similar results, these filters smooth the complete image (background and details). +Bilateral mean exhibits a high filtering rate for continuous area (i.e. background) while image higher frequencies +remains untouched. """ import numpy as np @@ -13,23 +27,21 @@ from skimage import data from skimage.morphology import disk import skimage.filter.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) +selem = disk(20) + +f1 = rank.percentile_mean(a16,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) +f3 = rank.mean(a16,selem = selem) # display results -fig, axes = plt.subplots(nrows=3, figsize=(15,15)) +fig, axes = plt.subplots(nrows=3, figsize=(15,10)) ax0, ax1, ax2 = axes -ax0.imshow(np.hstack((a8,f1))) +ax0.imshow(np.hstack((a16,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') +ax2.set_title('local mean') plt.show() diff --git a/doc/examples/plot_compare_bilateral.py b/doc/examples/plot_compare_bilateral.py new file mode 100644 index 00000000..977b7704 --- /dev/null +++ b/doc/examples/plot_compare_bilateral.py @@ -0,0 +1,63 @@ +""" +==================================================== +Bilateral comparison +==================================================== + +In this example, we compare both bilateral implementation + +* filter.denoise_bilateral +* filter.rank.bilateral_mean + +The first filter implements a spatial-gaussian and spectral-gaussian kernel bilateral filter whereas the latter implements +a cylindrical kernel bilateral filter i.e. spatial-flat and spectral-flat kernel. + +The timing comparison is just for information since the kernel are not the same. + +""" + +import numpy as np +import matplotlib.pyplot as plt + +from skimage import data +from skimage.filter._denoise import denoise_bilateral +from skimage.filter.rank import bilateral_mean +from skimage.morphology import disk +from skimage.filter import denoise_bilateral +import time + +def exec_and_timeit(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 + return (res,ms) + return wrapper + + +@exec_and_timeit +def den_bil(image): + return denoise_bilateral(a8,win_size=20,sigma_range=255,sigma_spatial=1)[:,:,0]*255 + +@exec_and_timeit +def rank_bil(image): + return bilateral_mean(a8.astype(np.uint16),disk(20),s0=10,s1=10) + +a8 = data.camera() +selem = disk(10) + +f1,t1 = den_bil(a8) +f2,t2 = rank_bil(a8) + +# display results +fig, axes = plt.subplots(nrows=2, figsize=(15,10)) +ax0, ax1= axes + +ax0.imshow(np.hstack((f1,a8-f1))) +ax0.set_title('denoise bilateral (%f ms)'%t1) +ax1.imshow(np.hstack((f2,a8-f1))) +ax1.set_title('bilateral mean (%f ms)'%t2) +plt.show() From bc08be76a8fca4a150642235a58c1970aa07d976 Mon Sep 17 00:00:00 2001 From: odebeir Date: Fri, 2 Nov 2012 09:50:07 +0100 Subject: [PATCH 178/195] rename rank.py to rank.pyx + adjust setup --- .../rank/{bilateral_rank.py => bilateral_rank.pyx} | 0 .../rank/{percentile_rank.py => percentile_rank.pyx} | 0 skimage/filter/rank/{rank.py => rank.pyx} | 0 skimage/filter/setup.py | 12 ++++++++++++ 4 files changed, 12 insertions(+) rename skimage/filter/rank/{bilateral_rank.py => bilateral_rank.pyx} (100%) rename skimage/filter/rank/{percentile_rank.py => percentile_rank.pyx} (100%) rename skimage/filter/rank/{rank.py => rank.pyx} (100%) diff --git a/skimage/filter/rank/bilateral_rank.py b/skimage/filter/rank/bilateral_rank.pyx similarity index 100% rename from skimage/filter/rank/bilateral_rank.py rename to skimage/filter/rank/bilateral_rank.pyx diff --git a/skimage/filter/rank/percentile_rank.py b/skimage/filter/rank/percentile_rank.pyx similarity index 100% rename from skimage/filter/rank/percentile_rank.py rename to skimage/filter/rank/percentile_rank.pyx diff --git a/skimage/filter/rank/rank.py b/skimage/filter/rank/rank.pyx similarity index 100% rename from skimage/filter/rank/rank.py rename to skimage/filter/rank/rank.pyx diff --git a/skimage/filter/setup.py b/skimage/filter/setup.py index 79755e87..56c1e9e5 100644 --- a/skimage/filter/setup.py +++ b/skimage/filter/setup.py @@ -21,6 +21,9 @@ def configuration(parent_package='', top_path=None): 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) + cython(['rank/rank.pyx'], working_path=base_path) + cython(['rank/percentile_rank.pyx'], working_path=base_path) + cython(['rank/bilateral_rank.pyx'], working_path=base_path) config.add_extension('_ctmf', sources=['_ctmf.c'], include_dirs=[get_numpy_include_dirs()]) @@ -43,6 +46,15 @@ def configuration(parent_package='', top_path=None): config.add_extension( 'rank/_crank16_bilateral', sources=['rank/_crank16_bilateral.c'], include_dirs=[get_numpy_include_dirs()]) + config.add_extension( + 'rank/rank', sources=['rank/rank.c'], + include_dirs=[get_numpy_include_dirs()]) + config.add_extension( + 'rank/percentile_rank', sources=['rank/percentile_rank.c'], + include_dirs=[get_numpy_include_dirs()]) + config.add_extension( + 'rank/bilateral_rank', sources=['rank/bilateral_rank.c'], + include_dirs=[get_numpy_include_dirs()]) return config From 10a6c23ff848cd66f81ac73e5940da47b7629773 Mon Sep 17 00:00:00 2001 From: odebeir Date: Fri, 2 Nov 2012 10:10:39 +0100 Subject: [PATCH 179/195] doc bilateral_rank --- skimage/filter/rank/bilateral_rank.pyx | 47 +++++--------------------- 1 file changed, 8 insertions(+), 39 deletions(-) diff --git a/skimage/filter/rank/bilateral_rank.pyx b/skimage/filter/rank/bilateral_rank.pyx index 69884e16..d72a84c9 100644 --- a/skimage/filter/rank/bilateral_rank.pyx +++ b/skimage/filter/rank/bilateral_rank.pyx @@ -81,33 +81,14 @@ def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal Examples -------- - >>> # Local mean - >>> from skimage.morphology import square - >>> 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], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> 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], - [ 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) - >>> 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], - [ 0, 4095, 4095, 4095, 0], - [ 0, 0, 0, 0, 0]], dtype=uint16) - + >>> from skimage import data + >>> from skimage.morphology import disk + >>> from skimage.filter.rank import bilateral_mean + >>> # bilateral filtering of cameraman image using a flat kernel + >>> # Load test image + >>> a8 = data.camera() + >>> # Apply bilateral filter + >>> bl8 = bilateral_mean(a8, disk(20), s0=10,s1=10) """ return _apply( @@ -161,18 +142,6 @@ def bilateral_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fals [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) - >>> 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], - [4, 4, 6, 4, 4], - [3, 4, 3, 4, 3]], dtype=uint16) - """ return _apply( From 29f187885b2a432cc33a51b99316ffb264342d43 Mon Sep 17 00:00:00 2001 From: odebeir Date: Fri, 2 Nov 2012 15:07:19 +0100 Subject: [PATCH 180/195] doc --- skimage/filter/rank/bilateral_rank.pyx | 41 +- skimage/filter/rank/rank.pyx | 502 ++++--------------------- 2 files changed, 111 insertions(+), 432 deletions(-) diff --git a/skimage/filter/rank/bilateral_rank.pyx b/skimage/filter/rank/bilateral_rank.pyx index d72a84c9..80349b0b 100644 --- a/skimage/filter/rank/bilateral_rank.pyx +++ b/skimage/filter/rank/bilateral_rank.pyx @@ -51,9 +51,17 @@ def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y, s0, 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. + """Apply a flat kernel bilateral filter. - bilateral mean is computed on the given structuring element. Only levels between [g-s0,g+s1] ,are used. + This is an edge-preserving and noise reducing denoising filter. It averages + pixels based on their spatial closeness and radiometric similarity. + + Spatial closeness is measured by considering only the local pixel neighborhood given by a + structuring element (selem). + + Radiometric similarity is defined by the gray level interval [g-s0,g+s1] where g is the current pixel gray level. + Only pixels belonging to the structuring element AND having a gray level inside this interval are averaged. + Return greyscale local bilateral_mean of an image. Parameters ---------- @@ -76,19 +84,29 @@ def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal Returns ------- - local bilateral mean : uint16 array (uint8 image are casted to uint16) + out : uint16 array (uint8 image are casted to uint16) The result of the local bilateral mean. + See also + -------- + skimage.filter.denoise_bilateral() for a gaussian bilateral filter. + + Notes + ----- + + * 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 + Examples -------- >>> from skimage import data >>> from skimage.morphology import disk >>> from skimage.filter.rank import bilateral_mean - >>> # bilateral filtering of cameraman image using a flat kernel >>> # Load test image - >>> a8 = data.camera() - >>> # Apply bilateral filter - >>> bl8 = bilateral_mean(a8, disk(20), s0=10,s1=10) + >>> ima = data.camera() + >>> # bilateral filtering of cameraman image using a flat kernel + >>> bilat_ima = bilateral_mean(ima, disk(20), s0=10,s1=10) """ return _apply( @@ -97,9 +115,8 @@ def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal 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. + """Return the number (population) of pixels actually inside the bilateral neighborhood, + i.e. being inside the structuring element AND having a gray level inside the interval [g-s0,g+s1]. Parameters ---------- @@ -122,8 +139,8 @@ def bilateral_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fals Returns ------- - local bilateral pop : uint16 array (uint8 image are casted to uint16) - The result of the local bilateral pop. + out : uint16 array (uint8 image are casted to uint16) + the local number of pixels inside the bilateral neighborhood Examples -------- diff --git a/skimage/filter/rank/rank.pyx b/skimage/filter/rank/rank.pyx index fc06d48b..730d37c7 100644 --- a/skimage/filter/rank/rank.pyx +++ b/skimage/filter/rank/rank.pyx @@ -38,9 +38,7 @@ def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y): 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. + """Autolevel image using local histogram. Parameters ---------- @@ -61,38 +59,18 @@ def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Returns ------- - local autolevel : uint8 array or uint16 array depending on input image + out : uint8 array or uint16 array (same as input image) The result of the local autolevel. Examples -------- - to be updated - >>> # Local mean - >>> from skimage.morphology import square - >>> 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], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> rank.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) - >>> rank.autolevel(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) + >>> from skimage import data + >>> from skimage.morphology import disk + >>> from skimage.filter.rank import autolevel + >>> # Load test image + >>> ima = data.camera() + >>> # Stretch image contrast locally + >>> auto = autolevel(ima, disk(20)) """ @@ -102,9 +80,7 @@ def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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. + """Returns greyscale local bottomhat of an image. Parameters ---------- @@ -128,35 +104,7 @@ def bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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 - >>> 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], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> rank.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) - >>> rank.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) """ return _apply( @@ -165,9 +113,7 @@ def bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): def equalize(image, selem, out=None, mask=None, shift_x=False, shift_y=False): - """Return greyscale local equalize of an image. - - equalize is computed on the given structuring element. + """Equalize image using local histogram. Parameters ---------- @@ -188,38 +134,18 @@ def equalize(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Returns ------- - local equalize : uint8 array or uint16 array depending on input image + out : uint8 array or uint16 array (same as input image) The result of the local equalize. Examples -------- - to be updated - >>> # Local mean - >>> from skimage.morphology import square - >>> 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], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> rank.equalize(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) - >>> rank.equalize(ima16, square(3)) - 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) + >>> from skimage import data + >>> from skimage.morphology import disk + >>> from skimage.filter.rank import equalize + >>> # Load test image + >>> ima = data.camera() + >>> # Local equalization + >>> equ = equalize(ima, disk(20)) """ return _apply( @@ -228,9 +154,8 @@ def equalize(image, selem, out=None, mask=None, shift_x=False, shift_y=False): def gradient(image, selem, out=None, mask=None, shift_x=False, shift_y=False): - """Return greyscale local gradient of an image. + """Return greyscale local gradient of an image (i.e. local maximum - local minimum). - gradient is computed on the given structuring element. Parameters ---------- @@ -251,38 +176,8 @@ def gradient(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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 - >>> 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], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> rank.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) - >>> rank.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) + out : uint8 array or uint16 array (same as input image) + The local gradient. """ @@ -294,7 +189,6 @@ def gradient(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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 ---------- @@ -315,38 +209,18 @@ def maximum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Returns ------- - local maximum : uint8 array or uint16 array depending on input image - The result of the local maximum. + out : uint8 array or uint16 array (same as input image) + The local maximum. - Examples + See also -------- - to be updated - >>> # Local maximum - >>> from skimage.morphology import square - >>> 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], - ... [0, 0, 0, 0, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> rank.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) + skimage.morphology.dilation() - >>> 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) - >>> rank.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) + Note + ---- + * input image can be 8 bit or 16 bit with a value < 4096 (i.e. 12 bit) + + * the lower algorithm complexity makes the rank.maximum() more efficient for larger images and structuring elements """ @@ -356,8 +230,6 @@ def maximum(image, selem, out=None, mask=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. - Parameters ---------- image : ndarray @@ -377,48 +249,25 @@ def mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Returns ------- - local mean : uint8 array or uint16 array depending on input image - The result of the local mean. + out : uint8 array or uint16 array (same as input image) + The local mean. Examples -------- - to be updated + >>> from skimage import data + >>> from skimage.morphology import disk + >>> from skimage.filter.rank import mean + >>> # Load test image + >>> ima = data.camera() >>> # Local mean - >>> from skimage.morphology import square - >>> 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], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> rank.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) - >>> rank.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) - + >>> avg = mean(ima, disk(20)) """ return _apply(_crank8.mean, _crank16.mean, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) 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. + """Return image substracted from its local mean. Parameters ---------- @@ -439,38 +288,10 @@ def meansubstraction(image, selem, out=None, mask=None, shift_x=False, shift_y=F Returns ------- - local meansubstraction : uint8 array or uint16 array depending on input image + out : uint8 array or uint16 array (same as input image) The result of the local meansubstraction. - Examples - -------- - to be updated - >>> # Local meansubstraction - >>> from skimage.morphology import square - >>> 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], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> rank.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) - >>> rank.meansubstraction(ima16, square(3)) - 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) """ @@ -482,7 +303,6 @@ def meansubstraction(image, selem, out=None, mask=None, shift_x=False, shift_y=F 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 ---------- @@ -503,39 +323,18 @@ def median(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Returns ------- - local median : uint8 array or uint16 array depending on input image - The result of the local median. + out : uint8 array or uint16 array (same as input image) + The local median. Examples -------- - to be updated - >>> # Local median - >>> from skimage.morphology import square - >>> 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], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> rank.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) - >>> rank.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) - + >>> from skimage import data + >>> from skimage.morphology import disk + >>> from skimage.filter.rank import median + >>> # Load test image + >>> ima = data.camera() + >>> # Local mean + >>> avg = median(ima, disk(20)) """ return _apply(_crank8.median, _crank16.median, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) @@ -544,8 +343,6 @@ def median(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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 @@ -565,39 +362,18 @@ def minimum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Returns ------- - local minimum : uint8 array or uint16 array depending on input image - The result of the local minimum. + out : uint8 array or uint16 array (same as input image) + The local minimum. - Examples + See also -------- - to be updated - >>> # Local minimum - >>> from skimage.morphology import square - >>> 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], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> rank.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) + skimage.morphology.erosion() + Note + ---- + * input image can be 8 bit or 16 bit with a value < 4096 (i.e. 12 bit) - >>> 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) - >>> rank.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) + * the lower algorithm complexity makes the rank.minimum() more efficient for larger images and structuring elements """ @@ -605,9 +381,7 @@ def minimum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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. + """Return greyscale local mode of an image. Parameters ---------- @@ -628,39 +402,9 @@ def modal(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Returns ------- - local modal : uint8 array or uint16 array depending on input image - The result of the local modal. + out : uint8 array or uint16 array (same as input image) + The local modal. - Examples - -------- - to be updated - >>> # Local modal - >>> from skimage.morphology import square - >>> import skimage.filter.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) - >>> rank.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) - >>> rank.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) """ @@ -668,9 +412,8 @@ def modal(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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. + """Enhance an image replacing each pixel by the local maximum if pixel graylevel is closest to maximimum + than local minimum OR local minimum otherwise. Parameters ---------- @@ -691,39 +434,18 @@ def morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa Returns ------- - local morph_contr_enh : uint8 array or uint16 array depending on input image + out : uint8 array or uint16 array (same as input image) The result of the local morph_contr_enh. Examples -------- - to be updated + >>> from skimage import data + >>> from skimage.morphology import disk + >>> from skimage.filter.rank import morph_contr_enh + >>> # Load test image + >>> ima = data.camera() >>> # Local mean - >>> from skimage.morphology import square - >>> import skimage.filter.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) - >>> rank.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) - >>> rank.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) - + >>> avg = morph_contr_enh(ima, disk(20)) """ return _apply( @@ -732,9 +454,7 @@ def morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa 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. + """Return the number (population) of pixels actually inside the neighborhood. Parameters ---------- @@ -755,38 +475,26 @@ def pop(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Returns ------- - local pop : uint8 array or uint16 array depending on input image - The result of the local pop. + out : uint8 array or uint16 array (same as input image) + The number of pixels belonging to the neighborhood. Examples -------- - to be updated >>> # Local mean >>> from skimage.morphology import square >>> import skimage.filter.rank as rank - >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], + >>> ima = 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) - >>> rank.pop(ima8, square(3)) + >>> rank.pop(ima, 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) - >>> rank.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) """ @@ -796,8 +504,6 @@ def pop(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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 @@ -817,39 +523,26 @@ def threshold(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Returns ------- - local threshold : uint8 array or uint16 array depending on input image + out : uint8 array or uint16 array (same as input image) The result of the local threshold. Examples -------- - to be updated - >>> # Local mean + >>> # Local threshold >>> from skimage.morphology import square - >>> import skimage.filter.rank as rank - >>> ima8 = 255*np.array([[0, 0, 0, 0, 0], + >>> from skimage.filter.rank import threshold + >>> ima = 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) - >>> rank.threshold(ima8, square(3)) + >>> threshold(ima, 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) - >>> rank.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) - """ @@ -861,8 +554,6 @@ def threshold(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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 @@ -882,38 +573,9 @@ def tophat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Returns ------- - local tophat : uint8 array or uint16 array depending on input image - The result of the local tophat. + out : uint8 array or uint16 array (same as input image) + The image tophat. - Examples - -------- - to be updated - >>> # Local mean - >>> from skimage.morphology import square - >>> 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], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> rank.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) - >>> rank.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) """ return _apply(_crank8.tophat, _crank16.tophat, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) From 890c473afe3f47f84af21ed9cebd8c48045317f8 Mon Sep 17 00:00:00 2001 From: odebeir Date: Sat, 3 Nov 2012 17:15:13 +0100 Subject: [PATCH 181/195] start filter bigger example --- .../applications/plot_image_filtering.py | 210 ++++++++++++++++++ skimage/filter/rank/tests/test_suite.py | 5 + 2 files changed, 215 insertions(+) create mode 100644 doc/examples/applications/plot_image_filtering.py diff --git a/doc/examples/applications/plot_image_filtering.py b/doc/examples/applications/plot_image_filtering.py new file mode 100644 index 00000000..a58d59aa --- /dev/null +++ b/doc/examples/applications/plot_image_filtering.py @@ -0,0 +1,210 @@ +""" +=============================================================== +Image filtering +=============================================================== + +Filtering is a common operation on images, it serves several purposes such as: + +* image quality enhancement + e.g. image smoothing, sharpening + +* image pre-processing + e.g. noise reduction, contrast enhancement + +* feature extraction + e.g. border detection, isolated point detection + +* post-processing + e.g. small object removal, object grouping, contour smoothing + + +Filters usually operate on image using a neighborhood situated around the pixel current pixel being treated. + +Depending on the type of operation traditionally filters fall into one of the following (not exclusive) types: + +* linear filter + where filtered pixel grey value results in a linear function of its neighborhood, linear filters are in fact + convolution and may be implemented using the Fourier transform (not discussed here). + +* non-linear + where relation may involve non-linear function such as logical test or grey level rank. + +* morphological filter + these filters belong to Mathematical morphology (MM) which "is a theory and technique for the analysis and processing + of geometrical structures" [1]_ + +.. [1] http://en.wikipedia.org/wiki/Mathematical_morphology + +Skimage implement several filters in ``skimage.filter``, ``skimage.filter.rank``, ``skimage.morphology``, some of +these filters are redundant for historical reasons, since there implementation are not identical, there respective +algorithm complexity may differ and therefore the choice may be function of image size or bitdepth +and filter parameters. + +In this example, we will see how to filter a grey level image using some of the linear and non-linear filters +availables in skimage. We use the ``camera`` image from ``skimage.data``. + +""" + +import numpy as np +import matplotlib.pyplot as plt + +from skimage import data + +ima = data.camera() +hist = np.histogram(ima, bins=np.arange(0, 256)) + +plt.figure(figsize=(8, 3)) +plt.subplot(121) +plt.imshow(ima, cmap=plt.cm.gray, interpolation='nearest') +plt.axis('off') +plt.subplot(122) +plt.plot(hist[1][:-1], hist[0], lw=2) +plt.title('histogram of grey values') + +""" +.. image:: PLOT2RST.current_figure + +Noise removal +============== + +some noise is added to the image, 1% of pixels are randomly set to 255, %1% are randomly set to 0. +The **median** filter is applied to remove the noise. + +""" + +noise = np.random.random(ima.shape) +nima = data.camera() +nima[noise>.99] = 255 +nima[noise<.01] = 0 + +from skimage.filter.rank import median +from skimage.morphology import disk + +fig = plt.figure(figsize=[10,7]) + +lo = median(nima,disk(1)) +hi = median(nima,disk(5)) +ext = median(nima,disk(20)) +plt.subplot(2,2,1) +plt.imshow(nima,cmap=plt.cm.gray,vmin=0,vmax=255) +plt.xlabel('noised image') +plt.subplot(2,2,2) +plt.imshow(lo,cmap=plt.cm.gray,vmin=0,vmax=255) +plt.xlabel('median $r=1$') +plt.subplot(2,2,3) +plt.imshow(hi,cmap=plt.cm.gray,vmin=0,vmax=255) +plt.xlabel('median $r=5$') +plt.subplot(2,2,4) +plt.imshow(ext,cmap=plt.cm.gray,vmin=0,vmax=255) +plt.xlabel('median $r=20$') + +""" +.. image:: PLOT2RST.current_figure + +The added noise is efficiently removed, as the image defaults are small (1 pixel wide), a small filter radius is +sufficient. As the radius is increasing, objects with a bigger size are filtered too such as the camera tripod. +Median filter is commonly used for noise removal because borders are preserved. + +Image smoothing +================ + +The example hereunder shows how a local **mean** smooth the cameraman image. + +""" +from skimage.filter.rank import mean + +fig = plt.figure(figsize=[10,7]) + +loc_mean = mean(nima,disk(10)) +plt.subplot(1,2,1) +plt.imshow(ima,cmap=plt.cm.gray,vmin=0,vmax=255) +plt.xlabel('original') +plt.subplot(1,2,2) +plt.imshow(loc_mean,cmap=plt.cm.gray,vmin=0,vmax=255) +plt.xlabel('local mean $r=10$') + +""" +.. image:: PLOT2RST.current_figure + +One may be interested in smoothing an image while preserving important borders (median filters already achieved this), +here we use the **bilateral** filter that restrict the local neighborhood to pixel having a grey level similar to the +central one. + +rem: a different implementations is available for color images in ``skimage.filter.denoise_bilateral``. + +""" + +from skimage.filter.rank import bilateral_mean + +ima = data.camera() +selem = disk(10) + +bilat = bilateral_mean(ima.astype(np.uint16),disk(20),s0=10,s1=10) + +# display results +fig = plt.figure(figsize=[10,7]) +plt.subplot(1,2,1) +plt.imshow(ima) +plt.xlabel('original') +plt.subplot(1,2,2) +plt.imshow(bilat) +plt.xlabel('bilateral mean') + +""" +One can see that the large continuous part of the image (e.g.sky) are smoothed whereas other details are preserved. + + +Contrast enhancement +==================== + +We compare here how the global histogram equalization is applied locally. + +The equalized image [2]_ has a roughly linear cumulative distribution function for each pixel neighborhood. +The local version [3]_ of the histogram equalization emphasized every local graylevel variations. + +.. [2] http://en.wikipedia.org/wiki/Histogram_equalization +.. [3] http://en.wikipedia.org/wiki/Adaptive_histogram_equalization + +""" + +from skimage.exposure import equalize as global_equalize +from skimage.filter.rank import equalize as local_equalize + +ima = data.camera() +# equalize globally and locally +loc = local_equalize(ima,disk(20)) +glob = global_equalize(ima) + +# extract histogram for each image +hist = np.histogram(ima, bins=np.arange(0, 256)) +glob_hist = np.histogram(glob, bins=np.arange(0, 256)) +loc_hist = np.histogram(loc, bins=np.arange(0, 256)) + +plt.figure(figsize=(10, 10)) +plt.subplot(321) +plt.imshow(ima, cmap=plt.cm.gray, interpolation='nearest') +plt.axis('off') +plt.subplot(322) +plt.plot(hist[1][:-1], hist[0], lw=2) +plt.title('histogram of grey values') +plt.subplot(323) +plt.imshow(glob, cmap=plt.cm.gray, interpolation='nearest') +plt.axis('off') +plt.subplot(324) +plt.plot(glob_hist[1][:-1], glob_hist[0], lw=2) +plt.title('histogram of grey values') +plt.subplot(325) +plt.imshow(loc, cmap=plt.cm.gray, interpolation='nearest') +plt.axis('off') +plt.subplot(326) +plt.plot(loc_hist[1][:-1], loc_hist[0], lw=2) +plt.title('histogram of grey values') + +""" +.. image:: PLOT2RST.current_figure + +Image morphology +================ + +""" +plt.show() diff --git a/skimage/filter/rank/tests/test_suite.py b/skimage/filter/rank/tests/test_suite.py index 4f1e6f81..66b6537c 100644 --- a/skimage/filter/rank/tests/test_suite.py +++ b/skimage/filter/rank/tests/test_suite.py @@ -1,3 +1,8 @@ +import sys +print sys.path +import skimage +print skimage + import unittest import numpy as np From acc1e1f7e4ef953a05885df3a51b1bde0f5aa181 Mon Sep 17 00:00:00 2001 From: odebeir Date: Sat, 3 Nov 2012 17:38:54 +0100 Subject: [PATCH 182/195] example continued --- .../applications/plot_image_filtering.py | 53 ++++++++++++++++--- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/doc/examples/applications/plot_image_filtering.py b/doc/examples/applications/plot_image_filtering.py index a58d59aa..e0ebea44 100644 --- a/doc/examples/applications/plot_image_filtering.py +++ b/doc/examples/applications/plot_image_filtering.py @@ -70,6 +70,8 @@ Noise removal some noise is added to the image, 1% of pixels are randomly set to 255, %1% are randomly set to 0. The **median** filter is applied to remove the noise. +.. note:: there is different implementations of median filter : ``skimage.filter.median_filter``and +`skimage.filter.rank.median`` """ noise = np.random.random(ima.shape) @@ -130,7 +132,7 @@ One may be interested in smoothing an image while preserving important borders ( here we use the **bilateral** filter that restrict the local neighborhood to pixel having a grey level similar to the central one. -rem: a different implementations is available for color images in ``skimage.filter.denoise_bilateral``. +.. note:: a different implementations is available for color images in ``skimage.filter.denoise_bilateral``. """ @@ -144,13 +146,15 @@ bilat = bilateral_mean(ima.astype(np.uint16),disk(20),s0=10,s1=10) # display results fig = plt.figure(figsize=[10,7]) plt.subplot(1,2,1) -plt.imshow(ima) +plt.imshow(ima,cmap=plt.cm.gray) plt.xlabel('original') plt.subplot(1,2,2) -plt.imshow(bilat) +plt.imshow(bilat,cmap=plt.cm.gray) plt.xlabel('bilateral mean') """ +.. image:: PLOT2RST.current_figure + One can see that the large continuous part of the image (e.g.sky) are smoothed whereas other details are preserved. @@ -167,13 +171,13 @@ The local version [3]_ of the histogram equalization emphasized every local gray """ -from skimage.exposure import equalize as global_equalize -from skimage.filter.rank import equalize as local_equalize +from skimage import exposure +from skimage.filter import rank ima = data.camera() # equalize globally and locally -loc = local_equalize(ima,disk(20)) -glob = global_equalize(ima) +glob = exposure.equalize(ima)*255 +loc = rank.equalize(ima,disk(20)) # extract histogram for each image hist = np.histogram(ima, bins=np.arange(0, 256)) @@ -199,6 +203,39 @@ plt.axis('off') plt.subplot(326) plt.plot(loc_hist[1][:-1], loc_hist[0], lw=2) plt.title('histogram of grey values') +""" +.. image:: PLOT2RST.current_figure + +an other way to maximize the number of grey level used for an image is to apply a local auto-leveling, +i.e. here a pixel grey level is proportionally remapped between local minimum and local maximum. + +The following example show how local autolevel enhance the camaraman picture. +""" +from skimage.filter.rank import autolevel + +ima = data.camera() +selem = disk(10) + +auto = autolevel(ima.astype(np.uint16),disk(20)) + +# display results +fig = plt.figure(figsize=[10,7]) +plt.subplot(1,2,1) +plt.imshow(ima,cmap=plt.cm.gray) +plt.xlabel('original') +plt.subplot(1,2,2) +plt.imshow(auto,cmap=plt.cm.gray) +plt.xlabel('local autolevel') +""" +.. image:: PLOT2RST.current_figure + +This filter is very sensitive to local outlayers, see the little white spot in the sky left part. This is due +to a local maximum which is very high comparing to the rest of the neighborhood. One can moderate this +using the percentile version of the autolevel filter which uses to given percentiles (one inferior, one superior) +in place of local minimum and maximim. The example bellow illustrate how the percentile parameters influence the +local autolevel result. + +""" """ .. image:: PLOT2RST.current_figure @@ -206,5 +243,7 @@ plt.title('histogram of grey values') Image morphology ================ + + """ plt.show() From e6199c78cfa1cf705421b2ef3d4e4961adeee78b Mon Sep 17 00:00:00 2001 From: odebeir Date: Sun, 4 Nov 2012 09:39:58 +0100 Subject: [PATCH 183/195] doc cont. --- ...mage_filtering.py => plot_rank_filters.py} | 119 ++++++++++++++---- 1 file changed, 94 insertions(+), 25 deletions(-) rename doc/examples/applications/{plot_image_filtering.py => plot_rank_filters.py} (66%) diff --git a/doc/examples/applications/plot_image_filtering.py b/doc/examples/applications/plot_rank_filters.py similarity index 66% rename from doc/examples/applications/plot_image_filtering.py rename to doc/examples/applications/plot_rank_filters.py index e0ebea44..19305fdc 100644 --- a/doc/examples/applications/plot_image_filtering.py +++ b/doc/examples/applications/plot_rank_filters.py @@ -1,9 +1,14 @@ """ =============================================================== -Image filtering +Rank filters =============================================================== -Filtering is a common operation on images, it serves several purposes such as: +Rank filters are non-linear filters using the local grey levels ordering to compute the filtered value. +This ensemble of filters share a common base: the local grey-level histogram extraction computed on +the neighborhood of a pixel (defined by a 2D structuring element). +If the filtered value is taken as the middle value of the histogram, we get the classical median filter. + +Rank filters can be used for several purposes such as: * image quality enhancement e.g. image smoothing, sharpening @@ -17,32 +22,15 @@ Filtering is a common operation on images, it serves several purposes such as: * post-processing e.g. small object removal, object grouping, contour smoothing +Some well known filters are specific cases of rank filters [1]_ e.g. morphological dilation, morphological erosion, +median filters. -Filters usually operate on image using a neighborhood situated around the pixel current pixel being treated. - -Depending on the type of operation traditionally filters fall into one of the following (not exclusive) types: - -* linear filter - where filtered pixel grey value results in a linear function of its neighborhood, linear filters are in fact - convolution and may be implemented using the Fourier transform (not discussed here). - -* non-linear - where relation may involve non-linear function such as logical test or grey level rank. - -* morphological filter - these filters belong to Mathematical morphology (MM) which "is a theory and technique for the analysis and processing - of geometrical structures" [1]_ - -.. [1] http://en.wikipedia.org/wiki/Mathematical_morphology - -Skimage implement several filters in ``skimage.filter``, ``skimage.filter.rank``, ``skimage.morphology``, some of -these filters are redundant for historical reasons, since there implementation are not identical, there respective -algorithm complexity may differ and therefore the choice may be function of image size or bitdepth -and filter parameters. +The different implementation availables in ``skimage`` are compared compare. In this example, we will see how to filter a grey level image using some of the linear and non-linear filters availables in skimage. We use the ``camera`` image from ``skimage.data``. +.. [1] Pierre Soille, On morphological operators based on rank filters, Pattern Recognition 35 (2002) 527-535. """ import numpy as np @@ -206,7 +194,7 @@ plt.title('histogram of grey values') """ .. image:: PLOT2RST.current_figure -an other way to maximize the number of grey level used for an image is to apply a local auto-leveling, +an other way to maximize the number of grey level used for an image is to apply a local autoleveling, i.e. here a pixel grey level is proportionally remapped between local minimum and local maximum. The following example show how local autolevel enhance the camaraman picture. @@ -232,10 +220,81 @@ plt.xlabel('local autolevel') This filter is very sensitive to local outlayers, see the little white spot in the sky left part. This is due to a local maximum which is very high comparing to the rest of the neighborhood. One can moderate this using the percentile version of the autolevel filter which uses to given percentiles (one inferior, one superior) -in place of local minimum and maximim. The example bellow illustrate how the percentile parameters influence the +in place of local minimum and maximum. The example bellow illustrate how the percentile parameters influence the local autolevel result. """ +from skimage.filter.rank import percentile_autolevel + +image = data.camera() + +selem = disk(20) +loc_autolevel = autolevel(image,selem=selem) +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) + +fig, axes = plt.subplots(nrows=3, figsize=(7, 8)) +ax0, ax1, ax2 = axes +plt.gray() + +ax0.imshow(np.hstack((image,loc_autolevel))) +ax0.set_title('original / autolevel') + +ax1.imshow(np.hstack((loc_perc_autolevel0,loc_perc_autolevel1)),vmin=0,vmax=255) +ax1.set_title('percentile autolevel 0%,1%') +ax2.imshow(np.hstack((loc_perc_autolevel2,loc_perc_autolevel3)),vmin=0,vmax=255) +ax2.set_title('percentile autolevel 5% and 10%') + +for ax in axes: + ax.axis('off') + +""" +.. image:: PLOT2RST.current_figure + +Morphological contrast enhancement filter replaces the central pixel by local maximum +if the original grey level value if closest to local maximum, by the minimum local otherwise. + +""" + +from skimage.filter.rank import morph_contr_enh + +ima = data.camera() + +enh = morph_contr_enh(ima,disk(5)) + +# display results +fig = plt.figure(figsize=[10,7]) +plt.subplot(1,2,1) +plt.imshow(ima,cmap=plt.cm.gray) +plt.xlabel('original') +plt.subplot(1,2,2) +plt.imshow(enh,cmap=plt.cm.gray) +plt.xlabel('local morphlogical contrast enhancement') + +""" +.. image:: PLOT2RST.current_figure + +The percentile version of the local morphological contrast enhancement, uses percentile p0 and p1 instead of local +minimum and local maximum. + +""" + +from skimage.filter.rank import percentile_morph_contr_enh + +ima = data.camera() + +penh = percentile_morph_contr_enh(ima,disk(5),p0=.1,p1=.9) + +# display results +fig = plt.figure(figsize=[10,7]) +plt.subplot(1,2,1) +plt.imshow(ima,cmap=plt.cm.gray) +plt.xlabel('original') +plt.subplot(1,2,2) +plt.imshow(penh,cmap=plt.cm.gray) +plt.xlabel('local morphlogical contrast enhancement') """ .. image:: PLOT2RST.current_figure @@ -243,7 +302,17 @@ local autolevel result. Image morphology ================ +Local maximum and local minimum are the base operators for grey level morphology. +""" + +""" +.. image:: PLOT2RST.current_figure + +Implementation +================ + +Implementation comparison w.r.t. image size and structuring element size. """ plt.show() From 8839c1d8f74a4effa810b0ccd5e67c129f6303c8 Mon Sep 17 00:00:00 2001 From: odebeir Date: Sun, 4 Nov 2012 14:51:43 +0100 Subject: [PATCH 184/195] doc add perf.comp. --- .../applications/plot_rank_filters.py | 209 +++++++++++++++++- skimage/filter/rank/rank.pyx | 28 +-- 2 files changed, 213 insertions(+), 24 deletions(-) diff --git a/doc/examples/applications/plot_rank_filters.py b/doc/examples/applications/plot_rank_filters.py index 19305fdc..dfc72052 100644 --- a/doc/examples/applications/plot_rank_filters.py +++ b/doc/examples/applications/plot_rank_filters.py @@ -120,7 +120,7 @@ One may be interested in smoothing an image while preserving important borders ( here we use the **bilateral** filter that restrict the local neighborhood to pixel having a grey level similar to the central one. -.. note:: a different implementations is available for color images in ``skimage.filter.denoise_bilateral``. +.. note:: a different implementation is available for color images in ``skimage.filter.denoise_bilateral``. """ @@ -133,12 +133,16 @@ bilat = bilateral_mean(ima.astype(np.uint16),disk(20),s0=10,s1=10) # display results fig = plt.figure(figsize=[10,7]) -plt.subplot(1,2,1) +plt.subplot(2,2,1) plt.imshow(ima,cmap=plt.cm.gray) plt.xlabel('original') -plt.subplot(1,2,2) +plt.subplot(2,2,3) plt.imshow(bilat,cmap=plt.cm.gray) plt.xlabel('bilateral mean') +plt.subplot(2,2,2) +plt.imshow(ima[200:350,350:450],cmap=plt.cm.gray) +plt.subplot(2,2,4) +plt.imshow(bilat[200:350,350:450],cmap=plt.cm.gray) """ .. image:: PLOT2RST.current_figure @@ -266,17 +270,21 @@ enh = morph_contr_enh(ima,disk(5)) # display results fig = plt.figure(figsize=[10,7]) -plt.subplot(1,2,1) +plt.subplot(2,2,1) plt.imshow(ima,cmap=plt.cm.gray) plt.xlabel('original') -plt.subplot(1,2,2) +plt.subplot(2,2,3) plt.imshow(enh,cmap=plt.cm.gray) plt.xlabel('local morphlogical contrast enhancement') +plt.subplot(2,2,2) +plt.imshow(ima[200:350,350:450],cmap=plt.cm.gray) +plt.subplot(2,2,4) +plt.imshow(enh[200:350,350:450],cmap=plt.cm.gray) """ .. image:: PLOT2RST.current_figure -The percentile version of the local morphological contrast enhancement, uses percentile p0 and p1 instead of local +The percentile version of the local morphological contrast enhancement, uses percentile *p0* and *p1* instead of local minimum and local maximum. """ @@ -289,12 +297,16 @@ penh = percentile_morph_contr_enh(ima,disk(5),p0=.1,p1=.9) # display results fig = plt.figure(figsize=[10,7]) -plt.subplot(1,2,1) +plt.subplot(2,2,1) plt.imshow(ima,cmap=plt.cm.gray) plt.xlabel('original') -plt.subplot(1,2,2) +plt.subplot(2,2,3) plt.imshow(penh,cmap=plt.cm.gray) -plt.xlabel('local morphlogical contrast enhancement') +plt.xlabel('local percentile morphlogical\n contrast enhancement') +plt.subplot(2,2,2) +plt.imshow(ima[200:350,350:450],cmap=plt.cm.gray) +plt.subplot(2,2,4) +plt.imshow(penh[200:350,350:450],cmap=plt.cm.gray) """ .. image:: PLOT2RST.current_figure @@ -304,15 +316,192 @@ Image morphology Local maximum and local minimum are the base operators for grey level morphology. +.. note:: ``skimage.dilate`` and ``skimage.erode`` are equivalent filters (see below for comparison). + +Here is an example of classical morphological grey level filters : opening, closing and morphological gradient. + """ +from skimage.filter.rank import maximum,minimum,gradient + +ima = data.camera() + +closing = maximum(minimum(ima,disk(5)),disk(5)) +opening = minimum(maximum(ima,disk(5)),disk(5)) +grad = gradient(ima,disk(5)) + +# display results +fig = plt.figure(figsize=[10,7]) +plt.subplot(2,2,1) +plt.imshow(ima,cmap=plt.cm.gray) +plt.xlabel('original') +plt.subplot(2,2,2) +plt.imshow(closing,cmap=plt.cm.gray) +plt.xlabel('grey level closing') +plt.subplot(2,2,3) +plt.imshow(opening,cmap=plt.cm.gray) +plt.xlabel('grey level opening') +plt.subplot(2,2,4) +plt.imshow(grad,cmap=plt.cm.gray) +plt.xlabel('morphological gradient') + """ .. image:: PLOT2RST.current_figure Implementation ================ -Implementation comparison w.r.t. image size and structuring element size. +The central part of the ``skimage.rank``filters is build on a sliding window that update local grey level histogram. +This approach limits the algorithm complexity to O(n) where n is the number of image pixels. The complexity is also +limited with respect to the structuring element size. """ +from time import time + +from scipy.ndimage.filters import percentile_filter +from skimage.morphology import dilation +from skimage.filter import median_filter +from skimage.filter.rank import median,maximum + +def exec_and_timeit(func): + """ Decorator that returns both function results and execution time + (result, ms) + """ + def wrapper(*arg): + t1 = time() + res = func(*arg) + t2 = time() + ms = (t2-t1)*1000.0 + return (res,ms) + return wrapper + + +@exec_and_timeit +def cr_med(image,selem): + return median(image=image,selem = selem) + +@exec_and_timeit +def cr_max(image,selem): + return maximum(image=image,selem = selem) + +@exec_and_timeit +def cm_dil(image,selem): + return dilation(image=image,selem = selem) + +@exec_and_timeit +def ctmf_med(image,radius): + return median_filter(image=image,radius=radius) + +@exec_and_timeit +def ndi_med(image,n): + return percentile_filter(image,50,size=n*2-1) + +""" +.. image:: PLOT2RST.current_figure + +Comparison between + +* rank.maximum +* cmorph.dilate + +on increasing structuring element size and increasing image size +""" + +a = data.camera() + +rec = [] +e_range = range(1,20,1) +for r in e_range: + elem = disk(r+1) + 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) + +plt.figure() +plt.title('increasing element size') +plt.plot(e_range,rec) +plt.legend(['crank.maximum','cmorph.dilate']) + +r = 9 +elem = disk(r+1) + +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)) + # same structuring element, the results must match + 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']) + + +""" +.. image:: PLOT2RST.current_figure + +Comparison between: + +* rank.median +* ctmf.median_filter +* ndimage.percentile + +on increasing structuring element size and increasing image size +""" + + +a = data.camera() + +rec = [] +e_range = range(2,30,4) +for r in e_range: + elem = disk(r+1) + rc,ms_rc = cr_med(a,elem) + rctmf,ms_rctmf = ctmf_med(a,r) + rndi,ms_ndi = ndi_med(a,r) + rec.append((ms_rc,ms_rctmf,ms_ndi)) + +rec = np.asarray(rec) + +plt.figure() +plt.title('increasing element size') +plt.plot(e_range,rec) +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 = disk(r+1) + +rec = [] +s_range = [100,200,500,1000] +for s in s_range: + a = (np.random.random((s,s))*256).astype('uint8') + (rc,ms_rc) = cr_med(a,elem) + rctmf,ms_rctmf = ctmf_med(a,r) + rndi,ms_ndi = ndi_med(a,r) + rec.append((ms_rc,ms_rctmf,ms_ndi)) + +rec = np.asarray(rec) + +plt.figure() +plt.title('increasing image size') +plt.plot(s_range,rec) +plt.legend(['rank.median','ctmf.median_filter','ndimage.percentile']) +plt.ylabel('time (ms)') +plt.xlabel('image size') + plt.show() diff --git a/skimage/filter/rank/rank.pyx b/skimage/filter/rank/rank.pyx index 730d37c7..2f144e98 100644 --- a/skimage/filter/rank/rank.pyx +++ b/skimage/filter/rank/rank.pyx @@ -43,7 +43,7 @@ def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, + Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, an exception will be raised if image has a value > 4095 selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. @@ -85,7 +85,7 @@ def bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, + Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, an exception will be raised if image has a value > 4095 selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. @@ -118,7 +118,7 @@ def equalize(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, + Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, an exception will be raised if image has a value > 4095 selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. @@ -160,7 +160,7 @@ def gradient(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, + Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, an exception will be raised if image has a value > 4095 selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. @@ -193,7 +193,7 @@ def maximum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, + Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, an exception will be raised if image has a value > 4095 selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. @@ -233,7 +233,7 @@ def mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, + Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, an exception will be raised if image has a value > 4095 selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. @@ -272,7 +272,7 @@ def meansubstraction(image, selem, out=None, mask=None, shift_x=False, shift_y=F Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, + Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, an exception will be raised if image has a value > 4095 selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. @@ -307,7 +307,7 @@ def median(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, + Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, an exception will be raised if image has a value > 4095 selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. @@ -346,7 +346,7 @@ def minimum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, + Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, an exception will be raised if image has a value > 4095 selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. @@ -386,7 +386,7 @@ def modal(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, + Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, an exception will be raised if image has a value > 4095 selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. @@ -418,7 +418,7 @@ def morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, + Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, an exception will be raised if image has a value > 4095 selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. @@ -459,7 +459,7 @@ def pop(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, + Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, an exception will be raised if image has a value > 4095 selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. @@ -507,7 +507,7 @@ def threshold(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, + Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, an exception will be raised if image has a value > 4095 selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. @@ -557,7 +557,7 @@ def tophat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Parameters ---------- image : ndarray - Image array (uint8 array or uint16). If image is uint16, as the algorithm uses max. 12bit histogram, + Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, an exception will be raised if image has a value > 4095 selem : ndarray The neighborhood expressed as a 2-D array of 1's and 0's. From 14d86ccb337d0e379cedee67f5d488d55efd7090 Mon Sep 17 00:00:00 2001 From: odebeir Date: Sun, 4 Nov 2012 15:45:36 +0100 Subject: [PATCH 185/195] document rank filters --- .../applications/plot_rank_filters.py | 51 +++++++++++++------ 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/doc/examples/applications/plot_rank_filters.py b/doc/examples/applications/plot_rank_filters.py index dfc72052..2ebb7b92 100644 --- a/doc/examples/applications/plot_rank_filters.py +++ b/doc/examples/applications/plot_rank_filters.py @@ -351,7 +351,7 @@ plt.xlabel('morphological gradient') Implementation ================ -The central part of the ``skimage.rank``filters is build on a sliding window that update local grey level histogram. +The central part of the ``skimage.rank`` filters is build on a sliding window that update local grey level histogram. This approach limits the algorithm complexity to O(n) where n is the number of image pixels. The complexity is also limited with respect to the structuring element size. @@ -397,35 +397,39 @@ def ndi_med(image,n): return percentile_filter(image,50,size=n*2-1) """ -.. image:: PLOT2RST.current_figure - Comparison between -* rank.maximum -* cmorph.dilate +* ``rank.maximum`` +* ``cmorph.dilate`` -on increasing structuring element size and increasing image size +on increasing structuring element size """ a = data.camera() rec = [] -e_range = range(1,20,1) +e_range = range(1,20,2) for r in e_range: elem = disk(r+1) 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) plt.figure() plt.title('increasing element size') +plt.ylabel('time (ms)') +plt.xlabel('element radius') plt.plot(e_range,rec) plt.legend(['crank.maximum','cmorph.dilate']) +""" +and increasing image size + +.. image:: PLOT2RST.current_figure +""" + r = 9 elem = disk(r+1) @@ -436,13 +440,13 @@ for s in s_range: (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) plt.figure() plt.title('increasing image size') +plt.ylabel('time (ms)') +plt.xlabel('image size') plt.plot(s_range,rec) plt.legend(['crank.maximum','cmorph.dilate']) @@ -452,11 +456,11 @@ plt.legend(['crank.maximum','cmorph.dilate']) Comparison between: -* rank.median -* ctmf.median_filter -* ndimage.percentile +* ``rank.median`` +* ``ctmf.median_filter`` +* ``ndimage.percentile`` -on increasing structuring element size and increasing image size +on increasing structuring element size """ @@ -479,10 +483,23 @@ plt.plot(e_range,rec) plt.legend(['rank.median','ctmf.median_filter','ndimage.percentile']) plt.ylabel('time (ms)') plt.xlabel('element radius') +""" +.. image:: PLOT2RST.current_figure + +comparison of outcome of the three methods + +""" plt.figure() plt.imshow(np.hstack((rc,rctmf,rndi))) plt.xlabel('rank.median vs ctmf.median_filter vs ndimage.percentile') +""" +.. image:: PLOT2RST.current_figure + +and increasing image size + +""" + r = 9 elem = disk(r+1) @@ -504,4 +521,8 @@ plt.legend(['rank.median','ctmf.median_filter','ndimage.percentile']) plt.ylabel('time (ms)') plt.xlabel('image size') +""" +.. image:: PLOT2RST.current_figure +""" + plt.show() From 271ea14c0e0f5454171e3d738c6529b3f911e0e3 Mon Sep 17 00:00:00 2001 From: odebeir Date: Sun, 4 Nov 2012 15:49:54 +0100 Subject: [PATCH 186/195] remove trivial examples from perentile_rank --- skimage/filter/rank/percentile_rank.pyx | 228 ------------------------ 1 file changed, 228 deletions(-) diff --git a/skimage/filter/rank/percentile_rank.pyx b/skimage/filter/rank/percentile_rank.pyx index 3817e1cd..90e24892 100644 --- a/skimage/filter/rank/percentile_rank.pyx +++ b/skimage/filter/rank/percentile_rank.pyx @@ -71,34 +71,6 @@ def percentile_autolevel(image, selem, out=None, mask=None, shift_x=False, shift local autolevel : uint8 array or uint16 array depending on input image The result of the local autolevel. - Examples - -------- - >>> # Local mean - >>> from skimage.morphology import square - >>> 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], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> rank.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, 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) - >>> rank.percentile_autolevel(ima16, square(3), p0=0.,p1=1.) - 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) """ @@ -136,35 +108,7 @@ def percentile_gradient(image, selem, out=None, mask=None, shift_x=False, shift_ local percentile_gradient : uint8 array or uint16 array depending on input image The result of the local percentile_gradient. - Examples - -------- - - >>> # Local gradient - >>> from skimage.morphology import square - >>> 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], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> 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], - [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) - >>> 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], - [4095, 4095, 4095, 4095, 4095], - [4095, 4095, 4095, 4095, 4095]], dtype=uint16) """ @@ -202,35 +146,6 @@ def percentile_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa local mean : uint8 array or uint16 array depending on input image The result of the local mean. - Examples - -------- - - >>> # Local mean - >>> from skimage.morphology import square - >>> 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], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> 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], - [ 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) - >>> 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], - [1365, 1820, 2730, 1820, 1365], - [1023, 1365, 2047, 1365, 1023]], dtype=uint16) """ @@ -268,35 +183,7 @@ def percentile_mean_substraction(image, selem, out=None, mask=None, shift_x=Fals local mean_substraction : uint8 array or uint16 array depending on input image The result of the local mean_substraction. - Examples - -------- - - >>> # Local mean_substraction - >>> from skimage.morphology import square - >>> 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], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> 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], - [ 84, 198, 169, 198, 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) - >>> 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], - [1365, 3185, 2730, 3185, 1365], - [1536, 1365, 1024, 1365, 1536]], dtype=uint16) """ @@ -334,35 +221,7 @@ def percentile_morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, local morph_contr_enh : uint8 array or uint16 array depending on input image The result of the local morph_contr_enh. - Examples - -------- - - >>> # Local mean - >>> from skimage.morphology import square - >>> 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], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> 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], - [ 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) - >>> 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], - [ 0, 4095, 4095, 4095, 0], - [ 0, 0, 0, 0, 0]], dtype=uint16) """ @@ -400,35 +259,6 @@ def percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, local percentile : uint8 array or uint16 array depending on input image The result of the local percentile. - Examples - -------- - - >>> # Local mean - >>> from skimage.morphology import square - >>> 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], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> 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], - [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) - >>> 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], - [0, 0, 0, 0, 0], - [0, 0, 0, 0, 0]], dtype=uint16) """ @@ -467,35 +297,7 @@ def percentile_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal local pop : uint8 array or uint16 array depending on input image The result of the local pop. - Examples - -------- - - >>> # Local mean - >>> from skimage.morphology import square - >>> 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], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> 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], - [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) - >>> 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], - [6, 9, 9, 9, 6], - [4, 6, 6, 6, 4]], dtype=uint16) """ @@ -533,37 +335,7 @@ def percentile_threshold(image, selem, out=None, mask=None, shift_x=False, shift local threshold : uint8 array or uint16 array depending on input image The result of the local threshold. - Examples - -------- - >>> # Local mean - >>> from skimage.morphology import square - >>> 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], - ... [0, 1, 1, 1, 0], - ... [0, 0, 0, 0, 0]], dtype=np.uint8) - >>> 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], - [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) - >>> 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], - [4095, 4095, 4095, 4095, 4095], - [4095, 4095, 4095, 4095, 4095]], dtype=uint16) - - """ return _apply( From df02bf893a3c048071ae81fb5684566ccc45d0fc Mon Sep 17 00:00:00 2001 From: odebeir Date: Sun, 4 Nov 2012 16:05:08 +0100 Subject: [PATCH 187/195] remove duplicate examples --- .../applications/plot_benchmark_rank.py | 173 ------------------ doc/examples/plot_compare_bilateral.py | 63 ------- doc/examples/plot_lena_bilateral_denoise.py | 50 ----- doc/examples/plot_local_autolevels.py | 47 ----- doc/examples/plot_local_threshold.py | 69 ------- skimage/filter/rank/percentile_rank.pyx | 2 +- 6 files changed, 1 insertion(+), 403 deletions(-) delete mode 100644 doc/examples/applications/plot_benchmark_rank.py delete mode 100644 doc/examples/plot_compare_bilateral.py delete mode 100644 doc/examples/plot_lena_bilateral_denoise.py delete mode 100644 doc/examples/plot_local_autolevels.py delete mode 100644 doc/examples/plot_local_threshold.py diff --git a/doc/examples/applications/plot_benchmark_rank.py b/doc/examples/applications/plot_benchmark_rank.py deleted file mode 100644 index 79357768..00000000 --- a/doc/examples/applications/plot_benchmark_rank.py +++ /dev/null @@ -1,173 +0,0 @@ -""" -============================== -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 - -from scipy.ndimage.filters import percentile_filter - -from skimage import data -from skimage.morphology import dilation,disk -from skimage.filter import median_filter -import skimage.filter.rank as rank - -def exec_and_timeit(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 - return (res,ms) - return wrapper - - -@exec_and_timeit -def cr_med(image,selem): - return rank.median(image=image,selem = selem) - -@exec_and_timeit -def cr_max(image,selem): - return rank.maximum(image=image,selem = selem) - -@exec_and_timeit -def cm_dil(image,selem): - return dilation(image=image,selem = selem) - -@exec_and_timeit -def ctmf_med(image,radius): - return median_filter(image=image,radius=radius) - -@exec_and_timeit -def ndi_med(image,n): - return percentile_filter(image,50,size=n*2-1) - -def compare_dilate(): - """ Comparison between - - crank.maximum rankfilter implementation - - cmorph.dilate cython implementation - - on increasing structuring element size and increasing image size - """ - a = data.camera() - - rec = [] - e_range = range(1,20,1) - for r in e_range: - 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)) - # same structuring element, the results must match - 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']) - - r = 9 - elem = disk(r+1) - - 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)) - # same structuring element, the results must match - 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))) - - -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,30,4) - for r in e_range: - elem = disk(r+1) - rc,ms_rc = cr_med(a,elem) - rctmf,ms_rctmf = ctmf_med(a,r) - 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 element size') - plt.plot(e_range,rec) - 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 = disk(r+1) - - rec = [] - 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_med(a,elem) - rctmf,ms_rctmf = ctmf_med(a,r) - 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','ndimage.percentile']) - plt.ylabel('time (ms)') - plt.xlabel('image size') - - - -compare_dilate() -compare_median() -plt.show() diff --git a/doc/examples/plot_compare_bilateral.py b/doc/examples/plot_compare_bilateral.py deleted file mode 100644 index 977b7704..00000000 --- a/doc/examples/plot_compare_bilateral.py +++ /dev/null @@ -1,63 +0,0 @@ -""" -==================================================== -Bilateral comparison -==================================================== - -In this example, we compare both bilateral implementation - -* filter.denoise_bilateral -* filter.rank.bilateral_mean - -The first filter implements a spatial-gaussian and spectral-gaussian kernel bilateral filter whereas the latter implements -a cylindrical kernel bilateral filter i.e. spatial-flat and spectral-flat kernel. - -The timing comparison is just for information since the kernel are not the same. - -""" - -import numpy as np -import matplotlib.pyplot as plt - -from skimage import data -from skimage.filter._denoise import denoise_bilateral -from skimage.filter.rank import bilateral_mean -from skimage.morphology import disk -from skimage.filter import denoise_bilateral -import time - -def exec_and_timeit(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 - return (res,ms) - return wrapper - - -@exec_and_timeit -def den_bil(image): - return denoise_bilateral(a8,win_size=20,sigma_range=255,sigma_spatial=1)[:,:,0]*255 - -@exec_and_timeit -def rank_bil(image): - return bilateral_mean(a8.astype(np.uint16),disk(20),s0=10,s1=10) - -a8 = data.camera() -selem = disk(10) - -f1,t1 = den_bil(a8) -f2,t2 = rank_bil(a8) - -# display results -fig, axes = plt.subplots(nrows=2, figsize=(15,10)) -ax0, ax1= axes - -ax0.imshow(np.hstack((f1,a8-f1))) -ax0.set_title('denoise bilateral (%f ms)'%t1) -ax1.imshow(np.hstack((f2,a8-f1))) -ax1.set_title('bilateral mean (%f ms)'%t2) -plt.show() diff --git a/doc/examples/plot_lena_bilateral_denoise.py b/doc/examples/plot_lena_bilateral_denoise.py deleted file mode 100644 index 03fc61d0..00000000 --- a/doc/examples/plot_lena_bilateral_denoise.py +++ /dev/null @@ -1,50 +0,0 @@ -""" -==================================================== -Denoising the picture of Lena using bilateral filter -==================================================== - -In this example, we denoise a noisy version of the picture of Lena -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.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) -approx_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(approx_bilateral_denoised, cmap=plt.cm.gray, vmin=40, vmax=220) -plt.axis('off') -plt.title('bilateral denoising', fontsize=20) - -selem = disk(30) -approx_bilateral_denoised = bilateral_mean(noisy.astype(np.uint8), selem=selem,s0=40,s1=40) -plt.subplot(133) -plt.imshow(approx_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_autolevels.py b/doc/examples/plot_local_autolevels.py deleted file mode 100644 index 7c750141..00000000 --- a/doc/examples/plot_local_autolevels.py +++ /dev/null @@ -1,47 +0,0 @@ -""" -===================== -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 -import numpy as np - -from skimage import data - -from skimage.filter.rank import percentile_autolevel,autolevel -from skimage.morphology import disk - - -image = data.camera() - -selem = disk(20) -loc_autolevel = autolevel(image,selem=selem) -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) - -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 -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 0%,1%,5% and 10%') - -for ax in axes: - ax.axis('off') - -plt.show() diff --git a/doc/examples/plot_local_threshold.py b/doc/examples/plot_local_threshold.py deleted file mode 100644 index 8bc79b30..00000000 --- a/doc/examples/plot_local_threshold.py +++ /dev/null @@ -1,69 +0,0 @@ -""" -===================== -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. - -An other approach is to binarize locally the image using local histogram distribution. - -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 - -from skimage import data -from skimage.filter import threshold_otsu, threshold_adaptive - -from skimage.filter.rank import threshold,morph_contr_enh -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(20) -loc_thresh = threshold(image,selem=selem) -loc_morph_contr_enh = morph_contr_enh(image,selem=selem) - -fig, axes = plt.subplots(nrows=5, figsize=(7, 8)) -ax0, ax1, ax2, ax3, ax4 = 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') - -ax4.imshow(loc_morph_contr_enh) -ax4.set_title('Local morphological contrast enhancement') - - -for ax in axes: - ax.axis('off') - -plt.show() diff --git a/skimage/filter/rank/percentile_rank.pyx b/skimage/filter/rank/percentile_rank.pyx index 90e24892..d45bcfe3 100644 --- a/skimage/filter/rank/percentile_rank.pyx +++ b/skimage/filter/rank/percentile_rank.pyx @@ -335,7 +335,7 @@ def percentile_threshold(image, selem, out=None, mask=None, shift_x=False, shift local threshold : uint8 array or uint16 array depending on input image The result of the local threshold. - + """ return _apply( From 298d2f9cdbc3872c532e7051b598e9e0c2782b5b Mon Sep 17 00:00:00 2001 From: odebeir Date: Sun, 4 Nov 2012 16:16:09 +0100 Subject: [PATCH 188/195] remove other duplicate examples --- doc/examples/plot_modal_filter.py | 67 ------------------------------- 1 file changed, 67 deletions(-) delete mode 100644 doc/examples/plot_modal_filter.py diff --git a/doc/examples/plot_modal_filter.py b/doc/examples/plot_modal_filter.py deleted file mode 100644 index a66da0a1..00000000 --- a/doc/examples/plot_modal_filter.py +++ /dev/null @@ -1,67 +0,0 @@ -""" -=================== -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 f61ffcaf53a4ee48710969a906f9eacf68c81e87 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Wed, 7 Nov 2012 17:26:59 +0100 Subject: [PATCH 189/195] test noise filter --- skimage/filter/rank/_crank8.pyx | 29 ++++++++++++++++++++++++ skimage/filter/rank/demo/demo_single.py | 21 +++++++++++++++++ skimage/filter/rank/rank.pyx | 30 ++++++++++++++++++++++++- 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/skimage/filter/rank/_crank8.pyx b/skimage/filter/rank/_crank8.pyx index da716bd9..a0c3cc35 100644 --- a/skimage/filter/rank/_crank8.pyx +++ b/skimage/filter/rank/_crank8.pyx @@ -223,6 +223,26 @@ cdef inline np.uint8_t kernel_tophat( return < np.uint8_t > (i - g) +cdef inline np.uint8_t kernel_noise_filter( + Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1, Py_ssize_t s0, + Py_ssize_t s1): + + cdef Py_ssize_t i + cdef Py_ssize_t min_i + + for i in range(255, g, -1): + if histo[i]: + break + min_i = i-g + for i in range(0, g): + if histo[i]: + break + if g-i < min_i: + return < np.uint8_t > (g-i) + else: + return < np.uint8_t > min_i + + # ----------------------------------------------------------------- # python wrappers # ----------------------------------------------------------------- @@ -380,3 +400,12 @@ def tophat(np.ndarray[np.uint8_t, ndim=2] image, """top hat """ return _core8(kernel_tophat, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + +def noise_filter(np.ndarray[np.uint8_t, ndim=2] image, + 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_noise_filter, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) diff --git a/skimage/filter/rank/demo/demo_single.py b/skimage/filter/rank/demo/demo_single.py index 652f2cc8..3b7eaa95 100644 --- a/skimage/filter/rank/demo/demo_single.py +++ b/skimage/filter/rank/demo/demo_single.py @@ -19,6 +19,27 @@ if __name__ == '__main__': den = denoise_bilateral(a8,win_size=10,sigma_range=10,sigma_spatial=2)[:,:,0] f16b= rank.bilateral_mean(a8.astype(np.uint16),disk(10),s0=10,s1=10) + + selem = np.ones((3,3)) + selem[1,1] = 0 + radius = 3 + selem = disk(radius) + selem[radius,radius] = 0 + print selem + noise = rank.noise_filter(a8,selem) + plt.imsave('noise.png',noise,cmap=plt.cm.gray) + plt.imsave('cam.png',a8,cmap=plt.cm.gray) + print noise + + plt.figure() + plt.subplot(1,2,1) + plt.imshow(a8) + plt.subplot(1,2,2) + plt.imshow(noise) + plt.colorbar() + plt.show() + + plt.figure() plt.subplot(1,2,1) plt.imshow(den) diff --git a/skimage/filter/rank/rank.pyx b/skimage/filter/rank/rank.pyx index 2f144e98..40ceecad 100644 --- a/skimage/filter/rank/rank.pyx +++ b/skimage/filter/rank/rank.pyx @@ -19,7 +19,7 @@ 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'] + 'modal', 'morph_contr_enh', 'pop', 'threshold', 'tophat','noise_filter'] def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y): @@ -580,3 +580,31 @@ 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) +def noise_filter(image, selem, out=None, mask=None, shift_x=False, shift_y=False): + """Return minimum absolute diffirence between a pixel and its neighborhood + + Parameters + ---------- + image : ndarray + Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, + an exception will be raised if image has a value > 4095 + 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 : (int) + Offset added to the structuring element center point. + Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + + Returns + ------- + out : uint8 array or uint16 array (same as input image) + The image noise . + + """ + + return _apply(_crank8.noise_filter, None, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) \ No newline at end of file From a8a5e33425f73cb7e02f4054a95ec65320111a93 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 8 Nov 2012 10:37:55 +0100 Subject: [PATCH 190/195] fix noise_filter --- skimage/filter/rank/_crank8.pyx | 46 +++++--------------- skimage/filter/rank/demo/demo_single.py | 9 +--- skimage/filter/rank/rank.pyx | 20 ++++++++- skimage/filter/rank/tests/test_histo.py | 57 +++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 44 deletions(-) create mode 100644 skimage/filter/rank/tests/test_histo.py diff --git a/skimage/filter/rank/_crank8.pyx b/skimage/filter/rank/_crank8.pyx index a0c3cc35..9ddcb12d 100644 --- a/skimage/filter/rank/_crank8.pyx +++ b/skimage/filter/rank/_crank8.pyx @@ -230,21 +230,26 @@ cdef inline np.uint8_t kernel_noise_filter( cdef Py_ssize_t i cdef Py_ssize_t min_i - for i in range(255, g, -1): + # early stop if at least one pixel of the neighborhood has the same g + if histo[g]>0: + return < np.uint8_t > 0 + + for i in range(g, -1, -1): if histo[i]: break - min_i = i-g - for i in range(0, g): + min_i = g-i + for i in range(g, 256): if histo[i]: break - if g-i < min_i: - return < np.uint8_t > (g-i) + if i-g < min_i: + return < np.uint8_t > (i-g) else: return < np.uint8_t > min_i # ----------------------------------------------------------------- # python wrappers +# used only internally # ----------------------------------------------------------------- @@ -253,8 +258,6 @@ 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): - """bottom hat - """ return _core8( kernel_autolevel, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -265,8 +268,6 @@ def bottomhat(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - """bottom hat - """ return _core8( kernel_bottomhat, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -277,8 +278,6 @@ def equalize(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - """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) @@ -289,8 +288,6 @@ def gradient(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - """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) @@ -301,8 +298,6 @@ def maximum(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - """local maximum gray level - """ return _core8(kernel_maximum, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -311,8 +306,6 @@ def mean(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - """average gray level (clipped on uint8) - """ return _core8(kernel_mean, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -321,8 +314,6 @@ def meansubstraction(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - """(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) @@ -333,8 +324,6 @@ def median(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - """local median - """ return _core8(kernel_median, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -343,8 +332,6 @@ def minimum(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - """local minimum gray level - """ return _core8(kernel_minimum, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -353,8 +340,6 @@ def morph_contr_enh(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - """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) @@ -365,8 +350,6 @@ def modal(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - """local mode - """ return _core8(kernel_modal, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -375,8 +358,6 @@ def pop(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - """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, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -385,8 +366,6 @@ def threshold(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - """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) @@ -397,15 +376,12 @@ def tophat(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): - """top hat - """ return _core8(kernel_tophat, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + def noise_filter(np.ndarray[np.uint8_t, ndim=2] image, 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_noise_filter, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) diff --git a/skimage/filter/rank/demo/demo_single.py b/skimage/filter/rank/demo/demo_single.py index 3b7eaa95..e3fe9c1e 100644 --- a/skimage/filter/rank/demo/demo_single.py +++ b/skimage/filter/rank/demo/demo_single.py @@ -20,16 +20,11 @@ if __name__ == '__main__': f16b= rank.bilateral_mean(a8.astype(np.uint16),disk(10),s0=10,s1=10) - selem = np.ones((3,3)) - selem[1,1] = 0 - radius = 3 - selem = disk(radius) - selem[radius,radius] = 0 - print selem +# selem = np.ones((3,3),dtype=np.uint8) noise = rank.noise_filter(a8,selem) plt.imsave('noise.png',noise,cmap=plt.cm.gray) plt.imsave('cam.png',a8,cmap=plt.cm.gray) - print noise + plt.figure() plt.subplot(1,2,1) diff --git a/skimage/filter/rank/rank.pyx b/skimage/filter/rank/rank.pyx index 40ceecad..74875d1c 100644 --- a/skimage/filter/rank/rank.pyx +++ b/skimage/filter/rank/rank.pyx @@ -27,8 +27,12 @@ def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y): if mask is not None: mask = img_as_ubyte(mask) if image.dtype == np.uint8: + if func8 is None: + raise TypeError("uint8 image not supported for this filter") return func8(image, selem, shift_x=shift_x, shift_y=shift_y, mask=mask, out=out) elif image.dtype == np.uint16: + if func16 is None: + raise TypeError("uint16 image not supported for this filter") bitdepth = find_bitdepth(image) if bitdepth > 11: raise ValueError("only uint16 <4096 image (12bit) supported!") @@ -581,7 +585,7 @@ 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) def noise_filter(image, selem, out=None, mask=None, shift_x=False, shift_y=False): - """Return minimum absolute diffirence between a pixel and its neighborhood + """Returns the noise feature as described in [1]_ Parameters ---------- @@ -600,11 +604,23 @@ def noise_filter(image, selem, out=None, mask=None, shift_x=False, shift_y=False Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + Reference + ---------- + + .. [1] N. Hashimoto et al. Referenceless image quality evaluation for whole slide imaging. J Pathol Inform 2012;3:9. + + Returns ------- out : uint8 array or uint16 array (same as input image) The image noise . """ + # ensure that the central pixel in the structuring element is empty + centre_r = int(selem.shape[0] / 2) + shift_y + centre_c = int(selem.shape[1] / 2) + shift_x + # make a local copy + selem_cpy = selem.copy() + selem_cpy[centre_r,centre_c] = 0 - return _apply(_crank8.noise_filter, None, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) \ No newline at end of file + return _apply(_crank8.noise_filter, None, image, selem_cpy, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) \ No newline at end of file diff --git a/skimage/filter/rank/tests/test_histo.py b/skimage/filter/rank/tests/test_histo.py new file mode 100644 index 00000000..b6a7bbca --- /dev/null +++ b/skimage/filter/rank/tests/test_histo.py @@ -0,0 +1,57 @@ +import sys +print sys.path +import skimage +print skimage + +import unittest + +import numpy as np +from skimage.filter import rank + +from skimage import data +from skimage.morphology import cmorph,disk +from skimage.filter.rank import _crank8, _crank16 +from skimage.filter.rank import _crank16_percentiles + + +class TestSequenceFunctions(unittest.TestCase): + + def setUp(self): + pass + + def test_trivial_selem(self): + # check that min, max and mean returns identity if structuring element contains only central pixel + + a = np.zeros((5,5),dtype='uint8') + a[2,2] = 255 + a[2,3] = 128 + a[1,2] = 16 + elem = np.asarray([[0,0,0],[0,1,0],[0,0,0]],dtype='uint8') + f = _crank8.mean(image=a,selem = elem,shift_x=0,shift_y=0) + np.testing.assert_array_equal(a,f) + f = _crank8.minimum(image=a,selem = elem,shift_x=0,shift_y=0) + np.testing.assert_array_equal(a,f) + f = _crank8.maximum(image=a,selem = elem,shift_x=0,shift_y=0) + np.testing.assert_array_equal(a,f) + + def test_smallest_selem(self): + # check that min, max and mean returns identity if structuring element contains only central pixel + + a = np.zeros((5,5),dtype='uint8') + a[2,2] = 255 + a[2,3] = 128 + a[1,2] = 16 + elem = np.asarray([[1]],dtype='uint8') + f = _crank8.mean(image=a,selem = elem,shift_x=0,shift_y=0) + np.testing.assert_array_equal(a,f) + f = _crank8.minimum(image=a,selem = elem,shift_x=0,shift_y=0) + np.testing.assert_array_equal(a,f) + f = _crank8.maximum(image=a,selem = elem,shift_x=0,shift_y=0) + np.testing.assert_array_equal(a,f) + + + +if __name__ == '__main__': + + suite = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions) + unittest.TextTestRunner(verbosity=2).run(suite) From e804f96f02a53864400dd40a8796c371b0e15647 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 8 Nov 2012 10:45:20 +0100 Subject: [PATCH 191/195] fix noise_filter --- skimage/filter/rank/_crank8.pyx | 23 +++++++++++++++++++++ skimage/filter/rank/rank.pyx | 36 ++++++++++++++++++++++++++++++--- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/skimage/filter/rank/_crank8.pyx b/skimage/filter/rank/_crank8.pyx index 9ddcb12d..5cb0b5ed 100644 --- a/skimage/filter/rank/_crank8.pyx +++ b/skimage/filter/rank/_crank8.pyx @@ -246,6 +246,22 @@ cdef inline np.uint8_t kernel_noise_filter( else: return < np.uint8_t > min_i +cdef inline np.uint8_t kernel_entropy( + Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1, Py_ssize_t s0, + Py_ssize_t s1): + + cdef Py_ssize_t i + cdef Py_ssize_t min_i + cdef float e,p + + e = 0 + + for i in range(256): + p = histo[i]/pop + if p>0: + e -= p*np.log2(p) + + return < np.uint8_t > e # ----------------------------------------------------------------- # python wrappers @@ -385,3 +401,10 @@ def noise_filter(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): return _core8(kernel_noise_filter, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + +def entropy(np.ndarray[np.uint8_t, ndim=2] image, + np.ndarray[np.uint8_t, ndim=2] selem, + np.ndarray[np.uint8_t, ndim=2] mask=None, + np.ndarray[np.uint8_t, ndim=2] out=None, + char shift_x=0, char shift_y=0): + return _core8(kernel_entropy, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) diff --git a/skimage/filter/rank/rank.pyx b/skimage/filter/rank/rank.pyx index 74875d1c..12517cfa 100644 --- a/skimage/filter/rank/rank.pyx +++ b/skimage/filter/rank/rank.pyx @@ -28,11 +28,11 @@ def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y): mask = img_as_ubyte(mask) if image.dtype == np.uint8: if func8 is None: - raise TypeError("uint8 image not supported for this filter") + raise TypeError("not implemented for uint8 image") return func8(image, selem, shift_x=shift_x, shift_y=shift_y, mask=mask, out=out) elif image.dtype == np.uint16: if func16 is None: - raise TypeError("uint16 image not supported for this filter") + raise TypeError("not implemented for uint16 image") bitdepth = find_bitdepth(image) if bitdepth > 11: raise ValueError("only uint16 <4096 image (12bit) supported!") @@ -623,4 +623,34 @@ def noise_filter(image, selem, out=None, mask=None, shift_x=False, shift_y=False selem_cpy = selem.copy() selem_cpy[centre_r,centre_c] = 0 - return _apply(_crank8.noise_filter, None, image, selem_cpy, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) \ No newline at end of file + return _apply(_crank8.noise_filter, None, image, selem_cpy, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) + +def entropy(image, selem, out=None, mask=None, shift_x=False, shift_y=False): + """Returns the entropy (in bit) computed locally (precision is limited due to image type used 8- or 16-bit) + + Parameters + ---------- + image : ndarray + Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, + an exception will be raised if image has a value > 4095 + 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 : (int) + Offset added to the structuring element center point. + Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + + + Returns + ------- + out : uint8 array or uint16 array (same as input image) + local entropy (in bit) + + """ + + return _apply(_crank8.entropy, None, image, selem_cpy, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) \ No newline at end of file From 665e05ff35b9750ea6a63b0b43ba1bef98239c84 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 8 Nov 2012 12:15:47 +0100 Subject: [PATCH 192/195] doc entropy --- .../applications/plot_rank_filters.py | 55 ++++++++++++++ doc/examples/plot_entropy.py | 44 +++++++++++ skimage/filter/rank/_crank16.pyx | 53 ++++++------- skimage/filter/rank/_crank8.pyx | 11 +-- skimage/filter/rank/bilateral_rank.pyx | 6 +- skimage/filter/rank/demo/demo_single.py | 5 +- skimage/filter/rank/percentile_rank.pyx | 24 ++---- skimage/filter/rank/rank.pyx | 76 ++++++++++--------- 8 files changed, 183 insertions(+), 91 deletions(-) create mode 100644 doc/examples/plot_entropy.py diff --git a/doc/examples/applications/plot_rank_filters.py b/doc/examples/applications/plot_rank_filters.py index 2ebb7b92..7b28d776 100644 --- a/doc/examples/applications/plot_rank_filters.py +++ b/doc/examples/applications/plot_rank_filters.py @@ -348,6 +348,61 @@ plt.xlabel('morphological gradient') """ .. image:: PLOT2RST.current_figure +Feature extraction +=================== + +Local histogram can be exploited to compute local entropy, which is related to the local image complexity. +Entropy is computed using base 2 logarithm i.e. the filter returns the minimum number of bits needed to encode local +greylevel distribution. + +``skimage.rank.entropy`` returns local entropy on a given structuring element. +The following example shows this filter applied on 8- and 16- bit images. + +.. note:: to better use the available image bit, the function returns 10x entropy for 8-bit images and 1000x entropy + for 16-bit images. + +""" + +from skimage import data +from skimage.filter.rank import entropy +from skimage.morphology import disk +import numpy as np +import matplotlib.pyplot as plt + +# defining a 8- and a 16-bit test images +a8 = data.camera() +a16 = data.camera().astype(np.uint16)*4 + +ent8 = entropy(a8,disk(5)) # pixel value contain 10x the local entropy +ent16 = entropy(a16,disk(5)) # pixel value contain 1000x the local entropy + +# display results +plt.figure(figsize=(10, 10)) + +plt.subplot(2,2,1) +plt.imshow(a8, cmap=plt.cm.gray) +plt.xlabel('8-bit image') +plt.colorbar() + +plt.subplot(2,2,2) +plt.imshow(ent8, cmap=plt.cm.jet) +plt.xlabel('entropy*10') +plt.colorbar() + +plt.subplot(2,2,3) +plt.imshow(a16, cmap=plt.cm.gray) +plt.xlabel('16-bit image') +plt.colorbar() + +plt.subplot(2,2,4) +plt.imshow(ent16, cmap=plt.cm.jet) +plt.xlabel('entropy*1000') +plt.colorbar() +plt.show() + +""" +.. image:: PLOT2RST.current_figure + Implementation ================ diff --git a/doc/examples/plot_entropy.py b/doc/examples/plot_entropy.py new file mode 100644 index 00000000..f019d79c --- /dev/null +++ b/doc/examples/plot_entropy.py @@ -0,0 +1,44 @@ +""" +=================== +Entropy +=================== + + +""" +from skimage import data +from skimage.filter.rank import entropy +from skimage.morphology import disk +import numpy as np +import matplotlib.pyplot as plt + +# defining a 8- and a 16-bit test images +a8 = data.camera() +a16 = data.camera().astype(np.uint16)*4 + +ent8 = entropy(a8,disk(5)) # pixel value contain 10x the local entropy +ent16 = entropy(a16,disk(5)) # pixel value contain 1000x the local entropy + +# display results +plt.figure(figsize=(10, 10)) + +plt.subplot(2,2,1) +plt.imshow(a8, cmap=plt.cm.gray) +plt.xlabel('8-bit image') +plt.colorbar() + +plt.subplot(2,2,2) +plt.imshow(ent8, cmap=plt.cm.jet) +plt.xlabel('entropy*10') +plt.colorbar() + +plt.subplot(2,2,3) +plt.imshow(a16, cmap=plt.cm.gray) +plt.xlabel('16-bit image') +plt.colorbar() + +plt.subplot(2,2,4) +plt.imshow(ent16, cmap=plt.cm.jet) +plt.xlabel('entropy*1000') +plt.colorbar() +plt.show() + diff --git a/skimage/filter/rank/_crank16.pyx b/skimage/filter/rank/_crank16.pyx index f6ad10e4..73e8e0bd 100644 --- a/skimage/filter/rank/_crank16.pyx +++ b/skimage/filter/rank/_crank16.pyx @@ -5,6 +5,7 @@ import numpy as np cimport numpy as np +from libc.math cimport log2 # import main loop from skimage.filter.rank._core16 cimport _core16 @@ -222,6 +223,23 @@ cdef inline np.uint16_t kernel_tophat( return < np.uint16_t > (i - g) + +cdef inline np.uint16_t kernel_entropy( + Py_ssize_t * histo, float pop, np.uint16_t g, + Py_ssize_t bitdepth, Py_ssize_t maxbin, Py_ssize_t midbin, + float p0, float p1, Py_ssize_t s0, Py_ssize_t s1): + cdef Py_ssize_t i + cdef float e,p + + e = 0. + + for i in range(maxbin): + p = histo[i]/pop + if p>0: + e -= p*log2(p) + + return < np.uint16_t > e*1000 + # ----------------------------------------------------------------- # python wrappers # ----------------------------------------------------------------- @@ -232,8 +250,6 @@ def autolevel(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - """bottom hat - """ return _core16(kernel_autolevel, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -242,8 +258,6 @@ def bottomhat(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - """bottom hat - """ return _core16(kernel_bottomhat, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -252,8 +266,6 @@ def equalize(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - """local egalisation of the gray level - """ return _core16(kernel_equalize, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -262,8 +274,6 @@ def gradient(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - """local maximum - local minimum gray level - """ return _core16(kernel_gradient, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -272,8 +282,6 @@ def maximum(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - """local maximum gray level - """ return _core16(kernel_maximum, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -282,8 +290,6 @@ def mean(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - """average gray level (clipped on uint8) - """ return _core16(kernel_mean, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -292,8 +298,6 @@ def meansubstraction(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - """(g - average gray level)/2+midbin (clipped on uint8) - """ return _core16(kernel_meansubstraction, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -302,8 +306,6 @@ def median(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - """local median - """ return _core16(kernel_median, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -312,8 +314,6 @@ def minimum(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - """local minimum gray level - """ return _core16(kernel_minimum, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -322,8 +322,6 @@ def morph_contr_enh(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - """morphological contrast enhancement - """ 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) @@ -332,8 +330,6 @@ def modal(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - """local mode - """ return _core16(kernel_modal, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -342,8 +338,6 @@ def pop(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - """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, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -352,8 +346,6 @@ def threshold(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - """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, < Py_ssize_t > 0, < Py_ssize_t > 0) @@ -362,6 +354,11 @@ def tophat(np.ndarray[np.uint16_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] mask=None, np.ndarray[np.uint16_t, ndim=2] out=None, char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): - """top hat - """ return _core16(kernel_tophat, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + +def entropy(np.ndarray[np.uint16_t, ndim=2] image, + np.ndarray[np.uint8_t, ndim=2] selem, + np.ndarray[np.uint8_t, ndim=2] mask=None, + np.ndarray[np.uint16_t, ndim=2] out=None, + char shift_x=0, char shift_y=0, Py_ssize_t bitdepth=8): + return _core16(kernel_entropy, image, selem, mask, out, shift_x, shift_y, bitdepth, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) diff --git a/skimage/filter/rank/_crank8.pyx b/skimage/filter/rank/_crank8.pyx index 5cb0b5ed..84ad9204 100644 --- a/skimage/filter/rank/_crank8.pyx +++ b/skimage/filter/rank/_crank8.pyx @@ -6,6 +6,8 @@ import numpy as np cimport numpy as np +from libc.math cimport log2 + # import main loop from skimage.filter.rank._core8 cimport _core8 @@ -251,17 +253,16 @@ cdef inline np.uint8_t kernel_entropy( Py_ssize_t s1): cdef Py_ssize_t i - cdef Py_ssize_t min_i cdef float e,p - e = 0 + e = 0. for i in range(256): - p = histo[i]/pop + p = histo[i]/pop if p>0: - e -= p*np.log2(p) + e -= p*log2(p) - return < np.uint8_t > e + return < np.uint8_t > e*10 # ----------------------------------------------------------------- # python wrappers diff --git a/skimage/filter/rank/bilateral_rank.pyx b/skimage/filter/rank/bilateral_rank.pyx index 80349b0b..f181735b 100644 --- a/skimage/filter/rank/bilateral_rank.pyx +++ b/skimage/filter/rank/bilateral_rank.pyx @@ -71,8 +71,7 @@ def bilateral_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -126,8 +125,7 @@ def bilateral_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fals 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). diff --git a/skimage/filter/rank/demo/demo_single.py b/skimage/filter/rank/demo/demo_single.py index e3fe9c1e..4afa546b 100644 --- a/skimage/filter/rank/demo/demo_single.py +++ b/skimage/filter/rank/demo/demo_single.py @@ -25,12 +25,15 @@ if __name__ == '__main__': plt.imsave('noise.png',noise,cmap=plt.cm.gray) plt.imsave('cam.png',a8,cmap=plt.cm.gray) + selem = disk(3) + ent = rank.entropy(a16,selem) + plt.figure() plt.subplot(1,2,1) plt.imshow(a8) plt.subplot(1,2,2) - plt.imshow(noise) + plt.imshow(ent) plt.colorbar() plt.show() diff --git a/skimage/filter/rank/percentile_rank.pyx b/skimage/filter/rank/percentile_rank.pyx index d45bcfe3..1bd89eb8 100644 --- a/skimage/filter/rank/percentile_rank.pyx +++ b/skimage/filter/rank/percentile_rank.pyx @@ -55,8 +55,7 @@ def percentile_autolevel(image, selem, out=None, mask=None, shift_x=False, shift 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -92,8 +91,7 @@ def percentile_gradient(image, selem, out=None, mask=None, shift_x=False, shift_ 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -130,8 +128,7 @@ def percentile_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -167,8 +164,7 @@ def percentile_mean_substraction(image, selem, out=None, mask=None, shift_x=Fals 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -205,8 +201,7 @@ def percentile_morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -243,8 +238,7 @@ def percentile(image, selem, out=None, mask=None, shift_x=False, shift_y=False, 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -281,8 +275,7 @@ def percentile_pop(image, selem, out=None, mask=None, shift_x=False, shift_y=Fal 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -319,8 +312,7 @@ def percentile_threshold(image, selem, out=None, mask=None, shift_x=False, shift 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). diff --git a/skimage/filter/rank/rank.pyx b/skimage/filter/rank/rank.pyx index 12517cfa..2c9b7326 100644 --- a/skimage/filter/rank/rank.pyx +++ b/skimage/filter/rank/rank.pyx @@ -19,7 +19,7 @@ from skimage.filter.rank import _crank8, _crank16 from skimage.filter.rank.generic import find_bitdepth __all__ = ['autolevel', 'bottomhat', 'equalize', 'gradient', 'maximum', 'mean', 'meansubstraction', 'median', 'minimum', - 'modal', 'morph_contr_enh', 'pop', 'threshold', 'tophat','noise_filter'] + 'modal', 'morph_contr_enh', 'pop', 'threshold', 'tophat','noise_filter','entropy'] def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y): @@ -52,8 +52,7 @@ def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -94,8 +93,7 @@ def bottomhat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -127,8 +125,7 @@ def equalize(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -169,8 +166,7 @@ def gradient(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -202,8 +198,7 @@ def maximum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -242,8 +237,7 @@ def mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -281,8 +275,7 @@ def meansubstraction(image, selem, out=None, mask=None, shift_x=False, shift_y=F 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -316,8 +309,7 @@ def median(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -355,8 +347,7 @@ def minimum(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -395,8 +386,7 @@ def modal(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -427,8 +417,7 @@ def morph_contr_enh(image, selem, out=None, mask=None, shift_x=False, shift_y=Fa 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -468,8 +457,7 @@ def pop(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -516,8 +504,7 @@ def threshold(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -566,8 +553,7 @@ def tophat(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -595,8 +581,7 @@ def noise_filter(image, selem, out=None, mask=None, shift_x=False, shift_y=False 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -626,7 +611,12 @@ def noise_filter(image, selem, out=None, mask=None, shift_x=False, shift_y=False return _apply(_crank8.noise_filter, None, image, selem_cpy, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) def entropy(image, selem, out=None, mask=None, shift_x=False, shift_y=False): - """Returns the entropy (in bit) computed locally (precision is limited due to image type used 8- or 16-bit) + """Returns the entropy [wiki_entropy]_ computed locally. Entropy is computed using base 2 logarithm i.e. + the filter returns the minimum number of bits needed to encode local greylevel distribution. + + References + ---------- + .. [wiki_entropy] http://en.wikipedia.org/wiki/Entropy_(information_theory) Parameters ---------- @@ -636,8 +626,7 @@ def entropy(image, selem, out=None, mask=None, shift_x=False, shift_y=False): 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. + If None, a new array will be allocated. mask : ndarray (uint8) Mask array that defines (>0) area of the image included in the local neighborhood. If None, the complete image is used (default). @@ -645,12 +634,25 @@ def entropy(image, selem, out=None, mask=None, shift_x=False, shift_y=False): Offset added to the structuring element center point. Shift is bounded to the structuring element sizes (center must be inside the given structuring element). - Returns ------- out : uint8 array or uint16 array (same as input image) - local entropy (in bit) + entropy x10 (uint8 images) and entropy x1000 (uint16 images) + + + Examples + -------- + + >>> # Local entropy + >>> from skimage import data + >>> from skimage.filter.rank import entropy + >>> from skimage.morphology import disk + >>> # defining a 8- and a 16-bit test images + >>> a8 = data.camera() + >>> a16 = data.camera().astype(np.uint16)*4 + >>> ent8 = entropy(a8,disk(5)) # pixel value contain 10x the local entropy + >>> ent16 = entropy(a16,disk(5)) # pixel value contain 1000x the local entropy """ - return _apply(_crank8.entropy, None, image, selem_cpy, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) \ No newline at end of file + return _apply(_crank8.entropy, _crank16.entropy, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) \ No newline at end of file From 8cf762f132b45a8b4b241d59138c034ac70edc9b Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 8 Nov 2012 12:17:22 +0100 Subject: [PATCH 193/195] doc noise filter --- skimage/filter/rank/rank.pyx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/skimage/filter/rank/rank.pyx b/skimage/filter/rank/rank.pyx index 2c9b7326..ad66fc65 100644 --- a/skimage/filter/rank/rank.pyx +++ b/skimage/filter/rank/rank.pyx @@ -571,7 +571,7 @@ 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) def noise_filter(image, selem, out=None, mask=None, shift_x=False, shift_y=False): - """Returns the noise feature as described in [1]_ + """Returns the noise feature as described in [Hashimoto12]_ Parameters ---------- @@ -579,7 +579,7 @@ def noise_filter(image, selem, out=None, mask=None, shift_x=False, shift_y=False Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, an exception will be raised if image has a value > 4095 selem : ndarray - The neighborhood expressed as a 2-D array of 1's and 0's. + The neighborhood expressed as a 2-D array of 1's and 0's. Central element is removed during the filtering. out : ndarray If None, a new array will be allocated. mask : ndarray (uint8) @@ -592,7 +592,7 @@ def noise_filter(image, selem, out=None, mask=None, shift_x=False, shift_y=False Reference ---------- - .. [1] N. Hashimoto et al. Referenceless image quality evaluation for whole slide imaging. J Pathol Inform 2012;3:9. + .. [Hashimoto12] N. Hashimoto et al. Referenceless image quality evaluation for whole slide imaging. J Pathol Inform 2012;3:9. Returns From 12209a50dec9f3457476fa9f0a192cd1c335e5ee Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 8 Nov 2012 15:36:09 +0100 Subject: [PATCH 194/195] modify example entropy --- doc/examples/applications/plot_rank_filters.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/examples/applications/plot_rank_filters.py b/doc/examples/applications/plot_rank_filters.py index 7b28d776..d52595f2 100644 --- a/doc/examples/applications/plot_rank_filters.py +++ b/doc/examples/applications/plot_rank_filters.py @@ -25,7 +25,7 @@ Rank filters can be used for several purposes such as: Some well known filters are specific cases of rank filters [1]_ e.g. morphological dilation, morphological erosion, median filters. -The different implementation availables in ``skimage`` are compared compare. +The different implementation availables in ``skimage`` are compared. In this example, we will see how to filter a grey level image using some of the linear and non-linear filters availables in skimage. We use the ``camera`` image from ``skimage.data``. @@ -363,6 +363,8 @@ The following example shows this filter applied on 8- and 16- bit images. """ + + from skimage import data from skimage.filter.rank import entropy from skimage.morphology import disk From 44ada6cb70501208e2a64364e1a373d084f10325 Mon Sep 17 00:00:00 2001 From: Olivier Debeir Date: Thu, 8 Nov 2012 17:10:00 +0100 Subject: [PATCH 195/195] add local Otsu threshold --- skimage/filter/rank/_crank8.pyx | 47 ++++++++++++++++++++++++ skimage/filter/rank/demo/demo_single.py | 46 +++-------------------- skimage/filter/rank/rank.pyx | 49 ++++++++++++++++++++++++- 3 files changed, 100 insertions(+), 42 deletions(-) diff --git a/skimage/filter/rank/_crank8.pyx b/skimage/filter/rank/_crank8.pyx index 84ad9204..4efd2bb0 100644 --- a/skimage/filter/rank/_crank8.pyx +++ b/skimage/filter/rank/_crank8.pyx @@ -264,6 +264,46 @@ cdef inline np.uint8_t kernel_entropy( return < np.uint8_t > e*10 +cdef inline np.uint8_t kernel_otsu( + Py_ssize_t * histo, float pop, np.uint8_t g, float p0, float p1, Py_ssize_t s0, + Py_ssize_t s1): + + cdef Py_ssize_t i + cdef Py_ssize_t max_i + cdef float P, mu1, mu2, q1,new_q1, sigma_b, max_sigma_b + cdef float mu = 0. + + # compute local mean + + if pop: + for i in range(256): + mu += histo[i] * i + mu = (mu / pop) + else: + return < np.uint8_t > (0) + + # maximizing the between class variance + max_i = 0 + q1 = histo[0]/pop + m1 = 0. + max_sigma_b = 0. + + for i in range(1,256): + P = histo[i]/pop + new_q1 = q1 + P + if new_q1>0: + mu1 = (q1*mu1 + i*P)/new_q1 + mu2 = (mu-new_q1*mu1)/(1.-new_q1) + sigma_b = new_q1*(1.-new_q1)*(mu1-mu2)**2 + if sigma_b>max_sigma_b: + max_sigma_b = sigma_b + max_i = i + q1 = new_q1 + + if g>max_i: + return < np.uint8_t > 255 + else: + return < np.uint8_t > 0 # ----------------------------------------------------------------- # python wrappers # used only internally @@ -409,3 +449,10 @@ def entropy(np.ndarray[np.uint8_t, ndim=2] image, np.ndarray[np.uint8_t, ndim=2] out=None, char shift_x=0, char shift_y=0): return _core8(kernel_entropy, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) + +def otsu(np.ndarray[np.uint8_t, ndim=2] image, + np.ndarray[np.uint8_t, ndim=2] selem, + np.ndarray[np.uint8_t, ndim=2] mask=None, + np.ndarray[np.uint8_t, ndim=2] out=None, + char shift_x=0, char shift_y=0): + return _core8(kernel_otsu, image, selem, mask, out, shift_x, shift_y, .0, .0, < Py_ssize_t > 0, < Py_ssize_t > 0) diff --git a/skimage/filter/rank/demo/demo_single.py b/skimage/filter/rank/demo/demo_single.py index 4afa546b..7e4ef405 100644 --- a/skimage/filter/rank/demo/demo_single.py +++ b/skimage/filter/rank/demo/demo_single.py @@ -10,57 +10,23 @@ from skimage.filter import denoise_bilateral if __name__ == '__main__': a8 = data.camera() 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.) + p8 = data.page() - den = denoise_bilateral(a8,win_size=10,sigma_range=10,sigma_spatial=2)[:,:,0] - f16b= rank.bilateral_mean(a8.astype(np.uint16),disk(10),s0=10,s1=10) + selem = disk(20) - -# selem = np.ones((3,3),dtype=np.uint8) - noise = rank.noise_filter(a8,selem) - plt.imsave('noise.png',noise,cmap=plt.cm.gray) - plt.imsave('cam.png',a8,cmap=plt.cm.gray) - - selem = disk(3) - ent = rank.entropy(a16,selem) + otsu = rank.otsu(p8,selem) plt.figure() plt.subplot(1,2,1) - plt.imshow(a8) + plt.imshow(p8) + plt.colorbar() plt.subplot(1,2,2) - plt.imshow(ent) + plt.imshow(otsu) plt.colorbar() plt.show() - plt.figure() - plt.subplot(1,2,1) - plt.imshow(den) - plt.subplot(1,2,2) - plt.imshow(f16b) - plt.show() - - print f16==f16p - - plt.figure() - plt.subplot(1,3,1) - plt.imshow(f16) - 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 - diff --git a/skimage/filter/rank/rank.pyx b/skimage/filter/rank/rank.pyx index ad66fc65..6a35920b 100644 --- a/skimage/filter/rank/rank.pyx +++ b/skimage/filter/rank/rank.pyx @@ -19,7 +19,7 @@ from skimage.filter.rank import _crank8, _crank16 from skimage.filter.rank.generic import find_bitdepth __all__ = ['autolevel', 'bottomhat', 'equalize', 'gradient', 'maximum', 'mean', 'meansubstraction', 'median', 'minimum', - 'modal', 'morph_contr_enh', 'pop', 'threshold', 'tophat','noise_filter','entropy'] + 'modal', 'morph_contr_enh', 'pop', 'threshold', 'tophat','noise_filter','entropy','otsu'] def _apply(func8, func16, image, selem, out, mask, shift_x, shift_y): @@ -655,4 +655,49 @@ def entropy(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """ - return _apply(_crank8.entropy, _crank16.entropy, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) \ No newline at end of file + return _apply(_crank8.entropy, _crank16.entropy, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) + +def otsu(image, selem, out=None, mask=None, shift_x=False, shift_y=False): + """Returns the image threshold using a the Otsu [otsu]_ locally . + + References + ---------- + + .. [otsu] http://en.wikipedia.org/wiki/Otsu's_method + + Parameters + ---------- + image : ndarray + Image array (uint8 array or uint16). If image is uint16, the algorithm uses max. 12bit histogram, + an exception will be raised if image has a value > 4095 + selem : ndarray + The neighborhood expressed as a 2-D array of 1's and 0's. + out : ndarray + If None, a new array will be allocated. + mask : ndarray (uint8) + Mask array that defines (>0) area of the image included in the local neighborhood. + If None, the complete image is used (default). + shift_x, shift_y : (int) + Offset added to the structuring element center point. + Shift is bounded to the structuring element sizes (center must be inside the given structuring element). + + Returns + ------- + out : uint8 array or uint16 array (same as input image) + threshold image + + + Examples + -------- + + >>> # Local entropy + >>> from skimage import data + >>> from skimage.filter.rank import otsu + >>> from skimage.morphology import disk + >>> # defining a 8- and a 16-bit test images + >>> a8 = data.camera() + >>> loc_otsu = otsu(a8,disk(5)) + + """ + + return _apply(_crank8.otsu, None, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) \ No newline at end of file