def create_config():
    config_fp = 'configs/cto.cfg'
    config_with_default_values_fp = 'configs/cto_default_values.cfg'
    if not os.path.isfile(config_fp):
        logger.info(
            'Config file missing ... create a copy from config with default values.'
        )
        copyfile(os.path.abspath(config_with_default_values_fp),
                 os.path.abspath(config_fp))
        logger.info(
            'Adjust the input path in the created config file (cto.cfg)')
        assert False
    return Config(config_fp=config_fp)
    def get_option_value(self, option, target_type, section=None):
        """
        :param section:
        :param option:
        :param target_type:
        :return:
        """
        if section is None:
            section = Config.default_section

        try:
            if target_type == list:
                option_str = self.config.get(section, option)
                option_str = Config.detect_missing_commas(option_str)
                option_str = Config.remove_appended_commas(option_str)
                result = json.loads(option_str)
            else:
                option_str = self.config.get(section, option)
                option_str = option_str.split('#')[0].rstrip()
                if target_type == bool:  # Allow True/False bool values in addition to 1/0
                    result = option_str == 'True' or option_str == 'T' or option_str == '1'
                else:
                    result = target_type(option_str)

        except configparser.NoOptionError as NoOptErr:
            logger.info('ERROR: ' + str(NoOptErr))
            logger.info('CONFIG FILE: ' + self.config_fp)
            assert False  # Option Missing
        except:
            logger.info('option_str: ' + str(option_str))
            raise

        return result
def examine_model_format(model_idp):
    txt_ext = '.txt'
    cameras_txt_fp, images_txt_fp, points3D_txt_fp = compute_model_fps(
        model_idp, txt_ext)
    txt_model_present = check_model_completness(cameras_txt_fp, images_txt_fp,
                                                points3D_txt_fp)

    bin_ext = '.bin'
    cameras_bin_fp, images_bin_fp, points3D_bin_fp = compute_model_fps(
        model_idp, bin_ext)
    bin_model_present = check_model_completness(cameras_bin_fp, images_bin_fp,
                                                points3D_bin_fp)

    logger.vinfo('txt_model_present', txt_model_present)
    logger.vinfo('bin_model_present', bin_model_present)
    logger.vinfo('model_idp', str(model_idp))

    # If both model formats are present, we use the txt format
    if txt_model_present:
        logger.info('Found TXT model in ' + str(model_idp))
        return txt_ext
    else:
        logger.info('Found BIN model in ' + str(model_idp))
        return bin_ext
