Exemple #1
0
def non_traversing_segments(a):
    """Find segments that enter the volume but do not leave it elsewhere.

    Parameters
    ----------
    a : array of int
        A segmented volume.

    Returns
    -------
    nt : 1D array of int
        The IDs of any segments not traversing the volume.

    Examples
    --------
    >>> segs = np.array([[1, 2, 3, 3, 4],
    ...                  [1, 2, 2, 3, 4],
    ...                  [1, 5, 5, 3, 4],
    ...                  [1, 1, 5, 3, 4]], int)
    >>> non_traversing_segments(segs)
    array([1, 2, 4, 5])
    """
    surface = hollowed(a)
    surface_ccs = measure.label(surface) + 1
    surface_ccs[surface == 0] = 0
    idxs = flatnonzero(surface)
    pairs = np.array(
        list(zip(surface.ravel()[idxs],
                 surface_ccs.ravel()[idxs])))
    unique_pairs = util.unique_rows(pairs)
    surface_singles = np.bincount(unique_pairs[:, 0]) == 1
    nt = np.flatnonzero(surface_singles)
    return nt
Exemple #2
0
def non_traversing_segments(a):
    """Find segments that enter the volume but do not leave it elsewhere.

    Parameters
    ----------
    a : array of int
        A segmented volume.

    Returns
    -------
    nt : 1D array of int
        The IDs of any segments not traversing the volume.

    Examples
    --------
    >>> segs = np.array([[1, 2, 3, 3, 4],
    ...                  [1, 2, 2, 3, 4],
    ...                  [1, 5, 5, 3, 4],
    ...                  [1, 1, 5, 3, 4]], int)
    >>> non_traversing_segments(segs)
    array([1, 2, 4, 5])
    """
    surface = hollowed(a)
    surface_ccs = measure.label(surface) + 1
    surface_ccs[surface == 0] = 0
    idxs = flatnonzero(surface)
    pairs = np.array(list(zip(surface.ravel()[idxs],
                              surface_ccs.ravel()[idxs])))
    unique_pairs = util.unique_rows(pairs)
    surface_singles = np.bincount(unique_pairs[:, 0]) == 1
    nt = np.flatnonzero(surface_singles)
    return nt
def nuclei_per_cell_histogram(nuc_im, cell_im, max_value=10):
    """Compute the histogram of nucleus count per cell object.

    Counts above or below max_value and min_value are clipped.

    Parameters
    ----------
    nuc_im : array of bool or int
        An image of nucleus objects, binary or labelled.
    cell_im : array of bool or int
        An image of cell objects, binary or labelled.
    max_value : int, optional
        The highest nucleus count we expect. Anything above this will
        be clipped to ``max_value + 1``.

    Returns
    -------
    fs : array of float, shape ``(max_value - min_value + 2,)``.
        The proportion of cells with each nucleus counts.
    names : list of string, same length as fs
        The name of each feature.
    """
    names = [('cells-with-%i-nuclei' % n) for n in range(max_value + 1)]
    names.append('cells-with->%i-nuclei' % max_value)
    nuc_lab = nd.label(nuc_im)[0]
    cell_lab = nd.label(cell_im)[0]
    match = np.vstack((nuc_lab.ravel(), cell_lab.ravel())).T
    match = match[(match.sum(axis=1) != 0), :]
    match = util.unique_rows(match).astype(np.int64)
    # number of nuclei in each cell
    cells = np.bincount(match[:, 1])
    # number of cells with x nuclei
    nhist = np.bincount(cells, minlength=max_value + 2)
    total = np.sum(nhist)
    fs = np.zeros((max_value + 2), np.float)
    fs[:(max_value + 1)] = nhist[:(max_value + 1)]
    fs[max_value + 1] = np.sum(nhist[(max_value + 1):])
    fs /= total
    return fs, names
Exemple #4
0
def nuclei_per_cell_histogram(nuc_im, cell_im, max_value=10):
    """Compute the histogram of nucleus count per cell object.

    Counts above or below max_value and min_value are clipped.

    Parameters
    ----------
    nuc_im : array of bool or int
        An image of nucleus objects, binary or labelled.
    cell_im : array of bool or int
        An image of cell objects, binary or labelled.
    max_value : int, optional
        The highest nucleus count we expect. Anything above this will
        be clipped to ``max_value + 1``.

    Returns
    -------
    fs : array of float, shape ``(max_value - min_value + 2,)``.
        The proportion of cells with each nucleus counts.
    names : list of string, same length as fs
        The name of each feature.
    """
    names = [('cells-with-%i-nuclei' % n) for n in range(max_value + 1)]
    names.append('cells-with->%i-nuclei' % max_value)
    nuc_lab = nd.label(nuc_im)[0]
    cell_lab = nd.label(cell_im)[0]
    match = np.vstack((nuc_lab.ravel(), cell_lab.ravel())).T
    match = match[(match.sum(axis=1) != 0), :]
    match = util.unique_rows(match).astype(np.int64)
    # number of nuclei in each cell
    cells = np.bincount(match[:, 1])
    # number of cells with x nuclei
    nhist = np.bincount(cells, minlength=max_value + 2)
    total = np.sum(nhist)
    fs = np.zeros((max_value + 2), np.float)
    fs[:(max_value + 1)] = nhist[:(max_value + 1)]
    fs[max_value + 1] = np.sum(nhist[(max_value + 1):])
    fs /= total
    return fs, names
