Example #1
0
    def test_2D_ewa_tsdf_generation4(self):
        filename = "zigzag1_depth_00064.png"
        depth_image = self.image_load_helper(filename)
        camera_intrinsic_matrix = np.array(
            [[700., 0., 320.], [0., 700., 240.], [0., 0., 1.]],
            dtype=np.float32)
        camera = cam.DepthCamera(intrinsics=cam.Camera.Intrinsics(
            (640, 3), intrinsic_matrix=camera_intrinsic_matrix),
                                 depth_unit_ratio=0.001)
        field = \
            ewa.generate_tsdf_2d_ewa_tsdf_inclusive(depth_image, camera, 200,
                                                    field_size=16,
                                                    array_offset=np.array([-232, -256, 490]),
                                                    voxel_size=0.004,
                                                    gaussian_covariance_scale=0.5
                                                    )

        self.assertTrue(np.allclose(field, data.out_sdf_field04))

        parameters = cpp_module.tsdf.Parameters2d()
        parameters.interpolation_method = cpp_module.tsdf.FilteringMethod.EWA_VOXEL_SPACE_INCLUSIVE
        parameters.projection_matrix = camera_intrinsic_matrix
        parameters.array_offset = cpp_module.Vector2i(-232, 490)
        parameters.field_shape = cpp_module.Vector2i(16, 16)
        parameters.smoothing_factor = 0.5

        generator = cpp_module.tsdf.Generator2d(parameters)
        field2 = generator.generate(depth_image,
                                    np.identity(4, dtype=np.float32), 1)
        self.assertTrue(np.allclose(field2, data.out_sdf_field04, atol=1e-5))
