def compute_maximum_label_overlap(seg_a, seg_b, ignore_zeros=False): """ For each node in seg_a, compute the node in seg_b with the biggest overalp. """ ids_a = np.unique(seg_a) overlaps = np.zeros(int(ids_a.max() + 1), dtype=seg_b.dtype) ovlp = ngt.overlap(seg_a, seg_b) ovlp = [ovlp.overlapArrays(id_a, True)[0] for id_a in ids_a] if ignore_zeros: ovlp = np.array([ ovl[1] if (ovl[0] == 0 and len(ovl) > 1) else ovl[0] for ovl in ovlp ]) else: ovlp = np.array([ovl[0] for ovl in ovlp]) overlaps[ids_a] = ovlp return overlaps
def assign_superpixels_to_boutons(): from nifty.ground_truth import overlap with h5py.File('./test_data.h5', 'r') as f: ws = f['watershed'][:] # boutons = f['boutons_corrected'][:] boutons = f['boutons'][:] boutons, _, _ = vigra.analysis.relabelConsecutive(boutons) ws_ids = np.unique(ws) ovlp = overlap(ws, boutons) ovlp = np.array([ ovlp.overlapArrays(ws_id, True)[0][0] if ws_id in ws_ids else 0 for ws_id in range(int(ws.max() + 1)) ], dtype='uint32') with h5py.File('./test_data.h5', 'a') as f: if 'bouton_overlaps' in f: del f['bouton_overlaps'] f.create_dataset('bouton_overlaps', data=ovlp)
def compute_overlaps(seg_a, seg_b, max_overlap=True): seg_ids = np.unique(seg_a) comp = ngt.overlap(seg_a, seg_b) overlaps = [comp.overlapArrays(ida, True) for ida in seg_ids] if max_overlap: # the max overlap can be ambiguous, need to filtr for this mask = np.array([ ovlp[1][0] != ovlp[1][1] if ovlp[1].size > 1 else True for ovlp in overlaps ]) overlaps = np.array([ovlp[0][0] for ovlp in overlaps]) assert mask.shape == overlaps.shape return overlaps, mask else: overlaps = { seg_id: ovlp for seg_id, ovlp in zip(seg_ids, overlaps) } return overlaps
def lifted_problem_from_segmentation(rag, watershed, input_segmentation, overlap_threshold, graph_depth, same_segment_cost, different_segment_cost, mode='all', n_threads=None): """ Compute lifted problem from segmentation by mapping segments to watershed superpixels. Arguments: rag [RegionAdjacencyGraph] - the region adjacency graph watershed [np.ndarray] - the watershed over segmentation input_segmentation [np.ndarray] - Segmentation used to determine node attribution. overlap_threshold [float] - minimal overlap to assign a segment id to node graph_depth [int] - maximal graph depth up to which lifted edges will be included same_segment_cost [float] - costs for edges between nodes with same segment id attribution different_segment_cost [float] - costs for edges between nodes with different segment id attribution mode [str] - mode for insertion of lifted edges. Can be "all" - lifted edges will be inserted in between all nodes with attribution "different" - lifted edges will only be inserted in between nodes attributed to different classes "same" - lifted edges will only be inserted in between nodes attribted to the same class (default: "different") n_threads [int] - number of threads used for the calculation (default: None) """ n_threads = multiprocessing.cpu_count() if n_threads is None else n_threads assert input_segmentation.shape == watershed.shape # compute the overlaps ovlp_comp = ngt.overlap(watershed, input_segmentation) ws_ids = np.unique(watershed) n_labels = ws_ids[-1] + 1 assert n_labels == rag.numberOfNodes, "%i, %i" % (n_labels, rag.numberOfNodes) # initialise the arrays for node labels, to be # dense in the watershed id space (even if some ws-ids are not present) node_labels = np.zeros(n_labels, dtype='uint64') # extract the overlap values and node labels from the overlap # computation results overlaps = [ ovlp_comp.overlapArraysNormalized(ws_id, sorted=False) for ws_id in ws_ids ] node_label_vals = np.array([ovlp[0][0] for ovlp in overlaps]) overlap_values = np.array([ovlp[1][0] for ovlp in overlaps]) node_label_vals[overlap_values < overlap_threshold] = 0 assert len(node_label_vals) == len(ws_ids) node_labels[ws_ids] = node_label_vals # find all lifted edges up to the graph depth between mapped nodes # NOTE we need to convert to the different graph type for now, but # it would be nice to support all nifty graphs at some type uv_ids = rag.uvIds() g_temp = ndist.Graph(uv_ids) lifted_uvs = ndist.liftedNeighborhoodFromNodeLabels( g_temp, node_labels, graph_depth, mode=mode, numberOfThreads=n_threads, ignoreLabel=0) # make sure that the lifted uv ids are in range of the node labels assert lifted_uvs.max() < rag.numberOfNodes, "%i, %i" % (int( lifted_uvs.max()), rag.numberOfNodes) lifted_labels = node_labels[lifted_uvs] lifted_costs = np.zeros_like(lifted_labels, dtype='float32') same_mask = lifted_labels[:, 0] == lifted_labels[:, 1] lifted_costs[same_mask] = same_segment_cost lifted_costs[~same_mask] = different_segment_cost return lifted_uvs, lifted_costs
def max_overlaps(a, b): ovlp = ngt.overlap(a, b) max_ols = [ovlp.overlapArrays(seg_id, sorted=True) for seg_id in range(int(a.max()) + 1)] max_ols = [max_ol[0][0] if len(max_ol[0]) > 0 else 0 for max_ol in max_ols] return np.array(max_ols, dtype='uint64')
def _stitch_face(offsets, overlap_prefix, block_a, block_b, face_a, face_b, overlap_threshold, ignore_label): off_a = offsets[block_a] off_b = offsets[block_b] path_a = '%s_%i_%i.npy' % (overlap_prefix, block_a, block_b) path_b = '%s_%i_%i.npy' % (overlap_prefix, block_b, block_a) # overlaps might not exist because they are empty if (not os.path.exists(path_a)) or (not os.path.exists(path_b)): return None ovlp_a = np.load(path_a) ovlp_b = np.load(path_b) assert ovlp_a.shape == ovlp_b.shape, "%s, %s" % (str( ovlp_a.shape), str(ovlp_b.shape)) # find the block face and the ids on the block face axis = vu.faces_to_ovlp_axis(face_a, face_b) face = tuple( slice(None) if dim != axis else slice(fa.stop - 1, fa.stop + 1) for dim, fa in enumerate(face_a)) # find the ids ON the actual block boundary segments_a = np.unique(ovlp_a[face]) segments_b = np.unique(ovlp_b[face]) # 0 is ignore label, so we don't consider it here if segments_a[0] == 0: segments_a = segments_a[1:] if segments_b[0] == 0: segments_b = segments_b[1:] # measure all overlaps overlaps_ab = ngt.overlap(ovlp_a, ovlp_b) overlaps_ba = ngt.overlap(ovlp_b, ovlp_a) assignments = [] # iterate over all segments on the face of block a for seg_a in segments_a: # get the segments of block b overlapping with seg_a ovlp_seg_a, counts_seg_a = overlaps_ab.overlapArraysNormalized( seg_a, sorted=True) if ignore_label is not None: ovlp_seg_a, counts_seg_a = _filter_ignore_label( ovlp_seg_a, counts_seg_a, ignore_label) seg_b = ovlp_seg_a[0] # continue if the max overlapping object is not on the face of block b if seg_b not in segments_b: continue # continue if the max overlapping objects do not agree ovlp_seg_b, counts_seg_b = overlaps_ba.overlapArraysNormalized( seg_b, sorted=True) if ignore_label is not None: ovlp_seg_b, counts_seg_b = _filter_ignore_label( ovlp_seg_b, counts_seg_b, ignore_label) if ovlp_seg_b[0] != seg_a: continue # merge the two ids if their mean overlap is larger than the overlap threshold ovlp_measure = (counts_seg_a[0] + counts_seg_b[0]) / 2. if ovlp_measure > overlap_threshold: assignments.append([seg_a + off_a, seg_b + off_b]) if assignments: return np.array(assignments, dtype='uint64') else: return None