def match_features(self, kapture_data):
     image_list = [
         filename
         for _, _, filename in kapture.flatten(kapture_data.records_camera)
     ]
     descriptors = []
     descriptor_type = kapture_data.descriptors.dtype
     descriptor_size = kapture_data.descriptors.dsize
     for image_path in image_list:
         descriptors_full_path = get_descriptors_fullpath(
             kapture_data.kapture_path, image_path)
         descriptors.append(
             image_descriptors_from_file(descriptors_full_path,
                                         descriptor_type, descriptor_size))
     kapture_data.matches = kapture.Matches()
     if self._sequential_length is None:
         self._sequential_length = len(image_list)
     for i in tqdm(range(len(image_list))):
         for j in range(i + 1,
                        min(len(image_list), i + self._sequential_length)):
             matches = self._matcher.match_descriptors(
                 descriptors[i], descriptors[j])
             if self._minimal_score is not None:
                 mask = matches[:, 2] > self._minimal_score
                 matches = matches[mask]
             kapture_data.matches.add(image_list[i], image_list[j])
             matches_full_path = get_matches_fullpath(
                 (image_list[i], image_list[j]), kapture_data.kapture_path)
             image_matches_to_file(matches_full_path, matches)
예제 #2
0
def load_descriptors(input_path: str, image_name: str, dtype, dsize):
    """
    load a descriptor. this functions caches up to 50 descriptors

    :param input_path: input path to kapture input root directory
    :param image_name: name of the image
    :param dtype: dtype of the numpy array
    :param dsize: size of the numpy array
    """
    descriptors_path = get_descriptors_fullpath(input_path, image_name)
    return image_descriptors_from_file(descriptors_path, dtype, dsize)
예제 #3
0
def load_descriptors(descriptors_type: str, input_path: str,
                     tar_handler: Optional[TarCollection], image_name: str,
                     dtype, dsize):
    """
    load a descriptor. this functions caches up to 50 descriptors

    :param descriptors_type: type of descriptors, name of the descriptors subfolder
    :param input_path: input path to kapture input root directory
    :param tar_handler: collection of preloaded tar archives
    :param image_name: name of the image
    :param dtype: dtype of the numpy array
    :param dsize: size of the numpy array
    """
    descriptors_path = get_descriptors_fullpath(descriptors_type, input_path,
                                                image_name, tar_handler)
    return image_descriptors_from_file(descriptors_path, dtype, dsize)
