def evaluate_endpoint_resegmentation(filename, seg_volume, resegmentation_radius, threshold=0.5): """Evaluates endpoint resegmentation. Args: filename: path to the file containing resegmentation results seg_volume: volume object with the original segmentation resegmentation_radius: (z, y, x) radius of the resegmentation subvolume threshold: threshold at which to create objects from the predicted object map Returns: EndpointResegmentationResult proto Raises: InvalidBaseSegmentatonError: when no base segmentation object with the expected ID matches the resegmentation data """ id1, _, x, y, z = parse_resegmentation_filename(filename) result = resegmentation_pb2.EndpointSegmentationResult() result.id = id1 start = result.start start.x, start.y, start.z = x, y, z sr = result.segmentation_radius sr.z, sr.y, sr.x = resegmentation_radius with gfile.Open(filename, 'rb') as f: data = np.load(f) prob = storage.dequantize_probability(data['probs']) prob = np.nan_to_num(prob) # nans indicate unvisited voxels sr = result.segmentation_radius orig_seg = seg_volume[0, (z - sr.z):(z + sr.z + 1), (y - sr.y):(y + sr.y + 1), (x - sr.x):(x + sr.x + 1)][0, ...] seg1 = orig_seg == id1 if not np.any(seg1): raise InvalidBaseSegmentatonError() new_seg = prob[0, ...] >= threshold result.num_voxels = int(np.sum(new_seg)) overlaps = pywrapsegment_util.ComputeOverlapCounts( orig_seg.ravel(), new_seg.astype(np.uint64).ravel()) for k, v in overlaps.items(): old, new = k if not new: continue result.overlaps[old].num_overlapping = v result.overlaps[old].num_original = int(np.sum(orig_seg == old)) if old == id1: result.source.CopyFrom(result.overlaps[old]) return result
def evaluate_pair_resegmentation(filename, seg_volume, resegmentation_radius, analysis_radius, voxel_size, threshold=0.5): """Evaluates segment pair resegmentation. Args: filename: path to the file containing resegmentation results seg_volume: VolumeStore object with the original segmentation resegmentation_radius: (z, y, x) radius of the resegmentation subvolume analysis_radius: (z, y, x) radius of the subvolume in which to perform analysis voxel_size: (z, y, x) voxel size in physical units threshold: threshold at which to create objects from the predicted object map Returns: PairResegmentationResult proto Raises: IncompleteResegmentationError: when the resegmentation data does not represent two finished segments InvalidBaseSegmentatonError: when no base segmentation object with the excepted ID matches the resegmentation data """ id1, id2, x, y, z = parse_resegmentation_filename(filename) result = resegmentation_pb2.PairResegmentationResult() result.id_a, result.id_b = id1, id2 p = result.point p.x, p.y, p.z = x, y, z sr = result.segmentation_radius sr.z, sr.y, sr.x = resegmentation_radius with gfile.Open(filename, 'rb') as f: data = np.load(f) prob = storage.dequantize_probability(data['probs']) prob = np.nan_to_num(prob) # nans indicate unvisited voxels dels = data['deletes'] moves = data['histories'] # z, y, x start_points = data['start_points'] # x, y, z if prob.shape[0] != 2: raise IncompleteResegmentationError() assert prob.ndim == 4 # Corner of the resegmentation subvolume in the global coordinate system. corner = np.array([p.x - sr.x, p.y - sr.y, p.z - sr.z]) # In case of multiple segmentation attempts, the last recorded start # point is the one we care about. origin_a = np.array(start_points[0][-1], dtype=np.int) + corner origin_b = np.array(start_points[1][-1], dtype=np.int) + corner oa = result.eval.from_a.origin oa.x, oa.y, oa.z = origin_a ob = result.eval.from_b.origin ob.x, ob.y, ob.z = origin_b # Record basic infromation about the resegmentation run. analysis_r = np.array(analysis_radius) r = result.eval.radius r.z, r.y, r.x = analysis_r seg = seg_volume[0, (z - analysis_r[0]):(z + analysis_r[0] + 1), (y - analysis_r[1]):(y + analysis_r[1] + 1), (x - analysis_r[2]):(x + analysis_r[2] + 1)][0, ...] seg1 = seg == id1 seg2 = seg == id2 result.eval.num_voxels_a = int(np.sum(seg1)) result.eval.num_voxels_b = int(np.sum(seg2)) if result.eval.num_voxels_a == 0 or result.eval.num_voxels_b == 0: raise InvalidBaseSegmentatonError() # Record information about the size of the original segments. result.eval.max_edt_a = float( ndimage.distance_transform_edt(seg1, sampling=voxel_size).max()) result.eval.max_edt_b = float( ndimage.distance_transform_edt(seg2, sampling=voxel_size).max()) # Offset of the analysis subvolume within the resegmentation subvolume. delta = np.array(resegmentation_radius) - analysis_r prob = prob[:, delta[0]:(delta[0] + 2 * analysis_r[0] + 1), delta[1]:(delta[1] + 2 * analysis_r[1] + 1), delta[2]:(delta[2] + 2 * analysis_r[2] + 1)] reseg = prob >= threshold result.eval.iou = compute_iou(reseg) # Record information about the size of the reconstructed segments. evaluate_segmentation_result( reseg[0, ...], dels[0], moves[0], delta, analysis_r, seg1, seg2, voxel_size, result.eval.from_a) evaluate_segmentation_result( reseg[1, ...], dels[1], moves[1], delta, analysis_r, seg1, seg2, voxel_size, result.eval.from_b) return result