Exemple #1
0
def resize(mask, output_shape):
    """Resize a mask to the requested output shape with nearest neighbors

    Parameters
    ----------
    mask : ndarray
        binary array
    output_shape : tuple
        requested shape

    Returns
    -------
    output_shape : tuple
        requested output shape


    TODO: It might be possible to combine this function with one of the transforms
    """
    assert_nD(mask, 2, 'mask')
    assert_binary(mask, 'mask')

    out = _resize(
        mask.astype(np.float), output_shape, order=0, mode='constant', cval=0,
        clip=True, preserve_range=False)

    return out.astype('uint8')
def random_rescale_2d(arr, zoom_perc):
    """Rescale an array in 2D.

    Parameters
    ----------
    arr : ndarray
        array to rescale
    zoom_percentage : float
        number between 0 and 1 to denote the percentage to scale

    Returns
    -------
    Randomly rescaled array of zoom_perc% and the selected zoom.
    """
    assert_nD(arr, 2)
    if zoom_perc < 0 or zoom_perc > 1:
        raise ValueError('zoom percentage should be in [0, 1]')

    zoom_range = 1 + zoom_perc
    if LooseVersion(__version__) < SKIMAGE_VERSION:
        raise RuntimeError('scikit-image >= %s needed for rescaling.' % SKIMAGE_VERSION)

    # scale to [2 - range, range]
    zoom = 2 - zoom_range + 2*(zoom_range - 1)*np.random.rand()
    arr = rescale(arr, zoom, anti_aliasing=True if zoom < 1 else False,
                  mode='constant', multichannel=False)
    return arr, zoom
def mask_to_coords(mask, get_contours=False):
    """Convert a mask to the coordinates of the centroids of each label.

    Parameters
    ----------
    mask : ndarray
        binary mask
    get_contours : bool
        if True, also output contours

    Returns
    -------
    centroids and optionally the coordinates.
    """
    assert_nD(mask, 2)
    assert_binary(mask)

    labels, num_labels = label(mask, background=0, return_num=True)
    regions = regionprops(labels, mask)

    # We can extract the contours as well, if we want.
    if get_contours:
        raise NotImplementedError(
            'Not Implemented. Use find_countours, mask is stored in `intensity_image` property.'
        )

    centroids = []
    for region in regions:
        centroids.append(region.centroid)

    return centroids
Exemple #4
0
def tpr(pred, gt, dist=1, mode='region'):
    """Compute the true positive rate of predictions ground truth (binary map). Both are lists of coordinates. If there is a point in the
    predictions list which is at most `dist` away from a point in the ground truth, this is counted as a true positive.

    If there are multiple ground truths, the result is the number of correct hits in the `region` mode, if the mode is `case` then the
    result is either 0 or 1, depending on if a region is matched or not.

    Parameters
    ----------
    pred : list or ndarray
        either a list of lists or a n x 2 ndarray.
    gt : list or ndarray
        either a list of lists or a n x 2 ndarray.
    dist : number
        distance between points which are considered as positives or negatives.
    mode : str
        either `region` or `case`.

    Returns
    -------
    float
    """
    pred = np.asarray(pred)
    gt = np.asarray(gt)

    if mode not in ['region', 'case']:
        raise ValueError('{} not a valid mode.'.format(mode))

    assert_nD(pred, 2, 'predictions')
    assert_nD(gt, 2, 'ground truth')
    assert pred.shape[1] == gt.shape[
        1], 'Both the predictions and ground truth should have the same dimensions.'

    if pred.shape[1] != 2:
        raise NotImplementedError(
            'Currently only 2D comparisons are available. If you wish to extend, '
            'take into account that the distance in the third dimension is often scaled because of a different resolution.'
        )

    hits = np.any(scipy.spatial.distance.cdist(pred, gt) <= dist,
                  axis=0).astype(np.float)
    if mode == 'region':
        tpr = hits.sum() / hits.size
    elif mode == 'case':
        tpr = float(hits.sum() > 0)

    return tpr