예제 #4
0
def export_opensfm(
        kapture_rootdir: str,
        opensfm_rootdir: str,
        force_overwrite_existing: bool = False,
        images_import_method: TransferAction = TransferAction.copy) -> None:
    """

    :param kapture_rootdir:
    :param opensfm_rootdir:
    :param force_overwrite_existing:
    :param images_import_method:
    :return:
    """

    disable_tqdm = logger.getEffectiveLevel(
    ) > logging.INFO  # dont display tqdm for non-verbose levels
    # load reconstruction
    kapture_data = kapture.io.csv.kapture_from_dir(
        kapture_dirpath=kapture_rootdir)

    # export cameras
    opensfm_cameras = {}
    kapture_cameras = {
        cam_id: cam
        for cam_id, cam in kapture_data.sensors.items()
        if cam.sensor_type == 'camera'
    }
    for cam_id, kapture_camera in kapture_cameras.items():
        opensfm_cameras[cam_id] = export_opensfm_camera(kapture_camera)

    # export shots
    opensfm_shots = {}
    for timestamp, camera_id, image_filename in tqdm(kapture.flatten(
            kapture_data.records_camera),
                                                     disable=disable_tqdm):
        # retrieve pose (if there is one).
        # opensfm_shots = {image_filename: shot}
        # shot = {camera , rotation, translation, capture_time, gps_position, ...}
        opensfm_shot = {
            'capture_time': 0,  # in ms != timestamp
            'camera': camera_id,
        }
        if (timestamp, camera_id) in kapture_data.trajectories:
            pose = kapture_data.trajectories[timestamp, camera_id]
            rotation_vector = quaternion.as_rotation_vector(pose.r)
            translation_vector = pose.t.flatten()
            opensfm_shot.update({
                'rotation': rotation_vector.tolist(),
                'translation': translation_vector.tolist()
            })
        opensfm_shots[image_filename] = opensfm_shot

    # pack it
    opensfm_reconstruction = {
        'cameras': opensfm_cameras,
        'shots': opensfm_shots,
    }

    # images
    logger.info(
        f'writing image files "{path.join(opensfm_rootdir, "images")}".')
    image_filenames = [
        f for _, _, f in kapture.flatten(kapture_data.records_camera)
    ]
    kapture_image_filepaths = [
        get_record_fullpath(kapture_rootdir, image_filename)
        for image_filename in image_filenames
    ]
    opensfm_image_filepaths = [
        path.join(opensfm_rootdir, 'images', image_filename)
        for image_filename in image_filenames
    ]
    transfer_files_from_dir(
        source_filepath_list=kapture_image_filepaths,
        destination_filepath_list=opensfm_image_filepaths,
        force_overwrite=force_overwrite_existing,
        copy_strategy=images_import_method,
    )

    # export features files (keypoints + descriptors)
    opensfm_features_suffix = '.features.npz'
    opensfm_features_dirpath = path.join(opensfm_rootdir, 'features')
    logger.info(
        f'exporting keypoint and descriptors to {opensfm_features_dirpath}')
    os.makedirs(opensfm_features_dirpath, exist_ok=True)
    for image_filename in tqdm(image_filenames, disable=disable_tqdm):
        opensfm_features = {}
        # look and load for keypoints in kapture
        if kapture_data.keypoints is not None and image_filename in kapture_data.keypoints:
            kapture_keypoints_filepath = get_keypoints_fullpath(
                kapture_dirpath=kapture_rootdir, image_filename=image_filename)
            logger.debug(f'loading {kapture_keypoints_filepath}')
            kapture_keypoint = image_keypoints_from_file(
                kapture_keypoints_filepath,
                dtype=kapture_data.keypoints.dtype,
                dsize=kapture_data.keypoints.dsize)
            opensfm_features['points'] = kapture_keypoint

        # look and load for descriptors in kapture
        if kapture_data.descriptors is not None and image_filename in kapture_data.descriptors:
            kapture_descriptor_filepath = get_descriptors_fullpath(
                kapture_dirpath=kapture_rootdir, image_filename=image_filename)
            logger.debug(f'loading {kapture_descriptor_filepath}')
            kapture_descriptor = image_descriptors_from_file(
                kapture_descriptor_filepath,
                dtype=kapture_data.descriptors.dtype,
                dsize=kapture_data.descriptors.dsize)
            opensfm_features['descriptors'] = kapture_descriptor

        # writing opensfm feature file
        if len(opensfm_features) > 0:
            opensfm_features_filepath = path.join(
                opensfm_features_dirpath,
                image_filename + opensfm_features_suffix)
            logger.debug(f'writing {opensfm_features_filepath}')
            os.makedirs(path.dirname(opensfm_features_filepath), exist_ok=True)
            np.save(opensfm_features_filepath, opensfm_features)

    # export matches files
    if kapture_data.matches is not None:
        opensfm_matches_suffix = '_matches.pkl.gz'
        opensfm_matches_dirpath = path.join(opensfm_rootdir, 'matches')
        os.makedirs(opensfm_matches_dirpath, exist_ok=True)
        logger.info(f'exporting matches to {opensfm_matches_dirpath}')
        opensfm_pairs = {}
        for image_filename1, image_filename2 in kapture_data.matches:
            opensfm_pairs.setdefault(image_filename1,
                                     []).append(image_filename2)

        for image_filename1 in tqdm(image_filenames, disable=disable_tqdm):
            opensfm_matches = {}
            opensfm_matches_filepath = path.join(
                opensfm_matches_dirpath,
                image_filename1 + opensfm_matches_suffix)
            logger.debug(f'loading matches for {image_filename1}')
            for image_filename2 in opensfm_pairs.get(image_filename1, []):
                # print(image_filename1, image_filename2)
                kapture_matches_filepath = get_matches_fullpath(
                    (image_filename1, image_filename2),
                    kapture_dirpath=kapture_rootdir)
                kapture_matches = image_matches_from_file(
                    kapture_matches_filepath)
                opensfm_matches[image_filename2] = kapture_matches[:,
                                                                   0:2].astype(
                                                                       np.int)

            os.makedirs(path.dirname(opensfm_matches_filepath), exist_ok=True)
            with gzip.open(opensfm_matches_filepath, 'wb') as f:
                pickle.dump(opensfm_matches, f)

    # export 3D-points files
    if kapture_data.points3d is not None:
        logger.info('exporting points 3-D')
        opensfm_reconstruction['points'] = {}
        for i, (x, y, z, r, g, b) in tqdm(enumerate(kapture_data.points3d),
                                          disable=disable_tqdm):
            opensfm_reconstruction['points'][i] = {
                'coordinates': [x, y, z],
                'color': [r, g, b]
            }

    # write json files #################################################################################################
    os.makedirs(opensfm_rootdir, exist_ok=True)
    # write reconstruction.json
    opensfm_reconstruction_filepath = path.join(opensfm_rootdir,
                                                'reconstruction.json')
    logger.info(
        f'writing reconstruction file "{opensfm_reconstruction_filepath}".')
    with open(opensfm_reconstruction_filepath, 'wt') as f:
        json.dump([opensfm_reconstruction], f, indent=4)

    # write camera_models.json
    opensfm_cameras_filepath = path.join(opensfm_rootdir, 'camera_models.json')
    logger.info(f'writing camera models file "{opensfm_cameras_filepath}".')
    with open(opensfm_cameras_filepath, 'wt') as f:
        json.dump(opensfm_cameras, f, indent=4)