Example #2
0
    def test_2d_ewa_tsdf_generation2(self):
        filename = "zigzag2_depth_00108.png"
        depth_image = self.image_load_helper(filename)
        test_full_image = False
        camera_intrinsic_matrix = np.array(
            [[700., 0., 320.], [0., 700., 240.], [0., 0., 1.]],
            dtype=np.float32)
        camera = cam.DepthCamera(intrinsics=cam.Camera.Intrinsics(
            (640, 480), intrinsic_matrix=camera_intrinsic_matrix),
                                 depth_unit_ratio=0.001)

        offset_full_image = np.array([-256, 0, 0])
        chunk_x_start = 210
        chunk_y_start = 103
        chunk_size = 16
        offset_chunk_from_image = np.array([chunk_x_start, 0, chunk_y_start])
        offset_chunk = offset_full_image + offset_chunk_from_image

        if test_full_image:
            parameters = cpp_module.tsdf.Parameters2d()
            parameters.projection_matrix = camera_intrinsic_matrix
            parameters.field_shape = cpp_module.Vector2i(512, 512)
            parameters.array_offset = cpp_module.Vector2i(
                int(offset_full_image[0]), int(offset_full_image[2]))
            parameters.interpolation_method = cpp_module.tsdf.FilteringMethod.EWA_IMAGE_SPACE

            generator = cpp_module.tsdf.Generator2d(parameters)
            field2 = generator.generate(depth_image,
                                        np.identity(4, dtype=np.float32), 200)
            chunk = field2[chunk_y_start:chunk_y_start + chunk_size,
                           chunk_x_start:chunk_x_start + chunk_size].copy()
        else:
            parameters = cpp_module.tsdf.Parameters2d()
            parameters.interpolation_method = cpp_module.tsdf.FilteringMethod.EWA_IMAGE_SPACE
            parameters.projection_matrix = camera_intrinsic_matrix
            parameters.array_offset = cpp_module.Vector2i(
                int(offset_chunk[0]), int(offset_chunk[2]))
            parameters.field_shape = cpp_module.Vector2i(16, 16)

            generator = cpp_module.tsdf.Generator2d(parameters)
            chunk = generator.generate(depth_image,
                                       np.identity(4, dtype=np.float32), 200)
        self.assertTrue(np.allclose(chunk, data.out_sdf_chunk))

        field = \
            ewa.generate_tsdf_2d_ewa_image(depth_image, camera, 200,
                                           field_size=chunk_size,
                                           array_offset=offset_chunk,
                                           voxel_size=0.004)
        self.assertTrue(np.allclose(field, data.out_sdf_chunk, atol=2e-5))
 def __init__(self,
              calibration_file_path,
              first_frame_path,
              second_frame_path,
              image_pixel_row,
              field_size,
              offset,
              voxel_size=0.004,
              focus_coordinates=(-1, -1, -1)):
     super().__init__(focus_coordinates)
     self.calibration_file_path = calibration_file_path
     self.first_frame_path = first_frame_path
     self.second_frame_path = second_frame_path
     self.image_pixel_row = image_pixel_row
     self.field_size = field_size
     self.offset = offset
     self.voxel_size = voxel_size
     if os.path.exists(self.calibration_file_path) and os.path.isdir(
             self.calibration_file_path):
         self.rig = DepthCameraRig.from_infinitam_format(
             self.calibration_file_path)
     else:
         camera_intrinsic_matrix = np.array(
             [[700., 0., 320.], [0., 700., 240.], [0., 0., 1.]],
             dtype=np.float32)
         camera = DepthCamera(intrinsics=Camera.Intrinsics(
             (480, 640), intrinsic_matrix=camera_intrinsic_matrix),
                              depth_unit_ratio=0.001)
         self.rig = DepthCameraRig(cameras=(camera, ))
     parameters_2d = cpp_module.tsdf.Parameters2d()
     parameters_2d.interpolation_method = cpp_module.tsdf.FilteringMethod.NONE
     parameters_2d.projection_matrix = self.rig.depth_camera.intrinsics.intrinsic_matrix.astype(
         np.float32)
     parameters_2d.array_offset = cpp_module.Vector2i(
         int(self.offset[0]), int(self.offset[2]))
     parameters_2d.field_shape = cpp_module.Vector2i(
         self.field_size, self.field_size)
     self.parameters_2d = parameters_2d
     parameters_3d = cpp_module.tsdf.Parameters3d()
     parameters_3d.interpolation_method = cpp_module.tsdf.FilteringMethod.NONE
     parameters_3d.projection_matrix = self.rig.depth_camera.intrinsics.intrinsic_matrix.astype(
         np.float32)
     parameters_3d.array_offset = cpp_module.Vector3i(
         int(self.offset[0]), int(self.offset[1]), int(self.offset[2]))
     parameters_3d.field_shape = cpp_module.Vector3i(
         self.field_size, self.field_size, self.field_size)
     self.parameters_3d = parameters_3d
    def test_nonrigid_optimization02(self):
        sampling.set_focus_coordinates(0, 0)
        field_size = 4
        live_field_template = np.array(
            [[1., 1., 0.49999955, 0.42499956],
             [1., 0.44999936, 0.34999937, 0.32499936],
             [1., 0.35000065, 0.25000066, 0.22500065],
             [1., 0.20000044, 0.15000044, 0.07500044]],
            dtype=np.float32)
        live_field = live_field_template.copy()
        canonical_field = np.array(
            [[1.0000000e+00, 1.0000000e+00, 3.7499955e-01, 2.4999955e-01],
             [1.0000000e+00, 3.2499936e-01, 1.9999936e-01, 1.4999935e-01],
             [1.0000000e+00, 1.7500064e-01, 1.0000064e-01, 5.0000645e-02],
             [1.0000000e+00, 7.5000443e-02, 4.4107438e-07, -9.9999562e-02]],
            dtype=np.float32)
        optimizer = make_optimizer(ComputeMethod.DIRECT, field_size, 2)
        optimizer.optimize(live_field, canonical_field)
        expected_live_field_out = np.array(
            [[1., 1., 0.48917317, 0.43777004],
             [1., 0.43342987, 0.3444094, 0.3287867],
             [1., 0.33020678, 0.24566807, 0.22797936],
             [1., 0.2261582, 0.17907946, 0.14683424]],
            dtype=np.float32)

        report1 = optimizer.get_convergence_report()

        self.assertTrue(np.allclose(live_field, expected_live_field_out))
        live_field = live_field_template.copy()
        optimizer = make_optimizer(ComputeMethod.VECTORIZED, field_size, 2)
        optimizer.optimize(live_field, canonical_field)
        self.assertTrue(np.allclose(live_field, expected_live_field_out))

        report2 = optimizer.get_convergence_report()
        self.assertTrue(report1 == report2)

        expected_warp_stats = \
            cpp_module.WarpDeltaStatistics2d(0.272727, 0.0, 0.0684823, 0.0364445,
                                             0.0167321, cpp_module.Vector2i(1, 2), False, False)
        expected_diff_stats = \
            cpp_module.TsdfDifferenceStatistics2d(0, 0.246834, 0.111843, 0.0812234, cpp_module.Vector2i(3, 3))

        expected_report = cpp_module.ConvergenceReport2d(
            2, True, expected_warp_stats, expected_diff_stats)

        self.assertTrue(report2 == expected_report)
