def _wd(labels0, labels, img0, img1): labels1 = -labels.copy() rps0 = regionprops(labels0, img0) from subdetect_operation import watershed_divide # DO NOT MOVE IT from utils.track_utils import _find_match untracked_labels = labels1.copy() untracked_labels[untracked_labels < 0] = 0 wshed_labels = watershed_divide(untracked_labels, regmax=REGMAX, min_size=MIN_SIZE) wshed_labels = label(wshed_labels) store = regionprops(wshed_labels, img1) good_cells = _find_match(rps0, store, DISPLACEMENT, MASSTHRES) for gc in good_cells: # needed to reuse _update_labels_neck_cut gccrds = gc.coords[0] gc.raw_label = labels1[gccrds[0], gccrds[1]] labels0, labels = _update_labels_neck_cut(labels0, labels1, good_cells) labels0, labels = nn_closer(img0, img1, labels0, -labels, DISPLACEMENT, MASSTHRES) return labels0, labels, good_cells
def track_neck_cut(img0, img1, labels0, labels1, DISPLACEMENT=10, MASSTHRES=0.2, EDGELEN=5, THRES_ANGLE=180, WSLIMIT=False, SMALL_RAD=3, CANDS_LIMIT=300): """ 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. The majority of cells need to be tracked before the this method to calculate LARGE_RAD and SMALL_RAD. 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. WSLIMIT (bool): Limit search points to ones overlapped with watershed transformed images. Set it True if calculation is slow. SMALL_RAD (int or None): The smallest radius of candidate objects. If you have many cells, set it to None will infer the radius from previous frame. CANDS_LIMIT(int): use lower if slow. limit a number of searches. """ labels0, labels = nn_closer(img0, img1, labels0, labels1, DISPLACEMENT, MASSTHRES) labels1 = -labels.copy() if SMALL_RAD is None and not hasattr(holder, 'SMALL_RAD'): tracked_area = [i.area for i in regionprops(labels)] holder.SMALL_RAD = np.sqrt(np.percentile(tracked_area, 5) / np.pi) elif SMALL_RAD is not None: holder.SMALL_RAD = SMALL_RAD SMALL_RAD = holder.SMALL_RAD rps0 = regionprops(labels0, img0) unique_labels = np.unique(labels1) if WSLIMIT: wlines = wshed_raw(labels1 > 0, img1) else: wlines = np.ones(labels1.shape, np.bool) store = [] coords_store = [] for label_id in unique_labels: if label_id == 0: continue cc = CellCutter(labels1 == label_id, img1, wlines, small_rad=SMALL_RAD, EDGELEN=EDGELEN, THRES=THRES_ANGLE, CANDS_LIMIT=CANDS_LIMIT) cc.prepare_coords_set() candidates = cc.search_cut_candidates(cc.bw.copy(), cc.coords_set[:CANDS_LIMIT]) for c in candidates: c.raw_label = label_id store.append(candidates) coords_store.append(cc.coords_set) coords_store = [i for i in coords_store if i] # Attempt a first cut. good_cells = _find_best_neck_cut(rps0, store, DISPLACEMENT, MASSTHRES) labels0, labels = _update_labels_neck_cut(labels0, labels1, good_cells) labels0, labels = nn_closer(img0, img1, labels0, -labels, DISPLACEMENT, MASSTHRES) # iteration from here. while good_cells: rps0 = regionprops(labels0, img0) labels1 = -labels.copy() rps0 = regionprops(labels0, img0) unique_labels = np.unique(labels1) store = [] for label_id in unique_labels: if label_id == 0: continue bw = labels1 == label_id coords_set = [ i for i in coords_store if bw[i[0][0][0], i[0][0][1]] ] if not coords_set: continue coords_set = coords_set[0] candidates = cc.search_cut_candidates(bw, coords_set) for c in candidates: c.raw_label = label_id store.append(candidates) coords_store.append(coords_set) good_cells = _find_best_neck_cut(rps0, store, DISPLACEMENT, MASSTHRES) labels0, labels = _update_labels_neck_cut(labels0, labels1, good_cells) labels0, labels = nn_closer(img0, img1, labels0, -labels, DISPLACEMENT, MASSTHRES) return labels0, labels