Fixed database typo and removed unnecessary class identifier.
This commit is contained in:
		
							parent
							
								
									00ad49a143
								
							
						
					
					
						commit
						45fb349a7d
					
				
					 5098 changed files with 952558 additions and 85 deletions
				
			
		
							
								
								
									
										230
									
								
								venv/Lib/site-packages/skimage/segmentation/boundaries.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								venv/Lib/site-packages/skimage/segmentation/boundaries.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,230 @@
 | 
			
		|||
 | 
			
		||||
import numpy as np
 | 
			
		||||
from scipy import ndimage as ndi
 | 
			
		||||
from ..morphology import dilation, erosion, square
 | 
			
		||||
from ..util import img_as_float, view_as_windows
 | 
			
		||||
from ..color import gray2rgb
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _find_boundaries_subpixel(label_img):
 | 
			
		||||
    """See ``find_boundaries(..., mode='subpixel')``.
 | 
			
		||||
 | 
			
		||||
    Notes
 | 
			
		||||
    -----
 | 
			
		||||
    This function puts in an empty row and column between each *actual*
 | 
			
		||||
    row and column of the image, for a corresponding shape of ``2s - 1``
 | 
			
		||||
    for every image dimension of size ``s``. These "interstitial" rows
 | 
			
		||||
    and columns are filled as ``True`` if they separate two labels in
 | 
			
		||||
    `label_img`, ``False`` otherwise.
 | 
			
		||||
 | 
			
		||||
    I used ``view_as_windows`` to get the neighborhood of each pixel.
 | 
			
		||||
    Then I check whether there are two labels or more in that
 | 
			
		||||
    neighborhood.
 | 
			
		||||
    """
 | 
			
		||||
    ndim = label_img.ndim
 | 
			
		||||
    max_label = np.iinfo(label_img.dtype).max
 | 
			
		||||
 | 
			
		||||
    label_img_expanded = np.zeros([(2 * s - 1) for s in label_img.shape],
 | 
			
		||||
                                  label_img.dtype)
 | 
			
		||||
    pixels = (slice(None, None, 2), ) * ndim
 | 
			
		||||
    label_img_expanded[pixels] = label_img
 | 
			
		||||
 | 
			
		||||
    edges = np.ones(label_img_expanded.shape, dtype=bool)
 | 
			
		||||
    edges[pixels] = False
 | 
			
		||||
    label_img_expanded[edges] = max_label
 | 
			
		||||
    windows = view_as_windows(np.pad(label_img_expanded, 1,
 | 
			
		||||
                                     mode='constant', constant_values=0),
 | 
			
		||||
                              (3,) * ndim)
 | 
			
		||||
 | 
			
		||||
    boundaries = np.zeros_like(edges)
 | 
			
		||||
    for index in np.ndindex(label_img_expanded.shape):
 | 
			
		||||
        if edges[index]:
 | 
			
		||||
            values = np.unique(windows[index].ravel())
 | 
			
		||||
            if len(values) > 2:  # single value and max_label
 | 
			
		||||
                boundaries[index] = True
 | 
			
		||||
    return boundaries
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def find_boundaries(label_img, connectivity=1, mode='thick', background=0):
 | 
			
		||||
    """Return bool array where boundaries between labeled regions are True.
 | 
			
		||||
 | 
			
		||||
    Parameters
 | 
			
		||||
    ----------
 | 
			
		||||
    label_img : array of int or bool
 | 
			
		||||
        An array in which different regions are labeled with either different
 | 
			
		||||
        integers or boolean values.
 | 
			
		||||
    connectivity : int in {1, ..., `label_img.ndim`}, optional
 | 
			
		||||
        A pixel is considered a boundary pixel if any of its neighbors
 | 
			
		||||
        has a different label. `connectivity` controls which pixels are
 | 
			
		||||
        considered neighbors. A connectivity of 1 (default) means
 | 
			
		||||
        pixels sharing an edge (in 2D) or a face (in 3D) will be
 | 
			
		||||
        considered neighbors. A connectivity of `label_img.ndim` means
 | 
			
		||||
        pixels sharing a corner will be considered neighbors.
 | 
			
		||||
    mode : string in {'thick', 'inner', 'outer', 'subpixel'}
 | 
			
		||||
        How to mark the boundaries:
 | 
			
		||||
 | 
			
		||||
        - thick: any pixel not completely surrounded by pixels of the
 | 
			
		||||
          same label (defined by `connectivity`) is marked as a boundary.
 | 
			
		||||
          This results in boundaries that are 2 pixels thick.
 | 
			
		||||
        - inner: outline the pixels *just inside* of objects, leaving
 | 
			
		||||
          background pixels untouched.
 | 
			
		||||
        - outer: outline pixels in the background around object
 | 
			
		||||
          boundaries. When two objects touch, their boundary is also
 | 
			
		||||
          marked.
 | 
			
		||||
        - subpixel: return a doubled image, with pixels *between* the
 | 
			
		||||
          original pixels marked as boundary where appropriate.
 | 
			
		||||
    background : int, optional
 | 
			
		||||
        For modes 'inner' and 'outer', a definition of a background
 | 
			
		||||
        label is required. See `mode` for descriptions of these two.
 | 
			
		||||
 | 
			
		||||
    Returns
 | 
			
		||||
    -------
 | 
			
		||||
    boundaries : array of bool, same shape as `label_img`
 | 
			
		||||
        A bool image where ``True`` represents a boundary pixel. For
 | 
			
		||||
        `mode` equal to 'subpixel', ``boundaries.shape[i]`` is equal
 | 
			
		||||
        to ``2 * label_img.shape[i] - 1`` for all ``i`` (a pixel is
 | 
			
		||||
        inserted in between all other pairs of pixels).
 | 
			
		||||
 | 
			
		||||
    Examples
 | 
			
		||||
    --------
 | 
			
		||||
    >>> labels = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 | 
			
		||||
    ...                    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 | 
			
		||||
    ...                    [0, 0, 0, 0, 0, 5, 5, 5, 0, 0],
 | 
			
		||||
    ...                    [0, 0, 1, 1, 1, 5, 5, 5, 0, 0],
 | 
			
		||||
    ...                    [0, 0, 1, 1, 1, 5, 5, 5, 0, 0],
 | 
			
		||||
    ...                    [0, 0, 1, 1, 1, 5, 5, 5, 0, 0],
 | 
			
		||||
    ...                    [0, 0, 0, 0, 0, 5, 5, 5, 0, 0],
 | 
			
		||||
    ...                    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 | 
			
		||||
    ...                    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=np.uint8)
 | 
			
		||||
    >>> find_boundaries(labels, mode='thick').astype(np.uint8)
 | 
			
		||||
    array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 | 
			
		||||
           [0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
 | 
			
		||||
           [0, 0, 1, 1, 1, 1, 1, 1, 1, 0],
 | 
			
		||||
           [0, 1, 1, 1, 1, 1, 0, 1, 1, 0],
 | 
			
		||||
           [0, 1, 1, 0, 1, 1, 0, 1, 1, 0],
 | 
			
		||||
           [0, 1, 1, 1, 1, 1, 0, 1, 1, 0],
 | 
			
		||||
           [0, 0, 1, 1, 1, 1, 1, 1, 1, 0],
 | 
			
		||||
           [0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
 | 
			
		||||
           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8)
 | 
			
		||||
    >>> find_boundaries(labels, mode='inner').astype(np.uint8)
 | 
			
		||||
    array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 | 
			
		||||
           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 | 
			
		||||
           [0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
 | 
			
		||||
           [0, 0, 1, 1, 1, 1, 0, 1, 0, 0],
 | 
			
		||||
           [0, 0, 1, 0, 1, 1, 0, 1, 0, 0],
 | 
			
		||||
           [0, 0, 1, 1, 1, 1, 0, 1, 0, 0],
 | 
			
		||||
           [0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
 | 
			
		||||
           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 | 
			
		||||
           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8)
 | 
			
		||||
    >>> find_boundaries(labels, mode='outer').astype(np.uint8)
 | 
			
		||||
    array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 | 
			
		||||
           [0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
 | 
			
		||||
           [0, 0, 1, 1, 1, 1, 0, 0, 1, 0],
 | 
			
		||||
           [0, 1, 0, 0, 1, 1, 0, 0, 1, 0],
 | 
			
		||||
           [0, 1, 0, 0, 1, 1, 0, 0, 1, 0],
 | 
			
		||||
           [0, 1, 0, 0, 1, 1, 0, 0, 1, 0],
 | 
			
		||||
           [0, 0, 1, 1, 1, 1, 0, 0, 1, 0],
 | 
			
		||||
           [0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
 | 
			
		||||
           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8)
 | 
			
		||||
    >>> labels_small = labels[::2, ::3]
 | 
			
		||||
    >>> labels_small
 | 
			
		||||
    array([[0, 0, 0, 0],
 | 
			
		||||
           [0, 0, 5, 0],
 | 
			
		||||
           [0, 1, 5, 0],
 | 
			
		||||
           [0, 0, 5, 0],
 | 
			
		||||
           [0, 0, 0, 0]], dtype=uint8)
 | 
			
		||||
    >>> find_boundaries(labels_small, mode='subpixel').astype(np.uint8)
 | 
			
		||||
    array([[0, 0, 0, 0, 0, 0, 0],
 | 
			
		||||
           [0, 0, 0, 1, 1, 1, 0],
 | 
			
		||||
           [0, 0, 0, 1, 0, 1, 0],
 | 
			
		||||
           [0, 1, 1, 1, 0, 1, 0],
 | 
			
		||||
           [0, 1, 0, 1, 0, 1, 0],
 | 
			
		||||
           [0, 1, 1, 1, 0, 1, 0],
 | 
			
		||||
           [0, 0, 0, 1, 0, 1, 0],
 | 
			
		||||
           [0, 0, 0, 1, 1, 1, 0],
 | 
			
		||||
           [0, 0, 0, 0, 0, 0, 0]], dtype=uint8)
 | 
			
		||||
    >>> bool_image = np.array([[False, False, False, False, False],
 | 
			
		||||
    ...                        [False, False, False, False, False],
 | 
			
		||||
    ...                        [False, False,  True,  True,  True],
 | 
			
		||||
    ...                        [False, False,  True,  True,  True],
 | 
			
		||||
    ...                        [False, False,  True,  True,  True]], dtype=np.bool)
 | 
			
		||||
    >>> find_boundaries(bool_image)
 | 
			
		||||
    array([[False, False, False, False, False],
 | 
			
		||||
           [False, False,  True,  True,  True],
 | 
			
		||||
           [False,  True,  True,  True,  True],
 | 
			
		||||
           [False,  True,  True, False, False],
 | 
			
		||||
           [False,  True,  True, False, False]])
 | 
			
		||||
    """
 | 
			
		||||
    if label_img.dtype == 'bool':
 | 
			
		||||
        label_img = label_img.astype(np.uint8)
 | 
			
		||||
    ndim = label_img.ndim
 | 
			
		||||
    selem = ndi.generate_binary_structure(ndim, connectivity)
 | 
			
		||||
    if mode != 'subpixel':
 | 
			
		||||
        boundaries = dilation(label_img, selem) != erosion(label_img, selem)
 | 
			
		||||
        if mode == 'inner':
 | 
			
		||||
            foreground_image = (label_img != background)
 | 
			
		||||
            boundaries &= foreground_image
 | 
			
		||||
        elif mode == 'outer':
 | 
			
		||||
            max_label = np.iinfo(label_img.dtype).max
 | 
			
		||||
            background_image = (label_img == background)
 | 
			
		||||
            selem = ndi.generate_binary_structure(ndim, ndim)
 | 
			
		||||
            inverted_background = np.array(label_img, copy=True)
 | 
			
		||||
            inverted_background[background_image] = max_label
 | 
			
		||||
            adjacent_objects = ((dilation(label_img, selem) !=
 | 
			
		||||
                                 erosion(inverted_background, selem)) &
 | 
			
		||||
                                ~background_image)
 | 
			
		||||
            boundaries &= (background_image | adjacent_objects)
 | 
			
		||||
        return boundaries
 | 
			
		||||
    else:
 | 
			
		||||
        boundaries = _find_boundaries_subpixel(label_img)
 | 
			
		||||
        return boundaries
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def mark_boundaries(image, label_img, color=(1, 1, 0),
 | 
			
		||||
                    outline_color=None, mode='outer', background_label=0):
 | 
			
		||||
    """Return image with boundaries between labeled regions highlighted.
 | 
			
		||||
 | 
			
		||||
    Parameters
 | 
			
		||||
    ----------
 | 
			
		||||
    image : (M, N[, 3]) array
 | 
			
		||||
        Grayscale or RGB image.
 | 
			
		||||
    label_img : (M, N) array of int
 | 
			
		||||
        Label array where regions are marked by different integer values.
 | 
			
		||||
    color : length-3 sequence, optional
 | 
			
		||||
        RGB color of boundaries in the output image.
 | 
			
		||||
    outline_color : length-3 sequence, optional
 | 
			
		||||
        RGB color surrounding boundaries in the output image. If None, no
 | 
			
		||||
        outline is drawn.
 | 
			
		||||
    mode : string in {'thick', 'inner', 'outer', 'subpixel'}, optional
 | 
			
		||||
        The mode for finding boundaries.
 | 
			
		||||
    background_label : int, optional
 | 
			
		||||
        Which label to consider background (this is only useful for
 | 
			
		||||
        modes ``inner`` and ``outer``).
 | 
			
		||||
 | 
			
		||||
    Returns
 | 
			
		||||
    -------
 | 
			
		||||
    marked : (M, N, 3) array of float
 | 
			
		||||
        An image in which the boundaries between labels are
 | 
			
		||||
        superimposed on the original image.
 | 
			
		||||
 | 
			
		||||
    See Also
 | 
			
		||||
    --------
 | 
			
		||||
    find_boundaries
 | 
			
		||||
    """
 | 
			
		||||
    marked = img_as_float(image, force_copy=True)
 | 
			
		||||
    if marked.ndim == 2:
 | 
			
		||||
        marked = gray2rgb(marked)
 | 
			
		||||
    if mode == 'subpixel':
 | 
			
		||||
        # Here, we want to interpose an extra line of pixels between
 | 
			
		||||
        # each original line - except for the last axis which holds
 | 
			
		||||
        # the RGB information. ``ndi.zoom`` then performs the (cubic)
 | 
			
		||||
        # interpolation, filling in the values of the interposed pixels
 | 
			
		||||
        marked = ndi.zoom(marked, [2 - 1/s for s in marked.shape[:-1]] + [1],
 | 
			
		||||
                          mode='reflect')
 | 
			
		||||
    boundaries = find_boundaries(label_img, mode=mode,
 | 
			
		||||
                                 background=background_label)
 | 
			
		||||
    if outline_color is not None:
 | 
			
		||||
        outlines = dilation(boundaries, square(3))
 | 
			
		||||
        marked[outlines] = outline_color
 | 
			
		||||
    marked[boundaries] = color
 | 
			
		||||
    return marked
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue