Loading autocnet/graph/edge.py +6 −9 Original line number Diff line number Diff line Loading @@ -113,15 +113,12 @@ class Edge(dict, MutableMapping): all_source_keypoints = self.source.get_keypoint_coordinates(matches['source_idx']) all_destin_keypoints = self.destination.get_keypoint_coordinates(matches['destination_idx']) matches, mask = self._clean(clean_keys) s_keypoints = self.source.get_keypoint_coordinates(matches['source_idx']).values d_keypoints = self.destination.get_keypoint_coordinates(matches['destination_idx']).values transformation_matrix, fundam_mask = od.compute_fundamental_matrix(s_keypoints, d_keypoints, **kwargs) try: fundam_mask = fundam_mask.ravel() except: Loading Loading @@ -274,7 +271,7 @@ class Edge(dict, MutableMapping): self.masks = ('threshold', threshold_mask) self.masks = ('subpixel', mask) def suppress(self, func=spf.correlation, clean_keys=[], **kwargs): def suppress(self, suppression_func=spf.correlation, clean_keys=[], **kwargs): """ Apply a disc based suppression algorithm to get a good spatial distribution of high quality points, where the user defines some Loading @@ -282,7 +279,7 @@ class Edge(dict, MutableMapping): Parameters ---------- func : object suppression_func : object A function that returns a scalar value to be used as the strength of a given row in the matches data frame. Loading @@ -300,7 +297,7 @@ class Edge(dict, MutableMapping): # Massage the dataframe into the correct structure coords = self.source.get_keypoint_coordinates() merged = matches.merge(coords, left_on=['source_idx'], right_index=True) merged['strength'] = merged.apply(func, axis=1) merged['strength'] = merged.apply(suppression_func, axis=1) if not hasattr(self, 'suppression'): # Instantiate the suppression object and suppress matches Loading autocnet/graph/network.py +42 −11 Original line number Diff line number Diff line from functools import singledispatch import itertools import math import os import dill as pickle import warnings import networkx as nx import numpy as np import pandas as pd Loading Loading @@ -39,6 +37,7 @@ class CandidateGraph(nx.Graph): list of node indices ---------- """ edge_attr_dict_factory = Edge def __init__(self, *args, basepath=None, **kwargs): super(CandidateGraph, self).__init__(*args, **kwargs) Loading @@ -46,23 +45,32 @@ class CandidateGraph(nx.Graph): node_labels = {} self.node_name_map = {} self.graph_masks = pd.DataFrame() # the node_name is the relative path for the image for node_name, node in self.nodes_iter(data=True): for node_name in self.nodes(): image_name = os.path.basename(node_name) image_path = node_name # Replace the default node dict with an object # Replace the default attr dict with a Node object self.node[node_name] = Node(image_name, image_path, self.node_counter) # fill the dictionary used for relabelling nodes with relative path keys node_labels[node_name] = self.node_counter # fill the dictionary used for mapping base name to node index self.node_name_map[self.node[node_name].image_name] = self.node_counter self.node_counter += 1 nx.relabel_nodes(self, node_labels, copy=False) for s, d in self.edges(): if s > d: s, d = d, s e = self.edge[s][d] e.source = self.node[s] e.destination = self.node[d] #del self.adj[d][s] # Add the Edge class as a edge data structure for s, d, edge in self.edges_iter(data=True): self.edge[s][d] = Edge(self.node[s], self.node[d]) #for s, d, edge in self.edges_iter(data=True): #self.edge[s][d] = Edge(self.node[s], self.node[d]) @classmethod def from_graph(cls, graph): Loading Loading @@ -244,7 +252,7 @@ class CandidateGraph(nx.Graph): hdf = None def load_features(self, in_path, nodes=[]): def load_features(self, in_path, nodes=[], nfeatures=None): """ Load features (keypoints and descriptors) for the specified nodes. Loading Loading @@ -656,10 +664,33 @@ class CandidateGraph(nx.Graph): H.adj[v] = H.adjlist_dict_factory() # Copy the edge attributes. H.edge[u][v] = self.edge[u][v] H.edge[v][u] = self.edge[v][u] #H.edge[v][u] = self.edge[v][u] H.graph = self.graph return H def size(self, weight=None): """ This replaces the built-in size method to properly support Python 3 rounding. Parameters ---------- weight : string or None, optional (default=None) The edge attribute that holds the numerical value used as a weight. If None, then each edge has weight 1. Returns ------- nedges : int The number of edges or sum of edge weights in the graph. """ s = sum(self.degree(weight=weight).values()) / 2 if weight is None: return math.ceil(s) else: return s def create_node_subgraph(self, nodes): """ Given a list of nodes, create a sub-graph and Loading autocnet/graph/node.py +4 −1 Original line number Diff line number Diff line Loading @@ -217,7 +217,10 @@ class Node(dict, MutableMapping): index = raw_kps['index'] clean_kps = utils.remove_field_name(raw_kps, 'index') columns = clean_kps.dtype.names self._keypoints = pd.DataFrame(data=clean_kps, columns=columns, index=index) allkps = pd.DataFrame(data=clean_kps, columns=columns, index=index) self._keypoints = allkps.sort_values(by='response', ascending=False).head(250) if isinstance(in_path, str): hdf = None Loading autocnet/graph/tests/test_network.py +0 −1 Original line number Diff line number Diff line Loading @@ -122,7 +122,6 @@ class TestCandidateGraph(unittest.TestCase): test_sub_graph = graph.create_node_subgraph([0, 1]) test_sub_graph.extract_features(extractor_parameters={'nfeatures': 500}) test_sub_graph.match_features(k=2) filtered_nodes = graph.filter_nodes(lambda node: hasattr(node, 'descriptors')) filtered_edges = graph.filter_edges(edge_func) Loading autocnet/graph/tests/test_node.py +2 −1 Original line number Diff line number Diff line Loading @@ -71,6 +71,7 @@ class TestNode(unittest.TestCase): kps = self.node.get_keypoints().copy() descriptors = self.node.descriptors.copy() self.node.load_features('node_test.hdf') self.assertTrue((kps == self.node.get_keypoints()).all().all()) self.assertTrue((kps.sort(axis=0) == self.node.get_keypoints().sort(axis=0)).all().all()) os.remove('node_test.hdf') Loading
autocnet/graph/edge.py +6 −9 Original line number Diff line number Diff line Loading @@ -113,15 +113,12 @@ class Edge(dict, MutableMapping): all_source_keypoints = self.source.get_keypoint_coordinates(matches['source_idx']) all_destin_keypoints = self.destination.get_keypoint_coordinates(matches['destination_idx']) matches, mask = self._clean(clean_keys) s_keypoints = self.source.get_keypoint_coordinates(matches['source_idx']).values d_keypoints = self.destination.get_keypoint_coordinates(matches['destination_idx']).values transformation_matrix, fundam_mask = od.compute_fundamental_matrix(s_keypoints, d_keypoints, **kwargs) try: fundam_mask = fundam_mask.ravel() except: Loading Loading @@ -274,7 +271,7 @@ class Edge(dict, MutableMapping): self.masks = ('threshold', threshold_mask) self.masks = ('subpixel', mask) def suppress(self, func=spf.correlation, clean_keys=[], **kwargs): def suppress(self, suppression_func=spf.correlation, clean_keys=[], **kwargs): """ Apply a disc based suppression algorithm to get a good spatial distribution of high quality points, where the user defines some Loading @@ -282,7 +279,7 @@ class Edge(dict, MutableMapping): Parameters ---------- func : object suppression_func : object A function that returns a scalar value to be used as the strength of a given row in the matches data frame. Loading @@ -300,7 +297,7 @@ class Edge(dict, MutableMapping): # Massage the dataframe into the correct structure coords = self.source.get_keypoint_coordinates() merged = matches.merge(coords, left_on=['source_idx'], right_index=True) merged['strength'] = merged.apply(func, axis=1) merged['strength'] = merged.apply(suppression_func, axis=1) if not hasattr(self, 'suppression'): # Instantiate the suppression object and suppress matches Loading
autocnet/graph/network.py +42 −11 Original line number Diff line number Diff line from functools import singledispatch import itertools import math import os import dill as pickle import warnings import networkx as nx import numpy as np import pandas as pd Loading Loading @@ -39,6 +37,7 @@ class CandidateGraph(nx.Graph): list of node indices ---------- """ edge_attr_dict_factory = Edge def __init__(self, *args, basepath=None, **kwargs): super(CandidateGraph, self).__init__(*args, **kwargs) Loading @@ -46,23 +45,32 @@ class CandidateGraph(nx.Graph): node_labels = {} self.node_name_map = {} self.graph_masks = pd.DataFrame() # the node_name is the relative path for the image for node_name, node in self.nodes_iter(data=True): for node_name in self.nodes(): image_name = os.path.basename(node_name) image_path = node_name # Replace the default node dict with an object # Replace the default attr dict with a Node object self.node[node_name] = Node(image_name, image_path, self.node_counter) # fill the dictionary used for relabelling nodes with relative path keys node_labels[node_name] = self.node_counter # fill the dictionary used for mapping base name to node index self.node_name_map[self.node[node_name].image_name] = self.node_counter self.node_counter += 1 nx.relabel_nodes(self, node_labels, copy=False) for s, d in self.edges(): if s > d: s, d = d, s e = self.edge[s][d] e.source = self.node[s] e.destination = self.node[d] #del self.adj[d][s] # Add the Edge class as a edge data structure for s, d, edge in self.edges_iter(data=True): self.edge[s][d] = Edge(self.node[s], self.node[d]) #for s, d, edge in self.edges_iter(data=True): #self.edge[s][d] = Edge(self.node[s], self.node[d]) @classmethod def from_graph(cls, graph): Loading Loading @@ -244,7 +252,7 @@ class CandidateGraph(nx.Graph): hdf = None def load_features(self, in_path, nodes=[]): def load_features(self, in_path, nodes=[], nfeatures=None): """ Load features (keypoints and descriptors) for the specified nodes. Loading Loading @@ -656,10 +664,33 @@ class CandidateGraph(nx.Graph): H.adj[v] = H.adjlist_dict_factory() # Copy the edge attributes. H.edge[u][v] = self.edge[u][v] H.edge[v][u] = self.edge[v][u] #H.edge[v][u] = self.edge[v][u] H.graph = self.graph return H def size(self, weight=None): """ This replaces the built-in size method to properly support Python 3 rounding. Parameters ---------- weight : string or None, optional (default=None) The edge attribute that holds the numerical value used as a weight. If None, then each edge has weight 1. Returns ------- nedges : int The number of edges or sum of edge weights in the graph. """ s = sum(self.degree(weight=weight).values()) / 2 if weight is None: return math.ceil(s) else: return s def create_node_subgraph(self, nodes): """ Given a list of nodes, create a sub-graph and Loading
autocnet/graph/node.py +4 −1 Original line number Diff line number Diff line Loading @@ -217,7 +217,10 @@ class Node(dict, MutableMapping): index = raw_kps['index'] clean_kps = utils.remove_field_name(raw_kps, 'index') columns = clean_kps.dtype.names self._keypoints = pd.DataFrame(data=clean_kps, columns=columns, index=index) allkps = pd.DataFrame(data=clean_kps, columns=columns, index=index) self._keypoints = allkps.sort_values(by='response', ascending=False).head(250) if isinstance(in_path, str): hdf = None Loading
autocnet/graph/tests/test_network.py +0 −1 Original line number Diff line number Diff line Loading @@ -122,7 +122,6 @@ class TestCandidateGraph(unittest.TestCase): test_sub_graph = graph.create_node_subgraph([0, 1]) test_sub_graph.extract_features(extractor_parameters={'nfeatures': 500}) test_sub_graph.match_features(k=2) filtered_nodes = graph.filter_nodes(lambda node: hasattr(node, 'descriptors')) filtered_edges = graph.filter_edges(edge_func) Loading
autocnet/graph/tests/test_node.py +2 −1 Original line number Diff line number Diff line Loading @@ -71,6 +71,7 @@ class TestNode(unittest.TestCase): kps = self.node.get_keypoints().copy() descriptors = self.node.descriptors.copy() self.node.load_features('node_test.hdf') self.assertTrue((kps == self.node.get_keypoints()).all().all()) self.assertTrue((kps.sort(axis=0) == self.node.get_keypoints().sort(axis=0)).all().all()) os.remove('node_test.hdf')