4 #include <visp3/core/vpConfig.h>
5 #include <visp3/core/vpDisplay.h>
6 #include <visp3/core/vpIoTools.h>
7 #include <visp3/core/vpXmlParserCamera.h>
8 #include <visp3/gui/vpDisplayGDI.h>
9 #include <visp3/gui/vpDisplayOpenCV.h>
10 #include <visp3/gui/vpDisplayX.h>
11 #include <visp3/io/vpImageIo.h>
12 #include <visp3/mbt/vpMbGenericTracker.h>
14 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGCODECS) && defined(VISP_HAVE_PUGIXML)
15 #ifdef ENABLE_VISP_NAMESPACE
21 bool read_data(
unsigned int cpt,
const std::string &video_color_images,
const std::string &video_depth_images,
22 bool disable_depth,
const std::string &video_ground_truth,
24 unsigned int &depth_width,
unsigned int &depth_height,
28 char buffer[FILENAME_MAX];
30 snprintf(buffer, FILENAME_MAX, video_color_images.c_str(), cpt);
31 std::string filename_color = buffer;
34 std::cerr <<
"Cannot read: " << filename_color << std::endl;
41 snprintf(buffer, FILENAME_MAX, video_depth_images.c_str(), cpt);
42 std::string filename_depth = buffer;
45 std::cerr <<
"Cannot read: " << filename_depth << std::endl;
48 cv::Mat depth_raw = cv::imread(filename_depth, cv::IMREAD_ANYDEPTH | cv::IMREAD_ANYCOLOR);
49 if (depth_raw.empty()) {
50 std::cerr <<
"Cannot read: " << filename_depth << std::endl;
54 depth_width =
static_cast<unsigned int>(depth_raw.cols);
55 depth_height =
static_cast<unsigned int>(depth_raw.rows);
56 I_depth_raw.
resize(depth_height, depth_width);
57 pointcloud.resize(depth_width * depth_height);
59 for (
int i = 0; i < depth_raw.rows; i++) {
60 for (
int j = 0; j < depth_raw.cols; j++) {
61 I_depth_raw[i][j] =
static_cast<uint16_t
>(32767.5f * depth_raw.at<cv::Vec3f>(i, j)[0]);
62 double x = 0.0, y = 0.0;
64 double Z = depth_raw.at<cv::Vec3f>(i, j)[0] > 2.0f ? 0.0 :
static_cast<double>(depth_raw.at<cv::Vec3f>(i, j)[0]);
66 size_t idx =
static_cast<size_t>(i * depth_raw.cols + j);
67 pointcloud[idx].resize(3);
68 pointcloud[idx][0] = x * Z;
69 pointcloud[idx][1] = y * Z;
70 pointcloud[idx][2] = Z;
76 snprintf(buffer, FILENAME_MAX, video_ground_truth.c_str(), cpt);
77 std::string filename_pose = buffer;
79 cMo_ground_truth.
load(filename_pose);
85 void usage(
const char **argv,
int error,
const std::string &data_path,
const std::string &model_path,
int first_frame)
87 std::cout <<
"Synopsis" << std::endl
89 <<
" [--data-path <path>] [--model-path <path>] [--first-frame <index>] [--depth-dense-mode <0|1>] "
90 <<
" [--depth-normals-mode <0|1>] [--me-mode <0|1>] [--klt-mode <0|1>] [--step-by-step] [--display-ground-truth] [--help, -h]" << std::endl
92 std::cout <<
"Description" << std::endl
93 <<
" --data-path <path> Path to the data generated by Blender get_camera_pose_teabox.py" << std::endl
95 <<
" Default: " << data_path << std::endl
97 <<
" --model-path <path> Path to the cad model and tracker settings." << std::endl
98 <<
" Default: " << model_path << std::endl
100 <<
" --first-frame <index> First frame number to process." << std::endl
101 <<
" Default: " << first_frame << std::endl
104 <<
" --depth-dense-mode Whether to use dense depth features (0 = off, 1 = on). default: 1" << std::endl
106 <<
" --depth-normals-mode Whether to use normal depth features (0 = off, 1 = on). default: 0" << std::endl
108 <<
" --me-mode Whether to use moving edge features (0 = off, 1 = on). default: 1" << std::endl
110 <<
" --klt-mode Whether to use KLT features (0 = off, 1 = on). Requires OpenCV. default: 1" << std::endl
113 <<
" --step-by-step Flag to enable step by step mode." << std::endl
115 <<
" --display-ground-truth Flag to enable displaying ground truth." << std::endl
116 <<
" When this flag is enabled, there is no tracking. This flag is useful" << std::endl
117 <<
" to validate the ground truth over the rendered images." << std::endl
119 <<
" --help, -h Print this helper message." << std::endl
122 std::cout <<
"Error" << std::endl
124 <<
"Unsupported parameter " << argv[error] << std::endl;
128 int main(
int argc,
const char **argv)
130 std::string opt_data_path =
"data/teabox";
131 std::string opt_model_path =
"model/teabox";
132 unsigned int opt_first_frame = 1;
133 int opt_meMode = 1, opt_kltMode = 1, opt_normalsMode = 0, opt_denseMode = 1;
135 bool disable_depth =
false;
136 bool opt_disable_klt =
false;
138 bool opt_display_ground_truth =
false;
139 bool opt_step_by_step =
false;
141 for (
int i = 1; i < argc; i++) {
142 if (std::string(argv[i]) ==
"--data-path" && i + 1 < argc) {
143 opt_data_path = std::string(argv[i + 1]);
146 else if (std::string(argv[i]) ==
"--model-path" && i + 1 < argc) {
147 opt_model_path = std::string(argv[i + 1]);
150 else if (std::string(argv[i]) ==
"--depth-dense-mode" && i + 1 < argc) {
151 opt_denseMode =
static_cast<unsigned int>(atoi(argv[i + 1]));
152 if (opt_denseMode < 0 || opt_denseMode > 1) {
153 usage(argv, 0, opt_data_path, opt_model_path, opt_first_frame);
158 else if (std::string(argv[i]) ==
"--depth-normals-mode" && i + 1 < argc) {
159 opt_normalsMode =
static_cast<unsigned int>(atoi(argv[i + 1]));
160 if (opt_normalsMode < 0 || opt_normalsMode > 1) {
161 usage(argv, 0, opt_data_path, opt_model_path, opt_first_frame);
166 else if (std::string(argv[i]) ==
"--me-mode" && i + 1 < argc) {
167 opt_meMode =
static_cast<unsigned int>(atoi(argv[i + 1]));
168 if (opt_meMode < 0 || opt_meMode > 1) {
169 usage(argv, 0, opt_data_path, opt_model_path, opt_first_frame);
174 else if (std::string(argv[i]) ==
"--klt-mode" && i + 1 < argc) {
175 opt_kltMode =
static_cast<unsigned int>(atoi(argv[i + 1]));
176 if (opt_kltMode < 0 || opt_kltMode > 1) {
177 usage(argv, 0, opt_data_path, opt_model_path, opt_first_frame);
182 else if (std::string(argv[i]) ==
"--display-ground-truth") {
183 opt_display_ground_truth =
true;
185 else if (std::string(argv[i]) ==
"--step-by-step") {
186 opt_step_by_step =
true;
188 else if (std::string(argv[i]) ==
"--first-frame" && i + 1 < argc) {
189 opt_first_frame =
static_cast<unsigned int>(atoi(argv[i + 1]));
192 else if (std::string(argv[i]) ==
"--help" || std::string(argv[i]) ==
"-h") {
193 usage(argv, 0, opt_data_path, opt_model_path, opt_first_frame);
197 usage(argv, i, opt_data_path, opt_model_path, opt_first_frame);
202 disable_depth = opt_denseMode == 0 && opt_normalsMode == 0;
208 std::string color_camera_name =
"Camera_L";
209 std::string depth_camera_name =
"Camera_R";
217 std::cout <<
"Input data" << std::endl;
218 std::cout <<
" Color images : " << video_color_images << std::endl;
219 std::cout <<
" Depth images : " << (disable_depth ?
"Disabled" : video_depth_images) << std::endl;
220 std::cout <<
" Extrinsics : " << (disable_depth ?
"Disabled" : extrinsic_file) << std::endl;
221 std::cout <<
" Color intrinsics: " << color_intrinsic_file << std::endl;
222 std::cout <<
" Depth intrinsics: " << (disable_depth ?
"Disabled" : depth_intrinsic_file) << std::endl;
223 std::cout <<
" Ground truth : " << ground_truth << std::endl;
224 std::cout <<
"Tracker settings" << std::endl;
225 std::cout <<
" Color config : " << mbt_config_color << std::endl;
226 std::cout <<
" Depth config : " << mbt_config_depth << std::endl;
227 std::cout <<
" CAD model : " << mbt_cad_model << std::endl;
228 std::cout <<
" First frame : " << opt_first_frame << std::endl;
229 std::cout <<
" Step by step : " << opt_step_by_step << std::endl;
230 if (opt_display_ground_truth) {
231 std::cout <<
" Ground truth is used to project the cad model (no tracking)" << std::endl;
234 std::cout <<
" Init file : " << mbt_init_file << std::endl;
235 std::cout <<
" Features : moving-edges " << (opt_disable_klt ?
"" :
"+ keypoints") << (disable_depth ?
"" :
" + depth") << std::endl;
239 std::vector<int> tracker_types;
240 int colorTracker = 0;
243 if (opt_meMode == 1) {
246 if (opt_kltMode == 1) {
247 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
248 colorTracker |= vpMbGenericTracker::KLT_TRACKER;
250 std::cerr <<
"Warning: keypoints cannot be used as features since ViSP is not built with OpenCV 3rd party" << std::endl;
254 if (colorTracker == 0) {
255 std::cerr <<
"You should use at least one type of color feature. If OpenCV is not installed, KLT features are disabled" << std::endl;
259 tracker_types.push_back(colorTracker);
261 if (!disable_depth) {
262 int depthTracker = 0;
263 if (opt_denseMode == 1) {
266 if (opt_normalsMode == 1) {
270 tracker_types.push_back(depthTracker);
274 if (!disable_depth) {
275 tracker.loadConfigFile(mbt_config_color, mbt_config_depth,
true);
278 tracker.loadConfigFile(mbt_config_color);
281 tracker.loadModel(mbt_cad_model);
288 std::cout <<
"Cannot found intrinsics for camera " << color_camera_name << std::endl;
292 std::cout <<
"Cannot found intrinsics for camera " << depth_camera_name << std::endl;
296 tracker.setCameraParameters(cam_color, cam_depth);
298 tracker.setCameraParameters(cam_color);
304 tracker.getCameraParameters(cam_color);
305 tracker.setDisplayFeatures(
true);
306 std::cout <<
"cam_color:\n" << cam_color << std::endl;
309 std::cout <<
"cam_depth:\n" << cam_depth << std::endl;
313 unsigned int depth_width = 0, depth_height = 0;
314 std::vector<vpColVector> pointcloud;
317 unsigned int frame_cpt = opt_first_frame;
318 read_data(frame_cpt, video_color_images, video_depth_images, disable_depth, ground_truth,
319 I, I_depth_raw, depth_width, depth_height, pointcloud, cam_depth, cMo_ground_truth);
322 #if defined(VISP_HAVE_X11)
324 #elif defined(VISP_HAVE_GDI)
326 #elif defined (HAVE_OPENCV_HIGHGUI)
330 d1.
init(I, 0, 0,
"Color image");
331 if (!disable_depth) {
332 d2.init(I_depth,
static_cast<int>(I.
getWidth()), 0,
"Depth image");
336 if (!disable_depth) {
337 depth_M_color.
load(extrinsic_file);
338 tracker.setCameraTransformationMatrix(
"Camera2", depth_M_color);
339 std::cout <<
"depth_M_color:\n" << depth_M_color << std::endl;
342 if (opt_display_ground_truth) {
343 tracker.initFromPose(I, cMo_ground_truth);
346 tracker.initClick(I, mbt_init_file,
true);
351 while (!quit && read_data(frame_cpt, video_color_images, video_depth_images, disable_depth,
352 ground_truth, I, I_depth_raw, depth_width, depth_height, pointcloud, cam_depth,
358 if (opt_display_ground_truth) {
359 tracker.initFromPose(I, cMo_ground_truth);
362 if (!disable_depth) {
363 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
364 std::map<std::string, const std::vector<vpColVector> *> mapOfPointClouds;
365 std::map<std::string, unsigned int> mapOfPointCloudWidths;
366 std::map<std::string, unsigned int> mapOfPointCloudHeights;
368 mapOfImages[
"Camera1"] = &I;
369 mapOfPointClouds[
"Camera2"] = &pointcloud;
370 mapOfPointCloudWidths[
"Camera2"] = depth_width;
371 mapOfPointCloudHeights[
"Camera2"] = depth_height;
372 tracker.track(mapOfImages, mapOfPointClouds, mapOfPointCloudWidths, mapOfPointCloudHeights);
380 std::cout <<
"\nFrame: " << frame_cpt << std::endl;
381 if (!opt_display_ground_truth)
382 std::cout <<
"cMo:\n" << cMo << std::endl;
383 std::cout <<
"cMo ground truth:\n" << cMo_ground_truth << std::endl;
384 if (!disable_depth) {
385 tracker.display(I, I_depth, cMo, depth_M_color * cMo, cam_color, cam_depth,
vpColor::red, 2);
393 std::ostringstream oss;
394 oss <<
"Frame: " << frame_cpt;
396 if (opt_step_by_step) {
404 if (!opt_display_ground_truth) {
406 std::stringstream ss;
407 ss <<
"Nb features: " << tracker.getError().size();
411 std::stringstream ss;
412 ss <<
"Features: edges " << tracker.getNbFeaturesEdge() <<
", klt " << tracker.getNbFeaturesKlt()
413 <<
", dense depth " << tracker.getNbFeaturesDepthDense() <<
", depth normals " << tracker.getNbFeaturesDepthNormal();
428 opt_step_by_step =
true;
431 opt_step_by_step =
false;
437 opt_step_by_step =
true;
447 catch (std::exception &e) {
448 std::cerr <<
"Catch exception: " << e.what() << std::endl;
456 std::cout <<
"To run this tutorial, ViSP should be built with OpenCV and pugixml libraries." << std::endl;
Generic class defining intrinsic camera parameters.
@ perspectiveProjWithoutDistortion
Perspective projection without distortion model.
static const vpColor none
Display for windows using GDI (available on any windows 32 platform).
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="") VP_OVERRIDE
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void display(const vpImage< unsigned char > &I)
static void displayFrame(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, double size, const vpColor &color=vpColor::none, unsigned int thickness=1, const vpImagePoint &offset=vpImagePoint(0, 0), const std::string &frameName="", const vpColor &textColor=vpColor::black, const vpImagePoint &textOffset=vpImagePoint(15, 15))
static void setTitle(const vpImage< unsigned char > &I, const std::string &windowtitle)
static void flush(const vpImage< unsigned char > &I)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
Implementation of an homogeneous matrix and operations on such kind of matrices.
void load(std::ifstream &f)
static void createDepthHistogram(const vpImage< uint16_t > &src_depth, vpImage< vpRGBa > &dest_rgba)
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
unsigned int getWidth() const
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
unsigned int getHeight() const
Real-time 6D object pose tracking using its CAD model.
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
XML parser to load and save intrinsic camera parameters.
vpCameraParameters getCameraParameters() const
int parse(vpCameraParameters &cam, const std::string &filename, const std::string &camera_name, const vpCameraParameters::vpCameraParametersProjType &projModel, unsigned int image_width=0, unsigned int image_height=0, bool verbose=true)