def segmentation(self):

        self.K = TreeModel()
        self.K_to_P = defaultdict(list) # ki -> list of (i, d)'s
        self.P_to_K = {} # pi -> (ki, d)

        self.level_to_graph = [None for _ in range(len(self.level_sets))]
        self.level_to_segment_graphs = [None for _ in
                                        range(len(self.level_sets))]

        for level, points in self.level_sets.items():
            N_level_inter = self.N.subgraph(points)
            segment_nodes_list = nx.connected_components(N_level_inter)

            self.level_to_graph[level] = N_level_inter
            self.level_to_segment_graphs[level] = \
              nx.connected_component_subgraphs(N_level_inter)

            for segment_nodes in segment_nodes_list:
                segment_centroid = harray(mean(self.P[[segment_nodes]], axis=0))
                node = self.K.add_node(pos=segment_centroid,
                                      points=set(segment_nodes), level=level)
                max_dist = float('-inf')
                avg_dist = 0
                for j in segment_nodes:
                    d = dist(segment_centroid, self.P[j])
                    max_dist = max(max_dist, d)
                    avg_dist += d
                    self.K_to_P[node.id].append((j, d))
                    assert j not in self.P_to_K
                    self.P_to_K[j] = (node.id, d)
                # initial radius estimation (can be refined with
                # volume_reconstruction)
                avg_dist /= len(segment_nodes)
                node.radius = avg_dist
Beispiel #2
0
 def compute_nearest_neighbors_in_radius(self, r):
     start = time.time()
     kdtree1 = KDTree(self.P)
     kdtree2 = KDTree(self.P)
     result = kdtree1.query_ball_tree(kdtree2, r)
     self.N_full = nx.Graph()
     for i, i_nns in enumerate(result):
         for j in i_nns:
             if i == j: continue
             d = dist(self.P[i], self.P[j])
             self.N_full.add_edge(i, j, weight=d)
     print time.time() - start
     print len(self.N_full.edges())
     self.find_nn_connected_components()
 def compute_nearest_neighbors_in_radius(self, r):
     start = time.time()
     kdtree1 = KDTree(self.P)
     kdtree2 = KDTree(self.P)
     result = kdtree1.query_ball_tree(kdtree2, r)
     self.N_full = nx.Graph()
     for i, i_nns in enumerate(result):
         for j in i_nns:
             if i == j: continue
             d = dist(self.P[i], self.P[j])
             self.N_full.add_edge(i, j, weight=d)
     print time.time() - start
     print len(self.N_full.edges())
     self.find_nn_connected_components()
Beispiel #4
0
    def segmentation(self):

        self.K = TreeModel()
        self.K_to_P = defaultdict(list)  # ki -> list of (i, d)'s
        self.P_to_K = {}  # pi -> (ki, d)

        self.level_to_graph = [None for _ in range(len(self.level_sets))]
        self.level_to_segment_graphs = [
            None for _ in range(len(self.level_sets))
        ]

        for level, points in self.level_sets.items():
            N_level_inter = self.N.subgraph(points)
            segment_nodes_list = nx.connected_components(N_level_inter)

            self.level_to_graph[level] = N_level_inter
            self.level_to_segment_graphs[level] = \
              nx.connected_component_subgraphs(N_level_inter)

            for segment_nodes in segment_nodes_list:
                segment_centroid = harray(mean(self.P[[segment_nodes]],
                                               axis=0))
                node = self.K.add_node(pos=segment_centroid,
                                       points=set(segment_nodes),
                                       level=level)
                max_dist = float('-inf')
                avg_dist = 0
                for j in segment_nodes:
                    d = dist(segment_centroid, self.P[j])
                    max_dist = max(max_dist, d)
                    avg_dist += d
                    self.K_to_P[node.id].append((j, d))
                    assert j not in self.P_to_K
                    self.P_to_K[j] = (node.id, d)
                # initial radius estimation (can be refined with
                # volume_reconstruction)
                avg_dist /= len(segment_nodes)
                node.radius = avg_dist
