def test_reconstruction_statistics_null( scene_synthetic: synthetic_scene.SyntheticInputData, null_scene: types.Reconstruction, ) -> None: dataset = synthetic_dataset.SyntheticDataSet( null_scene, scene_synthetic.exifs, scene_synthetic.features, scene_synthetic.tracks_manager, ) reconstruction_statistics = stats.reconstruction_statistics( dataset, scene_synthetic.tracks_manager, [null_scene] ) assert reconstruction_statistics["components"] == 1 assert not reconstruction_statistics["has_gps"] assert not reconstruction_statistics["has_gcp"] assert 4900 < reconstruction_statistics["initial_points_count"] < 5000 assert reconstruction_statistics["initial_shots_count"] == 0 assert reconstruction_statistics["reconstructed_points_count"] == 0 assert reconstruction_statistics["reconstructed_shots_count"] == 0 assert reconstruction_statistics["observations_count"] == 0 assert reconstruction_statistics["average_track_length"] == -1 assert reconstruction_statistics["average_track_length_over_two"] == -1 assert len(reconstruction_statistics["histogram_track_length"]) == 0 assert reconstruction_statistics["reprojection_error_normalized"] == -1.0 assert reconstruction_statistics["reprojection_error_pixels"] == -1.0 assert len(reconstruction_statistics["reprojection_histogram_normalized"][0]) == 0 assert len(reconstruction_statistics["reprojection_histogram_normalized"][1]) == 0 assert len(reconstruction_statistics["reprojection_histogram_pixels"][0]) == 0 assert len(reconstruction_statistics["reprojection_histogram_pixels"][1]) == 0
def test_reconstruction_incremental(scene): reference = scene.get_reconstruction() maximum_depth = 40 projection_noise = 1.0 gps_noise = 5.0 exifs = scene.get_scene_exifs(gps_noise) features, colors, graph = scene.get_tracks_data(maximum_depth, projection_noise) dataset = synthetic_dataset.SyntheticDataSet(reference, exifs, features, colors, graph) _, reconstructed_scene = reconstruction.\ incremental_reconstruction(dataset, graph) errors = scene.compare(reconstructed_scene[0]) assert errors['ratio_cameras'] == 1.0 assert 0.940 < errors['ratio_points'] < 0.950 assert 0.002 < errors['rotation_average'] < 0.09 assert 0.0002 < errors['rotation_std'] < 0.0012 # below, (av+std) should be in order of ||gps_noise||^2 assert 1.5 < errors['position_average'] < 3 assert 1.1 < errors['position_std'] < 4 assert 8.0 < errors['gps_std'] < 10.0 assert np.allclose(errors['gps_average'], 0.0)
def test_processing_statistics_normal( scene_synthetic: synthetic_scene.SyntheticInputData, ): reference = scene_synthetic.reconstruction dataset = synthetic_dataset.SyntheticDataSet( reference, scene_synthetic.exifs, scene_synthetic.features, scene_synthetic.descriptors, scene_synthetic.colors, scene_synthetic.tracks_manager, ) processing_statistics = stats.processing_statistics(dataset, [reference]) assert list( processing_statistics.keys()) == ["steps_times", "date", "area"] assert processing_statistics["steps_times"] == { "Feature Extraction": -1, "Features Matching": -1, "Tracks Merging": -1, "Reconstruction": -1, "Total Time": 0, } assert processing_statistics["date"] == "unknown" assert 3500 < processing_statistics["area"] < 3600
def test_cameras_statistics_normal( scene_synthetic: synthetic_scene.SyntheticInputData, ): reference = scene_synthetic.reconstruction dataset = synthetic_dataset.SyntheticDataSet( reference, scene_synthetic.exifs, scene_synthetic.features, scene_synthetic.tracks_manager, ) cameras_statistics = stats.cameras_statistics(dataset, [reference]) assert cameras_statistics == { "1": { "initial_values": { "k1": -0.1, "k2": 0.01, "focal": 0.7 }, "optimized_values": { "k1": -0.1, "k2": 0.01, "focal": 0.7 }, } }
def test_features_statistics_null( scene_synthetic: synthetic_scene.SyntheticInputData, null_scene: types.Reconstruction, ) -> None: dataset = synthetic_dataset.SyntheticDataSet( null_scene, scene_synthetic.exifs, scene_synthetic.features, scene_synthetic.tracks_manager, ) features_statistics = stats.features_statistics( dataset, scene_synthetic.tracks_manager, [null_scene] ) assert list(features_statistics.keys()) == [ "detected_features", "reconstructed_features", ] assert ( features_statistics["detected_features"] == features_statistics["reconstructed_features"] ) assert features_statistics["reconstructed_features"] == { "min": -1, "max": -1, "mean": -1, "median": -1, }
def test_reconstruction_statistics_normal( scene_synthetic: synthetic_scene.SyntheticInputData, ) -> None: reference = scene_synthetic.reconstruction dataset = synthetic_dataset.SyntheticDataSet( reference, scene_synthetic.exifs, scene_synthetic.features, scene_synthetic.tracks_manager, ) reconstruction_statistics = stats.reconstruction_statistics( dataset, scene_synthetic.tracks_manager, [reference] ) assert reconstruction_statistics["components"] == 1 assert not reconstruction_statistics["has_gps"] assert not reconstruction_statistics["has_gcp"] assert 4900 < reconstruction_statistics["initial_points_count"] < 5000 assert reconstruction_statistics["initial_shots_count"] == 20 assert 4900 < reconstruction_statistics["reconstructed_points_count"] < 5000 assert reconstruction_statistics["reconstructed_shots_count"] == 20 assert 16800 < reconstruction_statistics["observations_count"] < 16900 assert 3.3 < reconstruction_statistics["average_track_length"] < 3.4 assert 3.4 < reconstruction_statistics["average_track_length_over_two"] < 3.5 assert len(reconstruction_statistics["histogram_track_length"]) == 5 assert 0.15 < reconstruction_statistics["reprojection_error_normalized"] < 0.16 assert 1.25 < reconstruction_statistics["reprojection_error_pixels"] < 1.28 assert len(reconstruction_statistics["reprojection_histogram_normalized"][0]) == 30 assert len(reconstruction_statistics["reprojection_histogram_normalized"][1]) == 31 assert len(reconstruction_statistics["reprojection_histogram_pixels"][0]) == 30 assert len(reconstruction_statistics["reprojection_histogram_pixels"][1]) == 31
def test_match_images(scene_synthetic): reference = scene_synthetic[0].get_reconstruction() synthetic = synthetic_dataset.SyntheticDataSet( reference, scene_synthetic[1], scene_synthetic[2], scene_synthetic[3], scene_synthetic[4], scene_synthetic[5], ) synthetic.matches_exists = lambda im: False synthetic.save_matches = lambda im, m: False override = {} override["matching_gps_neighbors"] = 0 override["matching_gps_distance"] = 0 override["matching_time_neighbors"] = 2 images = sorted(synthetic.images()) pairs, _ = matching.match_images(synthetic, override, images, images) matching.save_matches(synthetic, images, pairs) for i in range(len(images) - 1): pair = images[i], images[i + 1] matches = pairs.get(pair) if matches is None or len(matches) == 1: matches = pairs.get(pair[::-1]) assert len(matches) > 25
def test_reconstruction_incremental(scene_synthetic): reference = scene_synthetic[0].get_reconstruction() dataset = synthetic_dataset.SyntheticDataSet( reference, scene_synthetic[1], scene_synthetic[2], scene_synthetic[3], scene_synthetic[4], scene_synthetic[5], ) _, reconstructed_scene = reconstruction.incremental_reconstruction( dataset, scene_synthetic[5] ) errors = synthetic_scene.compare(reference, reconstructed_scene[0]) assert errors["ratio_cameras"] == 1.0 assert 0.7 < errors["ratio_points"] < 1.0 assert 0 < errors["aligned_position_rmse"] < 0.02 assert 0 < errors["aligned_rotation_rmse"] < 0.001 assert 0 < errors["aligned_points_rmse"] < 0.1 # Sanity check that GPS error is similar to the generated gps_noise assert 4.0 < errors["absolute_gps_rmse"] < 7.0
def test_reconstruction_incremental_rig( scene_synthetic_rig: synthetic_scene.SyntheticInputData, ): reference = scene_synthetic_rig.reconstruction dataset = synthetic_dataset.SyntheticDataSet( reference, scene_synthetic_rig.exifs, scene_synthetic_rig.features, scene_synthetic_rig.tracks_manager, ) dataset.config["align_method"] = "orientation_prior" _, reconstructed_scene = reconstruction.incremental_reconstruction( dataset, scene_synthetic_rig.tracks_manager ) errors = synthetic_scene.compare(reference, reconstructed_scene[0]) assert reconstructed_scene[0].reference.lat == 47.0 assert reconstructed_scene[0].reference.lon == 6.0 assert errors["ratio_cameras"] == 1.0 assert 0.7 < errors["ratio_points"] < 1.0 assert 0 < errors["aligned_position_rmse"] < 0.005 assert 0 < errors["aligned_rotation_rmse"] < 0.001 assert 0 < errors["aligned_points_rmse"] < 0.05 assert 0 < errors["absolute_gps_rmse"] < 0.15
def test_reconstruction_incremental( scene_synthetic: synthetic_scene.SyntheticInputData, ): reference = scene_synthetic.reconstruction dataset = synthetic_dataset.SyntheticDataSet( reference, scene_synthetic.exifs, scene_synthetic.features, scene_synthetic.tracks_manager, ) _, reconstructed_scene = reconstruction.incremental_reconstruction( dataset, scene_synthetic.tracks_manager ) errors = synthetic_scene.compare(reference, reconstructed_scene[0]) assert reconstructed_scene[0].reference.lat == 47.0 assert reconstructed_scene[0].reference.lon == 6.0 assert errors["ratio_cameras"] == 1.0 assert 0.7 < errors["ratio_points"] < 1.0 assert 0 < errors["aligned_position_rmse"] < 0.02 assert 0 < errors["aligned_rotation_rmse"] < 0.001 assert 0 < errors["aligned_points_rmse"] < 0.1 # Sanity check that GPS error is similar to the generated gps_noise assert 4.0 < errors["absolute_gps_rmse"] < 7.0
def test_features_statistics_normal( scene_synthetic: synthetic_scene.SyntheticInputData, ) -> None: reference = scene_synthetic.reconstruction dataset = synthetic_dataset.SyntheticDataSet( reference, scene_synthetic.exifs, scene_synthetic.features, scene_synthetic.tracks_manager, ) features_statistics = stats.features_statistics( dataset, scene_synthetic.tracks_manager, [reference] ) assert list(features_statistics.keys()) == [ "detected_features", "reconstructed_features", ] assert ( features_statistics["detected_features"] == features_statistics["reconstructed_features"] ) assert features_statistics["reconstructed_features"] == { "min": 303, "max": 1065, "mean": 841, "median": 884, }
def test_processing_statistics_null( scene_synthetic: synthetic_scene.SyntheticInputData, null_scene: types.Reconstruction, ): dataset = synthetic_dataset.SyntheticDataSet( null_scene, scene_synthetic.exifs, scene_synthetic.features, scene_synthetic.descriptors, scene_synthetic.colors, scene_synthetic.tracks_manager, ) processing_statistics = stats.processing_statistics(dataset, [null_scene]) assert list( processing_statistics.keys()) == ["steps_times", "date", "area"] assert processing_statistics["steps_times"] == { "Feature Extraction": -1, "Features Matching": -1, "Tracks Merging": -1, "Reconstruction": -1, "Total Time": 0, } assert processing_statistics["date"] == "unknown" assert processing_statistics["area"] == -1
def test_gcp_errors_normal( scene_synthetic: synthetic_scene.SyntheticInputData, ): reference = scene_synthetic.reconstruction dataset = synthetic_dataset.SyntheticDataSet( reference, scene_synthetic.exifs, scene_synthetic.features, scene_synthetic.tracks_manager, ) gcp_errors = stats.gcp_errors(dataset, [reference]) assert gcp_errors == {}
def test_gcp_errors_null( scene_synthetic: synthetic_scene.SyntheticInputData, null_scene: types.Reconstruction, ) -> None: dataset = synthetic_dataset.SyntheticDataSet( null_scene, scene_synthetic.exifs, scene_synthetic.features, scene_synthetic.tracks_manager, ) gcp_errors = stats.gcp_errors(dataset, [null_scene]) assert gcp_errors == {}
def test_rig_statistics_null( scene_synthetic: synthetic_scene.SyntheticInputData, null_scene: types.Reconstruction, ) -> None: dataset = synthetic_dataset.SyntheticDataSet( null_scene, scene_synthetic.exifs, scene_synthetic.features, scene_synthetic.tracks_manager, ) cameras_statistics = stats.rig_statistics(dataset, [null_scene]) assert cameras_statistics == {}
def test_rig_statistics_normal( scene_synthetic: synthetic_scene.SyntheticInputData, ) -> None: reference = scene_synthetic.reconstruction dataset = synthetic_dataset.SyntheticDataSet( reference, scene_synthetic.exifs, scene_synthetic.features, scene_synthetic.tracks_manager, ) rig_statistics = stats.rig_statistics(dataset, [reference]) assert rig_statistics == {}
def test_reconstruction_incremental_rig(scene_synthetic_rig): reference = scene_synthetic_rig[0].get_reconstruction() dataset = synthetic_dataset.SyntheticDataSet( reference, scene_synthetic_rig[1], scene_synthetic_rig[2], scene_synthetic_rig[3], scene_synthetic_rig[4], scene_synthetic_rig[5], ) _, reconstructed_scene = reconstruction.incremental_reconstruction( dataset, scene_synthetic_rig[5] ) errors = synthetic_scene.compare(reference, reconstructed_scene[0])
def test_reconstruction_triangulation( scene_synthetic_triangulation: synthetic_scene.SyntheticInputData, ) -> None: reference = scene_synthetic_triangulation.reconstruction dataset = synthetic_dataset.SyntheticDataSet( reference, scene_synthetic_triangulation.exifs, scene_synthetic_triangulation.features, scene_synthetic_triangulation.tracks_manager, scene_synthetic_triangulation.gcps, ) dataset.config["bundle_compensate_gps_bias"] = True dataset.config["bundle_use_gcp"] = True _, reconstructed_scene = reconstruction.triangulation_reconstruction( dataset, scene_synthetic_triangulation.tracks_manager ) errors = synthetic_scene.compare( reference, scene_synthetic_triangulation.gcps, reconstructed_scene[0], ) assert reconstructed_scene[0].reference.lat == 47.0 assert reconstructed_scene[0].reference.lon == 6.0 assert errors["ratio_cameras"] == 1.0 assert 0.7 < errors["ratio_points"] < 1.0 assert 0 < errors["aligned_position_rmse"] < 0.030 assert 0 < errors["aligned_rotation_rmse"] < 0.002 assert 0 < errors["aligned_points_rmse"] < 0.1 # Sanity check that GPS error is similar to the generated gps_noise assert 0.01 < errors["absolute_gps_rmse"] < 0.1 # Sanity check that GCP error is similar to the generated gcp_noise assert 0.01 < errors["absolute_gcp_rmse_horizontal"] < 0.03 assert 0.005 < errors["absolute_gcp_rmse_vertical"] < 0.04 # Check that the GPS bias (only translation) is recovered translation = reconstructed_scene[0].biases["1"].translation assert 9.9 < translation[0] < 10.11 assert 99.9 < translation[2] < 100.11
def test_match_images(scene_synthetic): reference = scene_synthetic[0].get_reconstruction() synthetic = synthetic_dataset.SyntheticDataSet( reference, scene_synthetic[1], scene_synthetic[2], scene_synthetic[3], scene_synthetic[4], scene_synthetic[5]) synthetic.matches_exists = lambda im: False synthetic.save_matches = lambda im, m: False num_neighbors = 5 synthetic.config['matching_gps_neighbors'] = num_neighbors synthetic.config['bow_words_to_match'] = 8 synthetic.config['matcher_type'] = 'FLANN' images = synthetic.images() pairs, _ = matching.match_images(synthetic, images, images, True) assert len(pairs) == 62 value, margin = 11842, 0.01 assert value * (1 - margin) < sum([len(m) for m in pairs.values() ]) < value * (1 + margin)
def test_match_images(scene_synthetic) -> None: reference = scene_synthetic.reconstruction synthetic = synthetic_dataset.SyntheticDataSet( reference, scene_synthetic.exifs, scene_synthetic.features, scene_synthetic.tracks_manager, ) # pyre-fixme[8]: Attribute has type # `BoundMethod[typing.Callable(SyntheticDataSet.matches_exists)[[Named(self, # SyntheticDataSet), Named(image, str)], bool], SyntheticDataSet]`; used as `(im: # Any) -> bool`. synthetic.matches_exists = lambda im: False # pyre-fixme[8]: Attribute has type # `BoundMethod[typing.Callable(DataSet.save_matches)[[Named(self, DataSet), # Named(image, str), Named(matches, Dict[str, ndarray])], None], # SyntheticDataSet]`; used as `(im: Any, m: Any) -> bool`. synthetic.save_matches = lambda im, m: False override = {} override["matching_gps_neighbors"] = 0 override["matching_gps_distance"] = 0 override["matching_time_neighbors"] = 2 images = sorted(synthetic.images()) pairs, _ = matching.match_images(synthetic, override, images, images) matching.save_matches(synthetic, images, pairs) for i in range(len(images) - 1): pair = images[i], images[i + 1] matches = pairs.get(pair) if matches is None or len(matches) == 1: matches = pairs.get(pair[::-1]) # pyre-fixme[6]: For 1st param expected `Sized` but got # `Optional[List[Tuple[int, int]]]`. assert len(matches) > 25
def test_reconstruction_incremental(scene_synthetic): reference = scene_synthetic[0].get_reconstruction() dataset = synthetic_dataset.SyntheticDataSet(reference, scene_synthetic[1], scene_synthetic[2], scene_synthetic[3], scene_synthetic[4], scene_synthetic[5]) _, reconstructed_scene = reconstruction.\ incremental_reconstruction(dataset, scene_synthetic[5]) errors = synthetic_scene.compare(reference, reconstructed_scene[0]) assert errors[ 'ratio_cameras'] >= 0.95 # Keeps jumping last resection between 9 and 14 inliers with Python3 assert 0.920 < errors['ratio_points'] < 0.950 assert 0.002 < errors['rotation_average'] < 0.09 assert 0.0002 < errors['rotation_std'] < 0.0020 # below, (av+std) should be in order of ||gps_noise||^2 assert 1.5 < errors['position_average'] < 3 assert 1.1 < errors['position_std'] < 4 assert 8.0 < errors['gps_std'] < 10.0 assert np.allclose(errors['gps_average'], 0.0)
def test_reconstruction_incremental_rig(scene_synthetic_rig): reference = scene_synthetic_rig[0].get_reconstruction() dataset = synthetic_dataset.SyntheticDataSet( reference, scene_synthetic_rig[1], scene_synthetic_rig[2], scene_synthetic_rig[3], scene_synthetic_rig[4], scene_synthetic_rig[5], ) dataset.config["align_method"] = "orientation_prior" _, reconstructed_scene = reconstruction.incremental_reconstruction( dataset, scene_synthetic_rig[5]) errors = synthetic_scene.compare(reference, reconstructed_scene[0]) assert errors["ratio_cameras"] == 1.0 assert 0.7 < errors["ratio_points"] < 1.0 assert 0 < errors["aligned_position_rmse"] < 0.005 assert 0 < errors["aligned_rotation_rmse"] < 0.001 assert 0 < errors["aligned_points_rmse"] < 0.05 assert 0 < errors["absolute_gps_rmse"] < 0.15