Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
synthetic-data-mbt.py
35
36import argparse
37from dataclasses import dataclass
38from pathlib import Path
39from typing import List, Optional
40import numpy as np
41import time
42import faulthandler
43faulthandler.enable()
44
45from visp.core import XmlParserCamera, CameraParameters, ColVector, HomogeneousMatrix, Display, ImageConvert
46from visp.core import ImageGray, ImageUInt16
47from visp.io import ImageIo
48from visp.mbt import MbGenericTracker, MbTracker
49from visp.python.display_utils import get_display
50from visp.core import Color
51from visp.core import PixelMeterConversion
52
53try:
54 import cv2
55except:
56 print('Could not import opencv python! make sure that it is installed as it is required')
57 import sys
58 sys.exit(1)
59
60import matplotlib.pyplot as plt
61
62
64 def __init__(self, data_root: Path):
65 model_path = data_root / 'model' / 'teabox'
66 assert model_path.exists()
67 self.config_color = model_path / 'teabox_color.xml'
68 self.config_depth = model_path / 'teabox_depth.xml'
69 self.cad_file = model_path / 'teabox.cao'
70 self.init_file = model_path / 'teabox.init'
71
72
74 def __init__(self, data_root: Path):
75 data_path = data_root / 'data' / 'teabox'
76 assert data_path.exists()
77 self.color_camera_name = 'Camera_L'
78 self.depth_camera_name = 'Camera_R'
79
80 self.color_intrinsics_file = data_path / f'{self.color_camera_name}.xml'
81 self.depth_intrinsics_file = data_path / f'{self.depth_camera_name}.xml'
82
83 self.color_images_dir = data_path / 'color'
84 self.depth_images_dir = data_path / 'depth'
85 self.ground_truth_dir = data_path / 'ground-truth'
86
87
88 self.depth_intrinsics_file = data_path / f'{self.depth_camera_name}.xml'
89
90 self.extrinsic_file = str(data_path / 'depth_M_color.txt')
91 # self.ground_truth = str(data_root / 'data' / 'depth_M_color.txt')
92
93@dataclass
95 I: ImageGray
96 I_depth: Optional[ImageUInt16]
97 point_cloud: Optional[np.ndarray]
98 cMo_ground_truth: HomogeneousMatrix
99
100def read_data(exp_config: MBTConfig, cam_depth: CameraParameters | None, I: ImageGray):
101 color_format = '{:04d}_L.jpg'
102 depth_format = 'Image{:04d}_R.exr'
103 use_depth = cam_depth is not None
104 iteration = 1
105 while True:
106 start_parse_time = time.time()
107 color_filepath = exp_config.color_images_dir / color_format.format(iteration)
108 if not color_filepath.exists():
109 print(f'Could not find image {color_filepath}, is the sequence finished?')
110 return
111 ImageIo.read(I, str(color_filepath), ImageIo.IO_DEFAULT_BACKEND)
112
113
114 I_depth_raw = None
115 point_cloud = None
116 if use_depth:
117 t = time.time()
118 depth_filepath = exp_config.depth_images_dir / depth_format.format(iteration)
119 if not depth_filepath.exists():
120 print(f'Could not find image {depth_filepath}')
121 return
122 I_depth_np = cv2.imread(str(depth_filepath), cv2.IMREAD_ANYCOLOR | cv2.IMREAD_ANYDEPTH)
123 I_depth_np = I_depth_np[..., 0]
124 print(f'\tDepth load took {(time.time() - t) * 1000}ms')
125 I_depth_raw = ImageUInt16(I_depth_np * 32767.5)
126 if I_depth_np.size == 0:
127 print('Could not successfully read the depth image')
128 return
129 t = time.time()
130 # point_cloud = np.empty((*I_depth_np.shape, 3), dtype=np.float64)
131 Z = I_depth_np.copy()
132 Z[Z > 2] = 0.0 # Clamping values that are too high
133
134 vs, us = np.meshgrid(range(I_depth_np.shape[0]), range(I_depth_np.shape[1]), indexing='ij')
135 xs, ys = PixelMeterConversion.convertPoints(cam_depth, us, vs)
136 point_cloud = np.stack((xs * Z, ys * Z, Z), axis=-1)
137
138 print(f'\tPoint_cloud took {(time.time() - t) * 1000}ms')
139
140
141 cMo_ground_truth = HomogeneousMatrix()
142 ground_truth_file = exp_config.ground_truth_dir / (exp_config.color_camera_name + '_{:04d}.txt'.format(iteration))
143 cMo_ground_truth.load(str(ground_truth_file))
144 iteration += 1
145 end_parse_time = time.time()
146 print(f'Data parsing took: {(end_parse_time - start_parse_time) * 1000}ms')
147 yield FrameData(I, I_depth_raw, point_cloud, cMo_ground_truth)
148
149def parse_camera_file(exp_config: MBTConfig, is_color: bool) -> CameraParameters:
150 cam = CameraParameters()
151 xml_parser = XmlParserCamera()
152 if is_color:
153 camera_name, file_path = exp_config.color_camera_name, exp_config.color_intrinsics_file
154 else:
155 camera_name, file_path = exp_config.depth_camera_name, exp_config.depth_intrinsics_file
156 parse_res = xml_parser.parse(cam, str(file_path), camera_name,
157 CameraParameters.perspectiveProjWithoutDistortion, 0, 0, True)
158 assert parse_res == XmlParserCamera.SEQUENCE_OK # Check result
159 return cam
160
161if __name__ == '__main__':
162 parser = argparse.ArgumentParser()
163 parser.add_argument('--data-root', type=str, required=True,
164 help='Path to the folder containing all the data for the synthetic MBT example')
165 parser.add_argument('--disable-klt', action='store_true', help='Disable KLT features for tracking.')
166 parser.add_argument('--disable-depth', action='store_true', help='Do not use depth to perform tracking.')
167 parser.add_argument('--step-by-step', action='store_true', help='Perform tracking frame by frame. Go to the next frame by clicking.')
168 parser.add_argument('--init-ground-truth', action='store_true')
169
170 args = parser.parse_args()
171 data_root = Path(args.data_root)
172
173 mbt_model = MBTModelData(data_root)
174 exp_config = MBTConfig(data_root)
175
176 assert data_root.exists() and data_root.is_dir()
177
178 rgb_tracker: int = MbGenericTracker.EDGE_TRACKER | (MbGenericTracker.KLT_TRACKER if not args.disable_klt else 0)
179 tracker_types: List[int] = [rgb_tracker]
180 if not args.disable_depth:
181 depth_tracker = MbGenericTracker.DEPTH_DENSE_TRACKER
182 tracker_types.append(depth_tracker)
183
184 tracker = MbGenericTracker(tracker_types)
185
186 if args.disable_depth:
187 tracker.loadConfigFile(str(mbt_model.config_color))
188 else:
189 tracker.loadConfigFile(str(mbt_model.config_color), str(mbt_model.config_depth))
190 tracker.loadModel(str(mbt_model.cad_file))
191
192 # Camera intrinsics
193 cam_color = parse_camera_file(exp_config, True)
194 cam_depth = parse_camera_file(exp_config, False) if not args.disable_depth else None
195
196 tracker.setCameraParameters(*((cam_color,) if args.disable_depth else (cam_color, cam_depth)))
197 tracker.setDisplayFeatures(True)
198
199 print('Color intrinsics:', cam_color)
200 print('Depth intrinsics:', cam_depth)
201 I = ImageGray()
202 data_generator = read_data(exp_config, cam_depth, I)
203 frame_data = next(data_generator) # Get first frame for init
204
205 depth_M_color = HomogeneousMatrix()
206 if not args.disable_depth:
207 depth_M_color.load(exp_config.extrinsic_file)
208 tracker.setCameraTransformationMatrix('Camera2', depth_M_color)
209
210 # Initialize displays
211 dI = get_display()
212 dI.init(I, 0, 0, 'Color image')
213
214 I_depth = None if args.disable_depth else ImageGray()
215 dDepth = get_display()
216 if not args.disable_depth:
217 ImageConvert.createDepthHistogram(frame_data.I_depth, I_depth)
218 dDepth.init(I_depth, I.getWidth(), 0, 'Depth')
219
220 if args.init_ground_truth:
221 tracker.initFromPose(I, frame_data.cMo_ground_truth)
222 else:
223 tracker.initClick(I, str(mbt_model.init_file))
224
225 start_time = time.time()
226 for frame_data in data_generator:
227 if frame_data.I_depth is not None:
228 ImageConvert.createDepthHistogram(frame_data.I_depth, I_depth)
229
230 Display.display(I)
231 if not args.disable_depth:
232 Display.display(I_depth)
233
234 if args.disable_depth:
235 tracker.track(I=I)
236 else:
237 pc = frame_data.point_cloud
238 image_dict = {
239 'Camera1': I
240 }
241 t = time.time()
242 tracker.track(image_dict, {'Camera2': pc})
243 print(f'Tracking took {(time.time() - t) * 1000}ms')
244 cMo = HomogeneousMatrix()
245 tracker.getPose(cMo)
246
247 Display.displayFrame(I, cMo, cam_color, 0.05, Color.none, 2)
248 tracker.display(I, cMo, cam_color, Color.red, 2)
249 Display.flush(I)
250 if not args.disable_depth:
251 Display.flush(I_depth)
252 if args.step_by_step:
253 Display.getKeyboardEvent(I, blocking=True)
254 end_time = time.time()
255 print(f'total time = {end_time - start_time}s')
__init__(self, Path data_root)
CameraParameters parse_camera_file(MBTConfig exp_config, bool is_color)
read_data(MBTConfig exp_config, CameraParameters|None cam_depth, ImageGray I)