Beispiel #5
0
    def volume_reconstruction(self):

        for ki in self.K:
            if not self.K[ki].children:
                kj = ki
                while self.K[kj].parent is not None:
                    kj_start_points = self.level_start_points[self.K[kj].level] \
                      & self.K[kj].points
                    # if not, will use initial radius estimation (not good!)
                    if kj_start_points:
                        kj_to_parent_midpoint = mean(
                            (self.K[kj].pos, self.K[self.K[kj].parent].pos),
                            axis=0)
                        radius = 0
                        for pi in kj_start_points:
                            radius += dist(self.P[pi], kj_to_parent_midpoint)
                        radius /= len(kj_start_points)
                        self.K[kj].radius = radius
                    kj = self.K[kj].parent

        # segment radius smoothing

        roots = set()
        for ki in self.K:
            if not self.K[ki].children:
                segment = {}  # kj -> radius
                kj = ki
                while self.K[kj].parent is not None:
                    segment[kj] = self.K[kj].radius
                    if len(self.K[kj].children) > 1 or \
                        self.K[self.K[kj].parent].parent is None:
                        # flush segment
                        avg_segment_radius = sum(
                            segment.values()) / len(segment)
                        for kk in segment:
                            self.K[kk].radius = avg_segment_radius
                        segment = {}
                    kj = self.K[kj].parent
            if self.K[ki].parent is None:
                roots.add(ki)

        # roots radius

        #print 'roots: %s' % roots
        for ki in roots:
            #assert self.K[ki].get('radius', None) is None
            rad = 0
            for kj in self.K[ki].children:
                rad += self.K[kj].radius
            rad /= len(self.K[ki].children)
            self.K[ki].radius = rad

        # decreasing radius smoothing

        need_smoothing = True
        while need_smoothing:
            need_smoothing = False
            for ki in self.K:
                if not self.K[ki].children:
                    kj = ki
                    prev_radius = None
                    while self.K[kj].parent is not None:
                        curr_radius = self.K[kj].radius
                        next_radius = self.K[self.K[kj].parent].radius
                        if curr_radius > next_radius:
                            need_smoothing = True
                            if prev_radius:
                                curr_radius = (prev_radius + next_radius) / 2
                            else:
                                curr_radius = next_radius
                            curr_radius -= (0.01 * curr_radius)
                            self.K[kj].radius = curr_radius
                        prev_radius = curr_radius
                        kj = self.K[kj].parent