Example #5
0
    def test_2D_ewa_tsdf_generation1(self):
        depth_image = np.zeros((3, 640), dtype=np.uint16)
        depth_image[:] = np.iinfo(np.uint16).max
        depth_image_region = np.array(
            [[
                3233, 3246, 3243, 3256, 3253, 3268, 3263, 3279, 3272, 3289,
                3282, 3299, 3291, 3308, 3301, 3317, 3310, 3326
            ],
             [
                 3233, 3246, 3243, 3256, 3253, 3268, 3263, 3279, 3272, 3289,
                 3282, 3299, 3291, 3308, 3301, 3317, 3310, 3326
             ],
             [
                 3233, 3246, 3243, 3256, 3253, 3268, 3263, 3279, 3272, 3289,
                 3282, 3299, 3291, 3308, 3301, 3317, 3310, 3326
             ]],
            dtype=np.uint16)
        depth_image[:, 399:417] = depth_image_region
        camera_intrinsic_matrix = np.array(
            [[700., 0., 320.], [0., 700., 240.], [0., 0., 1.]],
            dtype=np.float32)
        camera = cam.DepthCamera(intrinsics=cam.Camera.Intrinsics(
            (640, 3), intrinsic_matrix=camera_intrinsic_matrix),
                                 depth_unit_ratio=0.001)
        field = \
            ewa.generate_tsdf_2d_ewa_image(depth_image, camera, 1,
                                           field_size=16,
                                           array_offset=np.array([94, -256, 804]),
                                           voxel_size=0.004)
        self.assertTrue(np.allclose(field, data.out_sdf_field01, atol=2e-5))

        parameters = cpp_module.tsdf.Parameters2d()
        parameters.interpolation_method = cpp_module.tsdf.FilteringMethod.EWA_IMAGE_SPACE
        parameters.projection_matrix = camera_intrinsic_matrix
        parameters.array_offset = cpp_module.Vector2i(94, 804)
        parameters.field_shape = cpp_module.Vector2i(16, 16)

        generator = cpp_module.tsdf.Generator2d(parameters)
        field2 = generator.generate(depth_image,
                                    np.identity(4, dtype=np.float32), 1)
        self.assertTrue(np.allclose(field2, data.out_sdf_field01, atol=1e-6))
    def test_sdf_generation11(self):
        filename = "zigzag2_depth_00108.png"
        depth_image = self.image_load_helper(filename)
        image_pixel_row = 200
        offset = np.array([-8, -8, 144], dtype=np.int32)
        field_size = 16
        narrow_band_width_voxels = 20
        camera_intrinsic_matrix = np.array(
            [[700., 0., 320.], [0., 700., 240.], [0., 0., 1.]],
            dtype=np.float32)
        camera_extrinsic_matrix = np.eye(4, dtype=np.float32)

        depth_camera = DepthCamera(intrinsics=DepthCamera.Intrinsics(
            (640, 480), intrinsic_matrix=camera_intrinsic_matrix),
                                   depth_unit_ratio=0.001)

        field = tsdf_gen.generate_2d_tsdf_field_from_depth_image(
            depth_image,
            depth_camera,
            image_pixel_row,
            camera_extrinsic_matrix=camera_extrinsic_matrix,
            field_size=field_size,
            default_value=-999,
            voxel_size=0.004,
            array_offset=offset,
            narrow_band_width_voxels=narrow_band_width_voxels)
        self.assertTrue(np.allclose(field, data.out_sdf_field01))

        parameters = cpp_module.tsdf.Parameters2d()
        parameters.interpolation_method = cpp_module.tsdf.FilteringMethod.NONE
        parameters.projection_matrix = camera_intrinsic_matrix
        parameters.array_offset = cpp_module.Vector2i(int(offset[0]),
                                                      int(offset[2]))
        parameters.field_shape = cpp_module.Vector2i(field_size, field_size)

        generator = cpp_module.tsdf.Generator2d(parameters)
        field2 = generator.generate(depth_image,
                                    np.identity(4, dtype=np.float32), 1)

        self.assertTrue(np.allclose(field, field2, atol=1e-6))
    def test_operation_same_cpp_to_py(self):
        canonical_frame_path = "tests/test_data/depth_000000.exr"
        live_frame_path = "tests/test_data/depth_000003.exr"

        if not os.path.exists(canonical_frame_path) or not os.path.exists(live_frame_path):
            canonical_frame_path = "test_data/depth_000000.exr"
            live_frame_path = "test_data/depth_000003.exr"

        image_pixel_row = 240
        intrinsic_matrix = np.array([[570.3999633789062, 0, 320],  # FX = 570.3999633789062 CX = 320.0
                                     [0, 570.3999633789062, 240],  # FY = 570.3999633789062 CY = 240.0
                                     [0, 0, 1]], dtype=np.float32)
        camera = DepthCamera(intrinsics=DepthCamera.Intrinsics(resolution=(480, 640),
                                                               intrinsic_matrix=intrinsic_matrix))
        voxel_size = 0.004
        narrow_band_width_voxels = 2
        field_size = 32
        offset = np.array([[-16], [-16], [93]], dtype=np.int32)
        eta = 0.01  # thickness, used to calculate sdf weight.
        camera_pose = np.eye(4, dtype=np.float32)

        shared_parameters = build_opt.Sdf2SdfOptimizer2dSharedParameters()
        shared_parameters.rate = 0.5
        shared_parameters.maximum_iteration_count = 8

        # For verbose output from py version:
        verbosity_parameters_py = sdf2sdfo_py.Sdf2SdfOptimizer2d.VerbosityParameters(True, True)
        verbosity_parameters_cpp = sdf2sdfo_cpp.Sdf2SdfOptimizer2d.VerbosityParameters(True, True)
        visualization_parameters_py = sdf2sdfv.Sdf2SdfVisualizer.Parameters()
        visualization_parameters_py.out_path = "out"

        # For C++ TSDF generator
        tsdf_generation_parameters = sdf2sdfo_cpp.tsdf.Parameters2d(
            depth_unit_ratio=0.001,  # mm to meter
            projection_matrix=intrinsic_matrix,
            near_clipping_distance=0.05,
            array_offset=sdf2sdfo_cpp.Vector2i(int(offset[0, 0]), int(offset[2, 0])),
            field_shape=sdf2sdfo_cpp.Vector2i(field_size, field_size),
            voxel_size=voxel_size,
            narrow_band_width_voxels=narrow_band_width_voxels,
            interpolation_method=sdf2sdfo_cpp.tsdf.FilteringMethod.NONE
        )

        # Read image for c++ optimizer, identical to python, which is done inside ImageBasedSingleFrameDataset class.
        canonical_depth_image = cv2.imread(canonical_frame_path, cv2.IMREAD_UNCHANGED)
        canonical_depth_image = canonical_depth_image.astype(np.uint16)  # mm
        canonical_depth_image = cv2.cvtColor(canonical_depth_image, cv2.COLOR_BGR2GRAY)
        canonical_depth_image[canonical_depth_image == 0] = np.iinfo(np.uint16).max

        live_depth_image = cv2.imread(live_frame_path, cv2.IMREAD_UNCHANGED)
        live_depth_image = live_depth_image.astype(np.uint16)  # mm
        live_depth_image = cv2.cvtColor(live_depth_image, cv2.COLOR_BGR2GRAY)
        live_depth_image[live_depth_image == 0] = np.iinfo(np.uint16).max
        canonical_field = \
            tsdf_gen.generate_2d_tsdf_field_from_depth_image(canonical_depth_image, camera, image_pixel_row,
                                                         field_size=field_size,
                                                         array_offset=offset,
                                                         narrow_band_width_voxels=narrow_band_width_voxels,
                                                         interpolation_method=sdf2sdfo_cpp.tsdf.FilteringMethod.NONE)

        optimizer_cpp = build_opt.make_sdf_2_sdf_optimizer2d(
            implementation_language=build_opt.ImplementationLanguage.CPP,
            shared_parameters=shared_parameters,
            verbosity_parameters_cpp=verbosity_parameters_cpp,
            verbosity_parameters_py=verbosity_parameters_py,
            visualization_parameters_py=visualization_parameters_py,
            tsdf_generation_parameters_cpp=tsdf_generation_parameters)

        twist_cpp = optimizer_cpp.optimize(image_y_coordinate=image_pixel_row,
                                           canonical_field=canonical_field,
                                           live_depth_image=live_depth_image,
                                           eta=eta,
                                           initial_camera_pose=camera_pose)
        # For python optimizer
        data_to_use = ImageBasedSingleFrameDataset(  # for python
            canonical_frame_path,  # dataset from original sdf2sdf paper, reference frame
            live_frame_path,  # dataset from original sdf2sdf paper, current frame
            image_pixel_row, field_size, offset, camera
        )

        optimizer_py = build_opt.make_sdf_2_sdf_optimizer2d(
            implementation_language=build_opt.ImplementationLanguage.PYTHON,
            shared_parameters=shared_parameters,
            verbosity_parameters_cpp=verbosity_parameters_cpp,
            verbosity_parameters_py=verbosity_parameters_py,
            visualization_parameters_py=visualization_parameters_py,
            tsdf_generation_parameters_cpp=tsdf_generation_parameters)

        twist_py = optimizer_py.optimize(data_to_use,
                                         voxel_size=0.004,
                                         narrow_band_width_voxels=narrow_band_width_voxels,
                                         iteration=shared_parameters.maximum_iteration_count,
                                         eta=eta)

        self.assertTrue(np.allclose(twist_cpp, transformation.twist_vector_to_matrix2d(twist_py), atol=1e-4))
