Loading .travis.yml +1 −1 Original line number Diff line number Diff line Loading @@ -65,7 +65,7 @@ install: - python condaci.py setup script: - pytest autocnet functional_tests - pytest autocnet tests after_success: # Upload to anaconda and push to coveralls Loading autocnet/graph/network.py +10 −79 Original line number Diff line number Diff line Loading @@ -227,34 +227,6 @@ class CandidateGraph(nx.Graph): """ return self.node[node_index]['image_name'] def get_matches(self, clean_keys=[]): """ For each edge get all valid matches, masked by the clean_keys. Parameters ---------- clean_keys: list of masks to use Returns ------- matches : list of matches dataframes """ matches = [] for s, d, e in self.edges_iter(data=True): match, _ = e.clean(clean_keys=clean_keys) match = match[['source_image', 'source_idx', 'destination_image', 'destination_idx']] skps = e.get_keypoints('source', index=match.source_idx) skps.columns = ['source_x', 'source_y'] dkps = e.get_keypoints('destination', index=match.destination_idx) dkps.columns = ['destination_x', 'destination_y'] match = match.join(skps, on='source_idx') match = match.join(dkps, on='destination_idx') matches.append(match) return matches def get_matches(self, clean_keys=[]): matches = [] for s, d, e in self.edges_iter(data=True): Loading Loading @@ -314,18 +286,7 @@ class CandidateGraph(nx.Graph): print('Processing {}'.format(node['image_name'])) node.extract_features_with_tiling(tilesize=tilesize, overlap=overlap, *args, **kwargs) def extract_subsets(self, *args, **kwargs): """ Extracts features from each image in those regions estimated to be overlapping. *args and **kwargs are passed to the feature extractor. For example, passing method='sift' will cause the extractor to use the sift method. """ for source, destination, e in self.edges_iter(data=True): e.extract_subset(*args, **kwargs) def save_features(self, out_path, nodes=[], **kwargs): def save_features(self, out_path): """ Save the features (keypoints and descriptors) for the Loading @@ -336,15 +297,11 @@ class CandidateGraph(nx.Graph): out_path : str Location of the output file. If the file exists, features are appended. Otherwise, the file is created. nodes : list of nodes to save features for. If empty, save for all nodes """ for i, n in self.nodes_iter(data=True): if nodes and not i in nodes: continue n.save_features(out_path, **kwargs) self.apply(Node.save_features, args=(out_path,), on='node') def load_features(self, in_path, nodes=[], nfeatures=None, **kwargs): """ Loading Loading @@ -457,7 +414,7 @@ class CandidateGraph(nx.Graph): mst = nx.minimum_spanning_tree(self) return self.create_edge_subgraph(mst.edges()) def apply_func_to_edges(self, function, *args, **kwargs): def apply_func_to_edges(self, function, nodes=[], *args, **kwargs): """ Iterates over edges using an optional mask and and applies the given function. If func is not an attribute of Edge, raises AttributeError Loading Loading @@ -486,7 +443,6 @@ class CandidateGraph(nx.Graph): if any(return_lis): return return_lis def apply(self, function, on='edge',out=None, args=(), **kwargs): """ Applys a function to every node or edge, returns collected return Loading Loading @@ -526,13 +482,16 @@ class CandidateGraph(nx.Graph): raise TypeError('{} is not callable.'.format(function)) res = [] obj = 1 # We just want to the object, not the indices, so slcie appropriately if options[on] == self.edges_iter: obj = 2 for elem in options[on](data=True): res.append(function(elem, *args, **kwargs)) res.append(function(elem[obj], *args, **kwargs)) if out: out=res else: return res def symmetry_checks(self): ''' Apply a symmetry check to all edges in the graph Loading Loading @@ -832,34 +791,6 @@ class CandidateGraph(nx.Graph): H.graph = self.graph return H # def nodes_iter(self, data=False): # s = super(CandidateGraph, self) # nodes = s.nodes_iter(data) # ret = [] # for n in nodes: # if data: # if n[0] in self.nodemask: # ret.append(n) # else: # if n in self.nodemask: # ret.append(n) # return iter(ret) # def edges_iter(self, nbunch=[], data=False, key=False): # s = super(CandidateGraph, self) # if not isinstance(nbunch, list): # nbunch = [nbunch] # # if nbunch: # nbunch = [node for node in nbunch if nbunch not in list(self.nodemask)] # else: # nbunch = list(self.nodemask) # # try: # return s.edges_iter(nbunch=nbunch, data=data) # except: # return s.edges_iter([self.node[node]['image_path'] for node in nbunch], data=data) def subgraph_from_matches(self): """ Returns a sub-graph where all edges have matches. Loading autocnet/graph/node.py +3 −7 Original line number Diff line number Diff line Loading @@ -402,24 +402,20 @@ class Node(dict, MutableMapping): def save_features(self, out_path): """ Save the extracted keypoints and descriptors to the given HDF5 file. By default, the .npz files are saved the given file. By default, the .npz files are saved along side the image, e.g. in the same folder as the image. Parameters ---------- out_path : str or object PATH to the hdf file or a HDFDataset object handle format : {'npy', 'hdf'} The desired output format. PATH to the directory for output and base file name """ if self.keypoints.empty: warnings.warn('Node {} has not had features extracted.'.format(self['node_id'])) return io_keypoints.to_npy(self.keypoints, self.descriptors, out_path) out_path + '_{}.npz'.format(self['node_id'])) def coverage_ratio(self, clean_keys=[]): """ Loading autocnet/graph/tests/test_network.py +8 −4 Original line number Diff line number Diff line Loading @@ -276,13 +276,17 @@ def test_is_complete(graph): assert False == incomplete_graph.is_complete() assert True == graph.is_complete() def test_get_matches(candidategraph): matches = candidategraph.get_matches() assert len(matches) == 3 assert 'source_x' in matches[0].columns assert len(matches[0]) == 8 def test_apply(graph): def set_matches(x): s,d,e = x def set_matches(e): e.matches = ['fake', 'fake', 'fake'] def get_matches(x): s,d,e = x def get_matches(e): return e.matches graph.apply(set_matches) Loading tests/test_save_load.py +10 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,8 @@ from autocnet.examples import get_path from autocnet.graph.network import CandidateGraph from autocnet.io.network import load import numpy as np def test_save_project(tmpdir, candidategraph): path = tmpdir.join('prject.proj') candidategraph.save(path.strpath) Loading @@ -9,3 +11,11 @@ def test_save_project(tmpdir, candidategraph): candidategraph2 = load(path.strpath) assert candidategraph == candidategraph2 def test_save_features(tmpdir, candidategraph): path = tmpdir.join('features') candidategraph.save_features(path.strpath) d = np.load(path.strpath + '_0.npz') np.testing.assert_array_equal(d['descriptors'], candidategraph.node[0].descriptors) Loading
.travis.yml +1 −1 Original line number Diff line number Diff line Loading @@ -65,7 +65,7 @@ install: - python condaci.py setup script: - pytest autocnet functional_tests - pytest autocnet tests after_success: # Upload to anaconda and push to coveralls Loading
autocnet/graph/network.py +10 −79 Original line number Diff line number Diff line Loading @@ -227,34 +227,6 @@ class CandidateGraph(nx.Graph): """ return self.node[node_index]['image_name'] def get_matches(self, clean_keys=[]): """ For each edge get all valid matches, masked by the clean_keys. Parameters ---------- clean_keys: list of masks to use Returns ------- matches : list of matches dataframes """ matches = [] for s, d, e in self.edges_iter(data=True): match, _ = e.clean(clean_keys=clean_keys) match = match[['source_image', 'source_idx', 'destination_image', 'destination_idx']] skps = e.get_keypoints('source', index=match.source_idx) skps.columns = ['source_x', 'source_y'] dkps = e.get_keypoints('destination', index=match.destination_idx) dkps.columns = ['destination_x', 'destination_y'] match = match.join(skps, on='source_idx') match = match.join(dkps, on='destination_idx') matches.append(match) return matches def get_matches(self, clean_keys=[]): matches = [] for s, d, e in self.edges_iter(data=True): Loading Loading @@ -314,18 +286,7 @@ class CandidateGraph(nx.Graph): print('Processing {}'.format(node['image_name'])) node.extract_features_with_tiling(tilesize=tilesize, overlap=overlap, *args, **kwargs) def extract_subsets(self, *args, **kwargs): """ Extracts features from each image in those regions estimated to be overlapping. *args and **kwargs are passed to the feature extractor. For example, passing method='sift' will cause the extractor to use the sift method. """ for source, destination, e in self.edges_iter(data=True): e.extract_subset(*args, **kwargs) def save_features(self, out_path, nodes=[], **kwargs): def save_features(self, out_path): """ Save the features (keypoints and descriptors) for the Loading @@ -336,15 +297,11 @@ class CandidateGraph(nx.Graph): out_path : str Location of the output file. If the file exists, features are appended. Otherwise, the file is created. nodes : list of nodes to save features for. If empty, save for all nodes """ for i, n in self.nodes_iter(data=True): if nodes and not i in nodes: continue n.save_features(out_path, **kwargs) self.apply(Node.save_features, args=(out_path,), on='node') def load_features(self, in_path, nodes=[], nfeatures=None, **kwargs): """ Loading Loading @@ -457,7 +414,7 @@ class CandidateGraph(nx.Graph): mst = nx.minimum_spanning_tree(self) return self.create_edge_subgraph(mst.edges()) def apply_func_to_edges(self, function, *args, **kwargs): def apply_func_to_edges(self, function, nodes=[], *args, **kwargs): """ Iterates over edges using an optional mask and and applies the given function. If func is not an attribute of Edge, raises AttributeError Loading Loading @@ -486,7 +443,6 @@ class CandidateGraph(nx.Graph): if any(return_lis): return return_lis def apply(self, function, on='edge',out=None, args=(), **kwargs): """ Applys a function to every node or edge, returns collected return Loading Loading @@ -526,13 +482,16 @@ class CandidateGraph(nx.Graph): raise TypeError('{} is not callable.'.format(function)) res = [] obj = 1 # We just want to the object, not the indices, so slcie appropriately if options[on] == self.edges_iter: obj = 2 for elem in options[on](data=True): res.append(function(elem, *args, **kwargs)) res.append(function(elem[obj], *args, **kwargs)) if out: out=res else: return res def symmetry_checks(self): ''' Apply a symmetry check to all edges in the graph Loading Loading @@ -832,34 +791,6 @@ class CandidateGraph(nx.Graph): H.graph = self.graph return H # def nodes_iter(self, data=False): # s = super(CandidateGraph, self) # nodes = s.nodes_iter(data) # ret = [] # for n in nodes: # if data: # if n[0] in self.nodemask: # ret.append(n) # else: # if n in self.nodemask: # ret.append(n) # return iter(ret) # def edges_iter(self, nbunch=[], data=False, key=False): # s = super(CandidateGraph, self) # if not isinstance(nbunch, list): # nbunch = [nbunch] # # if nbunch: # nbunch = [node for node in nbunch if nbunch not in list(self.nodemask)] # else: # nbunch = list(self.nodemask) # # try: # return s.edges_iter(nbunch=nbunch, data=data) # except: # return s.edges_iter([self.node[node]['image_path'] for node in nbunch], data=data) def subgraph_from_matches(self): """ Returns a sub-graph where all edges have matches. Loading
autocnet/graph/node.py +3 −7 Original line number Diff line number Diff line Loading @@ -402,24 +402,20 @@ class Node(dict, MutableMapping): def save_features(self, out_path): """ Save the extracted keypoints and descriptors to the given HDF5 file. By default, the .npz files are saved the given file. By default, the .npz files are saved along side the image, e.g. in the same folder as the image. Parameters ---------- out_path : str or object PATH to the hdf file or a HDFDataset object handle format : {'npy', 'hdf'} The desired output format. PATH to the directory for output and base file name """ if self.keypoints.empty: warnings.warn('Node {} has not had features extracted.'.format(self['node_id'])) return io_keypoints.to_npy(self.keypoints, self.descriptors, out_path) out_path + '_{}.npz'.format(self['node_id'])) def coverage_ratio(self, clean_keys=[]): """ Loading
autocnet/graph/tests/test_network.py +8 −4 Original line number Diff line number Diff line Loading @@ -276,13 +276,17 @@ def test_is_complete(graph): assert False == incomplete_graph.is_complete() assert True == graph.is_complete() def test_get_matches(candidategraph): matches = candidategraph.get_matches() assert len(matches) == 3 assert 'source_x' in matches[0].columns assert len(matches[0]) == 8 def test_apply(graph): def set_matches(x): s,d,e = x def set_matches(e): e.matches = ['fake', 'fake', 'fake'] def get_matches(x): s,d,e = x def get_matches(e): return e.matches graph.apply(set_matches) Loading
tests/test_save_load.py +10 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,8 @@ from autocnet.examples import get_path from autocnet.graph.network import CandidateGraph from autocnet.io.network import load import numpy as np def test_save_project(tmpdir, candidategraph): path = tmpdir.join('prject.proj') candidategraph.save(path.strpath) Loading @@ -9,3 +11,11 @@ def test_save_project(tmpdir, candidategraph): candidategraph2 = load(path.strpath) assert candidategraph == candidategraph2 def test_save_features(tmpdir, candidategraph): path = tmpdir.join('features') candidategraph.save_features(path.strpath) d = np.load(path.strpath + '_0.npz') np.testing.assert_array_equal(d['descriptors'], candidategraph.node[0].descriptors)