예제 #5
0
    def test_maupertuis_import_db_only(self):
        kapture_data = import_colmap_database(self._database_filepath, self._temp_dirpath,
                                              no_geometric_filtering=True)

        # check the numbers
        self.assertIsNone(kapture_data.trajectories)
        self.assertIsNone(kapture_data.points3d)
        self.assertIsNone(kapture_data.records_lidar)
        self.assertIsNone(kapture_data.records_wifi)
        self.assertIsNone(kapture_data.records_gnss)
        self.assertEqual(1, len(kapture_data.sensors))
        self.assertEqual(4, len(kapture_data.records_camera))
        self.assertEqual(4, len(kapture_data.keypoints))
        self.assertEqual(4, len(kapture_data.descriptors))
        self.assertEqual(6, len(kapture_data.matches))

        # check camera
        camera = kapture_data.sensors['cam_00001']
        self.assertEqual(kapture.SENSOR_TYPE_CAMERA, camera.sensor_type)
        self.assertEqual(kapture.CameraType.SIMPLE_PINHOLE, camera.camera_type)
        self.assertAlmostEqual(camera.camera_params, [1919.0, 1079.0, 2302.7999999999997, 959.5, 539.5])

        # check snapshots
        snapshots = kapture_data.records_camera
        self.assertTrue(all('cam_00001' in ts for ts in snapshots.values()))
        self.assertEqual(['00.jpg', '01.jpg', '02.jpg', '03.jpg'],
                         [filename for _, _, filename in kapture.flatten(snapshots, True)])

        # check keypoints
        keypoints = kapture_data.keypoints
        self.assertEqual(np.float32, keypoints.dtype)
        self.assertEqual(6, keypoints.dsize)
        self.assertEqual({'00.jpg', '01.jpg', '02.jpg', '03.jpg'}, keypoints)
        keypoints_filepaths_actual = kapture.io.features.keypoints_to_filepaths(keypoints, self._temp_dirpath)
        keypoints_filepaths_expected = {
            f'{i:02d}.jpg': path_secure(f'{self._temp_dirpath}/reconstruction/keypoints/{i:02d}.jpg.kpt')
            for i in [0, 1, 2, 3]}
        self.assertDictEqual(keypoints_filepaths_actual, keypoints_filepaths_expected)
        # check a keypoints file
        image_keypoints_filepaths = sorted(
            kapture.io.features.keypoints_to_filepaths(keypoints, self._temp_dirpath).values())
        image_keypoints = image_keypoints_from_file(image_keypoints_filepaths[0], keypoints.dtype, keypoints.dsize)
        self.assertEqual((6424, 6), image_keypoints.shape)
        self.assertAlmostEqual([1290.908447265625, 4.156360626220703, -1.3475048542022705,
                                1.4732409715652466, -1.4732409715652466, -1.3475048542022705],
                               image_keypoints[0].tolist())

        self.assertAlmostEqual([1381.316650390625, 668.8056640625, 59.981021881103516,
                                46.423213958740234, -46.423213958740234, 59.981021881103516],
                               image_keypoints[-1].tolist())

        # check descriptors
        descriptors = kapture_data.descriptors
        self.assertEqual(np.uint8, descriptors.dtype)
        self.assertEqual(128, descriptors.dsize)
        self.assertEqual({'00.jpg', '01.jpg', '02.jpg', '03.jpg'}, descriptors)
        descriptors_filepaths_actual = kapture.io.features.descriptors_to_filepaths(descriptors, self._temp_dirpath)
        descriptors_filepaths_expected = {
            f'{i:02d}.jpg': path_secure(f'{self._temp_dirpath}/reconstruction/descriptors/{i:02d}.jpg.desc')
            for i in [0, 1, 2, 3]}
        self.assertDictEqual(descriptors_filepaths_actual, descriptors_filepaths_expected)
        # check a descriptors file
        image_descriptors_filepaths = sorted(kapture.io.features.descriptors_to_filepaths(
            descriptors, self._temp_dirpath).values())
        image_descriptors = image_descriptors_from_file(
            image_descriptors_filepaths[0], descriptors.dtype, descriptors.dsize)
        self.assertEqual(image_keypoints.shape[0], image_descriptors.shape[0])

        # check matches
        matches = kapture_data.matches
        self.assertEqual({('01.jpg', '03.jpg'), ('00.jpg', '02.jpg'),
                          ('00.jpg', '03.jpg'), ('02.jpg', '03.jpg'),
                          ('00.jpg', '01.jpg'), ('01.jpg', '02.jpg')},
                         set(matches))
