Merge pull request #558 from chintak/convex_hull

FEAT: Function to compute separate convex hulls for unconnected objects
This commit is contained in:
Josh Warner
2013-05-28 22:37:11 -07:00
3 changed files with 93 additions and 7 deletions
+2 -1
View File
@@ -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']
+47 -4
View File
@@ -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
+44 -2
View File
@@ -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()