Exemple #1
0
def export_openmvg_command_line():
    """
    Do the kapture to openmvg export using the parameters given on the command line.
    """
    parser = argparse.ArgumentParser(
        description='Exports from kapture format to openMVG JSON file.')
    parser_verbosity = parser.add_mutually_exclusive_group()
    parser_verbosity.add_argument(
        '-v',
        '--verbose',
        nargs='?',
        default=logging.WARNING,
        const=logging.INFO,
        action=kapture.utils.logging.VerbosityParser,
        help=
        'verbosity level (debug, info, warning, critical, ... or int value) [warning]'
    )
    parser_verbosity.add_argument('-q',
                                  '--silent',
                                  '--quiet',
                                  action='store_const',
                                  dest='verbose',
                                  const=logging.CRITICAL)
    parser.add_argument('-f',
                        '-y',
                        '--force',
                        action='store_true',
                        default=False,
                        help='Force delete output file if already exists.')
    # create the parser for the export command #########################################################################
    parser.add_argument('-k',
                        '--kapture',
                        required=True,
                        help='input path to kapture data root directory')
    parser.add_argument('-o',
                        '--openmvg',
                        help='output openMVG JSON file path.')
    parser.add_argument('--image_action',
                        default='root_link',
                        type=TransferAction,
                        help=f'''what to do with images:
        {TransferAction.root_link.name}: link to the root of the images directory (default) ;
        {TransferAction.link_absolute.name}: absolute individual file link ;
        {TransferAction.link_relative.name}: relative individual file link ;
        {TransferAction.copy.name}: copy file instead of creating link ;
        {TransferAction.move.name}: move file instead of creating link ;
        {TransferAction.skip.name}: do not create links
                                      ''')

    args = parser.parse_args()

    logger.setLevel(args.verbose)
    if args.verbose <= logging.DEBUG:
        # for debug, let kapture express itself.
        kapture.utils.logging.getLogger().setLevel(args.verbose)
    logger.debug(f'{sys.argv[0]} \\\n' +
                 '  \\\n'.join('--{:20} {:100}'.format(k, str(v))
                               for k, v in vars(args).items()))

    # Check that we will not try to do symbolics links on Windows
    # because this is not possible today if the user is not admin
    if sys.platform.startswith("win") and \
            (args.image_link == TransferAction.link_relative or
             args.image_link == TransferAction.link_absolute or
             args.image_link == TransferAction.root_link):
        logger.fatal(
            "It is currently impossible to link files on a Windows platform")
        logger.fatal(
            f"Please try another option for the image: either do nothing ({TransferAction.skip}),"
            f" or {TransferAction.copy}")
        raise OSError("Image file linking not possible on Windows")
    else:
        export_openmvg(args.kapture, args.openmvg, args.image_action,
                       args.force)
