Ejemplo n.º 1
0
    def make_neuron_graph(self, skeleton, skeleton_labels,
                          trunks, branchpoints, endpoints, image):
        '''Make a table that captures the graph relationship of the skeleton

        skeleton - binary skeleton image + outline of seed objects
        skeleton_labels - labels matrix of skeleton
        trunks - binary image with trunk points as 1
        branchpoints - binary image with branchpoints as 1
        endpoints - binary image with endpoints as 1
        image - image for intensity measurement

        returns two tables.
        Table 1: edge table
        The edge table is a numpy record array with the following named
        columns in the following order:
        v1: index into vertex table of first vertex of edge
        v2: index into vertex table of second vertex of edge
        length: # of intermediate pixels + 2 (for two vertices)
        total_intensity: sum of intensities along the edge

        Table 2: vertex table
        The vertex table is a numpy record array:
        i: I coordinate of the vertex
        j: J coordinate of the vertex
        label: the vertex's label
        kind: kind of vertex = "T" for trunk, "B" for branchpoint or "E" for endpoint.
        '''
        i, j = np.mgrid[0:skeleton.shape[0], 0:skeleton.shape[1]]
        #
        # Give each point of interest a unique number
        #
        points_of_interest = trunks | branchpoints | endpoints
        number_of_points = np.sum(points_of_interest)
        #
        # Make up the vertex table
        #
        tbe = np.zeros(points_of_interest.shape, '|S1')
        tbe[trunks] = 'T'
        tbe[branchpoints] = 'B'
        tbe[endpoints] = 'E'
        i_idx = i[points_of_interest]
        j_idx = j[points_of_interest]
        poe_labels = skeleton_labels[points_of_interest]
        tbe = tbe[points_of_interest]
        vertex_table = {
            self.VF_I: i_idx,
            self.VF_J: j_idx,
            self.VF_LABELS: poe_labels,
            self.VF_KIND: tbe}
        #
        # First, break the skeleton by removing the branchpoints, endpoints
        # and trunks
        #
        broken_skeleton = skeleton & (~points_of_interest)
        #
        # Label the broken skeleton: this labels each edge differently
        #
        edge_labels, nlabels = morph.label_skeleton(skeleton)
        #
        # Reindex after removing the points of interest
        #
        edge_labels[points_of_interest] = 0
        if nlabels > 0:
            indexer = np.arange(nlabels + 1)
            unique_labels = np.sort(np.unique(edge_labels))
            nlabels = len(unique_labels) - 1
            indexer[unique_labels] = np.arange(len(unique_labels))
            edge_labels = indexer[edge_labels]
            #
            # find magnitudes and lengths for all edges
            #
            magnitudes = fix(scind.sum(image, edge_labels, np.arange(1, nlabels + 1, dtype=np.int32)))
            lengths = fix(scind.sum(np.ones(edge_labels.shape),
                                    edge_labels, np.arange(1, nlabels + 1, dtype=np.int32))).astype(int)
        else:
            magnitudes = np.zeros(0)
            lengths = np.zeros(0, int)
        #
        # combine the edge labels and indexes of points of interest with padding
        #
        edge_mask = edge_labels != 0
        all_labels = np.zeros(np.array(edge_labels.shape) + 2, int)
        all_labels[1:-1, 1:-1][edge_mask] = edge_labels[edge_mask] + number_of_points
        all_labels[i_idx + 1, j_idx + 1] = np.arange(1, number_of_points + 1)
        #
        # Collect all 8 neighbors for each point of interest
        #
        p1 = np.zeros(0, int)
        p2 = np.zeros(0, int)
        for i_off, j_off in ((0, 0), (0, 1), (0, 2),
                             (1, 0), (1, 2),
                             (2, 0), (2, 1), (2, 2)):
            p1 = np.hstack((p1, np.arange(1, number_of_points + 1)))
            p2 = np.hstack((p2, all_labels[i_idx + i_off, j_idx + j_off]))
        #
        # Get rid of zeros which are background
        #
        p1 = p1[p2 != 0]
        p2 = p2[p2 != 0]
        #
        # Find point_of_interest -> point_of_interest connections.
        #
        p1_poi = p1[(p2 <= number_of_points) & (p1 < p2)]
        p2_poi = p2[(p2 <= number_of_points) & (p1 < p2)]
        #
        # Make sure matches are labeled the same
        #
        same_labels = (skeleton_labels[i_idx[p1_poi - 1], j_idx[p1_poi - 1]] ==
                       skeleton_labels[i_idx[p2_poi - 1], j_idx[p2_poi - 1]])
        p1_poi = p1_poi[same_labels]
        p2_poi = p2_poi[same_labels]
        #
        # Find point_of_interest -> edge
        #
        p1_edge = p1[p2 > number_of_points]
        edge = p2[p2 > number_of_points]
        #
        # Now, each value that p2_edge takes forms a group and all
        # p1_edge whose p2_edge are connected together by the edge.
        # Possibly they touch each other without the edge, but we will
        # take the minimum distance connecting each pair to throw out
        # the edge.
        #
        edge, p1_edge, p2_edge = morph.pairwise_permutations(edge, p1_edge)
        indexer = edge - number_of_points - 1
        lengths = lengths[indexer]
        magnitudes = magnitudes[indexer]
        #
        # OK, now we make the edge table. First poi<->poi. Length = 2,
        # magnitude = magnitude at each point
        #
        poi_length = np.ones(len(p1_poi)) * 2
        poi_magnitude = (image[i_idx[p1_poi - 1], j_idx[p1_poi - 1]] +
                         image[i_idx[p2_poi - 1], j_idx[p2_poi - 1]])
        #
        # Now the edges...
        #
        poi_edge_length = lengths + 2
        poi_edge_magnitude = (image[i_idx[p1_edge - 1], j_idx[p1_edge - 1]] +
                              image[i_idx[p2_edge - 1], j_idx[p2_edge - 1]] +
                              magnitudes)
        #
        # Put together the columns
        #
        v1 = np.hstack((p1_poi, p1_edge))
        v2 = np.hstack((p2_poi, p2_edge))
        lengths = np.hstack((poi_length, poi_edge_length))
        magnitudes = np.hstack((poi_magnitude, poi_edge_magnitude))
        #
        # Sort by p1, p2 and length in order to pick the shortest length
        #
        indexer = np.lexsort((lengths, v1, v2))
        v1 = v1[indexer]
        v2 = v2[indexer]
        lengths = lengths[indexer]
        magnitudes = magnitudes[indexer]
        if len(v1) > 0:
            to_keep = np.hstack(([True],
                                 (v1[1:] != v1[:-1]) |
                                 (v2[1:] != v2[:-1])))
            v1 = v1[to_keep]
            v2 = v2[to_keep]
            lengths = lengths[to_keep]
            magnitudes = magnitudes[to_keep]
        #
        # Put it all together into a table
        #
        edge_table = {
            self.EF_V1: v1,
            self.EF_V2: v2,
            self.EF_LENGTH: lengths,
            self.EF_TOTAL_INTENSITY: magnitudes
        }
        return edge_table, vertex_table
