mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-03 14:53:30 +08:00
Add fallback decorator for 3D images
We don't support images greater than 2D, so fall back on ndimage
This commit is contained in:
@@ -2,8 +2,10 @@ import warnings
|
||||
import numpy as np
|
||||
from scipy import ndimage
|
||||
from .selem import _default_selem
|
||||
from .misc import default_fallback
|
||||
|
||||
|
||||
@default_fallback
|
||||
def binary_erosion(image, selem=None, out=None):
|
||||
"""Return fast binary morphological erosion of an image.
|
||||
|
||||
@@ -32,10 +34,6 @@ def binary_erosion(image, selem=None, out=None):
|
||||
|
||||
"""
|
||||
|
||||
# Default structure element
|
||||
if selem is None:
|
||||
selem = _default_selem(image.ndim)
|
||||
|
||||
selem = (selem != 0)
|
||||
selem_sum = np.sum(selem)
|
||||
|
||||
@@ -52,6 +50,7 @@ def binary_erosion(image, selem=None, out=None):
|
||||
return np.equal(conv, selem_sum, out=out)
|
||||
|
||||
|
||||
@default_fallback
|
||||
def binary_dilation(image, selem=None, out=None):
|
||||
"""Return fast binary morphological dilation of an image.
|
||||
|
||||
@@ -81,10 +80,6 @@ def binary_dilation(image, selem=None, out=None):
|
||||
|
||||
"""
|
||||
|
||||
# Default structure element
|
||||
if selem is None:
|
||||
selem = _default_selem(image.ndim)
|
||||
|
||||
selem = (selem != 0)
|
||||
|
||||
if np.sum(selem) <= 255:
|
||||
@@ -100,6 +95,7 @@ def binary_dilation(image, selem=None, out=None):
|
||||
return np.not_equal(conv, 0, out=out)
|
||||
|
||||
|
||||
@default_fallback
|
||||
def binary_opening(image, selem=None, out=None):
|
||||
"""Return fast binary morphological opening of an image.
|
||||
|
||||
@@ -133,6 +129,7 @@ def binary_opening(image, selem=None, out=None):
|
||||
return out
|
||||
|
||||
|
||||
@default_fallback
|
||||
def binary_closing(image, selem=None, out=None):
|
||||
"""Return fast binary morphological closing of an image.
|
||||
|
||||
|
||||
+14
-23
@@ -2,7 +2,7 @@ import warnings
|
||||
from skimage import img_as_ubyte
|
||||
from scipy import ndimage
|
||||
from .selem import _default_selem
|
||||
|
||||
from .misc import default_fallback
|
||||
|
||||
from . import cmorph
|
||||
|
||||
@@ -11,6 +11,7 @@ __all__ = ['erosion', 'dilation', 'opening', 'closing', 'white_tophat',
|
||||
'black_tophat']
|
||||
|
||||
|
||||
@default_fallback
|
||||
def erosion(image, selem=None, out=None, shift_x=False, shift_y=False):
|
||||
"""Return greyscale morphological erosion of an image.
|
||||
|
||||
@@ -56,9 +57,9 @@ def erosion(image, selem=None, out=None, shift_x=False, shift_y=False):
|
||||
|
||||
"""
|
||||
|
||||
# Default structure element
|
||||
if selem is None:
|
||||
selem = _default_selem(image.ndim)
|
||||
# If image has more than 2 dimensions, use scipy.ndimage
|
||||
if image.ndim > 2:
|
||||
return ndimage.morphology.grey_erosion(image, footprint=selem, out=out)
|
||||
|
||||
if image is out:
|
||||
raise NotImplementedError("In-place erosion not supported!")
|
||||
@@ -68,6 +69,7 @@ def erosion(image, selem=None, out=None, shift_x=False, shift_y=False):
|
||||
shift_x=shift_x, shift_y=shift_y)
|
||||
|
||||
|
||||
@default_fallback
|
||||
def dilation(image, selem=None, out=None, shift_x=False, shift_y=False):
|
||||
"""Return greyscale morphological dilation of an image.
|
||||
|
||||
@@ -114,18 +116,20 @@ def dilation(image, selem=None, out=None, shift_x=False, shift_y=False):
|
||||
|
||||
"""
|
||||
|
||||
# Default structure element
|
||||
if selem is None:
|
||||
selem = _default_selem(image.ndim)
|
||||
# If image has more than 2 dimensions, use scipy.ndimage
|
||||
if image.ndim > 2:
|
||||
return ndimage.morphology.grey_dilation(image, footprint=selem,out=out)
|
||||
|
||||
if image is out:
|
||||
raise NotImplementedError("In-place dilation not supported!")
|
||||
|
||||
image = img_as_ubyte(image)
|
||||
selem = img_as_ubyte(selem)
|
||||
return cmorph._dilate(image, selem, out=out,
|
||||
shift_x=shift_x, shift_y=shift_y)
|
||||
|
||||
|
||||
@default_fallback
|
||||
def opening(image, selem=None, out=None):
|
||||
"""Return greyscale morphological opening of an image.
|
||||
|
||||
@@ -169,10 +173,6 @@ def opening(image, selem=None, out=None):
|
||||
|
||||
"""
|
||||
|
||||
# Default structure element
|
||||
if selem is None:
|
||||
selem = _default_selem(image.ndim)
|
||||
|
||||
h, w = selem.shape
|
||||
shift_x = True if (w % 2) == 0 else False
|
||||
shift_y = True if (h % 2) == 0 else False
|
||||
@@ -182,6 +182,7 @@ def opening(image, selem=None, out=None):
|
||||
return out
|
||||
|
||||
|
||||
@default_fallback
|
||||
def closing(image, selem=None, out=None):
|
||||
"""Return greyscale morphological closing of an image.
|
||||
|
||||
@@ -225,10 +226,6 @@ def closing(image, selem=None, out=None):
|
||||
|
||||
"""
|
||||
|
||||
# Default structure element
|
||||
if selem is None:
|
||||
selem = _default_selem(image.ndim)
|
||||
|
||||
h, w = selem.shape
|
||||
shift_x = True if (w % 2) == 0 else False
|
||||
shift_y = True if (h % 2) == 0 else False
|
||||
@@ -238,6 +235,7 @@ def closing(image, selem=None, out=None):
|
||||
return out
|
||||
|
||||
|
||||
@default_fallback
|
||||
def white_tophat(image, selem=None, out=None):
|
||||
"""Return white top hat of an image.
|
||||
|
||||
@@ -280,10 +278,6 @@ def white_tophat(image, selem=None, out=None):
|
||||
|
||||
"""
|
||||
|
||||
# Default structure element
|
||||
if selem is None:
|
||||
selem = _default_selem(image.ndim)
|
||||
|
||||
if image is out:
|
||||
raise NotImplementedError("Cannot perform white top hat in place.")
|
||||
|
||||
@@ -292,6 +286,7 @@ def white_tophat(image, selem=None, out=None):
|
||||
return out
|
||||
|
||||
|
||||
@default_fallback
|
||||
def black_tophat(image, selem=None, out=None):
|
||||
"""Return black top hat of an image.
|
||||
|
||||
@@ -335,10 +330,6 @@ def black_tophat(image, selem=None, out=None):
|
||||
|
||||
"""
|
||||
|
||||
# Default structure element
|
||||
if selem is None:
|
||||
selem = _default_selem(image.ndim)
|
||||
|
||||
if image is out:
|
||||
raise NotImplementedError("Cannot perform white top hat in place.")
|
||||
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
import numpy as np
|
||||
import scipy.ndimage as nd
|
||||
from .selem import _default_selem
|
||||
|
||||
skimage2ndimage = {x: 'grey_' + x
|
||||
for x in ('erosion','dilation','opening','closing')}
|
||||
skimage2ndimage.update({x: x
|
||||
for x in ('binary_erosion','binary_dilation',
|
||||
'binary_opening','binary_closing',
|
||||
'black_tophat','white_tophat')})
|
||||
|
||||
|
||||
def default_fallback(func):
|
||||
def func_out(image, selem=None, out=None, **kwargs):
|
||||
# Default structure element
|
||||
if selem is None:
|
||||
selem = _default_selem(image.ndim)
|
||||
|
||||
# If image has more than 2 dimensions, use scipy.ndimage
|
||||
if image.ndim > 2:
|
||||
function = getattr(nd, skimage2ndimage[func.__name__])
|
||||
try:
|
||||
return function(image, footprint=selem, output=out, **kwargs)
|
||||
except TypeError:
|
||||
# nd.binary_* take structure instead of footprint
|
||||
return function(image, structure=selem, output=out, **kwargs)
|
||||
else:
|
||||
return func(image, selem=selem, out=out, **kwargs)
|
||||
|
||||
return func_out
|
||||
|
||||
|
||||
def remove_small_objects(ar, min_size=64, connectivity=1, in_place=False):
|
||||
|
||||
@@ -311,10 +311,3 @@ def _default_selem(ndim):
|
||||
|
||||
"""
|
||||
return ndimage.morphology.generate_binary_structure(ndim, 1)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -142,6 +142,30 @@ def test_default_selem():
|
||||
im_test = function(image)
|
||||
yield testing.assert_array_equal, im_expected, im_test
|
||||
|
||||
def test_3d_fallback_default_selem():
|
||||
# 3x3x3 cube inside a 7x7x7 image:
|
||||
image = np.zeros((7, 7, 7), np.bool)
|
||||
image[2:-2, 2:-2, 2:-2] = 1
|
||||
|
||||
opened = morphology.opening(image)
|
||||
|
||||
# expect a "hyper-cross" centered in the 5x5x5:
|
||||
image_expected = np.zeros((7, 7, 7), dtype=bool)
|
||||
image_expected[2:5, 2:5, 2:5] = ndimage.generate_binary_structure(3, 1)
|
||||
testing.assert_array_equal(opened, image_expected)
|
||||
|
||||
def test_3d_fallback_default_selem():
|
||||
# 3x3x3 cube inside a 7x7x7 image:
|
||||
image = np.zeros((7, 7, 7), np.bool)
|
||||
image[2:-2, 2:-2, 2:-2] = 1
|
||||
|
||||
cube = np.ones((3, 3, 3),dtype=np.uint8)
|
||||
|
||||
for function in [grey.closing, grey.opening]:
|
||||
new_image = function(image, cube)
|
||||
yield testing.assert_array_equal, new_image, image
|
||||
|
||||
|
||||
class TestDTypes():
|
||||
|
||||
def setUp(self):
|
||||
|
||||
Reference in New Issue
Block a user