from pathlib import Path import argparse from .utils import create_query_list_with_intrinsics, scale_sfm_images, evaluate from ... import extract_features, match_features, pairs_from_covisibility from ... import triangulation, localize_sfm, pairs_from_retrieval, logger SCENES = [ "KingsCollege", "OldHospital", "ShopFacade", "StMarysChurch", "GreatCourt", ] def run_scene(images, gt_dir, outputs, results, num_covis, num_loc): ref_sfm_sift = gt_dir / "model_train" test_list = gt_dir / "list_query.txt" outputs.mkdir(exist_ok=True, parents=True) ref_sfm = outputs / "sfm_superpoint+superglue" ref_sfm_scaled = outputs / "sfm_sift_scaled" query_list = outputs / "query_list_with_intrinsics.txt" sfm_pairs = outputs / f"pairs-db-covis{num_covis}.txt" loc_pairs = outputs / f"pairs-query-netvlad{num_loc}.txt" feature_conf = { "output": "feats-superpoint-n4096-r1024", "model": { "name": "superpoint", "nms_radius": 3, "max_keypoints": 4096, }, "preprocessing": { "grayscale": True, "resize_max": 1024, }, } matcher_conf = match_features.confs["superglue"] retrieval_conf = extract_features.confs["netvlad"] create_query_list_with_intrinsics( gt_dir / "empty_all", query_list, test_list, ext=".txt", image_dir=images, ) with open(test_list, "r") as f: query_seqs = {q.split("/")[0] for q in f.read().rstrip().split("\n")} global_descriptors = extract_features.main(retrieval_conf, images, outputs) pairs_from_retrieval.main( global_descriptors, loc_pairs, num_loc, db_model=ref_sfm_sift, query_prefix=query_seqs, ) features = extract_features.main( feature_conf, images, outputs, as_half=True ) pairs_from_covisibility.main(ref_sfm_sift, sfm_pairs, num_matched=num_covis) sfm_matches = match_features.main( matcher_conf, sfm_pairs, feature_conf["output"], outputs ) scale_sfm_images(ref_sfm_sift, ref_sfm_scaled, images) triangulation.main( ref_sfm, ref_sfm_scaled, images, sfm_pairs, features, sfm_matches ) loc_matches = match_features.main( matcher_conf, loc_pairs, feature_conf["output"], outputs ) localize_sfm.main( ref_sfm, query_list, loc_pairs, features, loc_matches, results, covisibility_clustering=False, prepend_camera_name=True, ) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--scenes", default=SCENES, choices=SCENES, nargs="+") parser.add_argument("--overwrite", action="store_true") parser.add_argument( "--dataset", type=Path, default="datasets/cambridge", help="Path to the dataset, default: %(default)s", ) parser.add_argument( "--outputs", type=Path, default="outputs/cambridge", help="Path to the output directory, default: %(default)s", ) parser.add_argument( "--num_covis", type=int, default=20, help="Number of image pairs for SfM, default: %(default)s", ) parser.add_argument( "--num_loc", type=int, default=10, help="Number of image pairs for loc, default: %(default)s", ) args = parser.parse_args() gt_dirs = args.dataset / "CambridgeLandmarks_Colmap_Retriangulated_1024px" all_results = {} for scene in args.scenes: logger.info(f'Working on scene "{scene}".') results = args.outputs / scene / "results.txt" if args.overwrite or not results.exists(): run_scene( args.dataset / scene, gt_dirs / scene, args.outputs / scene, results, args.num_covis, args.num_loc, ) all_results[scene] = results for scene in args.scenes: logger.info(f'Evaluate scene "{scene}".') evaluate( gt_dirs / scene / "empty_all", all_results[scene], gt_dirs / scene / "list_query.txt", ext=".txt", )