예제 #6
0
def _export_opensfm_features_and_matches(image_filenames, kapture_data,
                                         kapture_root_dir, opensfm_root_dir,
                                         disable_tqdm):
    """
    export features files (keypoints + descriptors) and matches
    """
    opensfm_features_suffix = '.features.npz'
    opensfm_features_dir_path = path.join(opensfm_root_dir, 'features')
    logger.info(
        f'exporting keypoint and descriptors to {opensfm_features_dir_path}')
    os.makedirs(opensfm_features_dir_path, exist_ok=True)
    for image_filename in tqdm(image_filenames, disable=disable_tqdm):
        opensfm_features = {}
        # look and load for keypoints in kapture
        if kapture_data.keypoints is not None and image_filename in kapture_data.keypoints:
            kapture_keypoints_filepath = get_keypoints_fullpath(
                kapture_dirpath=kapture_root_dir,
                image_filename=image_filename)
            logger.debug(f'loading {kapture_keypoints_filepath}')
            kapture_keypoint = image_keypoints_from_file(
                kapture_keypoints_filepath,
                dtype=kapture_data.keypoints.dtype,
                dsize=kapture_data.keypoints.dsize)
            opensfm_features['points'] = kapture_keypoint

        # look and load for descriptors in kapture
        if kapture_data.descriptors is not None and image_filename in kapture_data.descriptors:
            kapture_descriptor_filepath = get_descriptors_fullpath(
                kapture_dirpath=kapture_root_dir,
                image_filename=image_filename)
            logger.debug(f'loading {kapture_descriptor_filepath}')
            kapture_descriptor = image_descriptors_from_file(
                kapture_descriptor_filepath,
                dtype=kapture_data.descriptors.dtype,
                dsize=kapture_data.descriptors.dsize)
            opensfm_features['descriptors'] = kapture_descriptor

        # writing opensfm feature file
        if len(opensfm_features) > 0:
            opensfm_features_filepath = path.join(
                opensfm_features_dir_path,
                image_filename + opensfm_features_suffix)
            logger.debug(f'writing {opensfm_features_filepath}')
            os.makedirs(path.dirname(opensfm_features_filepath), exist_ok=True)
            np.save(opensfm_features_filepath, opensfm_features)

    # export matches files
    if kapture_data.matches is not None:
        opensfm_matches_suffix = '_matches.pkl.gz'
        opensfm_matches_dir_path = path.join(opensfm_root_dir, 'matches')
        os.makedirs(opensfm_matches_dir_path, exist_ok=True)
        logger.info(f'exporting matches to {opensfm_matches_dir_path}')
        opensfm_pairs = {}
        for image_filename1, image_filename2 in kapture_data.matches:
            opensfm_pairs.setdefault(image_filename1,
                                     []).append(image_filename2)

        for image_filename1 in tqdm(image_filenames, disable=disable_tqdm):
            opensfm_matches = {}
            opensfm_matches_filepath = path.join(
                opensfm_matches_dir_path,
                image_filename1 + opensfm_matches_suffix)
            logger.debug(f'loading matches for {image_filename1}')
            for image_filename2 in opensfm_pairs.get(image_filename1, []):
                # print(image_filename1, image_filename2)
                kapture_matches_filepath = get_matches_fullpath(
                    (image_filename1, image_filename2),
                    kapture_dirpath=kapture_root_dir)
                kapture_matches = image_matches_from_file(
                    kapture_matches_filepath)
                opensfm_matches[image_filename2] = kapture_matches[:,
                                                                   0:2].astype(
                                                                       np.int)

            os.makedirs(path.dirname(opensfm_matches_filepath), exist_ok=True)
            with gzip.open(opensfm_matches_filepath, 'wb') as f:
                pickle.dump(opensfm_matches, f)