Exemple #2
0
 def test_kapture_to_openmvg(self) -> None:
     """
     Test the kapture_to_openmvg export function on a small kapture dataset
     """
     self.assertTrue(path.exists(self._kapture_sample_path),
                     "Kapture directory exists")
     json_file = path.join(self._tempdir.name, 'sfm_export.json')
     export_openmvg(self._kapture_sample_path,
                    json_file,
                    TransferAction.copy,
                    force=True)
     self.assertTrue(path.isfile(json_file), "Openmvg JSON file created")
     with open(json_file, 'r') as f:
         sfm_data = json.load(f)
         self.assertEqual(SFM_DATA_VERSION_NUMBER,
                          sfm_data.get(SFM_DATA_VERSION),
                          "Sfm data version number")
         root_path = sfm_data.get(ROOT_PATH)
         self.assertIsNotNone(root_path, "Root path exported")
         self.assertEqual(self._tempdir.name, root_path,
                          "Root path correct")
         intrinsics = sfm_data.get(INTRINSICS)
         self.assertIsNotNone(intrinsics, "Intrinsics")
         self.assertEqual(9, len(intrinsics), "Cameras")
         camera_ids = {}
         # Search for camera 22970285 and lidar1
         basler = None
         lidar = None
         for intrinsic in intrinsics:
             camera_id = intrinsic.get(KEY)
             camera_ids[camera_id] = camera_id
             if camera_id == FIRST_BASLER_ID:
                 basler = intrinsic.get(VALUE)
             elif camera_id == LIDAR1:
                 lidar = intrinsic.get(VALUE)
         self.assertEqual(9, len(camera_ids),
                          "All camera identifiers are different")
         self.assertIsNotNone(basler, "First basler camera")
         self.assertEqual(CameraModel.pinhole_brown_t2.name,
                          basler.get(POLYMORPHIC_NAME), "Polymorphic name")
         camera_params = basler.get(PTR_WRAPPER).get(DATA).get(VALUE0)
         self.assertEqual(2048, camera_params.get(WIDTH), "Camera width")
         self.assertEqual(1536, camera_params.get(HEIGHT), "Camera height")
         self.assertAlmostEqual(1725.842032333,
                                camera_params.get(FOCAL_LENGTH),
                                msg="Focal length")
         self.assertEqual(1024,
                          camera_params.get(PRINCIPAL_POINT)[0],
                          "Principal point X")
         self.assertEqual(768,
                          camera_params.get(PRINCIPAL_POINT)[1],
                          "Principal point Y")
         self.assertIsNotNone(
             basler.get(PTR_WRAPPER).get(DATA).get(DISTO_T2),
             "Disto_t2 defined")
         # Make sure lidar has not been exported to openMVG
         self.assertIsNone(lidar, "Lidar 1")
         # Recorded images: views in openmvg format
         views = sfm_data.get(VIEWS)
         self.assertIsNotNone(views, "Views")
         self.assertEqual(18, len(views), "Recorded images")
         image_record = None
         for view in views:
             if view.get(KEY) == 3:
                 image_record = view.get(VALUE).get(PTR_WRAPPER).get(DATA)
                 break
         self.assertIsNotNone(image_record, "4th image record")
         local_path = image_record.get(LOCAL_PATH)
         self.assertEqual(FIRST_BASLER_ID, local_path,
                          "Local path is the camera id")
         self.assertEqual(FIRST_BASLER_ID, image_record.get(ID_INTRINSIC),
                          "id_intrinsic is the camera id")
         self.assertEqual(camera_params.get(WIDTH), image_record.get(WIDTH),
                          "Image has camera width")
         self.assertEqual(camera_params.get(HEIGHT),
                          image_record.get(HEIGHT),
                          "Image has camera height")
         filename = image_record.get(FILENAME)
         copied_image_path = path.join(root_path, local_path, filename)
         self.assertTrue(path.isfile(copied_image_path), "Image copied")
         self.assertIsNotNone(filename, "Filename is defined")
         pose_id = image_record.get(ID_POSE)
         self.assertIsNotNone(pose_id, "Pose id")
         self.assertTrue(image_record.get(USE_POSE_ROTATION_PRIOR),
                         "Use pose rotation prior is true")
         view_center = image_record.get(CENTER)
         view_rotation = image_record.get(ROTATION)
         self.assertIsNotNone(view_center, "Center of image")
         self.assertIsNotNone(view_rotation, "Rotation of image")
         # poses: extrinsics in openmvg format
         extrinsics = sfm_data.get(EXTRINSICS)
         self.assertIsNotNone(extrinsics, "Extrinsics")
         self.assertEqual(10, len(extrinsics), "Trajectory points")
         # Search for the pose of the above image
         pose = None
         for extrinsic in extrinsics:
             if extrinsic.get(KEY) == pose_id:
                 pose = extrinsic.get(VALUE)
                 break
         self.assertIsNotNone(pose, "Pose for image")
         pose_center = pose.get(CENTER)
         pose_rotation = pose.get(ROTATION)
         self.assertEqual(view_center, pose_center, "Center are equal")
         self.assertEqual(view_rotation, pose_rotation,
                          "Rotations are equal")