Exemple #5
0
def test_discontiguous_array():
    ar = np.array([[1, 0, 1], [0, 1, 0], [1, 0, 1]], np.uint8)
    ar = ar[::2]
    ar_out = unique_rows(ar)
    desired_ar_out = np.array([[1, 0, 1]], np.uint8)
    assert_equal(ar_out, desired_ar_out)
Exemple #6
0
def test_float_array():
    ar = np.array([[1.1, 0.0, 1.1], [0.0, 1.1, 0.0], [1.1, 0.0, 1.1]],
                  np.float)
    ar_out = unique_rows(ar)
    desired_ar_out = np.array([[0.0, 1.1, 0.0], [1.1, 0.0, 1.1]], np.float)
    assert_equal(ar_out, desired_ar_out)
Exemple #7
0
def test_uint8_array():
    ar = np.array([[1, 0, 1], [0, 1, 0], [1, 0, 1]], np.uint8)
    ar_out = unique_rows(ar)
    desired_ar_out = np.array([[0, 1, 0], [1, 0, 1]], np.uint8)
    assert_equal(ar_out, desired_ar_out)
Exemple #8
0
def convex_hull_image(image):
    """Compute the convex hull image of 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. This array is cast to bool before processing.

    Returns
    -------
    hull : ndarray of bool
        Binary image with pixels in convex hull set to True.

    References
    ----------
    .. [1] http://blogs.mathworks.com/steve/2011/10/04/binary-image-convex-hull-algorithm-notes/

    """

    image = image.astype(bool)

    # Here we do an optimisation by choosing only pixels that are
    # the starting or ending pixel of a row or column.  This vastly
    # limits the number of coordinates to examine for the virtual
    # hull.
    coords = possible_hull(image.astype(np.uint8))
    N = len(coords)

    # Add a vertex for the middle of each pixel edge
    coords_corners = np.empty((N * 4, 2))
    for i, (x_offset,
            y_offset) in enumerate(zip((0, 0, -0.5, 0.5), (-0.5, 0.5, 0, 0))):
        coords_corners[i * N:(i + 1) * N] = coords + [x_offset, y_offset]

    # repeated coordinates can *sometimes* cause problems in
    # scipy.spatial.Delaunay, so we remove them.
    coords = unique_rows(coords_corners)

    try:
        from scipy.spatial import Delaunay
    except ImportError:
        raise ImportError('Could not import scipy.spatial, only available in '
                          'scipy >= 0.9.')

    # Find the convex hull
    chull = Delaunay(coords).convex_hull
    v = coords[np.unique(chull)]

    # Sort vertices clock-wise
    v_centred = v - v.mean(axis=0)
    angles = np.arctan2(v_centred[:, 0], v_centred[:, 1])
    v = v[np.argsort(angles)]

    # For each pixel coordinate, check whether that pixel
    # lies inside the convex hull
    mask = grid_points_inside_poly(image.shape[:2], v)

    return mask
def convex_hull_image(image):
    """Compute the convex hull image of 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. This array is cast to bool before processing.

    Returns
    -------
    hull : ndarray of bool
        Binary image with pixels in convex hull set to True.

    References
    ----------
    .. [1] http://blogs.mathworks.com/steve/2011/10/04/binary-image-convex-hull-algorithm-notes/

    """

    image = image.astype(bool)

    # Here we do an optimisation by choosing only pixels that are
    # the starting or ending pixel of a row or column.  This vastly
    # limits the number of coordinates to examine for the virtual
    # hull.
    coords = possible_hull(image.astype(np.uint8))
    N = len(coords)

    # Add a vertex for the middle of each pixel edge
    coords_corners = np.empty((N * 4, 2))
    for i, (x_offset, y_offset) in enumerate(zip((0, 0, -0.5, 0.5),
                                                 (-0.5, 0.5, 0, 0))):
        coords_corners[i * N:(i + 1) * N] = coords + [x_offset, y_offset]

    # repeated coordinates can *sometimes* cause problems in
    # scipy.spatial.Delaunay, so we remove them.
    coords = unique_rows(coords_corners)

    try:
        from scipy.spatial import Delaunay
    except ImportError:
        raise ImportError('Could not import scipy.spatial, only available in '
                          'scipy >= 0.9.')

    # Subtract offset
    offset = coords.mean(axis=0)
    coords -= offset

    # Find the convex hull
    chull = Delaunay(coords).convex_hull
    v = coords[np.unique(chull)]

    # Sort vertices clock-wise
    v_centred = v - v.mean(axis=0)
    angles = np.arctan2(v_centred[:, 0], v_centred[:, 1])
    v = v[np.argsort(angles)]

    # Add back offset
    v += offset

    # For each pixel coordinate, check whether that pixel
    # lies inside the convex hull
    mask = grid_points_inside_poly(image.shape[:2], v)

    return mask
Exemple #10
0
def test_3d_array():
    ar = np.arange(8).reshape((2, 2, 2))
    with pytest.raises(ValueError):
        unique_rows(ar)
Exemple #11
0
def test_1d_array():
    ar = np.array([1, 0, 1, 1], np.uint8)
    with pytest.raises(ValueError):
        unique_rows(ar)
def test_3d_array():
    ar = np.arange(8).reshape((2, 2, 2))
    with testing.raises(ValueError):
        unique_rows(ar)
def test_1d_array():
    ar = np.array([1, 0, 1, 1], np.uint8)
    with testing.raises(ValueError):
        unique_rows(ar)