Example #1
0
def PruneCandidates(segmentation_one, segmentation_two, candidates, centers, radii, overlap):
    assert (segmentation_one.shape == segmentation_two.shape)
    zres, yres, xres = segmentation_one.shape

    # get the global grid box
    global_box = ib3shapes.IBBox((0, 0, 0), (zres, yres, xres))

    indices = []
    # iterate over every candidate
    for iv, candidate in enumerate(candidates):
        # create a local bounding box for this feature
        cz, cy, cx = centers[iv]
        mins = (cz - radii[IB_Z], cy - radii[IB_Y], cx - radii[IB_X])
        maxs = (cz + radii[IB_Z], cy + radii[IB_Y], cx + radii[IB_X])
        
        # first check if the local box is contained
        if 0 < mins[IB_X] and 0 < mins[IB_Y] and 0 < mins[IB_Z] and maxs[IB_X] < xres and maxs[IB_Y] < yres and maxs[IB_Z] < zres: indices.append(iv)
        # also allow otherwise valid candidates
        elif SearchCandidate(segmentation_one, segmentation_two, candidate, overlap, mins, maxs): indices.append(iv)

    # return which indices are valid
    return indices
Example #2
0
    def __init__(self, prefix):
        # initialize the prefix variable
        self.prefix = prefix

        # backwards compatability variable defaults
        self.affinity_filename = None
        self.boundary_filename = None
        self.gold_filename = None
        self.image_filename = None
        self.mask_filename = None
        self.rhoana_filename = None
        self.synapse = None
        self.crop_xmin = None
        self.crop_xmax = None
        self.crop_ymin = None
        self.crop_ymax = None
        self.crop_zmin = None
        self.crop_zmax = None

        # open the meta data txt file
        filename = 'meta/{}.meta'.format(prefix)
        with open(filename, 'r') as fd:
            lines = fd.readlines()

            for ix in range(0, len(lines), 2):
                # get the comment and the corresponding value
                comment = lines[ix].strip()
                value = lines[ix + 1].strip()

                if comment == '# resolution in nm':
                    # separate into individual dimensions
                    samples = value.split('x')
                    # need to use 2, 1, and 0 here since the outward facing convention is x,y,z, not z, y, x
                    self.resolution = (float(samples[2]), float(samples[1]),
                                       float(samples[0]))
                elif comment == '# affinity filename':
                    self.affinity_filename = value
                elif comment == '# boundary filename':
                    self.boundary_filename = value
                elif comment == '# gold filename':
                    self.gold_filename = value
                elif comment == '# image filename':
                    self.image_filename = value
                elif comment == '# mask filename':
                    self.mask_filename = value
                elif comment == '# rhoana filename':
                    self.rhoana_filename = value
                elif comment == '# synapse filename':
                    self.synapse_filename = value
                elif comment == '# world bounding box':
                    if value == 'None':
                        self.bounding_box = ib3shapes.IBBox((0, 0, 0),
                                                            (-1, -1, -1))
                        continue
                    # separate into minimums and maximums
                    minmax = value.split('-')
                    mins = (minmax[0].strip('()')).split(',')
                    maxs = (minmax[1].strip('()')).split(',')

                    # split into individual mins
                    for iv in range(NDIMS):
                        mins[iv] = int(mins[iv])
                        maxs[iv] = int(maxs[iv])

                    # swap x and z
                    tmp = mins[0]
                    mins[0] = mins[2]
                    mins[2] = tmp

                    tmp = maxs[0]
                    maxs[0] = maxs[2]
                    maxs[2] = tmp

                    # save the bounding box
                    self.bounding_box = ib3shapes.IBBox(mins, maxs)
                elif comment == '# grid size':
                    samples = value.split('x')
                    self.grid_size = (int(samples[2]), int(samples[1]),
                                      int(samples[0]))
                elif comment == '# train/val/test crop':
                    samples = value.split('x')
                    self.crop_xmin = int(samples[0].split(':')[0])
                    self.crop_xmax = int(samples[0].split(':')[1])
                    self.crop_ymin = int(samples[1].split(':')[0])
                    self.crop_ymax = int(samples[1].split(':')[1])
                    self.crop_zmin = int(samples[2].split(':')[0])
                    self.crop_zmax = int(samples[2].split(':')[1])
                else:
                    sys.stderr.write(
                        'Unrecognized attribute in {}: {}\n'.format(
                            prefix, comment))
                    sys.exit()
