Loading autocnet/graph/network.py +22 −0 Original line number Diff line number Diff line Loading @@ -510,4 +510,26 @@ class CandidateGraph(nx.Graph): adjacency_dict[n] = self.neighbors(n) io_json.write_json(adjacency_dict, outputfile) # This could easily be changed to return the image name instead of the node if desired def island_nodes(self): """ Finds single nodes that are completely disconnected from the rest of the graph Returns ------- : list A list of disconnected nodes, nodes of degree zero, island nodes, etc. """ return nx.isolates(self) # This could also easily be changed to return image names def connected_subgraphs(self): """ Finds and returns a list of each connected subgraph of nodes. Each subgraph is a set. Returns ------- : list A list of connected sub-graphs of nodes, with the largest sub-graph first. Each subgraph is a set. """ return sorted(nx.connected_components(self), key=len, reverse=True) autocnet/graph/tests/test_network.py +9 −0 Original line number Diff line number Diff line Loading @@ -51,5 +51,14 @@ class TestCandidateGraph(unittest.TestCase): self.assertIsInstance(node['descriptors'][0], np.ndarray) self.assertEquals(self.graph.get_keypoints(node_number), node['keypoints']) def test_island_nodes(self): self.assertEqual(len(self.graph.island_nodes()), 1) def test_connected_subgraphs(self): subgraph_list = self.graph.connected_subgraphs() self.assertEqual(len(subgraph_list), 2) island = self.graph.island_nodes()[0] self.assertTrue(island in subgraph_list[1]) def tearDown(self): pass autocnet/matcher/outlier_detector.py +44 −0 Original line number Diff line number Diff line import cv2 import numpy as np import pandas as pd def self_neighbors(matches): Loading Loading @@ -156,4 +157,47 @@ def compute_homography(kp1, kp2, outlier_algorithm=cv2.RANSAC, reproj_threshold= mask = mask.astype(bool) return transformation_matrix, mask # TODO: CITATION and better design? def adaptive_non_max_suppression(keypoints, n=100, robust=0.9): """ Select the top n keypoints, using Adaptive Non-Maximal Suppression (see: Brown (2005) [Brown2005]_) to rank the keypoints in order of largest minimum suppression radius. A mask with only the positions of the top n keypoints set to 1 (and all else set to 0) is returned. Parameters ---------- keypoints : list List of KeyPoint objects from a node of the graph or equivalently, for 1 image. n : int The number of top-ranked keypoints to return. Returns ------- keypoint_mask : list A list containing a 1 in the positions of the top n selected keypoints and 0 in the positions of all the other keypoints. """ minimum_suppression_radius = {} for i, kp1 in enumerate(keypoints): x1, y1 = kp1.pt temp = [] for kp2 in keypoints: #includes kp1 for now if kp1.response < robust*kp2.response: x2, y2 = kp2.pt temp.append(np.sqrt((x2-x1)**2 + (y2-y1)**2)) if(len(temp) > 0): minimum_suppression_radius[i] = np.min(np.array(temp)) else: minimum_suppression_radius[i] = np.nan df = pd.DataFrame(list(minimum_suppression_radius.items()), columns=['keypoint', 'radius']) top_n = df.sort_values(by='radius', ascending=False).head(n) temp_df = df.mask(df.radius < top_n.radius.min(), other=np.nan) temp_df = temp_df.where(np.isnan(temp_df.keypoint), other=1) temp_df = temp_df.mask(np.isnan(temp_df.keypoint), other=0) return list(temp_df.radius) autocnet/matcher/subpixel.py +4 −14 Original line number Diff line number Diff line Loading @@ -4,7 +4,6 @@ from autocnet.matcher import matcher # TODO: look into KeyPoint.size and perhaps use to determine an appropriately-sized search/template. def clip_roi(img, center, img_size): """ Given an input image, clip a square region of interest Loading Loading @@ -57,21 +56,12 @@ def subpixel_offset(template, search, upsampling=10): Parameters ---------- template_kp : KeyPoint The KeyPoint to match the search_kp to. search_kp : KeyPoint The KeyPoint to match to the template_kp template_img : numpy array template : numpy array The entire image that the template chip to match to will be taken out of. search_img : numpy array search : numpy array The entire image that the search chip to match to the template chip will be taken out of. template_size : int The length of one side of the square subset of the template image that will actually be used for the subpixel registration. Default is 9. Must be odd. search_size : int The length of one side of the square subset of the search image that will be used for subpixel registration. Default is 13. Must be odd. upsampling: int The amount to upsample the image. Returns ------- : tuple Loading docs/conf.py +1 −1 Original line number Diff line number Diff line Loading @@ -295,7 +295,7 @@ class Mock(MagicMock): # All imported libraries should be added to this mock modules list. MOCK_MODULES = ['proj4', 'numpy', 'pandas', 'scipy', 'osgeo', 'cv2', 'scikit-image', 'skimage'] 'scikit-image', 'skimage', 'skimage.feature', 'scipy', 'scipy.misc'] sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES) # NumpyDoc Options Loading Loading
autocnet/graph/network.py +22 −0 Original line number Diff line number Diff line Loading @@ -510,4 +510,26 @@ class CandidateGraph(nx.Graph): adjacency_dict[n] = self.neighbors(n) io_json.write_json(adjacency_dict, outputfile) # This could easily be changed to return the image name instead of the node if desired def island_nodes(self): """ Finds single nodes that are completely disconnected from the rest of the graph Returns ------- : list A list of disconnected nodes, nodes of degree zero, island nodes, etc. """ return nx.isolates(self) # This could also easily be changed to return image names def connected_subgraphs(self): """ Finds and returns a list of each connected subgraph of nodes. Each subgraph is a set. Returns ------- : list A list of connected sub-graphs of nodes, with the largest sub-graph first. Each subgraph is a set. """ return sorted(nx.connected_components(self), key=len, reverse=True)
autocnet/graph/tests/test_network.py +9 −0 Original line number Diff line number Diff line Loading @@ -51,5 +51,14 @@ class TestCandidateGraph(unittest.TestCase): self.assertIsInstance(node['descriptors'][0], np.ndarray) self.assertEquals(self.graph.get_keypoints(node_number), node['keypoints']) def test_island_nodes(self): self.assertEqual(len(self.graph.island_nodes()), 1) def test_connected_subgraphs(self): subgraph_list = self.graph.connected_subgraphs() self.assertEqual(len(subgraph_list), 2) island = self.graph.island_nodes()[0] self.assertTrue(island in subgraph_list[1]) def tearDown(self): pass
autocnet/matcher/outlier_detector.py +44 −0 Original line number Diff line number Diff line import cv2 import numpy as np import pandas as pd def self_neighbors(matches): Loading Loading @@ -156,4 +157,47 @@ def compute_homography(kp1, kp2, outlier_algorithm=cv2.RANSAC, reproj_threshold= mask = mask.astype(bool) return transformation_matrix, mask # TODO: CITATION and better design? def adaptive_non_max_suppression(keypoints, n=100, robust=0.9): """ Select the top n keypoints, using Adaptive Non-Maximal Suppression (see: Brown (2005) [Brown2005]_) to rank the keypoints in order of largest minimum suppression radius. A mask with only the positions of the top n keypoints set to 1 (and all else set to 0) is returned. Parameters ---------- keypoints : list List of KeyPoint objects from a node of the graph or equivalently, for 1 image. n : int The number of top-ranked keypoints to return. Returns ------- keypoint_mask : list A list containing a 1 in the positions of the top n selected keypoints and 0 in the positions of all the other keypoints. """ minimum_suppression_radius = {} for i, kp1 in enumerate(keypoints): x1, y1 = kp1.pt temp = [] for kp2 in keypoints: #includes kp1 for now if kp1.response < robust*kp2.response: x2, y2 = kp2.pt temp.append(np.sqrt((x2-x1)**2 + (y2-y1)**2)) if(len(temp) > 0): minimum_suppression_radius[i] = np.min(np.array(temp)) else: minimum_suppression_radius[i] = np.nan df = pd.DataFrame(list(minimum_suppression_radius.items()), columns=['keypoint', 'radius']) top_n = df.sort_values(by='radius', ascending=False).head(n) temp_df = df.mask(df.radius < top_n.radius.min(), other=np.nan) temp_df = temp_df.where(np.isnan(temp_df.keypoint), other=1) temp_df = temp_df.mask(np.isnan(temp_df.keypoint), other=0) return list(temp_df.radius)
autocnet/matcher/subpixel.py +4 −14 Original line number Diff line number Diff line Loading @@ -4,7 +4,6 @@ from autocnet.matcher import matcher # TODO: look into KeyPoint.size and perhaps use to determine an appropriately-sized search/template. def clip_roi(img, center, img_size): """ Given an input image, clip a square region of interest Loading Loading @@ -57,21 +56,12 @@ def subpixel_offset(template, search, upsampling=10): Parameters ---------- template_kp : KeyPoint The KeyPoint to match the search_kp to. search_kp : KeyPoint The KeyPoint to match to the template_kp template_img : numpy array template : numpy array The entire image that the template chip to match to will be taken out of. search_img : numpy array search : numpy array The entire image that the search chip to match to the template chip will be taken out of. template_size : int The length of one side of the square subset of the template image that will actually be used for the subpixel registration. Default is 9. Must be odd. search_size : int The length of one side of the square subset of the search image that will be used for subpixel registration. Default is 13. Must be odd. upsampling: int The amount to upsample the image. Returns ------- : tuple Loading
docs/conf.py +1 −1 Original line number Diff line number Diff line Loading @@ -295,7 +295,7 @@ class Mock(MagicMock): # All imported libraries should be added to this mock modules list. MOCK_MODULES = ['proj4', 'numpy', 'pandas', 'scipy', 'osgeo', 'cv2', 'scikit-image', 'skimage'] 'scikit-image', 'skimage', 'skimage.feature', 'scipy', 'scipy.misc'] sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES) # NumpyDoc Options Loading