예제 #7
0
def export_openmvg_regions(kapture_path: str,
                           kapture_keypoints: Optional[kapture.Keypoints],
                           kapture_descriptors: kapture.Descriptors,
                           openmvg_regions_dir_path: str,
                           image_path_flatten: bool):
    """
    exports openMVG regions ie keypoints and descriptors.

    :param kapture_path: input path to root kapture directory.
    :param kapture_keypoints: input kapture keypoints. Could be None if no keypoints.
    :param kapture_descriptors: input kapture descriptors. Could be None if no descriptors.
    :param openmvg_regions_dir_path: input path to output openMVG regions directory.
    :param image_path_flatten: if true, it means that image path are to be flatten.
    :return:
    """
    # early check we should do
    if kapture_keypoints is None or kapture_descriptors is None:
        logger.warning('no keypoints or descriptors to export.')
        return

    # make sure output directory is ready
    os.makedirs(openmvg_regions_dir_path, exist_ok=True)

    # only able to export SIFT
    if any([
            f.type_name.upper() != 'SIFT'
            for f in [kapture_keypoints, kapture_descriptors]
    ]):
        raise ValueError(
            f'unable to export other regions than sift '
            f'(got {kapture_keypoints.type_name}/{kapture_descriptors.type_name})'
        )

    os.makedirs(openmvg_regions_dir_path, exist_ok=True)
    polymorphic_registry = CerealPointerRegistry(
        id_key=JSON_KEY.POLYMORPHIC_ID, value_key=JSON_KEY.POLYMORPHIC_NAME)
    # create image_describer.json
    fake_regions_type = {
        "ptr_wrapper": {
            "valid": 1,
            "data": {
                "value0": [],
                "value1": []
            }
        }
    }
    fake_regions_type.update(polymorphic_registry.get_ids_dict('SIFT_Regions'))
    image_describer = {'regions_type': fake_regions_type}
    image_describer_file_path = path.join(openmvg_regions_dir_path,
                                          'image_describer.json')
    with open(image_describer_file_path, 'w') as fid:
        json.dump(image_describer, fid, indent=4)

    # this loop can be very long, lets show some progress
    hide_progress_bars = logger.getEffectiveLevel() > logging.INFO

    # copy keypoints files
    keypoints = keypoints_to_filepaths(kapture_keypoints, kapture_path)
    for kapture_image_name, kapture_keypoint_file_path in tqdm(
            keypoints.items(), disable=hide_progress_bars):
        openmvg_keypoint_file_name = get_openmvg_image_path(
            kapture_image_name, image_path_flatten)
        openmvg_keypoint_file_name = path.splitext(
            path.basename(openmvg_keypoint_file_name))[0] + '.feat'
        openmvg_keypoint_file_path = path.join(openmvg_regions_dir_path,
                                               openmvg_keypoint_file_name)
        keypoints_data = image_keypoints_from_file(kapture_keypoint_file_path,
                                                   kapture_keypoints.dtype,
                                                   kapture_keypoints.dsize)
        keypoints_data = keypoints_data[:, 0:4]
        np.savetxt(openmvg_keypoint_file_path, keypoints_data, fmt='%10.5f')

    # copy descriptors files
    """
    from openMVG regions_factory.hpp
    using SIFT_Regions = Scalar_Regions<SIOPointFeature, unsigned char, 128>;
    using AKAZE_Float_Regions = Scalar_Regions<SIOPointFeature, float, 64>;
    using AKAZE_Liop_Regions = Scalar_Regions<SIOPointFeature, unsigned char, 144>;
    using AKAZE_Binary_Regions = Binary_Regions<SIOPointFeature, 64>;
    """
    descriptors = descriptors_to_filepaths(kapture_descriptors, kapture_path)
    for kapture_image_name, kapture_descriptors_file_path in tqdm(
            descriptors.items(), disable=hide_progress_bars):
        openmvg_descriptors_file_name = get_openmvg_image_path(
            kapture_image_name, image_path_flatten)
        openmvg_descriptors_file_name = path.splitext(
            path.basename(openmvg_descriptors_file_name))[0] + '.desc'
        openmvg_descriptors_file_path = path.join(
            openmvg_regions_dir_path, openmvg_descriptors_file_name)
        kapture_descriptors_data = image_descriptors_from_file(
            kapture_descriptors_file_path, kapture_descriptors.dtype,
            kapture_descriptors.dsize)
        # assign a byte array of [size_t[1] + uint8[nb features x 128]
        size_t_len = 64 // 8
        openmvg_descriptors_data = np.empty(
            dtype=np.uint8,
            shape=(kapture_descriptors_data.size + size_t_len, ))
        openmvg_descriptors_data[0:size_t_len].view(
            dtype=np.uint64)[0] = kapture_descriptors_data.shape[0]
        openmvg_descriptors_data[
            size_t_len:] = kapture_descriptors_data.flatten()
        array_to_file(openmvg_descriptors_file_path, openmvg_descriptors_data)
