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