Example #3
0
def GenerateFeatures(prefix_one, prefix_two, threshold, maximum_distance):
    # read in all relevant information
    segmentation_one = dataIO.ReadSegmentationData(prefix_one)
    segmentation_two = dataIO.ReadSegmentationData(prefix_two)
    assert (segmentation_one.shape == segmentation_two.shape)
    bbox_one = dataIO.GetWorldBBox(prefix_one)
    bbox_two = dataIO.GetWorldBBox(prefix_two)
    world_res = dataIO.Resolution(prefix_one)
    assert (world_res == dataIO.Resolution(prefix_two))

    # get the radii for the relevant region
    radii = (int(maximum_distance / world_res[IB_Z] + 0.5), int(maximum_distance / world_res[IB_Y] + 0.5), int(maximum_distance / world_res[IB_X] + 0.5))



    # parse out small segments
    segmentation_one = seg2seg.RemoveSmallConnectedComponents(segmentation_one, min_size=threshold)
    segmentation_two = seg2seg.RemoveSmallConnectedComponents(segmentation_two, min_size=threshold)

    # get the bounding box for the intersection
    world_box = ib3shapes.IBBox(bbox_one.mins, bbox_one.maxs)
    world_box.Intersection(bbox_two)

    # get the mins and maxs of truncated box
    mins_one = WorldToGrid(world_box.mins, bbox_one)
    mins_two = WorldToGrid(world_box.mins, bbox_two)
    maxs_one = WorldToGrid(world_box.maxs, bbox_one)
    maxs_two = WorldToGrid(world_box.maxs, bbox_two)

    # get the relevant subsections
    segmentation_one = segmentation_one[mins_one[IB_Z]:maxs_one[IB_Z], mins_one[IB_Y]:maxs_one[IB_Y], mins_one[IB_X]:maxs_one[IB_X]]
    segmentation_two = segmentation_two[mins_two[IB_Z]:maxs_two[IB_Z], mins_two[IB_Y]:maxs_two[IB_Y], mins_two[IB_X]:maxs_two[IB_X]]



    # create an emptu set and add dumby variable for numba
    candidates_set = set()
    # this set represents tuples of labels from GRID_ONE and GRID_TWO
    candidates_set.add((np.uint64(0), np.uint64(0)))
    FindOverlapCandidates(segmentation_one, segmentation_two, candidates_set)

    # get the reverse mappings
    forward_mapping_one, reverse_mapping_one = seg2seg.ReduceLabels(segmentation_one)
    forward_mapping_two, reverse_mapping_two = seg2seg.ReduceLabels(segmentation_two)



    # get the number of unique labels
    nlabels_one = reverse_mapping_one.size
    nlabels_two = reverse_mapping_two.size

    # calculate the center of overlap regions
    sums = np.zeros((nlabels_one, nlabels_two, 3), dtype=np.uint64)
    counter = np.zeros((nlabels_one, nlabels_two), dtype=np.uint64)
    FindCenters(segmentation_one, segmentation_two, forward_mapping_one, forward_mapping_two, sums, counter)

    # get the number of occurrences of all labels
    _, counts_one = np.unique(segmentation_one, return_counts=True)
    _, counts_two = np.unique(segmentation_two, return_counts=True)



    # iterate through candidate and locate centers
    candidates = []
    centers = []
    counts = []
    for candidate in candidates_set:
        # skip extracellular space
        if not candidate[0] or not candidate[1]: continue

        # get forward mapping
        index_one = forward_mapping_one[candidate[0]]
        index_two = forward_mapping_two[candidate[1]]

        count = counter[index_one][index_two]
        center = (int(sums[index_one, index_two, IB_Z] / count + 0.5), int(sums[index_one, index_two, IB_Y] / count + 0.5), int(sums[index_one, index_two, IB_X] / count + 0.5))

        # append to the lists
        candidates.append(candidate)
        centers.append(center)
        counts.append((counts_one[index_one], counts_two[index_two], count))



    # find which dimension causes overlap
    if not bbox_one.mins[IB_X] == bbox_two.mins[IB_X]: overlap = IB_X
    if not bbox_one.mins[IB_Y] == bbox_two.mins[IB_Y]: overlap = IB_Y
    if not bbox_one.mins[IB_Z] == bbox_two.mins[IB_Z]: overlap = IB_Z



    # prune the candidates
    indices = PruneCandidates(segmentation_one, segmentation_two, candidates, centers, radii, overlap)
    pruned_candidates = []
    pruned_centers = []
    pruned_counts = []
    for index in indices:
        # add the candidates
        pruned_candidates.append(candidates[index])
        pruned_counts.append(counts[index])    

        center = (centers[index][IB_Z] + world_box.mins[IB_Z], centers[index][IB_Y] + world_box.mins[IB_Y], centers[index][IB_X] + world_box.mins[IB_X])
        pruned_centers.append(center)

    # save all features
    SaveFeatures(prefix_one, prefix_two, pruned_candidates, pruned_centers, pruned_counts, threshold, maximum_distance)