예제 #8
0
    def load_from_kapture(self, kapture_data, minimal_observation_count=10):
        image_list = [
            filename
            for _, _, filename in kapture.flatten(kapture_data.records_camera)
        ]
        descriptors = []
        keypoints = []
        points3d = []
        mask = []
        image_indexes = {}
        image_index_list = []
        keypoint_index_list = []
        self.keypoint_count = 0
        for i, image_path in enumerate(image_list):
            descriptors_full_path = get_descriptors_fullpath(
                self._descriptor_name, kapture_data.kapture_path, image_path)
            kapture_descriptors = kapture_data.descriptors[
                self._descriptor_name]
            descriptors.append(
                image_descriptors_from_file(descriptors_full_path,
                                            kapture_descriptors.dtype,
                                            kapture_descriptors.dsize))
            keypoints_full_path = get_keypoints_fullpath(
                self._descriptor_name, kapture_data.kapture_path, image_path)
            kapture_keypoints = kapture_data.keypoints[self._descriptor_name]
            keypoints.append(
                image_keypoints_from_file(keypoints_full_path,
                                          kapture_keypoints.dtype,
                                          kapture_keypoints.dsize))
            point_count = len(keypoints[i])
            points3d.append(np.zeros((point_count, 3), dtype=np.float32))
            mask.append(np.zeros(point_count, dtype=np.bool))
            image_indexes[image_path] = i
            image_index_list.append(np.array([i] * point_count))
            keypoint_index_list.append(np.arange(point_count))
            self.keypoint_count += point_count

        for point_index, observation in kapture_data.observations.items():
            if len(observation[
                    self._descriptor_name]) > minimal_observation_count:
                for observation_image_name, image_keypoints_index in observation[
                        self._descriptor_name]:
                    image_index = image_indexes[observation_image_name]
                    mask[image_index][image_keypoints_index] = True
                    points3d[image_index][
                        image_keypoints_index] = kapture_data.points3d[
                            point_index][:3]

        for i in range(len(mask)):
            self.image_index_list.extend(list(image_index_list[i]))
            self.keypoint_index_list.extend(list(keypoint_index_list[i]))
            self.masked_image_index_list.extend(
                list(image_index_list[i][mask[i]]))
            self.masked_keypoint_index_list.extend(
                list(keypoint_index_list[i][mask[i]]))
        self.descriptors = descriptors
        self.keypoints = keypoints
        self.points3d = points3d
        self.mask = mask

        self.image_index_from_image_name = image_indexes
        self.load_trajectory(kapture_data)