mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-10 21:10:28 +08:00
paste code
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
To use this to build your Cython file use the commandline options:
|
||||
|
||||
.. sourcecode:: text
|
||||
|
||||
$ python setup.py build_ext --inplace
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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 = <np.uint8_t*>out.data
|
||||
cdef np.uint8_t* image_data = <np.uint8_t*>image.data
|
||||
|
||||
cdef int r, c, rr, cc, s, value, local_max
|
||||
|
||||
cdef int selem_num = np.sum(selem != 0)
|
||||
cdef int* sr = <int*>malloc(selem_num * sizeof(int))
|
||||
cdef int* sc = <int*>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 = <np.uint8_t*>out.data
|
||||
cdef np.uint8_t* image_data = <np.uint8_t*>image.data
|
||||
|
||||
cdef int r, c, rr, cc, s, value, local_min
|
||||
|
||||
cdef int selem_num = np.sum(selem != 0)
|
||||
cdef int* sr = <int*>malloc(selem_num * sizeof(int))
|
||||
cdef int* sc = <int*>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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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 <np.uint8_t>(255.*(g-imin)/delta)
|
||||
else:
|
||||
return <np.uint8_t>(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 <np.uint8_t>(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 <np.uint8_t>((255*sum)/pop)
|
||||
else:
|
||||
return <np.uint8_t>(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 <np.uint8_t>(imax-imin)
|
||||
else:
|
||||
return <np.uint8_t>(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 <np.uint8_t>(i)
|
||||
|
||||
return <np.uint8_t>(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 <np.uint8_t>(mean/pop)
|
||||
else:
|
||||
return <np.uint8_t>(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 <np.uint8_t>((g-mean/pop)/2.+127)
|
||||
else:
|
||||
return <np.uint8_t>(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 <np.uint8_t>(i)
|
||||
|
||||
return <np.uint8_t>(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 <np.uint8_t>(i)
|
||||
|
||||
return <np.uint8_t>(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 <np.uint8_t>(imax)
|
||||
|
||||
return <np.uint8_t>(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 <np.uint8_t>(imax)
|
||||
else:
|
||||
return <np.uint8_t>(imin)
|
||||
else:
|
||||
return <np.uint8_t>(0)
|
||||
|
||||
cdef inline np.uint8_t kernel_pop(int* histo, float pop, np.uint8_t g):
|
||||
return <np.uint8_t>(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 <np.uint8_t>(g>(mean/pop))
|
||||
else:
|
||||
return <np.uint8_t>(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 <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):
|
||||
"""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)
|
||||
|
||||
@@ -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 <np.uint16_t>(maxbin*1.*(g-imin)/delta)
|
||||
else:
|
||||
return <np.uint16_t>(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 <np.uint16_t>(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 <np.uint16_t>((maxbin*1.*sum)/pop)
|
||||
else:
|
||||
return <np.uint16_t>(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 <np.uint16_t>(imax-imin)
|
||||
else:
|
||||
return <np.uint16_t>(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 <np.uint16_t>(i)
|
||||
|
||||
return <np.uint16_t>(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 <np.uint16_t>(mean/pop)
|
||||
else:
|
||||
return <np.uint16_t>(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 <np.uint16_t>((g-mean/pop)/2.+midbin)
|
||||
else:
|
||||
return <np.uint16_t>(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 <np.uint16_t>(i)
|
||||
|
||||
return <np.uint16_t>(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 <np.uint16_t>(i)
|
||||
|
||||
return <np.uint16_t>(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 <np.uint16_t>(imax)
|
||||
|
||||
return <np.uint16_t>(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 <np.uint16_t>(imax)
|
||||
else:
|
||||
return <np.uint16_t>(imin)
|
||||
else:
|
||||
return <np.uint16_t>(0)
|
||||
|
||||
cdef inline np.uint16_t kernel_pop(int* histo, float pop, np.uint16_t g,int bitdepth,int maxbin, int midbin):
|
||||
return <np.uint16_t>(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 <np.uint16_t>(g>(mean/pop))
|
||||
else:
|
||||
return <np.uint16_t>(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 <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, 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)
|
||||
@@ -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 <np.uint16_t>(maxbin-1)
|
||||
if g<imin:
|
||||
return <np.uint16_t>(0)
|
||||
if delta>0:
|
||||
return <np.uint16_t>((maxbin-1)*1.*(g-imin)/delta)
|
||||
else:
|
||||
return <np.uint16_t>(0)
|
||||
else:
|
||||
return <np.uint16_t>(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 <np.uint16_t>(imax-imin)
|
||||
else:
|
||||
return <np.uint16_t>(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 <np.uint16_t>(1.0*mean/n)
|
||||
else:
|
||||
return <np.uint16_t>(0)
|
||||
else:
|
||||
return <np.uint16_t>(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 <np.uint16_t>((g-(mean/n))*.5+midbin)
|
||||
else:
|
||||
return <np.uint16_t>(0)
|
||||
else:
|
||||
return <np.uint16_t>(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 <np.uint16_t>imax
|
||||
if g<imin:
|
||||
return <np.uint16_t>imin
|
||||
if imax-g < g-imin:
|
||||
return <np.uint16_t>imax
|
||||
else:
|
||||
return <np.uint16_t>imin
|
||||
else:
|
||||
return <np.uint16_t>(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 <np.uint16_t>(i)
|
||||
else:
|
||||
return <np.uint16_t>(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 <np.uint16_t>(n)
|
||||
else:
|
||||
return <np.uint16_t>(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 <np.uint16_t>((maxbin-1)*(g>=i))
|
||||
else:
|
||||
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.):
|
||||
"""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)
|
||||
@@ -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 <np.uint8_t>(255.*(g-imin)/delta)
|
||||
else:
|
||||
return <np.uint8_t>(0)
|
||||
else:
|
||||
return <np.uint8_t>(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 <np.uint8_t>(imax-imin)
|
||||
else:
|
||||
return <np.uint8_t>(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 <np.uint8_t>(1.0*mean/n)
|
||||
else:
|
||||
return <np.uint8_t>(0)
|
||||
else:
|
||||
return <np.uint8_t>(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 <np.uint8_t>((g-(mean/n))*.5+127)
|
||||
else:
|
||||
return <np.uint8_t>(0)
|
||||
else:
|
||||
return <np.uint8_t>(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 <np.uint8_t>imax
|
||||
if g<imin:
|
||||
return <np.uint8_t>imin
|
||||
if imax-g < g-imin:
|
||||
return <np.uint8_t>imax
|
||||
else:
|
||||
return <np.uint8_t>imin
|
||||
else:
|
||||
return <np.uint8_t>(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 <np.uint8_t>(i)
|
||||
else:
|
||||
return <np.uint8_t>(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 <np.uint8_t>(n)
|
||||
else:
|
||||
return <np.uint8_t>(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 <np.uint8_t>(255*(g>=i))
|
||||
else:
|
||||
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.):
|
||||
"""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)
|
||||
@@ -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()])]
|
||||
)
|
||||
@@ -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()
|
||||
Reference in New Issue
Block a user