Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
mbtGenericTrackingDepth.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Example of tracking with vpGenericTracker on Castel.
32 */
33
39
40#include <cstdlib>
41#include <iostream>
42#include <visp3/core/vpConfig.h>
43
44#if (defined(VISP_HAVE_MODULE_MBT) && defined(VISP_HAVE_DISPLAY)) && \
45 (defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV))
46
47#include <visp3/core/vpDebug.h>
48#include <visp3/core/vpHomogeneousMatrix.h>
49#include <visp3/core/vpIoTools.h>
50#include <visp3/core/vpMath.h>
51#include <visp3/gui/vpDisplayD3D.h>
52#include <visp3/gui/vpDisplayGDI.h>
53#include <visp3/gui/vpDisplayGTK.h>
54#include <visp3/gui/vpDisplayOpenCV.h>
55#include <visp3/gui/vpDisplayX.h>
56#include <visp3/io/vpImageIo.h>
57#include <visp3/io/vpParseArgv.h>
58#include <visp3/io/vpVideoReader.h>
59#include <visp3/mbt/vpMbGenericTracker.h>
60
61#define GETOPTARGS "x:X:m:M:i:n:dchfolwvpt:T:e:"
62
63#define USE_SMALL_DATASET 1 // small depth dataset in ViSP-images
64
65#ifdef ENABLE_VISP_NAMESPACE
66using namespace VISP_NAMESPACE_NAME;
67#endif
68
69namespace
70{
71void usage(const char *name, const char *badparam)
72{
73 fprintf(stdout, "\n\
74 Example of tracking with vpGenericTracker.\n\
75 \n\
76 SYNOPSIS\n\
77 %s [-i <test image path>] [-x <config file>] [-X <config file depth>]\n\
78 [-m <model name>] [-M <model name depth>] [-n <initialisation file base name>]\n\
79 [-f] [-c] [-d] [-h] [-o] [-w] [-l] [-v] [-p]\n\
80 [-t <tracker type>] [-T <tracker type>] [-e <last frame index>]\n",
81 name);
82
83 fprintf(stdout, "\n\
84 OPTIONS: \n\
85 -i <input image path> \n\
86 Set image input path.\n\
87 These images come from visp-images-x.y.z.tar.gz available \n\
88 on the ViSP website.\n\
89 Setting the VISP_INPUT_IMAGE_PATH environment\n\
90 variable produces the same behavior than using\n\
91 this option.\n\
92 \n\
93 -x <config file> \n\
94 Set the config file (the xml file) to use.\n\
95 The config file is used to specify the parameters of the tracker.\n\
96 \n\
97 -X <config file> \n\
98 Set the config file (the xml file) to use for the depth sensor.\n\
99 The config file is used to specify the parameters of the tracker.\n\
100 \n\
101 -m <model name> \n\
102 Specify the name of the file of the model.\n\
103 The model can either be a vrml model (.wrl) or a .cao file.\n\
104 \n\
105 -M <model name> \n\
106 Specify the name of the file of the model for the depth sensor.\n\
107 The model can either be a vrml model (.wrl) or a .cao file.\n\
108 \n\
109 -n <initialisation file base name> \n\
110 Base name of the initialisation file. The file will be 'base_name'.init .\n\
111 This base name is also used for the optional picture specifying where to \n\
112 click (a .ppm picture).\n\
113 \n\
114 -f \n\
115 Turn off the display of the the moving edges and Klt points. \n\
116 \n\
117 -d \n\
118 Turn off the display.\n\
119 \n\
120 -c\n\
121 Disable the mouse click. Useful to automate the \n\
122 execution of this program without human intervention.\n\
123 \n\
124 -o\n\
125 Use Ogre3D for visibility tests\n\
126 \n\
127 -w\n\
128 When Ogre3D is enable [-o] show Ogre3D configuration dialog that allows to set the renderer.\n\
129 \n\
130 -l\n\
131 Use the scanline for visibility tests.\n\
132 \n\
133 -v\n\
134 Compute covariance matrix.\n\
135 \n\
136 -p\n\
137 Compute gradient projection error.\n\
138 \n\
139 -t <tracker type>\n\
140 Set tracker type (<1 (Edge)>, <2 (KLT)>, <3 (both)>) for color sensor.\n\
141 \n\
142 -T <tracker type>\n\
143 Set tracker type (<4 (Depth normal)>, <8 (Depth dense)>, <12 (both)>) for depth sensor.\n\
144 \n\
145 -e <last frame index>\n\
146 Specify the index of the last frame. Once reached, the tracking is stopped.\n\
147 \n\
148 -h \n\
149 Print the help.\n\n");
150
151 if (badparam)
152 fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
153}
154
155bool getOptions(int argc, const char **argv, std::string &ipath, std::string &configFile, std::string &configFile_depth,
156 std::string &modelFile, std::string &modelFile_depth, std::string &initFile, bool &displayFeatures,
157 bool &click_allowed, bool &display, bool &useOgre, bool &showOgreConfigDialog, bool &useScanline,
158 bool &computeCovariance, bool &projectionError, int &trackerType, int &tracker_type_depth,
159 int &lastFrame)
160{
161 const char *optarg_;
162 int c;
163 while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
164
165 switch (c) {
166 case 'i':
167 ipath = optarg_;
168 break;
169 case 'x':
170 configFile = optarg_;
171 break;
172 case 'X':
173 configFile_depth = optarg_;
174 break;
175 case 'm':
176 modelFile = optarg_;
177 break;
178 case 'M':
179 modelFile_depth = optarg_;
180 break;
181 case 'n':
182 initFile = optarg_;
183 break;
184 case 'f':
185 displayFeatures = false;
186 break;
187 case 'c':
188 click_allowed = false;
189 break;
190 case 'd':
191 display = false;
192 break;
193 case 'o':
194 useOgre = true;
195 break;
196 case 'l':
197 useScanline = true;
198 break;
199 case 'w':
200 showOgreConfigDialog = true;
201 break;
202 case 'v':
203 computeCovariance = true;
204 break;
205 case 'p':
206 projectionError = true;
207 break;
208 case 't':
209 trackerType = atoi(optarg_);
210 break;
211 case 'T':
212 tracker_type_depth = atoi(optarg_);
213 break;
214 case 'e':
215 lastFrame = atoi(optarg_);
216 break;
217 case 'h':
218 usage(argv[0], nullptr);
219 return false;
220
221 default:
222 usage(argv[0], optarg_);
223 return false;
224 }
225 }
226
227 if ((c == 1) || (c == -1)) {
228 // standalone param or error
229 usage(argv[0], nullptr);
230 std::cerr << "ERROR: " << std::endl;
231 std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
232 return false;
233 }
234
235 return true;
236}
237
238struct vpRealsenseIntrinsics_t
239{
240 float ppx;
242 float ppy;
244 float fx;
246 float fy;
248 float coeffs[5];
249};
250
251void rs_deproject_pixel_to_point(float point[3], const vpRealsenseIntrinsics_t &intrin, const float pixel[2], float depth)
252{
253 float x = (pixel[0] - intrin.ppx) / intrin.fx;
254 float y = (pixel[1] - intrin.ppy) / intrin.fy;
255
256 float r2 = x * x + y * y;
257 float f = 1 + intrin.coeffs[0] * r2 + intrin.coeffs[1] * r2 * r2 + intrin.coeffs[4] * r2 * r2 * r2;
258 float ux = x * f + 2 * intrin.coeffs[2] * x * y + intrin.coeffs[3] * (r2 + 2 * x * x);
259 float uy = y * f + 2 * intrin.coeffs[3] * x * y + intrin.coeffs[2] * (r2 + 2 * y * y);
260
261 x = ux;
262 y = uy;
263
264 point[0] = depth * x;
265 point[1] = depth * y;
266 point[2] = depth;
267}
268
269bool read_data(unsigned int cpt, const std::string &input_directory, vpImage<unsigned char> &I,
270 vpImage<uint16_t> &I_depth_raw, std::vector<vpColVector> &pointcloud, unsigned int &pointcloud_width,
271 unsigned int &pointcloud_height)
272{
273#if defined(VISP_HAVE_DATASET)
274#if VISP_HAVE_DATASET_VERSION >= 0x030600
275 std::string ext("png");
276#else
277 std::string ext("pgm");
278#endif
279#else
280 // We suppose that the user will download a recent dataset
281 std::string ext("png");
282#endif
283 // Read image
284 std::string filename_image = vpIoTools::formatString(input_directory + "/image_%04d." + ext, cpt);
285 if (!vpIoTools::checkFilename(filename_image)) {
286 std::cerr << "Cannot read: " << filename_image << std::endl;
287 return false;
288 }
289 vpImageIo::read(I, filename_image);
290 // Read raw depth
291 std::string filename_depth = vpIoTools::formatString(input_directory + "/depth_image_%04d.bin", cpt);
292
293 std::ifstream file_depth(filename_depth.c_str(), std::ios::in | std::ios::binary);
294 if (!file_depth.is_open()) {
295 return false;
296 }
297
298 unsigned int height = 0, width = 0;
299 vpIoTools::readBinaryValueLE(file_depth, height);
300 vpIoTools::readBinaryValueLE(file_depth, width);
301
302 I_depth_raw.resize(height, width);
303
304 uint16_t depth_value = 0;
305 for (unsigned int i = 0; i < height; i++) {
306 for (unsigned int j = 0; j < width; j++) {
307 vpIoTools::readBinaryValueLE(file_depth, depth_value);
308 I_depth_raw[i][j] = depth_value;
309 }
310 }
311
312 // Transform pointcloud
313 pointcloud_width = width;
314 pointcloud_height = height;
315 pointcloud.resize(static_cast<size_t>(width * height));
316
317 // Only for Creative SR300
318 const float depth_scale = 0.000124986647f;
319 vpRealsenseIntrinsics_t depth_intrinsic;
320 depth_intrinsic.ppx = 311.484558f;
321 depth_intrinsic.ppy = 246.283234f;
322 depth_intrinsic.fx = 476.053619f;
323 depth_intrinsic.fy = 476.053497f;
324 depth_intrinsic.coeffs[0] = 0.165056542f;
325 depth_intrinsic.coeffs[1] = -0.0508309528f;
326 depth_intrinsic.coeffs[2] = 0.00435937941f;
327 depth_intrinsic.coeffs[3] = 0.00541406544f;
328 depth_intrinsic.coeffs[4] = 0.250085592f;
329
330 for (unsigned int i = 0; i < height; i++) {
331 for (unsigned int j = 0; j < width; j++) {
332 float scaled_depth = I_depth_raw[i][j] * depth_scale;
333 float point[3];
334 float pixel[2] = { static_cast<float>(j), static_cast<float>(i) };
335 rs_deproject_pixel_to_point(point, depth_intrinsic, pixel, scaled_depth);
336
337 vpColVector data_3D(3);
338 data_3D[0] = point[0];
339 data_3D[1] = point[1];
340 data_3D[2] = point[2];
341
342 pointcloud[static_cast<size_t>(i * width + j)] = data_3D;
343 }
344 }
345
346 return true;
347}
348
349void loadConfiguration(vpMbTracker *const tracker,
350 const std::string &
351#if defined(VISP_HAVE_PUGIXML)
352 configFile
353#endif
354 ,
355 const std::string &
356#if defined(VISP_HAVE_PUGIXML)
357 configFile_depth
358#endif
359)
360{
361#if defined(VISP_HAVE_PUGIXML)
362 // From the xml file
363 dynamic_cast<vpMbGenericTracker *>(tracker)->loadConfigFile(configFile, configFile_depth);
364#else
365 // Edge
366 vpMe me;
367 me.setMaskSize(5);
368 me.setMaskNumber(180);
369 me.setRange(8);
371 me.setThreshold(10);
372 me.setMu1(0.5);
373 me.setMu2(0.5);
374 me.setSampleStep(4);
375 dynamic_cast<vpMbGenericTracker *>(tracker)->setMovingEdge(me);
376
377 // Klt
378#if defined(VISP_HAVE_MODULE_KLT) && defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
379 vpKltOpencv klt;
380 klt.setMaxFeatures(10000);
381 klt.setWindowSize(5);
382 klt.setQuality(0.01);
383 klt.setMinDistance(5);
384 klt.setHarrisFreeParameter(0.02);
385 klt.setBlockSize(3);
386 klt.setPyramidLevels(3);
387
388 dynamic_cast<vpMbGenericTracker *>(tracker)->setKltOpencv(klt);
389 dynamic_cast<vpMbGenericTracker *>(tracker)->setKltMaskBorder(5);
390#endif
391
392 // Depth
393 dynamic_cast<vpMbGenericTracker *>(tracker)->setDepthNormalFeatureEstimationMethod(
395 dynamic_cast<vpMbGenericTracker *>(tracker)->setDepthNormalPclPlaneEstimationMethod(2);
396 dynamic_cast<vpMbGenericTracker *>(tracker)->setDepthNormalPclPlaneEstimationRansacMaxIter(200);
397 dynamic_cast<vpMbGenericTracker *>(tracker)->setDepthNormalPclPlaneEstimationRansacThreshold(0.001);
398 dynamic_cast<vpMbGenericTracker *>(tracker)->setDepthNormalSamplingStep(2, 2);
399
400 dynamic_cast<vpMbGenericTracker *>(tracker)->setDepthDenseSamplingStep(4, 4);
401
402 vpCameraParameters cam1, cam2;
403 cam1.initPersProjWithoutDistortion(615.1674804688, 615.1675415039, 312.1889953613, 243.4373779297);
404 cam2.initPersProjWithoutDistortion(476.0536193848, 476.0534973145, 311.4845581055, 246.2832336426);
405
406 dynamic_cast<vpMbGenericTracker *>(tracker)->setCameraParameters(cam1, cam2);
407
408 tracker->setAngleAppear(vpMath::rad(70));
409 tracker->setAngleDisappear(vpMath::rad(80));
410
411 // Specify the clipping to
412 tracker->setNearClippingDistance(0.01);
413 tracker->setFarClippingDistance(2.0);
414 tracker->setClipping(tracker->getClipping() | vpMbtPolygon::FOV_CLIPPING);
415 // tracker->setClipping(tracker->getClipping() | vpMbtPolygon::LEFT_CLIPPING
416 // | vpMbtPolygon::RIGHT_CLIPPING | vpMbtPolygon::UP_CLIPPING |
417 // vpMbtPolygon::DOWN_CLIPPING); // Equivalent to FOV_CLIPPING
418#endif
419}
420} // namespace
421
422int main(int argc, const char **argv)
423{
424 try {
425 std::string env_ipath;
426 std::string opt_ipath;
427 std::string ipath;
428 std::string opt_configFile;
429 std::string opt_configFile_depth;
430 std::string opt_modelFile;
431 std::string opt_modelFile_depth;
432 std::string opt_initFile;
433 std::string initFile;
434 bool displayFeatures = true;
435 bool opt_click_allowed = true;
436 bool opt_display = true;
437 bool useOgre = false;
438 bool showOgreConfigDialog = false;
439 bool useScanline = false;
440 bool computeCovariance = false;
441 bool projectionError = false;
442 int trackerType_image = vpMbGenericTracker::EDGE_TRACKER;
443 int trackerType_depth = vpMbGenericTracker::DEPTH_DENSE_TRACKER;
444#if defined(__mips__) || defined(__mips) || defined(mips) || defined(__MIPS__)
445 // To avoid Debian test timeout
446 int opt_lastFrame = 5;
447#else
448 int opt_lastFrame = -1;
449#endif
450
451 // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
452 // environment variable value
454
455 // Set the default input path
456 if (!env_ipath.empty())
457 ipath = env_ipath;
458
459 // Read the command line options
460 if (!getOptions(argc, argv, opt_ipath, opt_configFile, opt_configFile_depth, opt_modelFile, opt_modelFile_depth,
461 opt_initFile, displayFeatures, opt_click_allowed, opt_display, useOgre, showOgreConfigDialog,
462 useScanline, computeCovariance, projectionError, trackerType_image, trackerType_depth,
463 opt_lastFrame)) {
464 return EXIT_FAILURE;
465 }
466
467#if !(defined(VISP_HAVE_MODULE_KLT) && defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO))
468 if (trackerType_image == 2 || trackerType_image == 3) { // Use vpMbGenericTracker::KLT_TRACKER
469 std::cout << "KLT features cannot be used: ViSP is not built with "
470 "KLT module or OpenCV imgproc and video modules are not available."
471 << std::endl;
472 return EXIT_SUCCESS;
473 }
474#endif
475
476 // Test if an input path is set
477 if (opt_ipath.empty() && env_ipath.empty()) {
478 usage(argv[0], nullptr);
479 std::cerr << std::endl << "ERROR:" << std::endl;
480 std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
481 << " environment variable to specify the location of the " << std::endl
482 << " image path where test images are located." << std::endl
483 << std::endl;
484
485 return EXIT_FAILURE;
486 }
487
488 // Get the option values
489 ipath = vpIoTools::createFilePath(!opt_ipath.empty() ? opt_ipath : env_ipath, "mbt-depth/castel/castel");
490
491 std::string dir_path = vpIoTools::createFilePath(!opt_ipath.empty() ? opt_ipath : env_ipath, "mbt-depth");
492 if (!vpIoTools::checkDirectory(dir_path)) {
493 std::cerr << "ViSP-images does not contain the folder: " << dir_path << "!" << std::endl;
494 return EXIT_SUCCESS;
495 }
496
497 std::string configFile, configFile_depth;
498 if (!opt_configFile.empty())
499 configFile = opt_configFile;
500 else
501 configFile =
502 vpIoTools::createFilePath(!opt_ipath.empty() ? opt_ipath : env_ipath, "mbt-depth/castel/chateau.xml");
503
504 if (!opt_configFile_depth.empty())
505 configFile_depth = opt_configFile_depth;
506 else
507 configFile_depth =
508 vpIoTools::createFilePath(!opt_ipath.empty() ? opt_ipath : env_ipath, "mbt-depth/castel/chateau_depth.xml");
509
510 std::string modelFile, modelFile_depth;
511 if (!opt_modelFile.empty())
512 modelFile = opt_modelFile;
513 else {
514#if defined(VISP_HAVE_COIN3D) && (COIN_MAJOR_VERSION == 2 || COIN_MAJOR_VERSION == 3 || COIN_MAJOR_VERSION == 4)
515 modelFile =
516 vpIoTools::createFilePath(!opt_ipath.empty() ? opt_ipath : env_ipath, "mbt-depth/castel/chateau_gantry.wrl");
517#else
518 modelFile = vpIoTools::createFilePath(!opt_ipath.empty() ? opt_ipath : env_ipath, "mbt-depth/castel/chateau.cao");
519#endif
520 }
521
522 if (!opt_modelFile_depth.empty())
523 modelFile_depth = opt_modelFile_depth;
524 else
525 modelFile_depth =
526 vpIoTools::createFilePath(!opt_ipath.empty() ? opt_ipath : env_ipath, "mbt-depth/castel/chateau.cao");
527
528 std::string vrml_ext = ".wrl";
529 bool use_vrml =
530 (modelFile.compare(modelFile.length() - vrml_ext.length(), vrml_ext.length(), vrml_ext) == 0) ||
531 (modelFile_depth.compare(modelFile_depth.length() - vrml_ext.length(), vrml_ext.length(), vrml_ext) == 0);
532
533 if (use_vrml) {
534#if defined(VISP_HAVE_COIN3D) && (COIN_MAJOR_VERSION == 2 || COIN_MAJOR_VERSION == 3 || COIN_MAJOR_VERSION == 4)
535 std::cout << "use_vrml: " << use_vrml << std::endl;
536#else
537 std::cerr << "Error: vrml model file is only supported if ViSP is "
538 "build with Coin3D 3rd party"
539 << std::endl;
540 return EXIT_FAILURE;
541#endif
542 }
543
544 if (!opt_initFile.empty())
545 initFile = opt_initFile;
546 else
547 initFile = vpIoTools::createFilePath(!opt_ipath.empty() ? opt_ipath : env_ipath, "mbt-depth/castel/chateau.init");
548
550 vpImage<uint16_t> I_depth_raw;
551 std::vector<vpColVector> pointcloud;
552 unsigned int pointcloud_width, pointcloud_height;
553 if (!read_data(0, ipath, I, I_depth_raw, pointcloud, pointcloud_width, pointcloud_height)) {
554 std::cerr << "Cannot open sequence: " << ipath << std::endl;
555 return EXIT_FAILURE;
556 }
557
558 vpImageConvert::createDepthHistogram(I_depth_raw, I_depth);
559
560 // initialise a display
561#if defined(VISP_HAVE_X11)
562 vpDisplayX display1, display2;
563#elif defined(VISP_HAVE_GDI)
564 vpDisplayGDI display1, display2;
565#elif defined(HAVE_OPENCV_HIGHGUI)
566 vpDisplayOpenCV display1, display2;
567#elif defined(VISP_HAVE_D3D9)
568 vpDisplayD3D display1, display2;
569#elif defined(VISP_HAVE_GTK)
570 vpDisplayGTK display1, display2;
571#else
572 opt_display = false;
573#endif
574 if (opt_display) {
575#if defined(VISP_HAVE_DISPLAY)
578 display1.init(I, 100, 100, "Test tracking (Left)");
579 display2.init(I_depth, static_cast<int>(I.getWidth() / vpDisplay::getDownScalingFactor(I)) + 110, 100,
580 "Test tracking (Right)");
581#endif
583 vpDisplay::display(I_depth);
585 vpDisplay::flush(I_depth);
586 }
587
588 std::vector<int> trackerTypes(2);
589 trackerTypes[0] = trackerType_image;
590 trackerTypes[1] = trackerType_depth;
591 // Object pointer to check that inheritance is ok
592 vpMbTracker *tracker = new vpMbGenericTracker(trackerTypes);
593 vpHomogeneousMatrix c1Mo, c2Mo;
594 vpCameraParameters cam1, cam2;
595
596 loadConfiguration(tracker, configFile, configFile_depth);
597
599 std::string depth_M_color_filename =
600 vpIoTools::createFilePath(!opt_ipath.empty() ? opt_ipath : env_ipath, "mbt-depth/castel/depth_M_color.txt");
601 {
602 std::ifstream depth_M_color_file(depth_M_color_filename.c_str());
603 depth_M_color.load(depth_M_color_file);
604 std::map<std::string, vpHomogeneousMatrix> mapOfCameraTransformationMatrices;
605 mapOfCameraTransformationMatrices["Camera2"] = depth_M_color;
606 dynamic_cast<vpMbGenericTracker *>(tracker)->setCameraTransformationMatrix(mapOfCameraTransformationMatrices);
607 }
608
609 // Display the moving edges, and the Klt points
610 tracker->setDisplayFeatures(displayFeatures);
611
612 // Tells if the tracker has to use Ogre3D for visibility tests
613 tracker->setOgreVisibilityTest(useOgre);
614 if (useOgre)
615 tracker->setOgreShowConfigDialog(showOgreConfigDialog);
616
617 // Tells if the tracker has to use the scanline visibility tests
618 tracker->setScanLineVisibilityTest(useScanline);
619
620 // Tells if the tracker has to compute the covariance matrix
621 tracker->setCovarianceComputation(computeCovariance);
622
623 // Tells if the tracker has to compute the projection error
624 tracker->setProjectionErrorComputation(projectionError);
625
626 // Retrieve the camera parameters from the tracker
627 dynamic_cast<vpMbGenericTracker *>(tracker)->getCameraParameters(cam1, cam2);
628
629 // Loop to position the cube
630 if (opt_display && opt_click_allowed) {
631 while (!vpDisplay::getClick(I, false)) {
633 vpDisplay::displayText(I, 15, 10, "click after positioning the object", vpColor::red);
635 }
636 }
637
638 // Load the 3D model (either a vrml file or a .cao file)
639 dynamic_cast<vpMbGenericTracker *>(tracker)->loadModel(modelFile, modelFile_depth);
640
641 if (opt_display && opt_click_allowed) {
642 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
643 mapOfImages["Camera1"] = &I;
644 mapOfImages["Camera2"] = &I_depth;
645 std::map<std::string, std::string> mapOfInitFiles;
646 mapOfInitFiles["Camera1"] = initFile;
647
648 // Initialise the tracker by clicking on the image
649 dynamic_cast<vpMbGenericTracker *>(tracker)->initClick(mapOfImages, mapOfInitFiles, true);
650 dynamic_cast<vpMbGenericTracker *>(tracker)->getPose(c1Mo, c2Mo);
651 // display the 3D model at the given pose
652 dynamic_cast<vpMbGenericTracker *>(tracker)->display(I, I_depth, c1Mo, c2Mo, cam1, cam2, vpColor::red);
653 }
654 else {
655 vpHomogeneousMatrix c1Moi(0.06846423368, 0.09062570884, 0.3401096693, -2.671882598, 0.1174275908, -0.6011935263);
656 vpHomogeneousMatrix c2Moi(0.04431452054, 0.09294637757, 0.3357760654, -2.677922443, 0.121297639, -0.6028463357);
657 dynamic_cast<vpMbGenericTracker *>(tracker)->initFromPose(I, I_depth, c1Moi, c2Moi);
658 }
659
660 // track the model
661 {
662 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
663 mapOfImages["Camera1"] = &I;
664 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
665 mapOfPointclouds["Camera2"] = &pointcloud;
666 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
667 mapOfWidths["Camera2"] = pointcloud_width;
668 mapOfHeights["Camera2"] = pointcloud_height;
669
670 dynamic_cast<vpMbGenericTracker *>(tracker)->track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
671 }
672 dynamic_cast<vpMbGenericTracker *>(tracker)->getPose(c1Mo, c2Mo);
673
674 if (opt_display) {
676 vpDisplay::flush(I_depth);
677 }
678
679 bool quit = false, click = false;
680 unsigned int frame_index = 0;
681 std::vector<double> time_vec;
682 while (read_data(frame_index, ipath, I, I_depth_raw, pointcloud, pointcloud_width, pointcloud_height) && !quit &&
683 (opt_lastFrame > 0 ? static_cast<int>(frame_index) <= opt_lastFrame : true)) {
684 vpImageConvert::createDepthHistogram(I_depth_raw, I_depth);
685
686 if (opt_display) {
688 vpDisplay::display(I_depth);
689
690 std::stringstream ss;
691 ss << "Num frame: " << frame_index;
692 vpDisplay::displayText(I, 40, 20, ss.str(), vpColor::red);
693 }
694
695 // Test reset the tracker
696 if (frame_index == 10) {
697 std::cout << "----------Test reset tracker----------" << std::endl;
698 if (opt_display) {
700 vpDisplay::display(I_depth);
701 }
702
703 tracker->resetTracker();
704
705 loadConfiguration(tracker, configFile, configFile_depth);
706 dynamic_cast<vpMbGenericTracker *>(tracker)->loadModel(modelFile, modelFile_depth);
707 dynamic_cast<vpMbGenericTracker *>(tracker)->setCameraParameters(cam1, cam2);
708 tracker->setOgreVisibilityTest(useOgre);
709 tracker->setScanLineVisibilityTest(useScanline);
710 tracker->setCovarianceComputation(computeCovariance);
711 tracker->setProjectionErrorComputation(projectionError);
712 dynamic_cast<vpMbGenericTracker *>(tracker)->initFromPose(I, I_depth, c1Mo, c2Mo);
713 }
714
715 // Test to set an initial pose
716#if USE_SMALL_DATASET
717 if (frame_index == 20) {
718 c1Mo.buildFrom(0.07734634051, 0.08993639906, 0.342344402, -2.708409543, 0.0669276477, -0.3798958303);
719 c2Mo.buildFrom(0.05319520317, 0.09223511976, 0.3380095812, -2.71438192, 0.07141055397, -0.3810081638);
720#else
721 if (frame_index == 50) {
722 c1Mo.buildFrom(0.09280663035, 0.09277655672, 0.330415149, -2.724431817, 0.0293932671, 0.02027966377);
723 c2Mo.buildFrom(0.06865933578, 0.09494713501, 0.3260555142, -2.730027451, 0.03498390135, 0.01989831338);
724#endif
725 std::cout << "Test set pose" << std::endl;
726 dynamic_cast<vpMbGenericTracker *>(tracker)->setPose(I, I_depth, c1Mo, c2Mo);
727 }
728
729#if USE_SMALL_DATASET
730 // track the object: stop tracking from frame 15 to 20
731 if (frame_index < 15 || frame_index >= 20) {
732#else
733 // track the object: stop tracking from frame 30 to 50
734 if (frame_index < 30 || frame_index >= 50) {
735#endif
736 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
737 mapOfImages["Camera1"] = &I;
738 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
739 mapOfPointclouds["Camera2"] = &pointcloud;
740 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
741 mapOfWidths["Camera2"] = pointcloud_width;
742 mapOfHeights["Camera2"] = pointcloud_height;
743
744 double t = vpTime::measureTimeMs();
745 dynamic_cast<vpMbGenericTracker *>(tracker)->track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
747 time_vec.push_back(t);
748
749 dynamic_cast<vpMbGenericTracker *>(tracker)->getPose(c1Mo, c2Mo);
750
751 if (opt_display) {
752 // display the 3D model
753 dynamic_cast<vpMbGenericTracker *>(tracker)->display(I, I_depth, c1Mo, c2Mo, cam1, cam2, vpColor::darkRed);
754 // display the frame
755 vpDisplay::displayFrame(I, c1Mo, cam1, 0.05);
756 vpDisplay::displayFrame(I_depth, c2Mo, cam2, 0.05);
757 // computation time
758 std::stringstream ss;
759 ss << "Computation time: " << t << " ms";
760 vpDisplay::displayText(I, 60, 20, ss.str(), vpColor::red);
761 // nb features
762 ss.str("");
763 ss << "nb features: " << tracker->getError().getRows();
764 vpDisplay::displayText(I_depth, 80, 20, ss.str(), vpColor::red);
765 {
766 std::stringstream ss;
767 ss << "Features: edges " << dynamic_cast<vpMbGenericTracker *>(tracker)->getNbFeaturesEdge() << ", klt "
768 << dynamic_cast<vpMbGenericTracker *>(tracker)->getNbFeaturesKlt() << ", depth "
769 << dynamic_cast<vpMbGenericTracker *>(tracker)->getNbFeaturesDepthDense();
770 vpDisplay::displayText(I, I.getHeight() - 30, 20, ss.str(), vpColor::red);
771 }
772 }
773 }
774
775 if (opt_click_allowed && opt_display) {
776 vpDisplay::displayText(I, 10, 10, "Click to quit", vpColor::red);
778 if (vpDisplay::getClick(I, button, click)) {
779 switch (button) {
781 quit = !click;
782 break;
783
785 click = !click;
786 break;
787
788 default:
789 break;
790 }
791 }
792 }
793
794 if (computeCovariance) {
795 std::cout << "Covariance matrix: \n" << tracker->getCovarianceMatrix() << std::endl << std::endl;
796 }
797
798 if (projectionError) {
799 std::cout << "Projection error: " << tracker->getProjectionError() << std::endl << std::endl;
800 }
801
802 if (opt_display) {
804 vpDisplay::flush(I_depth);
805 }
806
807 frame_index++;
808 }
809
810 std::cout << "\nFinal poses, c1Mo:\n" << c1Mo << "\nc2Mo:\n" << c2Mo << std::endl;
811 std::cout << "\nComputation time, Mean: " << vpMath::getMean(time_vec)
812 << " ms ; Median: " << vpMath::getMedian(time_vec) << " ms ; Std: " << vpMath::getStdev(time_vec) << " ms"
813 << std::endl;
814
815 if (opt_click_allowed && !quit) {
817 }
818
819 delete tracker;
820 tracker = nullptr;
821
822 return EXIT_SUCCESS;
823 }
824 catch (const vpException &e) {
825 std::cout << "Catch an exception: " << e << std::endl;
826 return EXIT_FAILURE;
827 }
828 }
829
830#elif !(defined(VISP_HAVE_MODULE_MBT) && defined(VISP_HAVE_DISPLAY))
831int main()
832{
833 std::cout << "Cannot run this example: visp_mbt, visp_gui modules are required." << std::endl;
834 return EXIT_SUCCESS;
835}
836#else
837int main()
838{
839 std::cout << "Cannot run this example: install Lapack, Eigen3 or OpenCV" << std::endl;
840 return EXIT_SUCCESS;
841}
842#endif
Generic class defining intrinsic camera parameters.
void initPersProjWithoutDistortion(double px, double py, double u0, double v0)
Implementation of column vector and the associated operations.
static const vpColor red
Definition vpColor.h:198
static const vpColor darkRed
Definition vpColor.h:199
Display for windows using Direct3D 3rd party. Thus to enable this class Direct3D should be installed....
Display for windows using GDI (available on any windows 32 platform).
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition vpDisplayX.h:135
void init(vpImage< unsigned char > &I, int win_x=-1, int win_y=-1, const std::string &win_title="") VP_OVERRIDE
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
virtual void setDownScalingFactor(unsigned int scale)
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 flush(const vpImage< unsigned char > &I)
unsigned int getDownScalingFactor()
Definition vpDisplay.h:218
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
error that can be emitted by ViSP classes.
Definition vpException.h:60
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpHomogeneousMatrix & buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)
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)
Definition of the vpImage class member functions.
Definition vpImage.h:131
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition vpImage.h:544
static std::string getViSPImagesDataPath()
static bool checkFilename(const std::string &filename)
static void readBinaryValueLE(std::ifstream &file, int16_t &short_value)
static bool checkDirectory(const std::string &dirname)
static std::string formatString(const std::string &name, unsigned int val)
static std::string createFilePath(const std::string &parent, const std::string &child)
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented in OpenCV. Thus to enable this ...
Definition vpKltOpencv.h:83
void setBlockSize(int blockSize)
void setQuality(double qualityLevel)
void setHarrisFreeParameter(double harris_k)
void setMaxFeatures(int maxCount)
void setMinDistance(double minDistance)
void setWindowSize(int winSize)
void setPyramidLevels(int pyrMaxLevel)
static double rad(double deg)
Definition vpMath.h:129
static double getMedian(const std::vector< double > &v)
Definition vpMath.cpp:343
static double getStdev(const std::vector< double > &v, bool useBesselCorrection=false)
Definition vpMath.cpp:374
static double getMean(const std::vector< double > &v)
Definition vpMath.cpp:323
Real-time 6D object pose tracking using its CAD model.
Main methods for a model-based tracker.
@ ROBUST_FEATURE_ESTIMATION
Robust scheme to estimate the normal of the plane.
Definition vpMe.h:143
void setMu1(const double &mu_1)
Definition vpMe.h:408
void setRange(const unsigned int &range)
Definition vpMe.h:438
void setLikelihoodThresholdType(const vpLikelihoodThresholdType likelihood_threshold_type)
Definition vpMe.h:531
void setMaskNumber(const unsigned int &mask_number)
Definition vpMe.cpp:555
void setThreshold(const double &threshold)
Definition vpMe.h:489
void setSampleStep(const double &sample_step)
Definition vpMe.h:445
void setMaskSize(const unsigned int &mask_size)
Definition vpMe.cpp:563
void setMu2(const double &mu_2)
Definition vpMe.h:415
@ NORMALIZED_THRESHOLD
Definition vpMe.h:154
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
read_data(CameraParameters|None cam_depth, ImageGray I, rs.pipeline pipe)
VISP_EXPORT double measureTimeMs()