def resolve_paths(self, path_manager: PathManager): """ Use the path manager to find the required files on disk. Will raise various exceptions if the file is not available. You MUST call this before calling start_trial (run_task will handle that). :param path_manager: The PathManager, for locating files. :return: """ if self.vocabulary_file is None or len(self.vocabulary_file) <= 0: raise ValueError("No vocabulary available for ORB-SLAM {0}, did you build one?".format(self.pk)) self._temp_folder = path_manager.get_temp_folder() self._actual_vocab_file = path_manager.find_file(self.vocabulary_file)
def test_check_dir(self): subject = PathManager([find_project_root()]) self.assertTrue(subject.check_dir('arvet/config')) self.assertTrue(subject.check_dir(Path('arvet/config'))) self.assertFalse(subject.check_dir('arvet/config/path_manager.py')) self.assertFalse(subject.check_dir(Path('arvet/config/path_manager.py'))) self.assertFalse(subject.check_dir('notafolder')) self.assertFalse(subject.check_dir(Path('notafolder')))
def setUpClass(cls): dbconn.setup_image_manager() cls.temp_folder.mkdir(parents=True, exist_ok=True) cls.path_manager = PathManager([Path(__file__).parent], cls.temp_folder) image_builder = DemoImageBuilder(mode=ImageMode.STEREO, stereo_offset=0.15, width=320, height=240, num_stars=500, length=cls.max_time * cls.speed, speed=cls.speed, min_size=4, max_size=50) # Make an image source from the image builder images = [] for time in range(cls.num_frames): image = image_builder.create_frame(time) images.append(image) cls.image_collection = ImageCollection( images=images, timestamps=list(range(len(images))), sequence_type=ImageSequenceType.SEQUENTIAL)
def test_profile_stereo(self, ): import cProfile as profile stats_file = "orbslam_stereo.prof" path_manager = PathManager([Path(__file__).parent], self.temp_folder) system = OrbSlam2(vocabulary_file=self.vocab_path, mode=SensorMode.STEREO, orb_ini_threshold_fast=12, orb_min_threshold_fast=7) image_builder = DemoImageBuilder(mode=ImageMode.STEREO, stereo_offset=0.15, width=320, height=240, num_stars=500, length=self.max_time * self.speed, speed=self.speed, min_size=4, max_size=50) profile.runctx( "run_orbslam(system, image_builder, path_manager, self.num_frames, self.max_time)", locals=locals(), globals=globals(), filename=stats_file)
def test_profile_mono(self, ): import cProfile as profile stats_file = "orbslam_mono.prof" path_manager = PathManager([Path(__file__).parent], self.temp_folder) system = OrbSlam2(vocabulary_file=self.vocab_path, mode=SensorMode.MONOCULAR, orb_num_features=1000, orb_num_levels=8, orb_scale_factor=1.2, orb_ini_threshold_fast=7, orb_min_threshold_fast=12) image_builder = DemoImageBuilder(mode=ImageMode.MONOCULAR, width=640, height=480, num_stars=150, length=self.max_time * self.speed, speed=self.speed, close_ratio=0.6, min_size=10, max_size=100) profile.runctx( "run_orbslam(system, image_builder, path_manager, self.num_frames, self.max_time)", locals=locals(), globals=globals(), filename=stats_file)
def run_orbslam_with_vocab(vocab_path, temp_folder, seed=1000, num_frames=25): # Actually run the system using mocked images max_time = 50 speed = 0.1 path_manager = PathManager([Path(__file__).parent], temp_folder) image_builder = DemoImageBuilder(seed=seed, mode=ImageMode.STEREO, stereo_offset=0.15, width=320, height=240, num_stars=500, length=max_time * speed, speed=speed, min_size=4, max_size=50) subject = OrbSlam2(vocabulary_file=vocab_path, mode=SensorMode.STEREO, orb_ini_threshold_fast=12, orb_min_threshold_fast=7) subject.resolve_paths(path_manager) subject.set_camera_intrinsics(image_builder.get_camera_intrinsics(), max_time / num_frames) subject.set_stereo_offset(image_builder.get_stereo_offset()) subject.start_trial(ImageSequenceType.SEQUENTIAL) for idx in range(num_frames): time = max_time * idx / num_frames image = image_builder.create_frame(time) subject.process_image(image, time) return subject.finish_trial()
def setUp(self): system = mock_types.MockSystem() image_source = mock_types.MockImageSource() self.path_manager = PathManager(['~'], '~/tmp') self.metric = mock_types.MockTrialComparisonMetric() self.trial_result_1 = mock_types.MockTrialResult(system=system, image_source=image_source, success=False) self.trial_result_2 = mock_types.MockTrialResult(system=system, image_source=image_source, success=False)
def test_simple_trial_run_generated(self): # TODO: The state of things: # - With the configured sequence, the ORB-SLAM subprocess silently dies about frame 346-347 # - With my bastardised removal of the subprocess, it seems to work? and not crash? # - I have no idea what is different? the pipe? sequence_folder, left_path, right_path = ndds_loader.find_files(NDDS_SEQUENCE) camera_intrinsics = ndds_loader.read_camera_intrinsics(left_path / '_camera_settings.json') max_img_id = ndds_loader.find_max_img_id(lambda idx: left_path / ndds_loader.IMG_TEMPLATE.format(idx)) with (NDDS_SEQUENCE / 'timestamps.json').open('r') as fp: timestamps = json.load(fp) self.temp_folder.mkdir(parents=True, exist_ok=True) path_manager = PathManager([VOCAB_PATH.parent], self.temp_folder) subject = OrbSlam2( vocabulary_file=str(VOCAB_PATH.name), mode=SensorMode.STEREO, vocabulary_branching_factor=5, vocabulary_depth=6, vocabulary_seed=0, depth_threshold=387.0381720715473, orb_num_features=598, orb_scale_factor=np.power(480 / 104, 1 / 11), # = (480 / min_height)^(1/num_levels) orb_num_levels=11, orb_ini_threshold_fast=86, orb_min_threshold_fast=48 ) subject.resolve_paths(path_manager) subject.set_camera_intrinsics(camera_intrinsics, 0.1) # Read the first frame data to get the baseline left_frame_data = ndds_loader.read_json(left_path / ndds_loader.DATA_TEMPLATE.format(0)) right_frame_data = ndds_loader.read_json(right_path / ndds_loader.DATA_TEMPLATE.format(0)) left_camera_pose = ndds_loader.read_camera_pose(left_frame_data) right_camera_pose = ndds_loader.read_camera_pose(right_frame_data) subject.set_stereo_offset(left_camera_pose.find_relative(right_camera_pose)) subject.start_trial(ImageSequenceType.SEQUENTIAL, seed=0) image_group = 'test' with image_manager.get().get_group(image_group, allow_write=True): for img_idx in range(max_img_id + 1): left_pixels = image_utils.read_colour(left_path / ndds_loader.IMG_TEMPLATE.format(img_idx)) right_pixels = image_utils.read_colour(right_path / ndds_loader.IMG_TEMPLATE.format(img_idx)) image = StereoImage( pixels=left_pixels, right_pixels=right_pixels, image_group=image_group, metadata=imeta.ImageMetadata(camera_pose=left_camera_pose), right_metadata=imeta.ImageMetadata(camera_pose=right_camera_pose) ) subject.process_image(image, timestamps[img_idx]) result = subject.finish_trial() self.assertIsInstance(result, SLAMTrialResult) self.assertEqual(subject, result.system) self.assertTrue(result.success) self.assertFalse(result.has_scale) self.assertIsNotNone(result.run_time) self.assertEqual(max_img_id + 1, len(result.results))
def setUp(self): self.path_manager = PathManager(['~'], '~/tmp') mock_importer.reset() image = mock_types.make_image() self.image_collection = ImageCollection( images=[image], timestamps=[1.2], sequence_type=ImageSequenceType.SEQUENTIAL)
def main(experiment_id: str = '', output: str = '', mongodb_host: str = None, mongodb_port: int = None): """ :param experiment_id: :param output: :param mongodb_host: :param mongodb_port: """ # Load the configuration config = load_global_config('config.yml') if __name__ == '__main__': # Only configure the logging if this is the main function, don't reconfigure logging.config.dictConfig(config['logging']) # Configure the database and the image manager dbconn.configure(config['database'], override_host=mongodb_host, override_port=mongodb_port) im_manager.configure(config['image_manager']) # Set up the path manager path_manager = PathManager(paths=config['paths'], temp_folder=config['temp_folder'], output_dir=config.get('output_dir', None)) # No experiment specified, just list the options if experiment_id is None or experiment_id == '': print("Which experiment would you like to export data for?") return print_available_experiments() # Find an output dir, either using a selected one, or from the path manager if output is None or len(output) == 0: output_dir = path_manager.get_output_dir() else: output_dir = Path(output).expanduser().resolve() # Export the plot data to the cache folder try: Experiment.export_plot_data(experiment_id, output_dir) except Experiment.DoesNotExist: # Could not find experiment, print the list of valid ones, and return print("Could not find experiment \"{0}\"".format(experiment_id)) return print_available_experiments()
def setUpClass(cls): dbconn.connect_to_test_db() dbconn.setup_image_manager() cls.path_manager = PathManager(['~'], '~/tmp') cls.system = mock_types.MockSystem() cls.image_source = mock_types.MockImageSource() cls.image_source.build_images() cls.system.save() cls.image_source.save()
def test_can_run_on_colour_images(self): # Actually run the system using mocked images num_frames = 100 max_time = 50 speed = 0.1 path_manager = PathManager([Path(__file__).parent], self.temp_folder) image_builder = DemoImageBuilder(mode=ImageMode.MONOCULAR, width=640, height=480, num_stars=150, length=max_time * speed, speed=speed, close_ratio=0.6, min_size=10, max_size=100, colour=True) # image_builder.visualise_sequence(max_time, frame_interval=0.5) # return subject = OrbSlam2(vocabulary_file=self.vocab_path, mode=SensorMode.MONOCULAR, orb_num_features=1000, orb_num_levels=8, orb_scale_factor=1.2, orb_ini_threshold_fast=7, orb_min_threshold_fast=12) subject.resolve_paths(path_manager) subject.set_camera_intrinsics(image_builder.get_camera_intrinsics(), max_time / num_frames) subject.start_trial(ImageSequenceType.SEQUENTIAL) for idx in range(num_frames): time = max_time * idx / num_frames image = image_builder.create_frame(time) subject.process_image(image, time) result = subject.finish_trial() self.assertIsInstance(result, SLAMTrialResult) with no_auto_dereference(SLAMTrialResult): self.assertEqual(subject.pk, result.system) self.assertTrue(result.success) self.assertFalse(result.has_scale) self.assertIsNotNone(result.run_time) self.assertIsNotNone(result.settings) self.assertEqual(num_frames, len(result.results)) has_been_found = False for idx, frame_result in enumerate(result.results): self.assertEqual(max_time * idx / num_frames, frame_result.timestamp) self.assertIsNotNone(frame_result.pose) self.assertIsNotNone(frame_result.motion) if frame_result.tracking_state is TrackingState.OK: has_been_found = True self.assertTrue(has_been_found)
def test_find_file(self): root_dir = find_project_root() subject = PathManager([root_dir]) with self.assertRaises(FileNotFoundError): subject.find_file('arvet/config') self.assertEqual(root_dir / 'arvet' / 'config' / 'path_manager.py', subject.find_file('arvet/config/path_manager.py')) with self.assertRaises(FileNotFoundError): subject.find_file('notafile')
def test_run_with_loops(self): # Actually run the system using mocked images num_frames = [20, 20, 27, 25] max_time = 25 speed = 1 path_manager = PathManager([Path(__file__).parent], self.temp_folder) image_builder = DemoImageBuilder(mode=ImageMode.STEREO, stereo_offset=0.15, width=320, height=240, num_stars=300, length=max_time * speed, speed=speed, min_size=4, max_size=50, close_ratio=0.5) subject = OrbSlam2(vocabulary_file=self.vocab_path, mode=SensorMode.STEREO, orb_ini_threshold_fast=12, orb_min_threshold_fast=7) subject.resolve_paths(path_manager) subject.set_camera_intrinsics( image_builder.get_camera_intrinsics(), max_time * len(num_frames) / sum(num_frames)) subject.set_stereo_offset(image_builder.get_stereo_offset()) subject.start_trial(ImageSequenceType.SEQUENTIAL) for loop_idx, loop_frames in enumerate(num_frames): for idx in range(loop_frames): time = max_time * idx / loop_frames + max_time * loop_idx if loop_idx % 2 == 1: builder_time = max_time * (1 - idx / loop_frames) else: builder_time = max_time * idx / loop_frames image = image_builder.create_frame(builder_time) subject.process_image(image, time) result = subject.finish_trial() self.assertIsInstance(result, SLAMTrialResult) with no_auto_dereference(SLAMTrialResult): self.assertEqual(subject.pk, result.system) self.assertTrue(result.success) self.assertTrue(result.has_scale) self.assertIsNotNone(result.run_time) self.assertIsNotNone(result.settings) self.assertEqual(sum(num_frames), len(result.results)) has_been_found = False for idx, frame_result in enumerate(result.results): self.assertIsNotNone(frame_result.pose) self.assertIsNotNone(frame_result.motion) if frame_result.tracking_state is TrackingState.OK: has_been_found = True self.assertTrue(has_been_found)
def run_task(self, path_manager: PathManager): import logging import traceback import importlib # Try and import the desired loader module try: loader_module = importlib.import_module(self.module_name) except ImportError as exception: logging.getLogger(__name__).error( "Could not load module {0} for importing dataset, check it exists" .format(self.module_name)) self.mark_job_failed() raise exception # Check the module has the required function if not hasattr(loader_module, 'import_dataset'): logging.getLogger(__name__).error( "Module {0} does not have method 'import_dataset'".format( self.module_name)) self.mark_job_failed() return # Try and find the root directory or file to load the dataset from try: actual_path = path_manager.find_path(self.path) except FileNotFoundError: logging.getLogger(__name__).error( "Could not find dataset path {0}".format(self.path)) self.mark_job_failed() return logging.getLogger(__name__).info( "Importing dataset from {0} using module {1}".format( actual_path, self.module_name)) try: image_collection = loader_module.import_dataset( actual_path, **self.additional_args) except Exception as exception: logging.getLogger(__name__).error( "Exception occurred while importing dataset from {0} with module {1}:\n{2}" .format(actual_path, self.module_name, traceback.format_exc())) self.mark_job_failed() raise exception if image_collection is None: logging.getLogger(__name__).error( "Failed to import dataset from {0} with module {1}".format( actual_path, self.module_name)) self.mark_job_failed() else: self.result = image_collection self.mark_job_complete() logging.getLogger(__name__).info("Successfully imported dataset")
def test_expands_home_dir(self): subject = PathManager(['~']) result = subject.find_path('.') self.assertEqual(Path('~').expanduser().resolve(), result) subject = PathManager([Path('~')]) result = subject.find_path('.') self.assertEqual(Path('~').expanduser().resolve(), result)
def test_gets_absolute_path(self): subject = PathManager(['.']) result = subject.find_path('.') self.assertEqual(Path('.').resolve(), result) subject = PathManager([Path('.')]) result = subject.find_path('.') self.assertEqual(Path('.').resolve(), result)
def main(task_id: str, config_file: str = 'config.yml', mongodb_host: str = None, mongodb_port: int = None): """ Run a particular task. :args: Only argument is the id of the task to run :return: """ task_id = ObjectId(task_id) # Load the configuration config = load_global_config(config_file) if __name__ == '__main__': # Only configure the logging if this is the main function, don't reconfigure logging.config.dictConfig(config['logging']) # Configure the database and the image manager dbconn.configure(config['database'], override_host=mongodb_host, override_port=mongodb_port) im_manager.configure(config['image_manager']) # Set up the path manager path_manager = PathManager(paths=config['paths'], temp_folder=config['temp_folder'], output_dir=config.get('output_dir', None)) # Try and get the task object autoload_modules(Task, [task_id]) # Try and autoload the task subclass try: task = Task.objects.get({'_id': task_id}) except Exception as ex: logging.getLogger(__name__).critical( "Exception occurred while loading Task({0}):\n{1}".format( str(task_id), traceback.format_exc())) raise ex # Since we got the task, try and run it try: task.run_task(path_manager) except Exception as ex: logging.getLogger(__name__).critical( "Exception occurred while running {0}({1}):\n{2}".format( type(task).__name__, str(task_id), traceback.format_exc())) task.mark_job_failed() raise ex finally: task.save()
def setUp(self): self.path_manager = PathManager(['~'], '~/tmp') self.system = mock.create_autospec(VisionSystem) self.system.is_image_source_appropriate.return_value = True self.system.finish_trial.side_effect = lambda: mock_types.MockTrialResult(system=self.system, success=True) self.image_source = mock.create_autospec(ImageSource) self.image_source.stereo_offset = None self.image_source.camera_intrinsics = mock.Mock() def source_iter(): for idx in range(10): yield idx, mock.Mock() self.image_source.__iter__.side_effect = source_iter
def test_runs_real_time_60_fps_1920x1080(self): path_manager = PathManager(['~'], '~/tmp') task_id = make_task_for_test(1 / 60, 1920, 1080, 3600) task = Task.objects.get({'_id': task_id}) task.mark_job_started('unittest', 0) task.run_task(path_manager) # Check that the task has finished self.assertTrue(task.is_finished) # Check the actual times don't overtake the supposed times result = task.result self.assertIsInstance(result, TimerTrialResult) for delta_timestamp, delta_actual in zip( delta_iter(iter(result.timestamps)), delta_iter(iter(result.actual_times)), ): self.assertLessEqual(delta_actual, delta_timestamp)
def main(*args): """ Run analysis for a particular experiment :args: Only argument is the id of the task to run :return: """ if len(args) >= 1: experiment_id = ObjectId(args[0]) # patch_cwd() # Load the configuration config = load_global_config('config.yml') if __name__ == '__main__': # Only configure the logging if this is the main function, don't reconfigure logging.config.dictConfig(config['logging']) # Configure the database and the image manager dbconn.configure(config['database']) im_manager.configure(config['image_manager']) # Set up the path manager path_manger = PathManager(paths=config['paths'], temp_folder=config['temp_folder']) # Try and get the experiment object try: experiment = Experiment.objects.get({'_id': experiment_id}) except Exception as ex: logging.getLogger(__name__).critical( "Exception occurred while loading Experiment({0}):\n{1}". format(str(experiment_id), traceback.format_exc())) raise ex # Since we got the experiment, run the analyis try: experiment.perform_analysis() except Exception as ex: logging.getLogger(__name__).critical( "Exception occurred while performing analysis {0}({1}):\n{2}". format( type(experiment).__name__, str(experiment_id), traceback.format_exc())) raise ex
def setUp(self): self.system = mock_types.MockSystem() self.image_source = mock_types.MockImageSource() self.image_source.build_images(10) self.path_manager = PathManager(['~'], '~/tmp')
def test_get_output_dir_uses_configured_dir(self): output_dir = (Path('~') / 'my_dir' / 'output').expanduser().resolve() subject = PathManager(['~'], '~', output_dir=str(output_dir)) self.assertEqual(output_dir, subject.get_output_dir())
def test_get_temp_folder_expands_users(self): subject = PathManager(['~'], '~') self.assertEqual(Path('~').expanduser(), subject.get_temp_folder())
def test_get_temp_folder_returns_absolute_path(self): subject = PathManager(['~'], '.') self.assertEqual(Path('.').resolve(), subject.get_temp_folder())
def test_get_output_dir_expands_home_dir(self): subject = PathManager(['~'], '~', output_dir='~') self.assertEqual(Path('~').expanduser(), subject.get_output_dir())
def test_get_output_dir_defaults_to_first_path(self): first_path = Path(__file__).parent.resolve() subject = PathManager([str(first_path), '~'], '.') self.assertEqual(first_path, subject.get_output_dir())
def test_get_output_dir_falls_back_to_first_path_if_output_path_not_within_any_path(self): first_path = Path(__file__).parent.resolve() subject = PathManager([str(first_path)], '.', output_dir=str(first_path.parent / 'myfolder')) self.assertEqual(first_path, subject.get_output_dir())