mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-01 03:25:41 +08:00
Merge pull request #558 from chintak/convex_hull
FEAT: Function to compute separate convex hulls for unconnected objects
This commit is contained in:
@@ -8,7 +8,7 @@ from .selem import square, rectangle, diamond, disk, cube, octahedron, ball
|
||||
from .ccomp import label
|
||||
from .watershed import watershed, is_local_maximum
|
||||
from ._skeletonize import skeletonize, medial_axis
|
||||
from .convex_hull import convex_hull_image
|
||||
from .convex_hull import convex_hull_image, convex_hull_object
|
||||
from .greyreconstruct import reconstruction
|
||||
from .misc import remove_small_objects
|
||||
|
||||
@@ -42,5 +42,6 @@ __all__ = ['binary_erosion',
|
||||
'skeletonize',
|
||||
'medial_axis',
|
||||
'convex_hull_image',
|
||||
'convex_hull_object',
|
||||
'reconstruction',
|
||||
'remove_small_objects']
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
__all__ = ['convex_hull_image']
|
||||
__all__ = ['convex_hull_image', 'convex_hull_object']
|
||||
|
||||
import numpy as np
|
||||
from ._pnpoly import grid_points_inside_poly
|
||||
from ._convex_hull import possible_hull
|
||||
from skimage.morphology import label
|
||||
|
||||
|
||||
def convex_hull_image(image):
|
||||
@@ -14,12 +15,12 @@ def convex_hull_image(image):
|
||||
Parameters
|
||||
----------
|
||||
image : ndarray
|
||||
Binary input image. This array is cast to bool before processing.
|
||||
Binary input image. This array is cast to bool before processing.
|
||||
|
||||
Returns
|
||||
-------
|
||||
hull : ndarray of uint8
|
||||
Binary image with pixels in convex hull set to 255.
|
||||
hull : ndarray of bool
|
||||
Binary image with pixels in convex hull set to True.
|
||||
|
||||
References
|
||||
----------
|
||||
@@ -64,3 +65,45 @@ def convex_hull_image(image):
|
||||
mask = grid_points_inside_poly(image.shape[:2], v)
|
||||
|
||||
return mask
|
||||
|
||||
|
||||
def convex_hull_object(image, neighbors=8):
|
||||
"""Compute the convex hull image of individual objects in a binary image.
|
||||
|
||||
The convex hull is the set of pixels included in the smallest convex
|
||||
polygon that surround all white pixels in the input image.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : ndarray
|
||||
Binary input image.
|
||||
neighbors : {4, 8}, int
|
||||
Whether to use 4- or 8-connectivity.
|
||||
|
||||
Returns
|
||||
-------
|
||||
hull : ndarray of bool
|
||||
Binary image with pixels in convex hull set to True.
|
||||
|
||||
Note
|
||||
----
|
||||
This function uses skimage.morphology.label to define unique objects,
|
||||
finds the convex hull of each using convex_hull_image, and combines
|
||||
these regions with logical OR. Be aware the convex hulls of unconnected
|
||||
objects may overlap in the result. If this is suspected, consider using
|
||||
convex_hull_image separately on each object.
|
||||
|
||||
"""
|
||||
|
||||
if neighbors != 4 and neighbors != 8:
|
||||
raise ValueError('Neighbors must be either 4 or 8.')
|
||||
|
||||
labeled_im = label(image, neighbors, background=0)
|
||||
convex_obj = np.zeros(image.shape, dtype=bool)
|
||||
convex_img = np.zeros(image.shape, dtype=bool)
|
||||
|
||||
for i in range(0, labeled_im.max() + 1):
|
||||
convex_obj = convex_hull_image(labeled_im == i)
|
||||
convex_img = np.logical_or(convex_img, convex_obj)
|
||||
|
||||
return convex_img
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import numpy as np
|
||||
from numpy.testing import assert_array_equal
|
||||
from numpy.testing import assert_array_equal, assert_raises
|
||||
from numpy.testing.decorators import skipif
|
||||
from skimage.morphology import convex_hull_image
|
||||
from skimage.morphology import convex_hull_image, convex_hull_object
|
||||
from skimage.morphology._convex_hull import possible_hull
|
||||
|
||||
try:
|
||||
@@ -65,5 +65,47 @@ def test_possible_hull():
|
||||
ph = possible_hull(image)
|
||||
assert_array_equal(ph, expected)
|
||||
|
||||
|
||||
@skipif(not scipy_spatial)
|
||||
def test_object():
|
||||
image = np.array(
|
||||
[[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 1, 1, 1, 0, 0, 1, 0, 1],
|
||||
[1, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||
[1, 0, 0, 0, 0, 0, 1, 0, 1],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=bool)
|
||||
|
||||
expected4 = np.array(
|
||||
[[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 1, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 1, 1, 0, 0, 0, 0, 0, 0],
|
||||
[1, 1, 1, 1, 0, 0, 1, 0, 1],
|
||||
[1, 1, 1, 0, 0, 0, 0, 1, 0],
|
||||
[1, 1, 0, 0, 0, 0, 1, 0, 1],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=bool)
|
||||
|
||||
assert_array_equal(convex_hull_object(image, 4), expected4)
|
||||
|
||||
expected8 = np.array(
|
||||
[[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 1, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 1, 1, 0, 0, 0, 0, 0, 0],
|
||||
[1, 1, 1, 1, 0, 0, 1, 1, 1],
|
||||
[1, 1, 1, 0, 0, 0, 1, 1, 1],
|
||||
[1, 1, 0, 0, 0, 0, 1, 1, 1],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=bool)
|
||||
|
||||
assert_array_equal(convex_hull_object(image, 8), expected8)
|
||||
|
||||
assert_raises(ValueError, convex_hull_object, image, 7)
|
||||
|
||||
if __name__ == "__main__":
|
||||
np.testing.run_module_suite()
|
||||
|
||||
Reference in New Issue
Block a user