Loading .travis.yml +6 −4 Changes for .travis.yml: 6 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -27,13 +27,15 @@ install: - conda info -a # Create a virtual env and install dependencies - conda create -y -q -n test-env python=$TRAVIS_PYTHON_VERSION nose gdal numpy pillow scipy pandas networkx scikit-image - conda create -y -q -n test-env python=$TRAVIS_PYTHON_VERSION nose numpy pillow scipy pandas networkx scikit-image # Activate the env - source activate test-env # Install the non-conda packages if required, requirements.txt duplicates are ignored - conda install -c https://conda.anaconda.org/jlaura opencv3=3.0.0 - conda install -c https://conda.anaconda.org/osgeo gdal - conda install -c osgeo proj4 - conda upgrade numpy - pip install -r requirements.txt - pip install coverage - pip install coveralls Loading @@ -41,6 +43,9 @@ install: script: - nosetests --with-coverage --cover-package=autocnet after_success: - coveralls notifications: email: recipients: Loading @@ -50,6 +55,3 @@ notifications: - jwbacker@usgs.gov on_success: always on_failure: always No newline at end of file after_success: - coveralls autocnet/fileio/io_gdal.py +4 −2 Changes for autocnet/fileio/io_gdal.py: 4 added lines, 2 removed lines. Original line number Diff line number Diff line import os import numpy as np from osgeo import gdal from osgeo import osr import gdal import osr from autocnet.fileio import extract_metadata gdal.UseExceptions() NP2GDAL_CONVERSION = { "uint8": 1, "int8": 1, Loading autocnet/graph/network.py +73 −18 Changes for autocnet/graph/network.py: 73 added lines, 18 removed lines. Original line number Diff line number Diff line Loading @@ -258,7 +258,6 @@ class CandidateGraph(nx.Graph): transformation_matrix, ransac_mask = od.compute_homography(s_coords, d_coords) ransac_mask = ransac_mask.ravel() # Convert the truncated RANSAC mask back into a full length mask if clean_keys: Loading @@ -266,34 +265,78 @@ class CandidateGraph(nx.Graph): else: mask = ransac_mask # Compute the error in the homography s_trans = np.hstack((s_coords[::-1],np.ones(s_coords.shape[0]).reshape(-1,1))).T s_trans = np.dot(transformation_matrix, s_trans).T #Normalize the error for i in range(3): s_trans[i] /= s_trans[2] d_trans = np.hstack((d_coords[::-1], np.ones(d_coords.shape[0]).reshape(-1,1))) attributes['homography_error'] = np.sqrt(np.sum((d_trans - s_trans)**2, axis=1)) attributes['homography'] = transformation_matrix attributes['ransac'] = mask def compute_subpixel_offsets(self): def compute_subpixel_offsets(self, clean_keys=[], threshold=0.8, upsampling=10): """ For the entire graph, compute the subpixel offsets using pattern-matching and add the result as an attribute to each edge of the graph. Returns ------- subpixel_offsets : ndarray A numpy array containing all the subpixel offsets for the entire graph. Parameters ---------- clean_keys : list of string keys to masking arrays (created by calling outlier detection) threshold : float On the range [-1, 1]. Values less than or equal to this threshold are masked and can be considered outliers """ subpixel_offsets = [] for source, destination, attributes in self.edges_iter(data=True): #for each edge matches = attributes['matches'] #grab the matches for source, destination, attributes in self.edges_iter(data=True): matches = attributes['matches'] full_offsets = np.zeros((len(matches), 3)) # Build up a composite mask from all of the user specified masks if clean_keys: mask = np.prod([attributes[i] for i in clean_keys], axis=0, dtype=np.bool) matches = matches[mask] full_mask = np.where(mask == True) src_image = self.node[source]['image'] dest_image = self.node[destination]['image'] edge_offsets = [] for i, (idx, row) in enumerate(matches.iterrows()): #for each edge, calculate this for each keypoint pair # Preallocate the numpy array to avoid appending and type conversion edge_offsets = np.empty((len(matches),3)) # for each edge, calculate this for each keypoint pair for i, (idx, row) in enumerate(matches.iterrows()): s_idx = int(row['source_idx']) d_idx = int(row['destination_idx']) src_keypoint = self.node[source]['keypoints'][s_idx] dest_keypoint = self.node[destination]['keypoints'][d_idx] edge_offsets.append(sp.subpixel_offset(src_keypoint, dest_keypoint, src_image, dest_image)) attributes['subpixel_offsets'] = np.array(edge_offsets) subpixel_offsets.append(np.array(edge_offsets)) return subpixel_offsets # Compute the subpixel offset edge_offsets[i] = sp.subpixel_offset(src_keypoint, dest_keypoint, src_image, dest_image, upsampling=upsampling) # Compute the mask for correlations less than the threshold threshold_mask = edge_offsets[edge_offsets[:,-1] >= threshold] # Convert the truncated mask back into a full length mask if clean_keys: mask[full_mask] = threshold_mask full_offsets[full_mask] = edge_offsets else: mask = threshold_mask attributes['subpixel_offsets'] = pd.DataFrame(full_offsets, columns=['x_offset', 'y_offset', 'correlation']) attributes['subpixel'] = mask def to_cnet(self, clean_keys=[]): """ Loading Loading @@ -349,12 +392,15 @@ class CandidateGraph(nx.Graph): mask = np.prod([attributes[i] for i in clean_keys], axis=0, dtype=np.bool) matches = matches[mask] if 'subpixel' in clean_keys: offsets = attributes['subpixel_offsets'][attributes['subpixel']] print(offsets) kp1 = self.node[source]['keypoints'] kp2 = self.node[destination]['keypoints'] pt_idx = 0 values = [] for idx, row in matches.iterrows(): for i, (idx, row) in enumerate(matches.iterrows()): # Composite matching key (node_id, point_id) m1 = (source, int(row['source_idx'])) m2 = (destination, int(row['destination_idx'])) Loading @@ -365,8 +411,17 @@ class CandidateGraph(nx.Graph): pt_idx, source]) values.append([kp2[m2[1]].pt[0], kp2[m2[1]].pt[1], kp2x = kp2[m2[1]].pt[0] kp2y = kp2[m2[1]].pt[1] if 'subpixel' in clean_keys: print(idx) print(kp2x, kp2y) kp2x += offsets['x_offset'].values[i] kp2y += offsets['y_offset'].values[i] print(kp2x, kp2y) values.append([kp2x, kp2y, m2, pt_idx, destination]) Loading autocnet/graph/tests/test_network.py +7 −5 Changes for autocnet/graph/tests/test_network.py: 7 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -13,8 +13,9 @@ from .. import network class TestCandidateGraph(unittest.TestCase): def setUp(self): self.graph = network.CandidateGraph.from_adjacency(get_path('adjacency.json')) @classmethod def setUpClass(cls): cls.graph = network.CandidateGraph.from_adjacency(get_path('adjacency.json')) def test_get_name(self): node_number = self.graph.node_name_map['AS15-M-0297_SML.png'] Loading @@ -28,6 +29,10 @@ class TestCandidateGraph(unittest.TestCase): def test_to_json_file(self): self.graph.to_json_file('test_graph_to_json.json') self.assertTrue(os.path.exists('test_graph_to_json.json')) try: os.remove('test_graph_to_json.json') except: pass def test_extract_features(self): # also tests get_geodataset() and get_keypoints Loading @@ -42,7 +47,4 @@ class TestCandidateGraph(unittest.TestCase): self.assertEquals(self.graph.get_keypoints(node_number), node['keypoints']) def tearDown(self): try: os.remove('test_graph_to_json.json') except: pass autocnet/matcher/outlier_detector.py +2 −0 Changes for autocnet/matcher/outlier_detector.py: 2 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -148,3 +148,5 @@ def compute_homography(kp1, kp2, outlier_algorithm=cv2.RANSAC, reproj_threshold= reproj_threshold) mask = mask.astype(bool) return transformation_matrix, mask Loading
.travis.yml +6 −4 Changes for .travis.yml: 6 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -27,13 +27,15 @@ install: - conda info -a # Create a virtual env and install dependencies - conda create -y -q -n test-env python=$TRAVIS_PYTHON_VERSION nose gdal numpy pillow scipy pandas networkx scikit-image - conda create -y -q -n test-env python=$TRAVIS_PYTHON_VERSION nose numpy pillow scipy pandas networkx scikit-image # Activate the env - source activate test-env # Install the non-conda packages if required, requirements.txt duplicates are ignored - conda install -c https://conda.anaconda.org/jlaura opencv3=3.0.0 - conda install -c https://conda.anaconda.org/osgeo gdal - conda install -c osgeo proj4 - conda upgrade numpy - pip install -r requirements.txt - pip install coverage - pip install coveralls Loading @@ -41,6 +43,9 @@ install: script: - nosetests --with-coverage --cover-package=autocnet after_success: - coveralls notifications: email: recipients: Loading @@ -50,6 +55,3 @@ notifications: - jwbacker@usgs.gov on_success: always on_failure: always No newline at end of file after_success: - coveralls
autocnet/fileio/io_gdal.py +4 −2 Changes for autocnet/fileio/io_gdal.py: 4 added lines, 2 removed lines. Original line number Diff line number Diff line import os import numpy as np from osgeo import gdal from osgeo import osr import gdal import osr from autocnet.fileio import extract_metadata gdal.UseExceptions() NP2GDAL_CONVERSION = { "uint8": 1, "int8": 1, Loading
autocnet/graph/network.py +73 −18 Changes for autocnet/graph/network.py: 73 added lines, 18 removed lines. Original line number Diff line number Diff line Loading @@ -258,7 +258,6 @@ class CandidateGraph(nx.Graph): transformation_matrix, ransac_mask = od.compute_homography(s_coords, d_coords) ransac_mask = ransac_mask.ravel() # Convert the truncated RANSAC mask back into a full length mask if clean_keys: Loading @@ -266,34 +265,78 @@ class CandidateGraph(nx.Graph): else: mask = ransac_mask # Compute the error in the homography s_trans = np.hstack((s_coords[::-1],np.ones(s_coords.shape[0]).reshape(-1,1))).T s_trans = np.dot(transformation_matrix, s_trans).T #Normalize the error for i in range(3): s_trans[i] /= s_trans[2] d_trans = np.hstack((d_coords[::-1], np.ones(d_coords.shape[0]).reshape(-1,1))) attributes['homography_error'] = np.sqrt(np.sum((d_trans - s_trans)**2, axis=1)) attributes['homography'] = transformation_matrix attributes['ransac'] = mask def compute_subpixel_offsets(self): def compute_subpixel_offsets(self, clean_keys=[], threshold=0.8, upsampling=10): """ For the entire graph, compute the subpixel offsets using pattern-matching and add the result as an attribute to each edge of the graph. Returns ------- subpixel_offsets : ndarray A numpy array containing all the subpixel offsets for the entire graph. Parameters ---------- clean_keys : list of string keys to masking arrays (created by calling outlier detection) threshold : float On the range [-1, 1]. Values less than or equal to this threshold are masked and can be considered outliers """ subpixel_offsets = [] for source, destination, attributes in self.edges_iter(data=True): #for each edge matches = attributes['matches'] #grab the matches for source, destination, attributes in self.edges_iter(data=True): matches = attributes['matches'] full_offsets = np.zeros((len(matches), 3)) # Build up a composite mask from all of the user specified masks if clean_keys: mask = np.prod([attributes[i] for i in clean_keys], axis=0, dtype=np.bool) matches = matches[mask] full_mask = np.where(mask == True) src_image = self.node[source]['image'] dest_image = self.node[destination]['image'] edge_offsets = [] for i, (idx, row) in enumerate(matches.iterrows()): #for each edge, calculate this for each keypoint pair # Preallocate the numpy array to avoid appending and type conversion edge_offsets = np.empty((len(matches),3)) # for each edge, calculate this for each keypoint pair for i, (idx, row) in enumerate(matches.iterrows()): s_idx = int(row['source_idx']) d_idx = int(row['destination_idx']) src_keypoint = self.node[source]['keypoints'][s_idx] dest_keypoint = self.node[destination]['keypoints'][d_idx] edge_offsets.append(sp.subpixel_offset(src_keypoint, dest_keypoint, src_image, dest_image)) attributes['subpixel_offsets'] = np.array(edge_offsets) subpixel_offsets.append(np.array(edge_offsets)) return subpixel_offsets # Compute the subpixel offset edge_offsets[i] = sp.subpixel_offset(src_keypoint, dest_keypoint, src_image, dest_image, upsampling=upsampling) # Compute the mask for correlations less than the threshold threshold_mask = edge_offsets[edge_offsets[:,-1] >= threshold] # Convert the truncated mask back into a full length mask if clean_keys: mask[full_mask] = threshold_mask full_offsets[full_mask] = edge_offsets else: mask = threshold_mask attributes['subpixel_offsets'] = pd.DataFrame(full_offsets, columns=['x_offset', 'y_offset', 'correlation']) attributes['subpixel'] = mask def to_cnet(self, clean_keys=[]): """ Loading Loading @@ -349,12 +392,15 @@ class CandidateGraph(nx.Graph): mask = np.prod([attributes[i] for i in clean_keys], axis=0, dtype=np.bool) matches = matches[mask] if 'subpixel' in clean_keys: offsets = attributes['subpixel_offsets'][attributes['subpixel']] print(offsets) kp1 = self.node[source]['keypoints'] kp2 = self.node[destination]['keypoints'] pt_idx = 0 values = [] for idx, row in matches.iterrows(): for i, (idx, row) in enumerate(matches.iterrows()): # Composite matching key (node_id, point_id) m1 = (source, int(row['source_idx'])) m2 = (destination, int(row['destination_idx'])) Loading @@ -365,8 +411,17 @@ class CandidateGraph(nx.Graph): pt_idx, source]) values.append([kp2[m2[1]].pt[0], kp2[m2[1]].pt[1], kp2x = kp2[m2[1]].pt[0] kp2y = kp2[m2[1]].pt[1] if 'subpixel' in clean_keys: print(idx) print(kp2x, kp2y) kp2x += offsets['x_offset'].values[i] kp2y += offsets['y_offset'].values[i] print(kp2x, kp2y) values.append([kp2x, kp2y, m2, pt_idx, destination]) Loading
autocnet/graph/tests/test_network.py +7 −5 Changes for autocnet/graph/tests/test_network.py: 7 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -13,8 +13,9 @@ from .. import network class TestCandidateGraph(unittest.TestCase): def setUp(self): self.graph = network.CandidateGraph.from_adjacency(get_path('adjacency.json')) @classmethod def setUpClass(cls): cls.graph = network.CandidateGraph.from_adjacency(get_path('adjacency.json')) def test_get_name(self): node_number = self.graph.node_name_map['AS15-M-0297_SML.png'] Loading @@ -28,6 +29,10 @@ class TestCandidateGraph(unittest.TestCase): def test_to_json_file(self): self.graph.to_json_file('test_graph_to_json.json') self.assertTrue(os.path.exists('test_graph_to_json.json')) try: os.remove('test_graph_to_json.json') except: pass def test_extract_features(self): # also tests get_geodataset() and get_keypoints Loading @@ -42,7 +47,4 @@ class TestCandidateGraph(unittest.TestCase): self.assertEquals(self.graph.get_keypoints(node_number), node['keypoints']) def tearDown(self): try: os.remove('test_graph_to_json.json') except: pass
autocnet/matcher/outlier_detector.py +2 −0 Changes for autocnet/matcher/outlier_detector.py: 2 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -148,3 +148,5 @@ def compute_homography(kp1, kp2, outlier_algorithm=cv2.RANSAC, reproj_threshold= reproj_threshold) mask = mask.astype(bool) return transformation_matrix, mask