Example #8
0
    def optimize(self, live_field, canonical_field):

        self.visualizer = viz.SlavchevaVisualizer(len(live_field),
                                                  self.out_path,
                                                  self.visualization_settings)

        self.focus_neighborhood_log = \
            self.__generate_initial_focus_neighborhood_log(self.field_size)
        self.log = OptimizationLog()
        warp_field = np.zeros((self.field_size, self.field_size, 2),
                              dtype=np.float32)

        max_warp = np.inf
        max_warp_location = (0, 0)
        iteration_number = 0
        self.gradient_field = np.zeros_like(warp_field)

        self.__run_checks(live_field, canonical_field, warp_field)

        if self.adaptive_learning_rate_method == AdaptiveLearningRateMethod.RMS_PROP:
            # exponentially decaying average of squared gradients
            self.edasg_field = np.zeros_like(live_field)

        # do some logging initialization that requires canonical data
        for (x, y), log in self.focus_neighborhood_log.items():
            log.canonical_sdf = canonical_field[y, x]

        # write original raw live
        self.visualizer.write_live_sdf_visualizations(canonical_field,
                                                      live_field)

        # actually perform the optimization
        while (iteration_number < self.min_iterations) or \
                (iteration_number < self.max_iterations and
                 self.maximum_warp_length_lower_threshold < max_warp < self.maximum_warp_length_upper_threshold):

            if self.compute_method == ComputeMethod.DIRECT:
                max_warp, max_warp_location = \
                    self.__optimization_iteration_direct(live_field, canonical_field, warp_field)
            elif self.compute_method == ComputeMethod.VECTORIZED:
                max_warp, max_warp_location = \
                    self.__optimization_iteration_vectorized(live_field, canonical_field, warp_field)
            # log energy aggregates
            self.log.max_warps.append(max_warp)
            self.log.data_energies.append(self.total_data_energy)
            self.log.smoothing_energies.append(self.total_smoothing_energy)
            self.log.level_set_energies.append(self.total_level_set_energy)

            # print end-of-iteration output
            level_set_energy_string = ""
            if self.level_set_term_enabled:
                level_set_energy_string = "; level set energy: {:5f}".format(
                    self.total_level_set_energy)

            print(BOLD_RED,
                  "[Iteration ",
                  iteration_number,
                  " done],",
                  RESET,
                  " data energy: {:5f}".format(self.total_data_energy),
                  "; smoothing energy: {:5f}".format(
                      self.total_smoothing_energy),
                  level_set_energy_string,
                  "; total energy:",
                  self.total_data_energy + self.total_smoothing_energy +
                  self.total_level_set_energy,
                  "; max warp:",
                  max_warp,
                  "@",
                  max_warp_location,
                  sep="")

            self.visualizer.write_all_iteration_visualizations(
                iteration_number, warp_field, self.gradient_field, live_field,
                canonical_field)

            iteration_number += 1

        # log end-of-optimization stats
        if self.enable_convergence_status_logging:
            self.log.convergence_status = cpp_extension.ConvergenceStatus(
                iteration_number, float(max_warp),
                cpp_extension.Vector2i(int(max_warp_location.x),
                                       int(max_warp_location.y)),
                iteration_number >= self.max_iterations,
                bool(max_warp < self.maximum_warp_length_lower_threshold),
                bool(max_warp > self.maximum_warp_length_upper_threshold))

        del self.visualizer
        self.visualizer = None
        return live_field