Ejemplo n.º 2
0
    def make_objskeleton_graph(self, skeleton, skeleton_labels, trunks,
                               branchpoints, endpoints, image):
        '''Make a table that captures the graph relationship of the skeleton

        skeleton - binary skeleton image + outline of seed objects
        skeleton_labels - labels matrix of skeleton
        trunks - binary image with trunk points as 1
        branchpoints - binary image with branchpoints as 1
        endpoints - binary image with endpoints as 1
        image - image for intensity measurement

        returns two tables.
        Table 1: edge table
        The edge table is a numpy record array with the following named
        columns in the following order:
        v1: index into vertex table of first vertex of edge
        v2: index into vertex table of second vertex of edge
        length: # of intermediate pixels + 2 (for two vertices)
        total_intensity: sum of intensities along the edge

        Table 2: vertex table
        The vertex table is a numpy record array:
        i: I coordinate of the vertex
        j: J coordinate of the vertex
        label: the vertex's label
        kind: kind of vertex = "T" for trunk, "B" for branchpoint or "E" for endpoint.
        '''
        i, j = np.mgrid[0:skeleton.shape[0], 0:skeleton.shape[1]]
        #
        # Give each point of interest a unique number
        #
        points_of_interest = trunks | branchpoints | endpoints
        number_of_points = np.sum(points_of_interest)
        #
        # Make up the vertex table
        #
        tbe = np.zeros(points_of_interest.shape, '|S1')
        tbe[trunks] = 'T'
        tbe[branchpoints] = 'B'
        tbe[endpoints] = 'E'
        i_idx = i[points_of_interest]
        j_idx = j[points_of_interest]
        poe_labels = skeleton_labels[points_of_interest]
        tbe = tbe[points_of_interest]
        vertex_table = {
            self.VF_I: i_idx,
            self.VF_J: j_idx,
            self.VF_LABELS: poe_labels,
            self.VF_KIND: tbe
        }
        #
        # First, break the skeleton by removing the branchpoints, endpoints
        # and trunks
        #
        broken_skeleton = skeleton & (~points_of_interest)
        #
        # Label the broken skeleton: this labels each edge differently
        #
        edge_labels, nlabels = morph.label_skeleton(skeleton)
        #
        # Reindex after removing the points of interest
        #
        edge_labels[points_of_interest] = 0
        if nlabels > 0:
            indexer = np.arange(nlabels + 1)
            unique_labels = np.sort(np.unique(edge_labels))
            nlabels = len(unique_labels) - 1
            indexer[unique_labels] = np.arange(len(unique_labels))
            edge_labels = indexer[edge_labels]
            #
            # find magnitudes and lengths for all edges
            #
            magnitudes = fix(
                scind.sum(image, edge_labels,
                          np.arange(1, nlabels + 1, dtype=np.int32)))
            lengths = fix(
                scind.sum(np.ones(edge_labels.shape), edge_labels,
                          np.arange(1, nlabels + 1,
                                    dtype=np.int32))).astype(int)
        else:
            magnitudes = np.zeros(0)
            lengths = np.zeros(0, int)
        #
        # combine the edge labels and indexes of points of interest with padding
        #
        edge_mask = edge_labels != 0
        all_labels = np.zeros(np.array(edge_labels.shape) + 2, int)
        all_labels[1:-1,
                   1:-1][edge_mask] = edge_labels[edge_mask] + number_of_points
        all_labels[i_idx + 1, j_idx + 1] = np.arange(1, number_of_points + 1)
        #
        # Collect all 8 neighbors for each point of interest
        #
        p1 = np.zeros(0, int)
        p2 = np.zeros(0, int)
        for i_off, j_off in ((0, 0), (0, 1), (0, 2), (1, 0), (1, 2), (2, 0),
                             (2, 1), (2, 2)):
            p1 = np.hstack((p1, np.arange(1, number_of_points + 1)))
            p2 = np.hstack((p2, all_labels[i_idx + i_off, j_idx + j_off]))
        #
        # Get rid of zeros which are background
        #
        p1 = p1[p2 != 0]
        p2 = p2[p2 != 0]
        #
        # Find point_of_interest -> point_of_interest connections.
        #
        p1_poi = p1[(p2 <= number_of_points) & (p1 < p2)]
        p2_poi = p2[(p2 <= number_of_points) & (p1 < p2)]
        #
        # Make sure matches are labeled the same
        #
        same_labels = (
            skeleton_labels[i_idx[p1_poi - 1],
                            j_idx[p1_poi -
                                  1]] == skeleton_labels[i_idx[p2_poi - 1],
                                                         j_idx[p2_poi - 1]])
        p1_poi = p1_poi[same_labels]
        p2_poi = p2_poi[same_labels]
        #
        # Find point_of_interest -> edge
        #
        p1_edge = p1[p2 > number_of_points]
        edge = p2[p2 > number_of_points]
        #
        # Now, each value that p2_edge takes forms a group and all
        # p1_edge whose p2_edge are connected together by the edge.
        # Possibly they touch each other without the edge, but we will
        # take the minimum distance connecting each pair to throw out
        # the edge.
        #
        edge, p1_edge, p2_edge = morph.pairwise_permutations(edge, p1_edge)
        indexer = edge - number_of_points - 1
        lengths = lengths[indexer]
        magnitudes = magnitudes[indexer]
        #
        # OK, now we make the edge table. First poi<->poi. Length = 2,
        # magnitude = magnitude at each point
        #
        poi_length = np.ones(len(p1_poi)) * 2
        poi_magnitude = (image[i_idx[p1_poi - 1], j_idx[p1_poi - 1]] +
                         image[i_idx[p2_poi - 1], j_idx[p2_poi - 1]])
        #
        # Now the edges...
        #
        poi_edge_length = lengths + 2
        poi_edge_magnitude = (image[i_idx[p1_edge - 1], j_idx[p1_edge - 1]] +
                              image[i_idx[p2_edge - 1], j_idx[p2_edge - 1]] +
                              magnitudes)
        #
        # Put together the columns
        #
        v1 = np.hstack((p1_poi, p1_edge))
        v2 = np.hstack((p2_poi, p2_edge))
        lengths = np.hstack((poi_length, poi_edge_length))
        magnitudes = np.hstack((poi_magnitude, poi_edge_magnitude))
        #
        # Sort by p1, p2 and length in order to pick the shortest length
        #
        indexer = np.lexsort((lengths, v1, v2))
        v1 = v1[indexer]
        v2 = v2[indexer]
        lengths = lengths[indexer]
        magnitudes = magnitudes[indexer]
        if len(v1) > 0:
            to_keep = np.hstack(
                ([True], (v1[1:] != v1[:-1]) | (v2[1:] != v2[:-1])))
            v1 = v1[to_keep]
            v2 = v2[to_keep]
            lengths = lengths[to_keep]
            magnitudes = magnitudes[to_keep]
        #
        # Put it all together into a table
        #
        edge_table = {
            self.EF_V1: v1,
            self.EF_V2: v2,
            self.EF_LENGTH: lengths,
            self.EF_TOTAL_INTENSITY: magnitudes
        }
        return edge_table, vertex_table