def setUpClass(cls): cls.npts = 5 serial_times = {295: '1971-07-31T01:24:11.754', 296: '1971-07-31T01:24:36.970'} cls.serials = ['APOLLO15/METRIC/{}'.format(i) for i in serial_times.values()] net = CandidateGraph({'a': ['b'], 'b': ['a']}) for i, n in net.nodes_iter(data=True): n._keypoints = pd.DataFrame(np.arange(10).reshape(cls.npts,-1), columns=['x', 'y']) n._isis_serial = cls.serials[i] source = np.zeros(cls.npts) destination = np.ones(cls.npts) pid = np.arange(cls.npts) matches = pd.DataFrame(np.vstack((source, pid, destination, pid)).T, columns=['source_image', 'source_idx', 'destination_image', 'destination_idx']) net.edge[0][1].matches = matches net.generate_cnet(clean_keys=[]) cls.creation_date = net.creationdate cls.modified_date = net.modifieddate io_controlnetwork.to_isis('test.net', net, mode='wb', targetname='Moon') cls.header_message_size = 98 cls.point_start_byte = 65634
def match_images(args, config_dict): # Matches the images in the input file using various candidate graph methods # produces two files usable in isis try: cg = CandidateGraph.from_adjacency(find_in_dict(config_dict, 'inputfile_path') + args.input_file, basepath=find_in_dict(config_dict, 'basepath')) except: cg = CandidateGraph.from_filelist(find_in_dict(config_dict, 'inputfile_path') + args.input_file) # Apply SIFT to extract features cg.extract_features(method=config_dict['extract_features']['method'], extractor_parameters=find_in_dict(config_dict, 'extractor_parameters')) # Match cg.match_features(k=config_dict['match_features']['k']) # Apply outlier detection cg.apply_func_to_edges('symmetry_check') cg.apply_func_to_edges('ratio_check', ratio=find_in_dict(config_dict, 'ratio'), mask_name=find_in_dict(config_dict, 'mask_name'), single=find_in_dict(config_dict, 'single')) # Compute a homography and apply RANSAC cg.apply_func_to_edges('compute_fundamental_matrix', clean_keys=find_in_dict(config_dict, 'fundamental_matrices')['clean_keys'], method=find_in_dict(config_dict, 'fundamental_matrices')['method'], reproj_threshold=find_in_dict(config_dict, 'reproj_threshold'), confidence=find_in_dict(config_dict, 'confidence')) cg.apply_func_to_edges('subpixel_register', clean_keys=find_in_dict(config_dict, 'subpixel_register')['clean_keys'], template_size=find_in_dict(config_dict, 'template_size'), threshold=find_in_dict(config_dict, 'threshold'), search_size=find_in_dict(config_dict, 'search_size'), max_x_shift=find_in_dict(config_dict, 'max_x_shift'), max_y_shift=find_in_dict(config_dict, 'max_y_shift'), tiled=find_in_dict(config_dict, 'tiled'), upsampling = find_in_dict(config_dict, 'upsampling'), error_check = find_in_dict(config_dict, 'error_check')) cg.apply_func_to_edges('suppress', clean_keys=find_in_dict(config_dict, 'suppress')['clean_keys'], k=find_in_dict(config_dict, 'suppress')['k'], min_radius=find_in_dict(config_dict, 'min_radius'), error_k=find_in_dict(config_dict, 'error_k')) cnet = cg.to_cnet(clean_keys=find_in_dict(config_dict, 'cnet_conversion')['clean_keys'], isis_serials=True) filelist = cg.to_filelist() write_filelist(filelist, find_in_dict(config_dict, 'outputfile_path') + args.output_file + '.lis') to_isis(find_in_dict(config_dict, 'outputfile_path') + args.output_file + '.net', cnet, mode='wb', networkid=find_in_dict(config_dict, 'networkid'), targetname=find_in_dict(config_dict, 'targetname'), description=find_in_dict(config_dict, 'description'), username=find_in_dict(config_dict, 'username'))
def test_two_image(self): # Step: Create an adjacency graph adjacency = get_path('two_image_adjacency.json') basepath = get_path('Apollo15') cg = CandidateGraph.from_adjacency(adjacency, basepath=basepath) assert 2 == cg.number_of_nodes() assert 1 == cg.number_of_edges() # Step: Extract image data and attribute nodes cg.extract_features(extractor_method='vlfeat', extractor_parameters={"nfeatures":500}) for i, node in cg.nodes.data('data'): assert node.nkeypoints in range(5800, 6000) # Step: Compute the coverage ratios for i, node in cg.nodes.data('data'): ratio = node.coverage() assert 0.98 < round(ratio, 8) < 0.99 cg.decompose_and_match(k=2, maxiteration=2) assert isinstance(cg.edges[0,1]['data'].smembership, np.ndarray) # Create fundamental matrix cg.compute_fundamental_matrices() for s, d, e in cg.edges.data('data'): assert isinstance(e.fundamental_matrix, np.ndarray) e.compute_fundamental_error(clean_keys=['fundamental']) assert 'fundamental_equality' in e.costs.columns matches, _ = e.clean(clean_keys=['fundamental']) # Apply AMNS cg.suppress(k=30, xkey='x', ykey='y', suppression_func=error) # Step: Compute subpixel offsets for candidate points cg.subpixel_register(clean_keys=['suppression'])
def test_three_image(self): # Step: Create an adjacency graph adjacency = get_path('three_image_adjacency.json') basepath = get_path('Apollo15') cg = CandidateGraph.from_adjacency(adjacency, basepath) self.assertEqual(3, cg.number_of_nodes()) self.assertEqual(3, cg.number_of_edges()) # Step: Extract image data and attribute nodes cg.extract_features(extractor_parameters={'nfeatures':500}) for i, node, in cg.nodes_iter(data=True): self.assertIn(node.nkeypoints, range(490, 511)) cg.match_features(k=5) cg.symmetry_checks() cg.ratio_checks() cg.apply_func_to_edges("compute_homography", clean_keys=['symmetry', 'ratio']) cg.compute_fundamental_matrices(clean_keys=['symmetry', 'ratio']) # Step: And create a C object cg.generate_cnet(clean_keys=['symmetry', 'ratio', 'ransac']) # Step: Create a fromlist to go with the cnet and write it to a file filelist = cg.to_filelist() write_filelist(filelist, 'TestThreeImageMatching_fromlist.lis') # Step: Create a correspondence network cg.generate_cnet(clean_keys=['ransac'], deepen=True) to_isis('TestThreeImageMatching.net', cg.cn, mode='wb', networkid='TestThreeImageMatching', targetname='Moon')
def test_two_image(self): # Step: Create an adjacency graph adjacency = get_path('two_image_adjacency.json') basepath = get_path('Apollo15') cg = CandidateGraph.from_adjacency(adjacency, basepath=basepath) self.assertEqual(2, cg.number_of_nodes()) self.assertEqual(1, cg.number_of_edges()) # Step: Extract image data and attribute nodes cg.extract_features(method='sift', extractor_parameters={"nfeatures":500}) for i, node in cg.nodes_iter(data=True): self.assertIn(node.nkeypoints, range(490, 511)) # Step: Compute the coverage ratios truth_ratios = [0.95351579, 0.93595664] for i, node in cg.nodes_iter(data=True): ratio = node.coverage_ratio() self.assertIn(round(ratio, 8), truth_ratios) cg.match_features(k=2) # Perform the symmetry check cg.symmetry_checks() # Perform the ratio check cg.ratio_checks(clean_keys=['symmetry'], single=True) # Create fundamental matrix cg.compute_fundamental_matrices(clean_keys = ['symmetry', 'ratio']) for source, destination, edge in cg.edges_iter(data=True): # Perform the symmetry check self.assertIn(edge.masks['symmetry'].sum(), range(400, 600)) # Perform the ratio test self.assertIn(edge.masks['ratio'].sum(), range(225, 275)) # Range needs to be set self.assertIn(edge.masks['fundamental'].sum(), range(200, 250)) # Step: Compute the homographies and apply RANSAC cg.compute_homographies(clean_keys=['symmetry', 'ratio']) # Apply AMNS cg.suppress(k=30, suppression_func=error) # Step: Compute subpixel offsets for candidate points cg.subpixel_register(clean_keys=['suppression']) # Step: And create a C object cg.generate_cnet(clean_keys=['subpixel']) # Step: Create a fromlist to go with the cnet and write it to a file filelist = cg.to_filelist() write_filelist(filelist, path="fromlis.lis") # Step: Output a control network to_isis('TestTwoImageMatching.net', cg.cn, mode='wb', networkid='TestTwoImageMatching', targetname='Moon')
def test_two_image(self): # Step: Create an adjacency graph adjacency = get_path('two_image_adjacency.json') cg = CandidateGraph.from_adjacency(adjacency) self.assertEqual(2, cg.number_of_nodes()) self.assertEqual(1, cg.number_of_edges()) # Step: Extract image data and attribute nodes cg.extract_features(extractor_parameters={"nfeatures":500}) for node, attributes in cg.nodes_iter(data=True): self.assertIn(len(attributes['keypoints']), range(490, 511)) # Step: Then apply a FLANN matcher fl = FlannMatcher() for node, attributes in cg.nodes_iter(data=True): fl.add(attributes['descriptors'], key=node) fl.train() for node, attributes in cg.nodes_iter(data=True): descriptors = attributes['descriptors'] matches = fl.query(descriptors, node, k=5) cg.add_matches(matches) for source, destination, attributes in cg.edges_iter(data=True): matches = attributes['matches'] # Perform the symmetry check symmetry_mask = od.mirroring_test(matches) self.assertIn(symmetry_mask.sum(), range(430, 461)) attributes['symmetry'] = symmetry_mask # Perform the ratio test ratio_mask = od.distance_ratio(matches, ratio=0.95) self.assertIn(ratio_mask.sum(), range(390, 451)) attributes['ratio'] = ratio_mask mask = np.array(ratio_mask * symmetry_mask) self.assertIn(len(matches.loc[mask]), range(75,101)) # Step: Compute the homographies and apply RANSAC cg.compute_homographies(clean_keys=['symmetry', 'ratio']) # Step: Compute subpixel offsets for candidate points cg.compute_subpixel_offsets(clean_keys=['symmetry', 'ratio', 'ransac']) # Step: And create a C object cnet = cg.to_cnet(clean_keys=['symmetry', 'ratio', 'ransac', 'subpixel']) # Step update the serial numbers nid_to_serial = {} for node, attributes in cg.nodes_iter(data=True): nid_to_serial[node] = self.serial_numbers[attributes['image_name']] cnet.replace({'nid': nid_to_serial}, inplace=True) # Step: Output a control network to_isis('TestTwoImageMatching.net', cnet, mode='wb', networkid='TestTwoImageMatching', targetname='Moon')
def test_coverage(self): adjacency = get_path('two_image_adjacency.json') basepath = get_path('Apollo15') cg = CandidateGraph.from_adjacency(adjacency, basepath=basepath) keypoint_df = pd.DataFrame({'x': (15, 18, 18, 12, 12), 'y': (5, 10, 15, 15, 10)}) keypoint_matches = [[0, 0, 1, 0], [0, 1, 1, 1], [0, 2, 1, 2], [0, 3, 1, 3], [0, 4, 1, 4]] matches_df = pd.DataFrame(data = keypoint_matches, columns = ['source_image', 'source_idx', 'destination_image', 'destination_idx']) e = edge.Edge() source_node = MagicMock(spec = node.Node()) destination_node = MagicMock(spec = node.Node()) source_node.get_keypoint_coordinates = MagicMock(return_value=keypoint_df) destination_node.get_keypoint_coordinates = MagicMock(return_value=keypoint_df) e.source = source_node e.destination = destination_node source_geodata = Mock(spec = io_gdal.GeoDataset) destination_geodata = Mock(spec = io_gdal.GeoDataset) e.source.geodata = source_geodata e.destination.geodata = destination_geodata source_corners = [(0, 0), (20, 0), (20, 20), (0, 20)] destination_corners = [(10, 5), (30, 5), (30, 25), (10, 25)] e.source.geodata.latlon_corners = source_corners e.destination.geodata.latlon_corners = destination_corners vals = {(15, 5):(15, 5), (18, 10):(18, 10), (18, 15):(18, 15), (12, 15):(12, 15), (12, 10):(12, 10)} def pixel_to_latlon(i, j): return vals[(i, j)] e.source.geodata.pixel_to_latlon = MagicMock(side_effect = pixel_to_latlon) e.destination.geodata.pixel_to_latlon = MagicMock(side_effect = pixel_to_latlon) e.matches = matches_df self.assertRaises(AttributeError, cg.edge[0][1].coverage) self.assertEqual(e.coverage(), 0.3)
def test_two_image(self): # Step: Create an adjacency graph adjacency = get_path("two_image_adjacency.json") cg = CandidateGraph.from_adjacency(adjacency) self.assertEqual(2, cg.number_of_nodes()) self.assertEqual(1, cg.number_of_edges()) # Step: Extract image data and attribute nodes cg.extract_features(500) for node, attributes in cg.nodes_iter(data=True): self.assertIn(len(attributes["keypoints"]), range(490, 511)) # Step: Then apply a FLANN matcher fl = FlannMatcher() for node, attributes in cg.nodes_iter(data=True): fl.add(attributes["descriptors"], key=node) fl.train() for node, attributes in cg.nodes_iter(data=True): descriptors = attributes["descriptors"] matches = fl.query(descriptors, node, k=5) cg.add_matches(matches) for source, destination, attributes in cg.edges_iter(data=True): matches = attributes["matches"] # Perform the symmetry check symmetry_mask = od.mirroring_test(matches) self.assertIn(symmetry_mask.sum(), range(430, 461)) attributes["symmetry"] = symmetry_mask # Perform the ratio test ratio_mask = od.distance_ratio(matches, ratio=0.95) self.assertIn(ratio_mask.sum(), range(400, 451)) attributes["ratio"] = ratio_mask mask = np.array(ratio_mask * symmetry_mask) self.assertIn(len(matches.loc[mask]), range(75, 101)) cg.compute_homographies(clean_keys=["symmetry", "ratio"]) # Step: And create a C object cnet = cg.to_cnet(clean_keys=["symmetry", "ratio", "ransac"]) # Step update the serial numbers nid_to_serial = {} for node, attributes in cg.nodes_iter(data=True): nid_to_serial[node] = self.serial_numbers[attributes["image_name"]] cnet.replace({"nid": nid_to_serial}, inplace=True) # Step: Output a control network to_isis("TestTwoImageMatching.net", cnet, mode="wb", networkid="TestTwoImageMatching", targetname="Moon")
def candidategraph(node_a, node_b, node_c): # TODO: Getting this fixture from the global conf is causing deepycopy # to fail. Why? cg = CandidateGraph() # Create a candidategraph object - we instantiate a real CandidateGraph to # have access of networkx functionality we do not want to test and then # mock all autocnet functionality to control test behavior. edges = [(0, 1, { 'data': edge.Edge(0, 1) }), (0, 2, { 'data': edge.Edge(0, 2) }), (1, 2, { 'data': edge.Edge(1, 2) })] cg.add_edges_from(edges) match_indices = [([0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7]), ([0, 1, 2, 3, 4, 5, 8, 9], [0, 1, 2, 3, 4, 5, 8, 9]), ([0, 1, 2, 3, 4, 5, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7])] matches = [] for i, e in enumerate(edges): c = match_indices[i] source_image = np.repeat(e[0], 8) destin_image = np.repeat(e[1], 8) coords = np.zeros(8) data = np.vstack((source_image, c[0], destin_image, c[1], coords, coords, coords, coords)).T matches_df = pd.DataFrame(data, columns=[ 'source_image', 'source_idx', 'destination_image', 'destination_idx', 'source_x', 'source_y', 'destination_x', 'destination_y' ]) matches.append(matches_df) # Mock in autocnet methods cg.get_matches = MagicMock(return_value=matches) # Mock in the node objects onto the candidate graph cg.node[0]['data'] = node_a cg.node[1]['data'] = node_b cg.node[2]['data'] = node_c return cg
def setUpClass(cls): cls.npts = 5 serial_times = { 295: '1971-07-31T01:24:11.754', 296: '1971-07-31T01:24:36.970' } cls.serials = [ 'APOLLO15/METRIC/{}'.format(i) for i in serial_times.values() ] net = CandidateGraph({'a': ['b'], 'b': ['a']}) for i, n in net.nodes_iter(data=True): n._keypoints = pd.DataFrame(np.arange(10).reshape(cls.npts, -1), columns=['x', 'y']) n._isis_serial = cls.serials[i] source = np.zeros(cls.npts) destination = np.ones(cls.npts) pid = np.arange(cls.npts) matches = pd.DataFrame(np.vstack((source, pid, destination, pid)).T, columns=[ 'source_image', 'source_idx', 'destination_image', 'destination_idx' ]) net.edge[0][1].matches = matches net.generate_cnet(clean_keys=[]) cls.creation_date = net.creationdate cls.modified_date = net.modifieddate io_controlnetwork.to_isis('test.net', net, mode='wb', targetname='Moon') cls.header_message_size = 98 cls.point_start_byte = 65634
def test_three_image(self): # Step: Create an adjacency graph adjacency = get_path('three_image_adjacency.json') cg = CandidateGraph.from_adjacency(adjacency) self.assertEqual(3, cg.number_of_nodes()) self.assertEqual(3, cg.number_of_edges()) # Step: Extract image data and attribute nodes cg.extract_features(extractor_parameters={'nfeatures':500}) for node, attributes in cg.nodes_iter(data=True): self.assertIn(len(attributes['keypoints']), range(490, 511)) fl = FlannMatcher() for node, attributes in cg.nodes_iter(data=True): fl.add(attributes['descriptors'], key=node) fl.train() for node, attributes in cg.nodes_iter(data=True): descriptors = attributes['descriptors'] matches = fl.query(descriptors, node, k=5) cg.add_matches(matches) for source, destination, attributes in cg.edges_iter(data=True): matches = attributes['matches'] # Perform the symmetry check symmetry_mask = od.mirroring_test(matches) attributes['symmetry'] = symmetry_mask # Perform the ratio test ratio_mask = od.distance_ratio(matches, ratio=0.8) attributes['ratio'] = ratio_mask cg.compute_homographies(clean_keys=['symmetry', 'ratio']) # Step: And create a C object cnet = cg.to_cnet(clean_keys=['symmetry', 'ratio', 'ransac']) # Step update the serial numbers nid_to_serial = {} for node, attributes in cg.nodes_iter(data=True): nid_to_serial[node] = self.serial_numbers[attributes['image_name']] cnet.replace({'nid': nid_to_serial}, inplace=True) # Step: Output a control network to_isis('TestThreeImageMatching.net', cnet, mode='wb', networkid='TestThreeImageMatching', targetname='Moon')
def test_cpu_match(self): # Build a graph adjacency = get_path('two_image_adjacency.json') basepath = get_path('Apollo15') cang = CandidateGraph.from_adjacency(adjacency, basepath=basepath) # Extract features cang.extract_features(extractor_parameters={'nfeatures': 700}) # Make sure cpu matcher is used for test edges = list() from autocnet.matcher.cpu_matcher import match as match for s, d in cang.edges(): cang[s][d]['data']._match = match edges.append(cang[s][d]) # Assert none of the edges have masks yet for edge in edges: self.assertTrue(edge['data'].masks.empty) # Match & outlier detect cang.match() cang.symmetry_checks() # Grab the length of a matches df match_len = len(edges[0]['data'].matches.index) # Assert symmetry check is now in all edge masks for edge in edges: self.assertTrue('symmetry' in edge['data'].masks) # Assert matches have been populated for edge in edges: self.assertTrue(not edge['data'].matches.empty) # Re-match cang.match() # Assert that new matches have been added on to old ones self.assertEqual(len(edges[0]['data'].matches.index), match_len * 2) # Assert that the match cleared the masks df for edge in edges: self.assertTrue(edge['data'].masks.empty)
def test_three_image(self): # Step: Create an adjacency graph adjacency = get_path('three_image_adjacency.json') basepath = get_path('Apollo15') cg = CandidateGraph.from_adjacency(adjacency, basepath) self.assertEqual(3, cg.number_of_nodes()) self.assertEqual(3, cg.number_of_edges()) # Step: Extract image data and attribute nodes cg.extract_features(extractor_parameters={'nfeatures': 500}) for i, node, in cg.nodes_iter(data=True): self.assertIn(node.nkeypoints, range(490, 511)) cg.match_features(k=5) for source, destination, edge in cg.edges_iter(data=True): matches = edge.matches edge.symmetry_check() edge.ratio_check(ratio=0.8) cg.compute_homographies(clean_keys=['symmetry', 'ratio']) # Step: And create a C object cnet = cg.to_cnet(clean_keys=['symmetry', 'ratio', 'ransac']) # Step: Create a fromlist to go with the cnet and write it to a file filelist = cg.to_filelist() write_filelist(filelist, 'TestThreeImageMatching_fromlist.lis') # Step update the serial numbers nid_to_serial = {} for i, node in cg.nodes_iter(data=True): nid_to_serial[i] = self.serial_numbers[node.image_name] cnet.replace({'nid': nid_to_serial}, inplace=True) # Step: Output a control network to_isis('TestThreeImageMatching.net', cnet, mode='wb', networkid='TestThreeImageMatching', targetname='Moon')
def test_three_image(self): # Step: Create an adjacency graph adjacency = get_path('three_image_adjacency.json') basepath = get_path('Apollo15') cg = CandidateGraph.from_adjacency(adjacency, basepath=basepath) self.assertEqual(3, cg.number_of_nodes()) self.assertEqual(3, cg.number_of_edges()) # Step: Extract image data and attribute nodes cg.extract_features(extractor_method='vlfeat') for i, node, in cg.nodes_iter(data=True): self.assertIn(node.nkeypoints, range(5800, 6000)) cg.match(k=2) cg.symmetry_checks() cg.ratio_checks() cg.apply_func_to_edges("compute_homography", clean_keys=['symmetry', 'ratio']) for s, d, e in cg.edges_iter(data=True): self.assertTrue('homography' in e.keys()) cg.compute_fundamental_matrices(clean_keys=['symmetry', 'ratio'], reproj_threshold=3.0, method='ransac')
def candidategraph(): a = '/fake_path/a.img' b = '/fake_path/b.img' c = '/fake_path/c.img' adj = {a:[b,c], b:[a,c], c:[a, b]} cg = CandidateGraph.from_adjacency(adj) match_data = np.array([[0.0, 188.0, 1.0, 0.0, 170.754211], [0.0, 189.0, 1.0, 0.0, 217.451141], [0.0, 185.0, 1.0, 1.0, 108.843925]]) matches = pd.DataFrame(match_data, columns=['source_image', 'source_idx', 'destination_image', 'destination_idx', 'distance']) masks = pd.DataFrame([[True, True], [False, True], [True, False]], columns=['rain', 'maker']) for s, d, e in cg.edges.data('data'): e['fundamental_matrix'] = np.random.random(size=(3,3)) e.matches = matches e.masks = masks e['source_mbr'] = [[0,1], [0,2]] e['destin_mbr'] = [[0.5, 0.5], [1, 1]] kps = np.array([[233.358475, 105.288162, 0.035672, 4.486887, 164.181046, 0.0, 1.0], [366.288116, 98.761131, 0.035900, 4.158592, 147.278580, 0.0, 1.0], [170.932114, 114.173912, 0.037852, 94.446655, 0.401794, 0.0, 3.0]]) keypoints = pd.DataFrame(kps, columns=['x', 'y', 'response', 'size', 'angle', 'octave', 'layer']) for i, n in cg.nodes.data('data'): n.keypoints = keypoints n.descriptors = np.random.random(size=(3, 128)) n.masks = masks return cg
def test_three_image(self): # Step: Create an adjacency graph adjacency = get_path('three_image_adjacency.json') basepath = get_path('Apollo15') cg = CandidateGraph.from_adjacency(adjacency, basepath) self.assertEqual(3, cg.number_of_nodes()) self.assertEqual(3, cg.number_of_edges()) # Step: Extract image data and attribute nodes cg.extract_features(extractor_parameters={'nfeatures': 500}) for i, node, in cg.nodes_iter(data=True): self.assertIn(node.nkeypoints, range(490, 511)) cg.match_features(k=5) for source, destination, edge in cg.edges_iter(data=True): edge.symmetry_check() edge.ratio_check(clean_keys=['symmetry'], ratio=0.99) cg.apply_func_to_edges("compute_homography", clean_keys=['symmetry', 'ratio']) cg.compute_fundamental_matrices(clean_keys=['symmetry', 'ratio']) # Step: And create a C object cg.generate_cnet(clean_keys=['symmetry', 'ratio', 'ransac']) # Step: Create a fromlist to go with the cnet and write it to a file filelist = cg.to_filelist() write_filelist(filelist, 'TestThreeImageMatching_fromlist.lis') # Step: Create a correspondence network cg.generate_cnet(clean_keys=['symmetry', 'ratio', 'ransac'], deepen=True) to_isis('TestThreeImageMatching.net', cg, mode='wb', networkid='TestThreeImageMatching', targetname='Moon')
def candidategraph(node_a, node_b, node_c): # TODO: Getting this fixture from the global conf is causing deepycopy # to fail. Why? cg = CandidateGraph() # Create a candidategraph object - we instantiate a real CandidateGraph to # have access of networkx functionality we do not want to test and then # mock all autocnet functionality to control test behavior. edges = [(0,1,{'data':edge.Edge(0,1)}), (0,2,{'data':edge.Edge(0,2)}), (1,2,{'data':edge.Edge(1,2)})] cg.add_edges_from(edges) match_indices = [([0,1,2,3,4,5,6,7], [0,1,2,3,4,5,6,7]), ([0,1,2,3,4,5,8,9], [0,1,2,3,4,5,8,9]), ([0,1,2,3,4,5,8,9], [0,1,2,3,4,5,6,7])] matches = [] for i, e in enumerate(edges): c = match_indices[i] source_image = np.repeat(e[0], 8) destin_image = np.repeat(e[1], 8) coords = np.zeros(8) data = np.vstack((source_image, c[0], destin_image, c[1], coords, coords, coords, coords)).T matches_df = pd.DataFrame(data, columns=['source_image', 'source_idx', 'destination_image', 'destination_idx', 'source_x', 'source_y', 'destination_x', 'destination_y']) matches.append(matches_df) # Mock in autocnet methods cg.get_matches = MagicMock(return_value=matches) # Mock in the node objects onto the candidate graph cg.node[0]['data'] = node_a cg.node[1]['data'] = node_b cg.node[2]['data'] = node_c return cg
def test_three_image(self): # Step: Create an adjacency graph adjacency = get_path('three_image_adjacency.json') basepath = get_path('Apollo15') cg = CandidateGraph.from_adjacency(adjacency, basepath) self.assertEqual(3, cg.number_of_nodes()) self.assertEqual(3, cg.number_of_edges()) # Step: Extract image data and attribute nodes cg.extract_features(extractor_parameters={'nfeatures':500}) for i, node, in cg.nodes_iter(data=True): self.assertIn(node.nkeypoints, range(490, 511)) cg.match_features(k=5) for source, destination, edge in cg.edges_iter(data=True): matches = edge.matches edge.symmetry_check() edge.ratio_check(ratio=0.8) cg.compute_homographies(clean_keys=['symmetry', 'ratio']) # Step: And create a C object cnet = cg.to_cnet(clean_keys=['symmetry', 'ratio', 'ransac']) # Step: Create a fromlist to go with the cnet and write it to a file filelist = cg.to_filelist() write_filelist(filelist, 'TestThreeImageMatching_fromlist.lis') # Step update the serial numbers nid_to_serial = {} for i, node in cg.nodes_iter(data=True): nid_to_serial[i] = self.serial_numbers[node.image_name] cnet.replace({'nid': nid_to_serial}, inplace=True) # Step: Output a control network to_isis('TestThreeImageMatching.net', cnet, mode='wb', networkid='TestThreeImageMatching', targetname='Moon')
def test_two_image(self): # Step: Create an adjacency graph adjacency = get_path('two_image_adjacency.json') basepath = get_path('Apollo15') cg = CandidateGraph.from_adjacency(adjacency, basepath=basepath) self.assertEqual(2, cg.number_of_nodes()) self.assertEqual(1, cg.number_of_edges()) # Step: Extract image data and attribute nodes cg.extract_features(extractor_method='sift', extractor_parameters={"nfeatures": 500}) for i, node in cg.nodes.data('data'): self.assertIn(node.nkeypoints, range(490, 510)) # Step: Compute the coverage ratios for i, node in cg.nodes.data('data'): ratio = node.coverage() self.assertTrue(0.93 < round(ratio, 8) < 0.96) cg.decompose_and_match(k=2, maxiteration=2) self.assertTrue( isinstance(cg.edges[0, 1]['data'].smembership, np.ndarray)) # Create fundamental matrix cg.compute_fundamental_matrices() for s, d, e in cg.edges.data('data'): assert isinstance(e.fundamental_matrix, np.ndarray) e.compute_fundamental_error(clean_keys=['fundamental']) assert 'fundamental_equality' in e.costs.columns matches, _ = e.clean(clean_keys=['fundamental']) # Apply AMNS cg.suppress(k=30, xkey='x', ykey='y', suppression_func=error) # Step: Compute subpixel offsets for candidate points cg.subpixel_register(clean_keys=['suppression'])
def test_three_image(self): # Step: Create an adjacency graph adjacency = get_path("three_image_adjacency.json") basepath = get_path("Apollo15") cg = CandidateGraph.from_adjacency(adjacency, basepath) self.assertEqual(3, cg.number_of_nodes()) self.assertEqual(3, cg.number_of_edges()) # Step: Extract image data and attribute nodes cg.extract_features(extractor_parameters={"nfeatures": 500}) for i, node in cg.nodes_iter(data=True): self.assertIn(node.nkeypoints, range(490, 511)) cg.match_features(k=5) for source, destination, edge in cg.edges_iter(data=True): edge.symmetry_check() edge.ratio_check(clean_keys=["symmetry"], ratio=0.99) cg.apply_func_to_edges("compute_homography", clean_keys=["symmetry", "ratio"]) # Step: And create a C object cnet = cg.to_cnet(clean_keys=["symmetry", "ratio", "ransac"]) # Step: Create a fromlist to go with the cnet and write it to a file filelist = cg.to_filelist() write_filelist(filelist, "TestThreeImageMatching_fromlist.lis") # Step update the serial numbers nid_to_serial = {} for i, node in cg.nodes_iter(data=True): nid_to_serial[i] = self.serial_numbers[node.image_name] cnet.replace({"nid": nid_to_serial}, inplace=True) # Step: Output a control network to_isis("TestThreeImageMatching.net", cnet, mode="wb", networkid="TestThreeImageMatching", targetname="Moon")
def test_three_image(self): # Step: Create an adjacency graph adjacency = get_path('three_image_adjacency.json') basepath = get_path('Apollo15') cg = CandidateGraph.from_adjacency(adjacency, basepath=basepath) self.assertEqual(3, cg.number_of_nodes()) self.assertEqual(3, cg.number_of_edges()) # Step: Extract image data and attribute nodes cg.extract_features(extractor_parameters={'nfeatures': 500}) for i, node, in cg.nodes_iter(data=True): self.assertIn(node.nkeypoints, range(490, 511)) cg.match(k=2) cg.symmetry_checks() cg.ratio_checks() cg.apply_func_to_edges("compute_homography", clean_keys=['symmetry', 'ratio']) for s, d, e in cg.edges_iter(data=True): self.assertTrue('homography' in e.keys()) cg.compute_fundamental_matrices(clean_keys=['symmetry', 'ratio'], reproj_threshold=3.0, method='ransac')
def match_images(args, config_dict): # Matches the images in the input file using various candidate graph methods # produces two files usable in isis try: cg = CandidateGraph.from_adjacency( find_in_dict(config_dict, 'inputfile_path') + args.input_file, basepath=find_in_dict(config_dict, 'basepath')) except: cg = CandidateGraph.from_filelist( find_in_dict(config_dict, 'inputfile_path') + args.input_file) # Apply SIFT to extract features cg.extract_features(method=config_dict['extract_features']['method'], extractor_parameters=find_in_dict( config_dict, 'extractor_parameters')) # Match cg.match_features(k=config_dict['match_features']['k']) # Apply outlier detection cg.apply_func_to_edges('symmetry_check') cg.apply_func_to_edges('ratio_check', ratio=find_in_dict(config_dict, 'ratio'), mask_name=find_in_dict(config_dict, 'mask_name'), single=find_in_dict(config_dict, 'single')) # Compute a homography and apply RANSAC cg.apply_func_to_edges( 'compute_fundamental_matrix', clean_keys=find_in_dict(config_dict, 'fundamental_matrices')['clean_keys'], method=find_in_dict(config_dict, 'fundamental_matrices')['method'], reproj_threshold=find_in_dict(config_dict, 'reproj_threshold'), confidence=find_in_dict(config_dict, 'confidence')) cg.apply_func_to_edges( 'subpixel_register', clean_keys=find_in_dict(config_dict, 'subpixel_register')['clean_keys'], template_size=find_in_dict(config_dict, 'template_size'), threshold=find_in_dict(config_dict, 'threshold'), search_size=find_in_dict(config_dict, 'search_size'), max_x_shift=find_in_dict(config_dict, 'max_x_shift'), max_y_shift=find_in_dict(config_dict, 'max_y_shift'), tiled=find_in_dict(config_dict, 'tiled'), upsampling=find_in_dict(config_dict, 'upsampling'), error_check=find_in_dict(config_dict, 'error_check')) cg.apply_func_to_edges('suppress', clean_keys=find_in_dict(config_dict, 'suppress')['clean_keys'], k=find_in_dict(config_dict, 'suppress')['k'], min_radius=find_in_dict(config_dict, 'min_radius'), error_k=find_in_dict(config_dict, 'error_k')) cnet = cg.to_cnet(clean_keys=find_in_dict(config_dict, 'cnet_conversion')['clean_keys'], isis_serials=True) filelist = cg.to_filelist() write_filelist( filelist, find_in_dict(config_dict, 'outputfile_path') + args.output_file + '.lis') to_isis(find_in_dict(config_dict, 'outputfile_path') + args.output_file + '.net', cnet, mode='wb', networkid=find_in_dict(config_dict, 'networkid'), targetname=find_in_dict(config_dict, 'targetname'), description=find_in_dict(config_dict, 'description'), username=find_in_dict(config_dict, 'username'))
def test_two_image(self): # Step: Create an adjacency graph adjacency = get_path('two_image_adjacency.json') basepath = get_path('Apollo15') cg = CandidateGraph.from_adjacency(adjacency, basepath=basepath) self.assertEqual(2, cg.number_of_nodes()) self.assertEqual(1, cg.number_of_edges()) # Step: Extract image data and attribute nodes cg.extract_features(method='sift', extractor_parameters={"nfeatures":500}) for i, node in cg.nodes_iter(data=True): self.assertIn(node.nkeypoints, range(490, 511)) #Step: Compute the coverage ratios truth_ratios = [0.95351579, 0.93595664] for i, node in cg.nodes_iter(data=True): ratio = node.coverage_ratio() self.assertIn(round(ratio,8), truth_ratios) # Step: apply Adaptive non-maximal suppression for i, node in cg.nodes_iter(data=True): pass #node.anms() #self.assertNotEqual(node.nkeypoints, sum(node._mask_arrays['anms'])) cg.match_features(k=5) for source, destination, edge in cg.edges_iter(data=True): # Perform the symmetry check edge.symmetry_check() self.assertIn(edge._mask_arrays['symmetry'].sum(), range(430, 461)) # Perform the ratio test edge.ratio_check(ratio=0.8) self.assertIn(edge._mask_arrays['ratio'].sum(), range(250, 350)) # Step: Compute the homographies and apply RANSAC cg.compute_homographies(clean_keys=['symmetry', 'ratio']) # Step: Compute the overlap ratio and coverage ratio for s, d, edge in cg.edges_iter(data=True): ratio = edge.coverage_ratio(clean_keys=['symmetry', 'ratio']) # Step: Compute subpixel offsets for candidate points cg.compute_subpixel_offsets(clean_keys=['ransac']) # Step: And create a C object cnet = cg.to_cnet(clean_keys=['symmetry', 'ratio', 'ransac', 'subpixel']) # Step: Create a fromlist to go with the cnet and write it to a file filelist = cg.to_filelist() write_filelist(filelist, path="fromlis.lis") # Step update the serial numbers nid_to_serial = {} for i, node in cg.nodes_iter(data=True): nid_to_serial[i] = self.serial_numbers[node.image_name] cnet.replace({'nid': nid_to_serial}, inplace=True) # Step: Output a control network to_isis('TestTwoImageMatching.net', cnet, mode='wb', networkid='TestTwoImageMatching', targetname='Moon')
def test_two_image(self): # Step: Create an adjacency graph adjacency = get_path('two_image_adjacency.json') basepath = get_path('Apollo15') cg = CandidateGraph.from_adjacency(adjacency, basepath=basepath) self.assertEqual(2, cg.number_of_nodes()) self.assertEqual(1, cg.number_of_edges()) # Step: Extract image data and attribute nodes cg.extract_features(method='sift', extractor_parameters={"nfeatures":500}) for i, node in cg.nodes_iter(data=True): self.assertIn(node.nkeypoints, range(490, 511)) #Step: Compute the coverage ratios truth_ratios = [0.95351579, 0.93595664] for i, node in cg.nodes_iter(data=True): ratio = node.coverage_ratio() self.assertIn(round(ratio,8), truth_ratios) # Step: apply Adaptive non-maximal suppression for i, node in cg.nodes_iter(data=True): pass #node.anms() #self.assertNotEqual(node.nkeypoints, sum(node._mask_arrays['anms'])) cg.match_features(k=5) for source, destination, edge in cg.edges_iter(data=True): # Perform the symmetry check edge.symmetry_check() self.assertIn(edge.masks['symmetry'].sum(), range(430, 461)) # Perform the ratio test edge.ratio_check(ratio=0.9, clean_keys=['symmetry']) self.assertIn(edge.masks['ratio'].sum(), range(25, 50)) # Step: Compute the homographies and apply RANSAC cg.compute_homographies(clean_keys=['symmetry', 'ratio']) # Step: Compute the overlap ratio and coverage ratio for s, d, edge in cg.edges_iter(data=True): ratio = edge.coverage_ratio(clean_keys=['symmetry', 'ratio']) # Step: Compute subpixel offsets for candidate points cg.subpixel_register(clean_keys=['ransac']) # Step: And create a C object cnet = cg.to_cnet(clean_keys=['symmetry', 'ratio', 'ransac', 'subpixel']) # Step: Create a fromlist to go with the cnet and write it to a file filelist = cg.to_filelist() write_filelist(filelist, path="fromlis.lis") # Step update the serial numbers nid_to_serial = {} for i, node in cg.nodes_iter(data=True): nid_to_serial[i] = self.serial_numbers[node.image_name] cnet.replace({'nid': nid_to_serial}, inplace=True) # Step: Output a control network to_isis('TestTwoImageMatching.net', cnet, mode='wb', networkid='TestTwoImageMatching', targetname='Moon')
def new(self): self.cg = CandidateGraph() return 'success'
def setUp(self): self.g = CandidateGraph.from_graph(get_path('sixty_four_apollo.graph'))
def test_coverage(self): adjacency = get_path('two_image_adjacency.json') basepath = get_path('Apollo15') cg = CandidateGraph.from_adjacency(adjacency, basepath=basepath) keypoint_df = pd.DataFrame({ 'x': (15, 18, 18, 12, 12), 'y': (5, 10, 15, 15, 10) }) keypoint_matches = [[0, 0, 1, 0], [0, 1, 1, 1], [0, 2, 1, 2], [0, 3, 1, 3], [0, 4, 1, 4]] matches_df = pd.DataFrame(data=keypoint_matches, columns=[ 'source_image', 'source_idx', 'destination_image', 'destination_idx' ]) e = edge.Edge() source_node = MagicMock(spec=node.Node()) destination_node = MagicMock(spec=node.Node()) source_node.get_keypoint_coordinates = MagicMock( return_value=keypoint_df) destination_node.get_keypoint_coordinates = MagicMock( return_value=keypoint_df) e.source = source_node e.destination = destination_node source_geodata = Mock(spec=io_gdal.GeoDataset) destination_geodata = Mock(spec=io_gdal.GeoDataset) e.source.geodata = source_geodata e.destination.geodata = destination_geodata source_corners = [(0, 0), (20, 0), (20, 20), (0, 20)] destination_corners = [(10, 5), (30, 5), (30, 25), (10, 25)] e.source.geodata.latlon_corners = source_corners e.destination.geodata.latlon_corners = destination_corners vals = { (15, 5): (15, 5), (18, 10): (18, 10), (18, 15): (18, 15), (12, 15): (12, 15), (12, 10): (12, 10) } def pixel_to_latlon(i, j): return vals[(i, j)] e.source.geodata.pixel_to_latlon = MagicMock( side_effect=pixel_to_latlon) e.destination.geodata.pixel_to_latlon = MagicMock( side_effect=pixel_to_latlon) e.matches = matches_df self.assertRaises(AttributeError, cg.edge[0][1].coverage) self.assertEqual(e.coverage(), 0.3)
def test_two_image(self): # Step: Create an adjacency graph adjacency = get_path('two_image_adjacency.json') basepath = get_path('Apollo15') cg = CandidateGraph.from_adjacency(adjacency, basepath=basepath) self.assertEqual(2, cg.number_of_nodes()) self.assertEqual(1, cg.number_of_edges()) # Step: Extract image data and attribute nodes cg.extract_features(method='sift', extractor_parameters={"nfeatures": 500}) for i, node in cg.nodes_iter(data=True): self.assertIn(node.nkeypoints, range(490, 511)) # Step: Compute the coverage ratios truth_ratios = [0.95351579, 0.93595664] for i, node in cg.nodes_iter(data=True): ratio = node.coverage_ratio() self.assertIn(round(ratio, 8), truth_ratios) cg.match_features(k=2) # Perform the symmetry check cg.symmetry_checks() # Perform the ratio check cg.ratio_checks(clean_keys=['symmetry'], single=True) # Create fundamental matrix cg.compute_fundamental_matrices(clean_keys=['symmetry', 'ratio']) for source, destination, edge in cg.edges_iter(data=True): # Perform the symmetry check self.assertIn(edge.masks['symmetry'].sum(), range(400, 600)) # Perform the ratio test self.assertIn(edge.masks['ratio'].sum(), range(225, 275)) # Range needs to be set self.assertIn(edge.masks['fundamental'].sum(), range(200, 250)) # Step: Compute the homographies and apply RANSAC cg.compute_homographies(clean_keys=['symmetry', 'ratio']) # Apply AMNS cg.suppress(k=30, suppression_func=error) # Step: Compute subpixel offsets for candidate points cg.subpixel_register(clean_keys=['suppression']) # Step: And create a C object cg.generate_cnet(clean_keys=['subpixel']) # Step: Create a fromlist to go with the cnet and write it to a file filelist = cg.to_filelist() write_filelist(filelist, path="fromlis.lis") # Step: Output a control network to_isis('TestTwoImageMatching.net', cg, mode='wb', networkid='TestTwoImageMatching', targetname='Moon')