def compute_depth_maps_from_geometry(mesh_ifp,
                                     camera_trajectory,
                                     ordered_image_names,
                                     depth_map_callback,
                                     config=None):

    logger.info('create_depth_maps_from_mesh: ... ')

    num_params = len(camera_trajectory.parameters)
    logger.vinfo('num_params', num_params)

    camera_parameter_list = camera_trajectory.parameters
    num_images = None
    if num_images is not None:
        camera_parameter_list = camera_parameter_list[:num_images]

    assert os.path.isfile(mesh_ifp)
    # required for certain methods called below
    off_screen_rendering = True
    for image_name, camera_parameters in zip(ordered_image_names,
                                             camera_parameter_list):

        extrinsics = camera_parameters.extrinsic
        cam_to_world_mat_computer_vision = invert_transformation_mat(
            extrinsics)

        # http://www.open3d.org/docs/release/python_api/open3d.camera.PinholeCameraIntrinsic.html
        intrinsics = camera_parameters.intrinsic
        render_compatible_camera_parameters = build_vtk_render_compatible_camera_parameters(
            camera_parameters)

        width = intrinsics.width
        height = intrinsics.height

        render_interface = RenderInterface(
            off_screen_rendering=off_screen_rendering,
            width=width,
            height=height,
            background_color=(0, 127, 127))

        # Can we avoid this redundant loading
        render_interface.load_vtk_mesh_or_point_cloud(mesh_ifp,
                                                      texture_ifp=None)

        render_interface.set_active_cam_from_computer_vision_cam_to_world_mat(
            cam_to_world_mat_computer_vision,
            render_compatible_camera_parameters.intrinsic.intrinsic_matrix,
            width,
            height,
            max_clipping_range=sys.float_info.max)

        render_interface.render()
        #render_interface.show_z_buffer()
        if not off_screen_rendering:
            render_interface.render_and_start()

        # We apply an affine transformation to the depth_map images
        # to compensate differences in the intrinsic parameters
        affine_mat = build_affine_transformation_matrix(
            camera_parameters, render_compatible_camera_parameters)

        depth_map = render_interface.get_computer_vision_depth_buffer_as_numpy_arr(
        )
        color_image = render_interface.get_rgba_buffer_as_numpy_arr()

        color_image = cv2.warpAffine(
            color_image, affine_mat,
            (color_image.shape[1], color_image.shape[0]), cv2.WARP_INVERSE_MAP,
            cv2.BORDER_CONSTANT, 0)

        depth_map = cv2.warpAffine(depth_map, affine_mat,
                                   (depth_map.shape[1], depth_map.shape[0]),
                                   cv2.WARP_INVERSE_MAP, cv2.BORDER_CONSTANT,
                                   0)

        depth_map_callback(image_name, depth_map, color_image)

    # if not off_screen_rendering:
    #     render_interface.render_and_start()
    logger.info('create_depth_maps_from_mesh: Done ')
 def log_option_value_pairs(self):
     for val in self.config.values():
         logger.info(val)
                                           target_type,
                                           section=section)
        return result

    def log_option_value_pairs(self):
        for val in self.config.values():
            logger.info(val)

    def write_state_to_disc(self):
        with open(self.path_to_working_copy, 'w') as configfile:
            self.config.write(configfile)


if __name__ == '__main__':

    logger.info('Main called')

    config = Config(path_to_config_file='example.cfg')
    section_option_value_pairs = [('option1', '125'), ('option2', 'aaa'),
                                  ('option1', '222'), ('option3', '213')]
    config.add_option_value_pairs(section_option_value_pairs,
                                  section='Section1')

    option_value_pairs = [('option5', '333'), ('option6', '555')]
    config.add_option_value_pairs(option_value_pairs)

    config.log_option_value_pairs()
    config.write_state_to_disc()

    some_number = config.get_option_value('option1', int, section='Section1')
    logger.info(some_number)
