예제 #1
0
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
예제 #2
0
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