Exemple #3
0
def export_openmvg_command_line():
    """
    Do the kapture to openmvg export using the parameters given on the command line.
    """
    parser = argparse.ArgumentParser(
        description='Exports from kapture format to openMVG JSON file.')
    parser_verbosity = parser.add_mutually_exclusive_group()
    parser_verbosity.add_argument(
        '-v',
        '--verbose',
        nargs='?',
        default=logging.WARNING,
        const=logging.INFO,
        action=kapture.utils.logging.VerbosityParser,
        help=
        'verbosity level (debug, info, warning, critical, ... or int value) [warning]'
    )
    parser_verbosity.add_argument('-q',
                                  '--silent',
                                  '--quiet',
                                  action='store_const',
                                  dest='verbose',
                                  const=logging.CRITICAL)
    parser.add_argument('-f',
                        '-y',
                        '--force',
                        action='store_true',
                        default=False,
                        help='Force delete output file if already exists.')
    # create the parser for the export command #########################################################################
    parser.add_argument('-i',
                        '-k',
                        '--kapture',
                        required=True,
                        help='path to input kapture data root directory')
    parser.add_argument(
        '-o',
        '--openmvg',
        help='root path to openmvg data structure (subpath are guessed).')
    parser.add_argument('-s',
                        '--sfm_data',
                        help='path to output openMVG sfm_data JSON file.')
    parser.add_argument('-im',
                        '--images',
                        help='path to output openMVG image directory.')
    parser.add_argument(
        '-r',
        '--regions',
        help=
        'path to output openMVG regions directory (for features and descriptors).'
    )
    parser.add_argument('-m',
                        '--matches',
                        help='path to output openMVG matches file.')
    parser.add_argument('--image_action',
                        default='skip',
                        type=TransferAction,
                        help=f'''what to do with images:
        {TransferAction.root_link.name}: link to the root of the images directory (default) ;
        {TransferAction.link_absolute.name}: absolute individual file link ;
        {TransferAction.link_relative.name}: relative individual file link ;
        {TransferAction.copy.name}: copy file instead of creating link ;
        {TransferAction.move.name}: move file instead of creating link ;
        {TransferAction.skip.name}: do not create links
                                      ''')
    parser.add_argument(
        '--image_path_flatten',
        action='store_true',
        help=
        'flatten image subpath, to make sure there is no collision in image names.'
    )

    args = parser.parse_args()
    logger.setLevel(args.verbose)

    if args.openmvg is None and args.sfm_data is None:
        raise ValueError('at least one output path should be given.')

    if args.verbose <= logging.DEBUG:
        # for debug, let kapture express itself.
        kapture.utils.logging.getLogger().setLevel(args.verbose)
    logger.debug(f'{sys.argv[0]} \\\n' +
                 '  \\\n'.join('--{:20} {:100}'.format(k, str(v))
                               for k, v in vars(args).items()))

    # auto complete using args.openmvg
    if args.openmvg and args.sfm_data is None:
        args.sfm_data = path.join(args.openmvg, 'sfm_data.json')
        logger.debug(f'guessing output sfm_data is {args.sfm_data}')
    if args.openmvg and args.images is None:
        args.images = path.join(args.openmvg, 'images')
        logger.debug(f'guessing output images is {args.images}')
    if args.openmvg and args.regions is None:
        args.regions = path.join(args.openmvg, 'matches')
        logger.debug(f'guessing output regions is {args.regions}')
    if args.openmvg and args.matches is None:
        args.matches = path.join(args.openmvg, 'matches', 'matches.txt')
        logger.debug(f'guessing output matches is {args.matches}')

    # no image dir == sip transfer
    if args.images is None:
        args.image_action = TransferAction.skip
    if args.image_action == TransferAction.skip:
        args.images = None

    if not args.image_action == TransferAction.skip:
        if args.images is None:
            raise ValueError(
                f'You must specify an image root path for this transfer ({args.image_action})'
            )

    export_openmvg(kapture_path=args.kapture,
                   openmvg_sfm_data_file_path=args.sfm_data,
                   openmvg_image_root_path=args.images,
                   openmvg_regions_dir_path=args.regions,
                   openmvg_matches_file_path=args.matches,
                   image_action=args.image_action,
                   image_path_flatten=args.image_path_flatten,
                   force=args.force)