44 #include <visp3/core/vpConfig.h>
46 #if (defined(VISP_HAVE_MODULE_MBT) && defined(VISP_HAVE_DISPLAY)) && \
47 (defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV))
49 #include <visp3/core/vpDebug.h>
50 #include <visp3/core/vpHomogeneousMatrix.h>
51 #include <visp3/core/vpIoTools.h>
52 #include <visp3/core/vpMath.h>
53 #include <visp3/gui/vpDisplayD3D.h>
54 #include <visp3/gui/vpDisplayGDI.h>
55 #include <visp3/gui/vpDisplayGTK.h>
56 #include <visp3/gui/vpDisplayOpenCV.h>
57 #include <visp3/gui/vpDisplayX.h>
58 #include <visp3/io/vpImageIo.h>
59 #include <visp3/io/vpParseArgv.h>
60 #include <visp3/io/vpVideoReader.h>
61 #include <visp3/mbt/vpMbGenericTracker.h>
63 #define GETOPTARGS "X:M:i:n:dchfolwvpT:e:u:"
65 #define USE_SMALL_DATASET 1
67 #ifdef ENABLE_VISP_NAMESPACE
73 void usage(
const char *name,
const char *badparam)
76 Example of tracking with vpGenericTracker.\n\
79 %s [-i <test image path>] [-X <config file depth>]\n\
80 [-M <model name depth>] [-n <initialisation file base name>]\n\
81 [-f] [-c] [-d] [-h] [-o] [-w] [-l] [-v] [-p]\n\
82 [-T <tracker type>] [-e <last frame index>]\n\
83 [-u <disable face>]\n",
88 -i <input image path> \n\
89 Set image input path.\n\
90 These images come from ViSP-images-x.y.z.tar.gz available \n\
91 on the ViSP website.\n\
92 Setting the VISP_INPUT_IMAGE_PATH environment\n\
93 variable produces the same behavior than using\n\
97 Set the config file (the xml file) to use for the depth sensor.\n\
98 The config file is used to specify the parameters of the tracker.\n\
101 Specify the name of the file of the model for the depth sensor.\n\
102 The model can either be a vrml model (.wrl) or a .cao file.\n\
104 -n <initialisation file base name> \n\
105 Base name of the initialisation file. The file will be 'base_name'.init .\n\
106 This base name is also used for the optional picture specifying where to \n\
107 click (a .ppm picture).\n\
110 Turn off the display of the visual features. \n\
113 Turn off the display.\n\
116 Disable the mouse click. Useful to automate the \n\
117 execution of this program without human intervention.\n\
120 Use Ogre3D for visibility tests\n\
123 When Ogre3D is enable [-o] show Ogre3D configuration dialog that allows to set the renderer.\n\
126 Use the scanline for visibility tests.\n\
129 Compute covariance matrix.\n\
132 Compute gradient projection error.\n\
135 Set tracker type (<4 (Depth normal)>, <8 (Depth dense)>, <12 (both)>) for depth sensor.\n\
137 -e <last frame index>\n\
138 Specify the index of the last frame. Once reached, the tracking is stopped.\n\
141 Disable castle element (1=floor, 2=front_door, 4=slope, 8=tower_front, 16=tower_left, 32=tower_right, 64=tower_back).\n\
144 Print the help.\n\n");
147 fprintf(stdout,
"\nERROR: Bad parameter [%s]\n", badparam);
150 bool getOptions(
int argc,
const char **argv, std::string &ipath, std::string &configFile_depth,
151 std::string &modelFile_depth, std::string &initFile,
bool &displayFeatures,
bool &click_allowed,
152 bool &display,
bool &useOgre,
bool &showOgreConfigDialog,
bool &useScanline,
bool &computeCovariance,
153 bool &projectionError,
int &tracker_type_depth,
int &lastFrame,
int &disable_castle_faces)
164 configFile_depth = optarg_;
167 modelFile_depth = optarg_;
173 displayFeatures =
false;
176 click_allowed =
false;
188 showOgreConfigDialog =
true;
191 computeCovariance =
true;
194 projectionError =
true;
197 tracker_type_depth = atoi(optarg_);
200 lastFrame = atoi(optarg_);
203 disable_castle_faces = atoi(optarg_);
207 usage(argv[0],
nullptr);
211 usage(argv[0], optarg_);
217 if ((c == 1) || (c == -1)) {
219 usage(argv[0],
nullptr);
220 std::cerr <<
"ERROR: " << std::endl;
221 std::cerr <<
" Bad argument " << optarg_ << std::endl << std::endl;
228 struct vpRealsenseIntrinsics_t
241 void rs_deproject_pixel_to_point(
float point[3],
const vpRealsenseIntrinsics_t &intrin,
const float pixel[2],
float depth)
243 float x = (pixel[0] - intrin.ppx) / intrin.fx;
244 float y = (pixel[1] - intrin.ppy) / intrin.fy;
246 float r2 = x * x + y * y;
247 float f = 1 + intrin.coeffs[0] * r2 + intrin.coeffs[1] * r2 * r2 + intrin.coeffs[4] * r2 * r2 * r2;
248 float ux = x * f + 2 * intrin.coeffs[2] * x * y + intrin.coeffs[3] * (r2 + 2 * x * x);
249 float uy = y * f + 2 * intrin.coeffs[3] * x * y + intrin.coeffs[2] * (r2 + 2 * y * y);
254 point[0] = depth * x;
255 point[1] = depth * y;
260 vpImage<uint16_t> &I_depth_raw, std::vector<vpColVector> &pointcloud,
unsigned int &pointcloud_width,
261 unsigned int &pointcloud_height)
263 #if VISP_HAVE_DATASET_VERSION >= 0x030600
264 std::string ext(
"png");
266 std::string ext(
"pgm");
269 std::stringstream ss;
270 ss << input_directory <<
"/image_";
271 ss << std::setfill(
'0') << std::setw(4);
275 std::string filename_image = ss.str();
278 std::cerr <<
"Cannot read: " << filename_image << std::endl;
285 ss << input_directory <<
"/depth_image_";
286 ss << std::setfill(
'0') << std::setw(4);
289 std::string filename_depth = ss.str();
291 std::ifstream file_depth(filename_depth.c_str(), std::ios::in | std::ios::binary);
292 if (!file_depth.is_open()) {
296 unsigned int height = 0, width = 0;
300 I_depth_raw.
resize(height, width);
302 uint16_t depth_value = 0;
303 for (
unsigned int i = 0; i < height; i++) {
304 for (
unsigned int j = 0; j < width; j++) {
306 I_depth_raw[i][j] = depth_value;
311 pointcloud_width = width;
312 pointcloud_height = height;
313 pointcloud.
resize((
size_t)width * height);
316 const float depth_scale = 0.000124986647f;
317 vpRealsenseIntrinsics_t depth_intrinsic;
318 depth_intrinsic.ppx = 311.484558f;
319 depth_intrinsic.ppy = 246.283234f;
320 depth_intrinsic.fx = 476.053619f;
321 depth_intrinsic.fy = 476.053497f;
322 depth_intrinsic.coeffs[0] = 0.165056542f;
323 depth_intrinsic.coeffs[1] = -0.0508309528f;
324 depth_intrinsic.coeffs[2] = 0.00435937941f;
325 depth_intrinsic.coeffs[3] = 0.00541406544f;
326 depth_intrinsic.coeffs[4] = 0.250085592f;
328 for (
unsigned int i = 0; i < height; i++) {
329 for (
unsigned int j = 0; j < width; j++) {
330 float scaled_depth = I_depth_raw[i][j] * depth_scale;
332 float pixel[2] = { (float)j, (
float)i };
333 rs_deproject_pixel_to_point(point, depth_intrinsic, pixel, scaled_depth);
336 data_3D[0] = point[0];
337 data_3D[1] = point[1];
338 data_3D[2] = point[2];
340 pointcloud[(size_t)(i * width + j)] = data_3D;
347 void loadConfiguration(
vpMbTracker *
const tracker,
const std::string &
348 #
if defined(VISP_HAVE_PUGIXML)
353 #if defined(VISP_HAVE_PUGIXML)
360 dynamic_cast<vpMbGenericTracker *
>(tracker)->setDepthNormalPclPlaneEstimationMethod(2);
361 dynamic_cast<vpMbGenericTracker *
>(tracker)->setDepthNormalPclPlaneEstimationRansacMaxIter(200);
362 dynamic_cast<vpMbGenericTracker *
>(tracker)->setDepthNormalPclPlaneEstimationRansacThreshold(0.001);
385 std::vector<std::string> getCastleElementNames(
const int element)
387 std::vector<std::string> element_names;
390 element_names.push_back(
"floor");
392 element_names.push_back(
"front_door");
394 element_names.push_back(
"slope");
396 element_names.push_back(
"tower_front");
398 element_names.push_back(
"tower_left");
400 element_names.push_back(
"tower_right");
402 element_names.push_back(
"tower_back");
404 return element_names;
408 int main(
int argc,
const char **argv)
411 std::string env_ipath;
412 std::string opt_ipath;
414 std::string opt_configFile_depth;
415 std::string opt_modelFile_depth;
416 std::string opt_initFile;
417 std::string initFile;
418 bool displayFeatures =
true;
419 bool opt_click_allowed =
true;
420 bool opt_display =
true;
421 bool useOgre =
false;
422 bool showOgreConfigDialog =
false;
423 bool useScanline =
false;
424 bool computeCovariance =
false;
425 bool projectionError =
false;
427 #if defined(__mips__) || defined(__mips) || defined(mips) || defined(__MIPS__)
429 int opt_lastFrame = 5;
431 int opt_lastFrame = -1;
433 int disable_castle_faces = 0;
440 if (!env_ipath.empty())
444 if (!getOptions(argc, argv, opt_ipath, opt_configFile_depth, opt_modelFile_depth, opt_initFile, displayFeatures,
445 opt_click_allowed, opt_display, useOgre, showOgreConfigDialog, useScanline, computeCovariance,
446 projectionError, trackerType_depth, opt_lastFrame, disable_castle_faces)) {
451 if (opt_ipath.empty() && env_ipath.empty()) {
452 usage(argv[0],
nullptr);
453 std::cerr << std::endl <<
"ERROR:" << std::endl;
454 std::cerr <<
" Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
455 <<
" environment variable to specify the location of the " << std::endl
456 <<
" image path where test images are located." << std::endl
467 std::cerr <<
"ViSP-images does not contain the folder: " << dir_path <<
"!" << std::endl;
471 std::string configFile_depth;
472 if (!opt_configFile_depth.empty())
473 configFile_depth = opt_configFile_depth;
478 std::string modelFile_depth;
479 if (!opt_modelFile_depth.empty())
480 modelFile_depth = opt_modelFile_depth;
485 std::string vrml_ext =
".wrl";
487 (modelFile_depth.compare(modelFile_depth.length() - vrml_ext.length(), vrml_ext.length(), vrml_ext) == 0);
490 #if defined(VISP_HAVE_COIN3D) && (COIN_MAJOR_VERSION == 2 || COIN_MAJOR_VERSION == 3 || COIN_MAJOR_VERSION == 4)
491 std::cout <<
"use_vrml: " << use_vrml << std::endl;
493 std::cerr <<
"Error: vrml model file is only supported if ViSP is "
494 "build with Coin3D 3rd party"
500 if (!opt_initFile.empty())
501 initFile = opt_initFile;
507 std::vector<vpColVector> pointcloud;
508 unsigned int pointcloud_width, pointcloud_height;
509 if (!read_data(0, ipath, I, I_depth_raw, pointcloud, pointcloud_width, pointcloud_height)) {
510 std::cerr <<
"Cannot open sequence: " << ipath << std::endl;
517 #if defined(VISP_HAVE_X11)
518 vpDisplayX display, display2;
519 #elif defined(VISP_HAVE_GDI)
521 #elif defined(HAVE_OPENCV_HIGHGUI)
523 #elif defined(VISP_HAVE_D3D9)
525 #elif defined(VISP_HAVE_GTK)
531 #if defined(VISP_HAVE_DISPLAY)
533 display.init(I_depth, 100, 100,
"Depth");
535 display2.init(I, I_depth.
getWidth() + 100, 100,
"Image");
548 loadConfiguration(tracker, configFile_depth);
578 std::string depth_M_color_filename =
581 std::ifstream depth_M_color_file(depth_M_color_filename.c_str());
582 depth_M_color.
load(depth_M_color_file);
586 if (opt_display && opt_click_allowed) {
597 if (opt_display && opt_click_allowed) {
605 vpHomogeneousMatrix cMoi(0.04431452054, 0.09294637757, 0.3357760654, -2.677922443, 0.121297639, -0.6028463357);
611 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
612 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
613 mapOfPointclouds[
"Camera"] = &pointcloud;
614 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
615 mapOfWidths[
"Camera"] = pointcloud_width;
616 mapOfHeights[
"Camera"] = pointcloud_height;
618 dynamic_cast<vpMbGenericTracker *
>(tracker)->track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
626 bool quit =
false, click =
false;
627 unsigned int frame_index = 0;
628 std::vector<double> time_vec;
629 while (read_data(frame_index, ipath, I, I_depth_raw, pointcloud, pointcloud_width, pointcloud_height) && !quit &&
630 (opt_lastFrame > 0 ? (
int)frame_index <= opt_lastFrame :
true)) {
637 std::stringstream ss;
638 ss <<
"Num frame: " << frame_index;
643 if (frame_index == 10) {
644 std::cout <<
"----------Test reset tracker----------" << std::endl;
651 loadConfiguration(tracker, configFile_depth);
662 #if USE_SMALL_DATASET
663 if (frame_index == 20) {
664 cMo.
buildFrom(0.05319520317, 0.09223511976, 0.3380095812, -2.71438192, 0.07141055397, -0.3810081638);
666 if (frame_index == 50) {
667 cMo.
buildFrom(0.06865933578, 0.09494713501, 0.3260555142, -2.730027451, 0.03498390135, 0.01989831338);
669 std::cout <<
"Test set pose" << std::endl;
673 #if USE_SMALL_DATASET
675 if (frame_index < 15 || frame_index >= 20) {
678 if (frame_index < 30 || frame_index >= 50) {
680 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
681 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
682 mapOfPointclouds[
"Camera"] = &pointcloud;
683 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
684 mapOfWidths[
"Camera"] = pointcloud_width;
685 mapOfHeights[
"Camera"] = pointcloud_height;
687 if (disable_castle_faces) {
688 std::vector<std::string> element_names = getCastleElementNames(disable_castle_faces);
689 std::cout <<
"Disable: ";
690 for (
size_t idx = 0; idx < element_names.size(); idx++) {
691 std::cout << element_names[idx];
692 if (idx + 1 < element_names.size())
696 dynamic_cast<vpMbGenericTracker *
>(tracker)->setUseDepthDenseTracking(element_names[idx],
false);
698 dynamic_cast<vpMbGenericTracker *
>(tracker)->setUseDepthNormalTracking(element_names[idx],
false);
700 std::cout << std::endl;
704 dynamic_cast<vpMbGenericTracker *
>(tracker)->track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
706 time_vec.push_back(t);
716 std::stringstream ss;
717 ss <<
"Computation time: " << t <<
" ms";
727 ss <<
"Projection error: " << projection_error;
732 if (opt_click_allowed && opt_display) {
751 if (computeCovariance) {
752 std::cout <<
"Covariance matrix: \n" << tracker->
getCovarianceMatrix() << std::endl << std::endl;
755 if (projectionError) {
756 std::cout <<
"Projection error: " << tracker->
getProjectionError() << std::endl << std::endl;
767 std::cout <<
"\nFinal poses, cMo:\n" << cMo << std::endl;
772 if (opt_click_allowed && !quit) {
782 std::cout <<
"Catch an exception: " << e << std::endl;
787 #elif !(defined(VISP_HAVE_MODULE_MBT) && defined(VISP_HAVE_DISPLAY))
790 std::cout <<
"Cannot run this example: visp_mbt, visp_gui modules are required." << std::endl;
796 std::cout <<
"Cannot run this example: install Lapack, Eigen3 or OpenCV" << std::endl;
unsigned int getRows() const
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 darkRed
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...
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 flush(const vpImage< unsigned char > &I)
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.
Implementation of an homogeneous matrix and operations on such kind of matrices.
void load(std::ifstream &f)
vpHomogeneousMatrix & buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)
vpHomogeneousMatrix inverse() const
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
static double rad(double deg)
static double getMedian(const std::vector< double > &v)
static double getStdev(const std::vector< double > &v, bool useBesselCorrection=false)
static double getMean(const std::vector< double > &v)
Real-time 6D object pose tracking using its CAD model.
Main methods for a model-based tracker.
virtual void setProjectionErrorDisplayArrowLength(unsigned int length)
virtual double computeCurrentProjectionError(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &_cMo, const vpCameraParameters &_cam)
virtual void resetTracker()=0
virtual void setOgreShowConfigDialog(bool showConfigDialog)
virtual void setDisplayFeatures(bool displayF)
virtual vpColVector getError() const =0
virtual void setAngleDisappear(const double &a)
virtual void setCovarianceComputation(const bool &flag)
virtual void setScanLineVisibilityTest(const bool &v)
virtual void setOgreVisibilityTest(const bool &v)
virtual vpMatrix getCovarianceMatrix() const
virtual void setProjectionErrorDisplay(bool display)
virtual void setNearClippingDistance(const double &dist)
virtual void setFarClippingDistance(const double &dist)
virtual double getProjectionError() const
virtual void setProjectionErrorComputation(const bool &flag)
virtual void setClipping(const unsigned int &flags)
virtual void setProjectionErrorDisplayArrowThickness(unsigned int thickness)
virtual void setAngleAppear(const double &a)
virtual unsigned int getClipping() const
@ ROBUST_FEATURE_ESTIMATION
Robust scheme to estimate the normal of the plane.
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
VISP_EXPORT double measureTimeMs()