Beispiel #6
0
    def skeleton_reconstruction(self,
                                use_greedy_search=True,
                                extend_end_segments=True):
        for k in self.K:
            if self.K[k].level == 0: continue
            potential_k_parents = []  # list of (dist, potential_k_parent)'s
            found_k_parent = False
            for i, dist_ki in self.K_to_P[k]:
                # travel from k toward source, via one of its belonging paths
                for j in self.shortest_paths[i][::-1]:
                    if j not in self.P_to_K: continue
                    l, dist_lj = self.P_to_K[j]
                    if self.K[l].level >= self.K[k].level: continue
                    dist_kl = dist(self.K[k].pos, self.K[l].pos)
                    cost = dist_ki + dist_kl + dist_lj
                    potential_k_parents.append((cost, l))
                    if use_greedy_search:
                        # for full search (takes really longer),
                        # comment out these two lines (not sure it
                        # makes sense though!)
                        found_k_parent = True
                        break
                if found_k_parent:
                    break
            #assert potential_k_parents
            if not potential_k_parents:
                print "warning: couldn't find a parent for skeleton node %s" % k
                continue
            k_parent = sorted(potential_k_parents)[0][1]
            self.K[k].parent = k_parent
            self.K[k_parent].children.add(k)

        self.K.remove_orphan_nodes()

        if extend_end_segments:

            # more precise method, derived from:
            # http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
            for k, node in self.K.items():

                if not node.children:
                    # find point with max dist from source
                    p_max_dist = [float('-inf'), None]
                    for i in node.points:
                        if self.P_dist[i] > p_max_dist[0]:
                            p_max_dist[0] = self.P_dist[i]
                            p_max_dist[1] = i
                    p_max_dist = self.P[p_max_dist[1]]
                    x1 = self.K[node.parent].pos
                    x2 = node.pos
                    x0 = p_max_dist
                    s = -dot((x1 - x0), (x2 - x1)) / (linalg.norm(x2 - x1)**2)
                    v = x1 + (x2 - x1) * s
                    self.K[k].pos = v

                if node.parent is None:
                    p_min_dist = [float('inf'),
                                  None]  # should be the src point?
                    for i in node.points:
                        if self.P_dist[i] < p_min_dist[0]:
                            p_min_dist[0] = self.P_dist[i]
                            p_min_dist[1] = i
                    p_min_dist = self.P[p_min_dist[1]]
                    first_child_k = list(node.children)[0]
                    x1 = self.K[first_child_k].pos
                    x2 = node.pos
                    x0 = p_min_dist
                    s = -dot((x1 - x0), (x2 - x1)) / (linalg.norm(x2 - x1)**2)
                    v = x1 + (x2 - x1) * s
                    self.K[k].pos = v
    def volume_reconstruction(self):

        for ki in self.K:
            if not self.K[ki].children:
                kj = ki
                while self.K[kj].parent is not None:
                    kj_start_points = self.level_start_points[self.K[kj].level] \
                      & self.K[kj].points
                    # if not, will use initial radius estimation (not good!)
                    if kj_start_points:
                        kj_to_parent_midpoint = mean((self.K[kj].pos,
                                        self.K[self.K[kj].parent].pos), axis=0)
                        radius = 0
                        for pi in kj_start_points:
                            radius += dist(self.P[pi], kj_to_parent_midpoint)
                        radius /= len(kj_start_points)
                        self.K[kj].radius = radius
                    kj = self.K[kj].parent

        # segment radius smoothing

        roots = set()
        for ki in self.K:
            if not self.K[ki].children:
                segment = {} # kj -> radius
                kj = ki
                while self.K[kj].parent is not None:
                    segment[kj] = self.K[kj].radius
                    if len(self.K[kj].children) > 1 or \
                        self.K[self.K[kj].parent].parent is None:
                        # flush segment
                        avg_segment_radius = sum(segment.values()) / len(segment)
                        for kk in segment:
                            self.K[kk].radius = avg_segment_radius
                        segment = {}
                    kj = self.K[kj].parent
            if self.K[ki].parent is None:
                roots.add(ki)

        # roots radius

        #print 'roots: %s' % roots
        for ki in roots:
            #assert self.K[ki].get('radius', None) is None
            rad = 0
            for kj in self.K[ki].children:
                rad += self.K[kj].radius
            rad /= len(self.K[ki].children)
            self.K[ki].radius = rad

        # decreasing radius smoothing

        need_smoothing = True
        while need_smoothing:
            need_smoothing = False
            for ki in self.K:
                if not self.K[ki].children:
                    kj = ki
                    prev_radius = None
                    while self.K[kj].parent is not None:
                        curr_radius = self.K[kj].radius
                        next_radius = self.K[self.K[kj].parent].radius
                        if curr_radius > next_radius:
                            need_smoothing = True
                            if prev_radius:
                                curr_radius = (prev_radius + next_radius) / 2
                            else:
                                curr_radius = next_radius
                            curr_radius -= (0.01 * curr_radius)
                            self.K[kj].radius = curr_radius
                        prev_radius = curr_radius
                        kj = self.K[kj].parent
    def skeleton_reconstruction(self, use_greedy_search=True,
                               extend_end_segments=True):
        for k in self.K:
            if self.K[k].level == 0: continue
            potential_k_parents = [] # list of (dist, potential_k_parent)'s
            found_k_parent = False
            for i, dist_ki in self.K_to_P[k]:
                # travel from k toward source, via one of its belonging paths
                for j in self.shortest_paths[i][::-1]:
                    if j not in self.P_to_K: continue
                    l, dist_lj = self.P_to_K[j]
                    if self.K[l].level >= self.K[k].level: continue
                    dist_kl = dist(self.K[k].pos, self.K[l].pos)
                    cost = dist_ki + dist_kl + dist_lj
                    potential_k_parents.append((cost, l))
                    if use_greedy_search:
                        # for full search (takes really longer),
                        # comment out these two lines (not sure it
                        # makes sense though!)
                        found_k_parent = True
                        break
                if found_k_parent:
                    break
            #assert potential_k_parents
            if not potential_k_parents:
                print "warning: couldn't find a parent for skeleton node %s" % k
                continue
            k_parent = sorted(potential_k_parents)[0][1]
            self.K[k].parent = k_parent
            self.K[k_parent].children.add(k)

        self.K.remove_orphan_nodes()

        if extend_end_segments:

            # more precise method, derived from:
            # http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
            for k, node in self.K.items():

                if not node.children:
                    # find point with max dist from source
                    p_max_dist = [float('-inf'), None]
                    for i in node.points:
                        if self.P_dist[i] > p_max_dist[0]:
                            p_max_dist[0] = self.P_dist[i]
                            p_max_dist[1] = i
                    p_max_dist = self.P[p_max_dist[1]]
                    x1 = self.K[node.parent].pos
                    x2 = node.pos
                    x0 = p_max_dist
                    s = -dot((x1 - x0), (x2 - x1)) / (linalg.norm(x2 - x1) ** 2)
                    v = x1 + (x2 - x1) * s
                    self.K[k].pos = v

                if node.parent is None:
                    p_min_dist = [float('inf'), None] # should be the src point?
                    for i in node.points:
                        if self.P_dist[i] < p_min_dist[0]:
                            p_min_dist[0] = self.P_dist[i]
                            p_min_dist[1] = i
                    p_min_dist = self.P[p_min_dist[1]]
                    first_child_k = list(node.children)[0]
                    x1 = self.K[first_child_k].pos
                    x2 = node.pos
                    x0 = p_min_dist
                    s = -dot((x1 - x0), (x2 - x1)) / (linalg.norm(x2 - x1) ** 2)
                    v = x1 + (x2 - x1) * s
                    self.K[k].pos = v