def random_rotate_2d(arr, angle_range):
    """Random rotate an array.

    Parameters
    ----------
    arr : ndarray
        array to zoom
    angle_range : int
        rotation range in degrees

    Returns
    -------
    Randomly rotated array between -angle_range and angle_range, and the randomly selected angle.

    """
    assert_nD(arr, 2)
    angle = np.random.randint(-angle_range, angle_range)
    arr = rotate(arr, angle, mode='constant')
    return arr, angle
Exemple #6
0
def add_2d_contours(mask, axes, linewidth=0.5, color='r'):
    """Plot the contours around the `1`'s in the mask

    Parameters
    ----------
    mask : ndarray
        2D binary array.
    axis : axis object
        matplotlib axis object.
    linewidth : float
        thickness of the overlay lines.
    color : str
        matplotlib supported color string for contour overlay.

    TODO: In utils.mask_utils we have function which computes one contour, perhaps these can be merged.
    """
    assert_nD(mask, 2, 'mask')
    assert_binary(mask, 'mask')
    contours = find_contours(mask, 0.5)

    for contour in contours:
        axes.plot(*(contour[:, [1, 0]].T), color=color, linewidth=linewidth)
Exemple #7
0
def add_2d_overlay(overlay,
                   ax,
                   linewidth,
                   threshold=0.1,
                   cmap='jet',
                   alpha=0.1,
                   closing_radius=15,
                   contour_color='g'):
    """Adds an overlay of the probability map and predicted regions

    overlay : ndarray
    ax : axis object
       matplotlib axis object
    linewidth : float
       thickness of the overlay lines;
    threshold : float
    cmap : str
       matplotlib supported cmap.
    alpha : float
       alpha values for the overlay.
    closing_radius : int
       radius for the postprocessing closing
    contour_color : str
       matplotlib supported color for the contour.

    """
    assert_nD(overlay, 2, 'overlay')
    assert_prob(overlay, 'overlay')
    if threshold:
        overlay = ma.masked_where(overlay < threshold, overlay)

    ax.imshow(overlay, cmap=cmap, alpha=alpha)

    if contour_color:
        mask = closing(overlay.copy(), disk(closing_radius))
        mask[mask < threshold] = 0
        mask[mask >= threshold] = 1
        add_2d_contours(mask, ax, linewidth=linewidth, color=contour_color)
def find_contour(mask, tolerance=0):
    """"""

    assert_nD(mask, 2)
    assert_binary(mask)

    contours = find_contours(mask, 0.5)
    if len(contours) != 1:
        raise ValueError('To find the contour, the mask cannot have holes.')

    contour = contours[0]

    # Check if contour is closed
    if np.all(contour[0] == contour[-1]):
        return contour

    # Otherwise we close the contour
    # Check if mask is to the left or right
    point_0 = contour[0]
    point_1 = contour[1]
    point_end = contour[-1]

    diff = point_1 - point_0
    is_left = diff[0] > 0

    # If mask is left, connect first point along a straight line to the edge
    if is_left:
        new_start = np.array([point_0[0], 0])
        new_end = np.array([point_end[0], 0])
    else:
        new_start = np.array([point_0[0], mask.shape[1] - 1])
        new_end = np.array([point_end[0], mask.shape[1] - 1])

    contour = np.vstack([new_start, contour, new_end, new_start])
    contour = approximate_polygon(contour, tolerance)

    return contour
Exemple #9
0
def bounding_box(mask):
    """Compute the bounding box for a given binary mask, and the center of mass

    Parameters
    ----------
    mask : ndarray
        binary array

    Returns
    -------
    List of ((col, row, height, width), (col, row)) tuples.
    """
    assert_nD(mask, 2, 'mask')
    assert_binary(mask, 'mask')

    regions = regionprops(label(mask))
    bboxes = []
    for region in regions:
        center_of_mass = map(int, region.centroid)
        bbox_ = np.array(region.bbox).astype(np.int)
        bbox = np.concatenate([bbox_[:2], bbox_[2:] - bbox_[:2]]).tolist()
        bboxes.append((bbox, center_of_mass))

    return bboxes