Ejemplo n.º 1
0
def find_initial_worm(small_image, well_mask):
    # plan here is to find known good worm edges with Canny using a stringent threshold, then
    # relax the threshold in the vicinity of the good edges.
    # back off another pixel from the well edge to avoid gradient from the edge
    shrunk_mask = ndimage.binary_erosion(well_mask, structure=S)
    smoothed, gradient, sobel = canny.prepare_canny(small_image, 2, shrunk_mask)
    local_maxima = canny.canny_local_maxima(gradient, sobel)
    # Calculate stringent and medium-stringent thresholds. The stringent threshold
    # is the 200th-brightest edge pixel, and the medium is the 450th-brightest pixel
    highp = 100 * (1-200/local_maxima.sum())
    highp = max(highp, 94)
    mediump = 100 * (1-450/local_maxima.sum())
    mediump = max(mediump, 94)
    low_worm, medium_worm, high_worm = numpy.percentile(gradient[local_maxima], [94, mediump, highp])
    stringent_worm = canny.canny_hysteresis(local_maxima, gradient, low_worm, high_worm)
    # Expand out 20 pixels from the stringent worm edges to make our search space
    stringent_area = ndimage.binary_dilation(stringent_worm, mask=well_mask, iterations=20)
    # now use the relaxed threshold but only in the stringent area
    relaxed_worm = canny.canny_hysteresis(local_maxima, gradient, low_worm, medium_worm) & stringent_area
    # join very close-by objects, and remove remaining small objects
    candidate_worm = ndimage.binary_dilation(relaxed_worm, structure=S)
    candidate_worm = ndimage.binary_erosion(candidate_worm)
    candidate_worm = mask.remove_small_area_objects(candidate_worm, 30, structure=S)
    # Now figure out the biggest blob of nearby edges, and call that the worm region
    glommed_candidate = ndimage.binary_dilation(candidate_worm, structure=S, iterations=2)
    glommed_candidate = ndimage.binary_erosion(glommed_candidate, iterations=2)
    # get just outline, not any regions filled-in due to closing
    glommed_candidate ^= ndimage.binary_erosion(glommed_candidate)
    glommed_candidate = mask.get_largest_object(glommed_candidate, structure=S)
    worm_area = ndimage.binary_dilation(glommed_candidate, mask=well_mask, structure=S, iterations=12)
    worm_area = mask.fill_small_radius_holes(worm_area, max_radius=15)
    candidate_edges = relaxed_worm & candidate_worm & worm_area
    return candidate_edges, worm_area
Ejemplo n.º 2
0
def get_well_mask(image):
    small_image = pyramid.pyr_down(image, 4)
    smoothed, gradient, sobel = canny.prepare_canny(small_image, 2)
    local_maxima = canny.canny_local_maxima(gradient, sobel)
    # well outline has ~6000 px full-size = 1500 px at 4x downsampled
    # So find the intensity value of the 2000th-brightest pixel, via percentile:
    highp = 100 * (1-2000/local_maxima.sum())
    highp = max(highp, 90)
    low_edge, high_edge = numpy.percentile(gradient[local_maxima], [90, highp])
    # Do canny edge-finding starting with gradient pixels as bright or brighter
    # than the 2000th-brightest pixel, and spread out to the 90th percentile
    # intensity:
    well_edge = canny.canny_hysteresis(local_maxima, gradient, low_edge, high_edge)
    # connect nearby edges and remove small unconnected bits
    well_edge = ndimage.binary_closing(well_edge, structure=S)
    well_edge = mask.remove_small_area_objects(well_edge, 300, structure=S)
    # Get map of distances and directions to nearest edge to use for contour-fitting
    distances, nearest_edge = active_contour.edge_direction(well_edge)
    # initial curve is the whole image less one pixel on the outside
    initial = numpy.ones(well_edge.shape, dtype=bool)
    initial[:,[0,-1]] = 0
    initial[[0,-1],:] = 0
    # Now evolve the curve inward until it contacts the canny well edges.
    gac = active_contour.GAC(initial, nearest_edge, advection_mask=(distances < 10), balloon_direction=-1)
    stopper = active_contour.StoppingCondition(gac, max_iterations=200)
    while stopper.should_continue():
        # otherwise evolve the curve by shrinking, advecting toward edges, and smoothing
        gac.balloon_force(iters=3)
        gac.advect(iters=2)
        gac.smooth()
    gac.smooth(depth=3)
    # now erode everywhere the contour edge is right on a canny edge:
    gac.move_to_outside(well_edge[tuple(gac.inside_border_indices.T)])
    gac.smooth()
    well_mask = gac.mask
    if well_mask.sum() / well_mask.size < 0.25:
        # if the well mask is too small, something went very wrong
        well_mask = None
    return small_image, well_mask