def parse_MVS_colmap_file(mvs_colmap_ifp,
                              file_name_to_camera_id,
                              with_nxnynz=True,
                              n_th_point=1):
        """
        :param mvs_colmap_ifp:
        :return:
        """
        logger.info('parse_MVS_colmap_file: ...')
        logger.vinfo('mvs_colmap_ifp', mvs_colmap_ifp)
        logger.vinfo('n_th_point', n_th_point)

        camera_index_to_current_feature_index = defaultdict(int)
        points = []

        with open(mvs_colmap_ifp, 'r') as input_file:

            remaining_content = input_file.readlines()
            remaining_content = [x.strip() for x in remaining_content]

            # first line is a comment
            remaining_content = remaining_content[1:]  # skipp 1 line

            dense_index_to_image_name = dict()

            num_dense_images = int(remaining_content[0])
            remaining_content = remaining_content[1:]  # skipp 1 line
            for index in range(num_dense_images):
                dense_index_and_image_name = remaining_content[index].split()
                assert len(dense_index_and_image_name) == 2
                dense_index_to_image_name[int(dense_index_and_image_name[0])] = \
                    dense_index_and_image_name[1]

            remaining_content = remaining_content[
                num_dense_images:]  # skipp lines

            #logger.info(dense_index_to_image_name)

            # next 3 lines are comments
            #logger.info(remaining_content[0])
            #logger.info(remaining_content[1])
            #logger.info(remaining_content[2])
            remaining_content = remaining_content[3:]

            dense_index_to_camera_index = {}
            if file_name_to_camera_id is not None:
                for dense_index, image_name in dense_index_to_image_name.items(
                ):
                    camera_id = file_name_to_camera_id[image_name]
                    dense_index_to_camera_index[dense_index] = camera_id

            #logger.info(dense_index_to_camera_index)

            # DENSE_IMAGE_ID != CAMERA_ID and DENSE_IMAGE_ID != IMAGE_ID
            # POINT3D_ID, X, Y, Z, NX, NY, NZ, R, G, B, TRACK[] as (DENSE_IMAGE_ID, DENSE_COL, DENSE_ROW)
            remaining_content = remaining_content[::n_th_point]
            num_points = len(remaining_content)
            for index, point_line in enumerate(remaining_content):

                if index % 100000 == 0:
                    logger.pinfo(index, num_points)

                point_line_elements = (point_line.rstrip()).split()
                current_point = Point()

                # Adjust the point_3d id w.r.t n_th_point
                point_3d_id = index  # int(point_line_elements[0])
                current_point.id = point_3d_id

                xyz_vec = list(map(float, point_line_elements[1:4]))
                current_point.set_coord(xyz_vec)

                if with_nxnynz:
                    nxnynz_vec = list(map(float, point_line_elements[4:7]))
                    current_point.set_normal(nxnynz_vec)

                    rgb_vec = list(map(int, point_line_elements[7:10]))
                    current_point.set_color(rgb_vec)

                    img_id_col_row_triples_as_str = point_line_elements[10:]

                else:
                    rgb_vec = list(map(int, point_line_elements[4:7]))
                    current_point.set_color(rgb_vec)

                    img_id_col_row_triples_as_str = point_line_elements[7:]

                assert len(img_id_col_row_triples_as_str) % 3 == 0

                dense_image_ids = list(
                    map(int, img_id_col_row_triples_as_str[0::3]))
                cols = list(map(float, img_id_col_row_triples_as_str[1::3]))
                rows = list(map(float, img_id_col_row_triples_as_str[2::3]))

                measurements = []
                #
                for dense_image_id, col, row in zip(dense_image_ids, cols,
                                                    rows):

                    if file_name_to_camera_id is not None:
                        camera_id = dense_index_to_camera_index[dense_image_id]
                    else:
                        camera_id = dense_image_id

                    measurement = Measurement(
                        camera_index=camera_id,
                        # Adding None here would create parsing problems
                        feature_index=camera_index_to_current_feature_index[
                            camera_id],
                        x=col,
                        y=row,
                        x_y_are_image_coords=True)
                    measurements.append(measurement)

                    camera_index_to_current_feature_index[camera_id] += 1

                current_point.measurements = measurements
                points.append(current_point)

            # Detect bad point ids
            point_ids = [point.id for point in points]
            assert len(list(set(point_ids))) == len(point_ids)

        # Compute REAL 2D image coordinates (the one of colmap are probably not correct)
        #cameras_background
        logger.info('parse_MVS_colmap_file: Done')

        return points
    def parse_points(json_data, image_index_to_camera_index, path_to_input_files=None, view_index_to_file_name=None):

        compute_color = (not path_to_input_files is None) and (not view_index_to_file_name is None)
        structure = json_data['structure']

        if compute_color:
            logger.info('Computing color information from files: ...')
            view_index_to_image = {}
            for view_index, file_name in view_index_to_file_name.items():
                image_path = os.path.join(path_to_input_files, file_name)
                pil_image = Image.open(image_path)
                view_index_to_image[view_index] = pil_image

            logger.info('Computing color information from files: Done')

            logger.vinfo('view_index_to_image.keys()', view_index_to_image.keys())

        points = []
        for json_point in structure:
            custom_point = Point()
            position = json_point['value']['X']
            custom_point.set_coord(np.array(position))
            custom_point.id = int(json_point['key'])
            custom_point.measurements = []

            r = g = b = 0

            # color information can only be computed if input files are provided
            if compute_color:
                for observation in json_point['value']['observations']:
                    view_index = int(observation['key'])

                    # REMARK: The order of ndarray.shape (first height, then width) is complimentary to
                    # pils image.size (first width, then height).
                    # That means
                    # height, width = segmentation_as_matrix.shape
                    # width, height = image.size

                    # Therefore: x_in_openmvg_file == x_image == y_ndarray
                    # and y_in_openmvg_file == y_image == x_ndarray
                    x_in_json_file = float(observation['value']['x'][0])    # x has index 0
                    y_in_json_file = float(observation['value']['x'][1])    # y has index 1

                    current_image = view_index_to_image[view_index]
                    current_r, current_g, current_b = current_image.getpixel((x_in_json_file, y_in_json_file))
                    r += current_r
                    g += current_g
                    b += current_b

                    # Measurements is a list of < Measurement >
                    # < Measurement > = < Image index > < Feature Index > < xy >
                    custom_point.measurements.append(
                        Measurement(
                            camera_index= image_index_to_camera_index[view_index],
                            feature_index=int(observation['value']['id_feat']),
                            x=x_in_json_file,
                            y=y_in_json_file,
                            x_y_are_image_coords=True))

                # normalize the rgb values
                amount_observations = len(json_point['value']['observations'])
                r /= amount_observations
                g /= amount_observations
                b /= amount_observations

            custom_point.set_color(np.array([r, g, b], dtype=int))
            points.append(custom_point)
        return points