Exemplo n.º 1
0
def nearest_neighbor(img,
                     label,
                     container,
                     holder,
                     DISPLACEMENT=100,
                     MASSTHRES=0.2):
    """Link two cells if they are the only two cells within DISPLACEMENT and MASSTHRES. 

    Args:
    DISPLACEMENT (int): The maximum distance (in pixel)
    MASSTHRES (float): The maximum difference of total intensity changes.
                        0.2 means it allows for 20% total intensity changes.
    """

    DISPLACEMENT = DISPLACEMENT
    MASSTHRES = MASSTHRES
    withinarea = container._dist_unlinked < DISPLACEMENT
    withinmass = abs(container._masschange_unlinked) < MASSTHRES
    binarymat = withinarea * withinmass
    binarycost = binarymat
    good_curr_idx, good_prev_idx = find_one_to_one_assign(binarycost)
    prev_cells, curr_cells = container.unlinked
    for ci, pi in zip(good_curr_idx, good_prev_idx):
        prev_cells[pi].next = curr_cells[ci]
    return container
Exemplo n.º 2
0
def watershed_distance(img, label, container, holder, ERODI=5,
                       DEBRISAREA=50, DISPLACEMENT=50, MASSTHRES=0.2):
    '''watershed existing label, meaning make a cut at the deflection.
    After the cuts, objects will be linked if they are within DISPLACEMENT and MASSTHRES.
    If two candidates are found, it will pick a closer one.

    Args:
    ERODI (int):        Erosion size element for generating watershed seeds.
                        Smaller ERODI will allow more cuts.
    DISPLACEMENT (int): The maximum distance (in pixel)
    MASSTHRES (float):  The maximum difference of total intensity changes.
                        0.2 means it allows for 20% total intensity changes.
    '''

    untr_prev, untr_curr = container.unlinked
    mask_untracked = container._label_untracked.astype(bool)
    wshed_label = watershed(mask_untracked, ERODI)
    wshed_label = skilabel(sizefilterandopen(wshed_label, DEBRISAREA, np.Inf, 0))
    newcells = CellListMaker(img, wshed_label, holder, holder.frame).make_list()
    distanceUntracked = _distance_diff(untr_prev, newcells)
    masschangeUntracked = _totalintensity_difference(untr_prev, newcells)

    withinarea = distanceUntracked < DISPLACEMENT
    withinmass = abs(masschangeUntracked) < MASSTHRES
    withinareaMass = withinarea * withinmass

    withinareaMass = pick_closer_binarycostmat(withinareaMass, distanceUntracked)
    good_curr_idx, good_prev_idx = find_one_to_one_assign(withinareaMass)

    # update the link
    for ci, pi in zip(good_curr_idx, good_prev_idx):
        untr_prev[pi].next = newcells[ci]
    # Get all linear coordinates from good newly segmented cells
    good_curr_coords = [newcells[n].prop.coords for n in good_curr_idx]
    lin_curr_coords = [convert_coords_to_linear(i, holder.img_shape) for i in flatlist(good_curr_coords)]
    # find cells in old mask (in current) that overlaps with good new cells
    old_cells_to_remove, lin_old_coords_remove = find_coords_overlap_coords(untr_curr, lin_curr_coords, holder.img_shape)
    # find cells in new mask which overlaps with the cells in old mask
    newcells_to_update = find_cells_overlap_linear_coords(newcells, lin_old_coords_remove, holder.img_shape)
    # remove old cells
    for old_cell in old_cells_to_remove:
        container.curr_cells.remove(old_cell)
    # add new cells
    container.curr_cells.extend(newcells_to_update)
    return container
Exemplo n.º 3
0
def track_neck_cut(img,
                   label,
                   container,
                   holder,
                   ERODI=5,
                   DEBRISAREA=50,
                   DISPLACEMENT=50,
                   MASSTHRES=0.2,
                   LIM=10,
                   EDGELEN=5,
                   THRES_ANGLE=180,
                   STEPLIM=10):
    """
        Adaptive segmentation by using tracking informaiton.
        Separate two objects by making a cut at the deflection. For each points on the outline,
        it will make a triangle separated by EDGELEN and calculates the angle facing inside of concave.

        EDGELEN (int):      A length of edges of triangle on the nuclear perimeter.
        THRES_ANGLE (int):  Define the neck points if a triangle has more than this angle.
        STEPLIM (int):      points of neck needs to be separated by at least STEPLIM in parimeters.
        """

    untr_prev, untr_curr = container.unlinked
    label_untracked = container._label_untracked
    unique_labels = np.unique(label_untracked)
    unique_labels = unique_labels[unique_labels > 0]
    newcells = []
    all_new_cells = []
    for label_id in unique_labels:
        mask = label_untracked == label_id
        cl_label = clear_border(mask)
        outlines = labels2outlines(cl_label).astype(np.uint16)
        rps = regionprops(outlines)
        rps = [i for i in rps if i.perimeter > STEPLIM]
        for cell in rps:
            score, coords = calc_neck_score_thres_filtered(cell.coords,
                                                           edgelen=EDGELEN,
                                                           thres=THRES_ANGLE,
                                                           steplim=STEPLIM)
            if len(score) > 1:
                r0, c0 = coords[0, :]
                if coords.shape[0] > LIM:
                    coords = coords[:LIM, :]
                for cand in coords[1:, :]:
                    untr_prev = container.unlinked[0]

                    cut_label = skilabel(cut_neck(cl_label, r0, c0, cand[0],
                                                  cand[1]),
                                         conn=1)
                    new_cells_temp = CellListMaker(img, cut_label, holder,
                                                   holder.frame).make_list()
                    if len(new_cells_temp) > 1:
                        distanceUntracked = _distance_diff(
                            untr_prev, new_cells_temp)
                        masschangeUntracked = _totalintensity_difference(
                            untr_prev, new_cells_temp)

                        withinarea = distanceUntracked < DISPLACEMENT
                        withinmass = abs(masschangeUntracked) < MASSTHRES
                        withinareaMass = withinarea * withinmass

                        withinareaMass = pick_closer_binarycostmat(
                            withinareaMass, distanceUntracked)
                        good_curr_idx, good_prev_idx = find_one_to_one_assign(
                            withinareaMass)
                        if len(good_curr_idx) > 0:
                            # update the link
                            all_new_cells.append(new_cells_temp)
                            for ci, pi in zip(good_curr_idx, good_prev_idx):
                                newcells.append(new_cells_temp[ci])
                                untr_prev[pi].next = new_cells_temp[ci]
                            break

    good_curr_coords = [n.prop.coords for n in newcells]
    lin_curr_coords = [
        convert_coords_to_linear(i, holder.img_shape)
        for i in flatlist(good_curr_coords)
    ]
    # find cells in old mask (in current) that overlaps with good new cells
    old_cells_to_remove, lin_old_coords_remove = find_coords_overlap_coords(
        untr_curr, lin_curr_coords, holder.img_shape)
    # find cells in new mask which overlaps with the cells in old mask
    all_new_cells = [i for j in all_new_cells for i in j]
    newcells_to_update = find_cells_overlap_linear_coords(
        all_new_cells, lin_old_coords_remove, holder.img_shape)
    # remove old cells
    for old_cell in old_cells_to_remove:
        container.curr_cells.remove(old_cell)
    # add new cells
    container.curr_cells.extend(newcells_to_update)
    return container