def compute_depth_maps_from_geometry(mesh_ifp, camera_trajectory,
                                     ordered_image_names, depth_map_callback,
                                     config):
    logger.info('create_depth_maps_from_mesh: ... ')

    # https://github.com/intel-isl/Open3D/blob/master/cpp/open3d/visualization/Visualizer/ViewControl.cpp#L189
    #   bool ViewControl::ConvertFromPinholeCameraParameters(
    #       ...
    #         window_height_ != intrinsic.height_ ||
    #         window_width_ != intrinsic.width_ ||
    #         intrinsic.intrinsic_matrix_(0, 2) !=
    #                 (double)window_width_ / 2.0 - 0.5 ||
    #         intrinsic.intrinsic_matrix_(1, 2) !=
    #                 (double)window_height_ / 2.0 - 0.5) {
    #         utility::LogWarning(
    #                 "[ViewControl] ConvertFromPinholeCameraParameters() failed "
    #                 "because window height and width do not match.");
    #   Therefore, only specific intrinsic matrices are allowed

    num_params = len(camera_trajectory.parameters)
    logger.vinfo('num_params', num_params)

    camera_parameter_list = camera_trajectory.parameters
    num_images = None
    if num_images is not None:
        camera_parameter_list = camera_parameter_list[:num_images]

    # http://www.open3d.org/docs/release/python_api/open3d.visualization.html
    # http://www.open3d.org/docs/release/python_api/open3d.visualization.Visualizer.html
    vis = o3d.visualization.Visualizer()
    show_rendering = False
    for image_name, camera_parameters in zip(ordered_image_names,
                                             camera_parameter_list):

        # http://www.open3d.org/docs/release/python_api/open3d.camera.PinholeCameraIntrinsic.html
        intrinsics = camera_parameters.intrinsic

        if show_rendering:
            if intrinsics.width > 1920 or intrinsics.height > 1080:
                # https://github.com/intel-isl/Open3D/issues/2036
                logger.warning(
                    'THERE IS A KNOWN ISSUE FOR VISUALIZING WINDOW SIZES GREATER THAN THE DEFAULT VALUES: '
                    + '({}, {}) vs ({}, {})'.format(
                        intrinsics.width, intrinsics.height, 1920, 1080))
                logger.warning(
                    'Setting show_rendering=False should avoid this problem ')

        vis.create_window(width=intrinsics.width,
                          height=intrinsics.height,
                          left=0,
                          top=0,
                          visible=show_rendering)

        mesh = o3d.io.read_triangle_mesh(mesh_ifp)
        vis.add_geometry(mesh)

        view_control = vis.get_view_control()
        render_compatible_camera_parameters = build_o3d_render_compatible_camera_parameters(
            camera_parameters)

        view_control.convert_from_pinhole_camera_parameters(
            render_compatible_camera_parameters)

        # http://www.open3d.org/docs/release/tutorial/Advanced/non_blocking_visualization.html
        # vis.update_geometry(pcd)
        vis.poll_events()  # CRUCIAL
        vis.update_renderer()

        # We apply an affine transformation to the depth_map images
        # to compensate differences in the intrinsic parameters
        affine_mat = build_affine_transformation_matrix(
            camera_parameters, render_compatible_camera_parameters)

        # http://www.open3d.org/docs/release/python_api/open3d.visualization.Visualizer.html
        color_image = np.asarray(
            vis.capture_screen_float_buffer(do_render=False), dtype=np.float32)

        depth_map = np.asarray(vis.capture_depth_float_buffer(do_render=False),
                               dtype=np.float32)

        color_image = cv2.warpAffine(
            color_image, affine_mat,
            (color_image.shape[1], color_image.shape[0]), cv2.WARP_INVERSE_MAP,
            cv2.BORDER_CONSTANT, 0)

        depth_map = cv2.warpAffine(depth_map, affine_mat,
                                   (depth_map.shape[1], depth_map.shape[0]),
                                   cv2.WARP_INVERSE_MAP, cv2.BORDER_CONSTANT,
                                   0)

        depth_map_callback(image_name, depth_map, color_image)

    logger.info('create_depth_maps_from_mesh: Done ')
    def show_color_and_depth_renderings(self, image_name,
                                        color_image_original_ifp,
                                        depth_map_original_ifp,
                                        color_image_from_mesh,
                                        depth_map_from_mesh,
                                        depth_map_from_mesh_masked):

        logger.info('show_color_and_depth_renderings: ...')
        # if not image_name == '100_7100_resized.JPG':
        #     return

        main_fig, ax_arr_2_by_5 = plt.subplots(
            nrows=2,
            ncols=5,
            gridspec_kw={'height_ratios': (1, 1)}
            # gridspec_kw=dict(
            #     # https://stackoverflow.com/questions/34921930/in-a-matplotlib-plot-consisting-of-histogram-subplots-how-can-the-height-and-ba
            #     height_ratios=(1, 1),
            #     wspace=0.1,
            #     hspace=0.1,
            #     top=0.9,
            #     bottom=0,
            #     left=0.1,
            #     right=0.9)
        )

        depth_map_from_mesh_nan = copy.deepcopy(depth_map_from_mesh)
        depth_map_from_mesh_nan[depth_map_from_mesh_nan == 0] = np.nan

        main_fig.suptitle(image_name)

        width_in_inches = 1080 / main_fig.dpi
        height_in_inches = 1080 / main_fig.dpi
        main_fig.set_size_inches((width_in_inches, height_in_inches))

        depth_map_original = self.read_depth_map(depth_map_original_ifp)
        depth_map_original_nan = copy.deepcopy(depth_map_original)
        depth_map_original_nan[depth_map_original_nan == 0] = np.nan

        min_original = np.nanmin(depth_map_original_nan)
        max_original = np.nanmax(depth_map_original_nan)

        min_mesh = np.nanmin(depth_map_from_mesh_nan)
        min_value = min(min_original, min_mesh)

        max_mesh = np.nanmax(depth_map_original_nan)
        max_value = max(max_original, max_mesh)

        color_image_original_ax = ax_arr_2_by_5[0, 0]
        color_image_original_ax.set_title('color_image_original')
        color_image_original_ax.imshow(mpimg.imread(color_image_original_ifp))

        color_image_original_ax = ax_arr_2_by_5[0, 1]
        color_image_original_ax.set_title('color_image_from_mesh')
        color_image_original_ax.imshow(color_image_from_mesh)

        depth_map_original_ax = ax_arr_2_by_5[0, 2]
        depth_map_original_ax.set_title('depth_map_original_nan')
        depth_map_original_ax.imshow(depth_map_original_nan,
                                     vmin=min_value,
                                     vmax=max_value)
        depth_map_original_ax.annotate('min_original: ' + str(min_original),
                                       (0, 0), (0, -20),
                                       xycoords='axes fraction',
                                       textcoords='offset points',
                                       va='top')
        depth_map_original_ax.annotate('max_original: ' + str(max_original),
                                       (0, 0), (0, -40),
                                       xycoords='axes fraction',
                                       textcoords='offset points',
                                       va='top')

        depth_map_from_mesh_ax = ax_arr_2_by_5[0, 3]
        depth_map_from_mesh_ax.set_title('depth_map_from_mesh_nan')
        depth_map_from_mesh_ax.imshow(depth_map_from_mesh_nan,
                                      vmin=min_value,
                                      vmax=max_value)
        depth_map_from_mesh_ax.annotate('min_mesh: ' + str(min_mesh), (0, 0),
                                        (0, -20),
                                        xycoords='axes fraction',
                                        textcoords='offset points',
                                        va='top')
        depth_map_from_mesh_ax.annotate('max_mesh: ' + str(max_mesh), (0, 0),
                                        (0, -40),
                                        xycoords='axes fraction',
                                        textcoords='offset points',
                                        va='top')

        if self.use_original_depth_maps_as_mask:
            depth_map_from_mesh_masked_nan = copy.deepcopy(
                depth_map_from_mesh_masked)
            depth_map_from_mesh_masked_nan[depth_map_from_mesh_masked ==
                                           0] = np.nan
            depth_map_from_mesh_masked_ax = ax_arr_2_by_5[0, 4]
            depth_map_from_mesh_masked_ax.set_title(
                'depth_map_from_mesh_masked_nan')
            depth_map_from_mesh_masked_ax.imshow(
                depth_map_from_mesh_masked_nan, vmin=min_value, vmax=max_value)

        show_histogram = False
        if show_histogram:
            num_bins = 10
            # https://matplotlib.org/api/_as_gen/matplotlib.pyplot.hist.html
            depth_map_original_hist_ax = ax_arr_2_by_5[1, 0]
            depth_map_original_hist_ax.hist(depth_map_original,
                                            range=(min_value, max_value))
            depth_map_from_mesh_hist_ax = ax_arr_2_by_5[1, 1]
            depth_map_from_mesh_hist_ax.hist(depth_map_from_mesh,
                                             range=(min_value, max_value))
            if self.use_original_depth_maps_as_mask:
                depth_map_from_mesh_masked_hist_ax = ax_arr_2_by_5[1, 2]
                depth_map_from_mesh_masked_hist_ax.hist(
                    depth_map_from_mesh_masked, range=(min_value, max_value))

        # main_fig.subplots_adjust(right=0.8)
        # cbar_ax = main_fig.add_axes([0.85, 0.15, 0.05, 0.7])
        # main_fig.colorbar(im, cax=cbar_ax)

        plt.show()

        # ColmapDepthMapHandler.visualize_depth_map(depth_map_original, show=False)
        # ColmapDepthMapHandler.visualize_depth_map(depth_map_from_mesh, show=True)
        logger.info('show_color_and_depth_renderings: ...')