mirror of
https://github.com/wassname/scikit-image.git
synced 2026-06-29 00:39:44 +08:00
Refactor erosion and dilation for better performance
This commit is contained in:
@@ -1,116 +1,120 @@
|
||||
"""
|
||||
:author: Damian Eads, 2009
|
||||
:license: modified BSD
|
||||
"""
|
||||
#cython: cdivision=True
|
||||
#cython: boundscheck=False
|
||||
#cython: nonecheck=False
|
||||
#cython: wraparound=False
|
||||
|
||||
from __future__ import division
|
||||
import numpy as np
|
||||
|
||||
cimport numpy as np
|
||||
cimport cython
|
||||
from cpython cimport bool
|
||||
from libc.stdlib cimport malloc, free
|
||||
|
||||
STREL_DTYPE = np.uint8
|
||||
ctypedef np.uint8_t STREL_DTYPE_t
|
||||
|
||||
IMAGE_DTYPE = np.uint8
|
||||
ctypedef np.uint8_t IMAGE_DTYPE_t
|
||||
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,
|
||||
shift_x=False, shift_y=False):
|
||||
|
||||
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 int rows = image.shape[0]
|
||||
cdef int cols = image.shape[1]
|
||||
cdef int srows = selem.shape[0]
|
||||
cdef int scols = selem.shape[1]
|
||||
|
||||
@cython.boundscheck(False)
|
||||
def dilate(np.ndarray[IMAGE_DTYPE_t, ndim=2] image not None,
|
||||
np.ndarray[IMAGE_DTYPE_t, ndim=2] selem not None,
|
||||
np.ndarray[IMAGE_DTYPE_t, ndim=2] out,
|
||||
bool shift_x, bool shift_y):
|
||||
cdef int hw = selem.shape[0] // 2
|
||||
cdef int hh = selem.shape[1] // 2
|
||||
if shift_x:
|
||||
hh -= 1
|
||||
if shift_y:
|
||||
hw -= 1
|
||||
cdef int centre_r = int(selem.shape[0] / 2) - shift_y
|
||||
cdef int centre_c = int(selem.shape[1] / 2) - shift_x
|
||||
|
||||
cdef int width = image.shape[0], height = image.shape[1]
|
||||
image = np.ascontiguousarray(image)
|
||||
if out is None:
|
||||
out = np.zeros([width, height], dtype=IMAGE_DTYPE)
|
||||
out = np.zeros((rows, cols), dtype=np.uint8)
|
||||
else:
|
||||
out = np.ascontiguousarray(out)
|
||||
|
||||
assert out.shape[0] == image.shape[0]
|
||||
assert out.shape[1] == image.shape[1]
|
||||
cdef np.uint8_t* out_data = <np.uint8_t*>out.data
|
||||
cdef np.uint8_t* image_data = <np.uint8_t*>image.data
|
||||
|
||||
cdef int x, y, ix, iy, cx, cy
|
||||
cdef IMAGE_DTYPE_t max_so_far
|
||||
cdef int r, c, rr, cc, s, value, local_max
|
||||
|
||||
cdef int sw = selem.shape[0], sh = selem.shape[1]
|
||||
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))
|
||||
|
||||
cdef np.ndarray[np.int_t, ndim=2] xinc = np.zeros([sw, sh], dtype=np.int)
|
||||
cdef np.ndarray[np.int_t, ndim=2] yinc = np.zeros([sw, sh], dtype=np.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 x in range(sw):
|
||||
for y in range(sh):
|
||||
xinc[x, y] = (x - hw)
|
||||
yinc[x, y] = (y - hh)
|
||||
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 * rows + cc]
|
||||
if value > local_max:
|
||||
local_max = value
|
||||
|
||||
out_data[r * cols + c] = local_max
|
||||
|
||||
for x in range(width):
|
||||
for y in range(height):
|
||||
max_so_far = 0
|
||||
for cx in range(0, sw):
|
||||
for cy in range(0, sh):
|
||||
ix = x + xinc[cx,cy]
|
||||
iy = y + yinc[cx,cy]
|
||||
if ix>=0 and iy>=0 and ix < width and iy < height \
|
||||
and selem[cx, cy] == 1 \
|
||||
and image[ix,iy] > max_so_far:
|
||||
max_so_far = image[ix,iy]
|
||||
out[x,y] = max_so_far
|
||||
free(sr)
|
||||
free(sc)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
@cython.boundscheck(False)
|
||||
def erode(np.ndarray[IMAGE_DTYPE_t, ndim=2] image not None,
|
||||
np.ndarray[IMAGE_DTYPE_t, ndim=2] selem not None,
|
||||
np.ndarray[IMAGE_DTYPE_t, ndim=2] out,
|
||||
bool shift_x, bool shift_y):
|
||||
cdef int hw = selem.shape[0] // 2
|
||||
cdef int hh = selem.shape[1] // 2
|
||||
if shift_x:
|
||||
hh -= 1
|
||||
if shift_y:
|
||||
hw -= 1
|
||||
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,
|
||||
shift_x=False, shift_y=False):
|
||||
|
||||
cdef int width = image.shape[0], height = image.shape[1]
|
||||
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([width, height], dtype=IMAGE_DTYPE)
|
||||
out = np.zeros((rows, cols), dtype=np.uint8)
|
||||
else:
|
||||
out = np.ascontiguousarray(out)
|
||||
|
||||
assert out.shape[0] == image.shape[0]
|
||||
assert out.shape[1] == image.shape[1]
|
||||
cdef np.uint8_t* out_data = <np.uint8_t*>out.data
|
||||
cdef np.uint8_t* image_data = <np.uint8_t*>image.data
|
||||
|
||||
cdef int x, y, ix, iy, cx, cy
|
||||
cdef IMAGE_DTYPE_t min_so_far
|
||||
cdef int r, c, rr, cc, s, value, local_max
|
||||
|
||||
cdef int sw = selem.shape[0], sh = selem.shape[1]
|
||||
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))
|
||||
|
||||
cdef np.ndarray[np.int_t, ndim=2] xinc = np.zeros([sw, sh], dtype=np.int)
|
||||
cdef np.ndarray[np.int_t, ndim=2] yinc = np.zeros([sw, sh], dtype=np.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 x in range(sw):
|
||||
for y in range(sh):
|
||||
xinc[x, y] = (x - hw)
|
||||
yinc[x, y] = (y - hh)
|
||||
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 * rows + cc]
|
||||
if value < local_min:
|
||||
local_min = value
|
||||
|
||||
for x in range(width):
|
||||
for y in range(height):
|
||||
min_so_far = 255
|
||||
for cx in range(0, sw):
|
||||
for cy in range(0, sh):
|
||||
ix = x + xinc[cx,cy]
|
||||
iy = y + yinc[cx,cy]
|
||||
if ix>=0 and iy>=0 and ix < width \
|
||||
and iy < height and selem[cx, cy] == 1 \
|
||||
and image[ix,iy] < min_so_far:
|
||||
min_so_far = image[ix,iy]
|
||||
out[x,y] = min_so_far
|
||||
out_data[r * cols + c] = local_min
|
||||
|
||||
free(sr)
|
||||
free(sc)
|
||||
|
||||
return out
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
|
||||
import skimage
|
||||
|
||||
from . import cmorph
|
||||
|
||||
|
||||
__all__ = ['erosion', 'dilation', 'opening', 'closing', 'white_tophat',
|
||||
'black_tophat', 'greyscale_erode', 'greyscale_dilate',
|
||||
@@ -66,14 +66,8 @@ def erosion(image, selem, out=None, shift_x=False, shift_y=False):
|
||||
if image is out:
|
||||
raise NotImplementedError("In-place erosion not supported!")
|
||||
image = skimage.img_as_ubyte(image)
|
||||
|
||||
try:
|
||||
import skimage.morphology.cmorph as cmorph
|
||||
out = cmorph.erode(image, selem, out=out,
|
||||
shift_x=shift_x, shift_y=shift_y)
|
||||
return out
|
||||
except ImportError:
|
||||
raise ImportError("cmorph extension not available.")
|
||||
return cmorph.erode(image, selem, out=out,
|
||||
shift_x=shift_x, shift_y=shift_y)
|
||||
|
||||
|
||||
def dilation(image, selem, out=None, shift_x=False, shift_y=False):
|
||||
@@ -125,14 +119,8 @@ def dilation(image, selem, out=None, shift_x=False, shift_y=False):
|
||||
if image is out:
|
||||
raise NotImplementedError("In-place dilation not supported!")
|
||||
image = skimage.img_as_ubyte(image)
|
||||
|
||||
try:
|
||||
from . import cmorph
|
||||
out = cmorph.dilate(image, selem, out=out,
|
||||
shift_x=shift_x, shift_y=shift_y)
|
||||
return out
|
||||
except ImportError:
|
||||
raise ImportError("cmorph extension not available.")
|
||||
return cmorph.dilate(image, selem, out=out,
|
||||
shift_x=shift_x, shift_y=shift_y)
|
||||
|
||||
|
||||
def opening(image, selem, out=None):
|
||||
|
||||
Reference in New Issue
Block a user