42#include <visp3/core/vpConfig.h>
44#if (defined(VISP_HAVE_MODULE_MBT) && defined(VISP_HAVE_DISPLAY)) && \
45 (defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV))
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>
61#define GETOPTARGS "X:M:i:n:dchfolwvpT:e:u:"
63#define USE_SMALL_DATASET 1
65#ifdef ENABLE_VISP_NAMESPACE
71void usage(
const char *name,
const char *badparam)
74 Example of tracking with vpGenericTracker.\n\
77 %s [-i <test image path>] [-X <config file depth>]\n\
78 [-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>] [-e <last frame index>]\n\
81 [-u <disable face>]\n",
86 -i <input image path> \n\
87 Set image input path.\n\
88 These images come from ViSP-images-x.y.z.tar.gz available \n\
89 on the ViSP website.\n\
90 Setting the VISP_INPUT_IMAGE_PATH environment\n\
91 variable produces the same behavior than using\n\
95 Set the config file (the xml file) to use for the depth sensor.\n\
96 The config file is used to specify the parameters of the tracker.\n\
99 Specify the name of the file of the model for the depth sensor.\n\
100 The model can either be a vrml model (.wrl) or a .cao file.\n\
102 -n <initialisation file base name> \n\
103 Base name of the initialisation file. The file will be 'base_name'.init .\n\
104 This base name is also used for the optional picture specifying where to \n\
105 click (a .ppm picture).\n\
108 Turn off the display of the visual features. \n\
111 Turn off the display.\n\
114 Disable the mouse click. Useful to automate the \n\
115 execution of this program without human intervention.\n\
118 Use Ogre3D for visibility tests\n\
121 When Ogre3D is enable [-o] show Ogre3D configuration dialog that allows to set the renderer.\n\
124 Use the scanline for visibility tests.\n\
127 Compute covariance matrix.\n\
130 Compute gradient projection error.\n\
133 Set tracker type (<4 (Depth normal)>, <8 (Depth dense)>, <12 (both)>) for depth sensor.\n\
135 -e <last frame index>\n\
136 Specify the index of the last frame. Once reached, the tracking is stopped.\n\
139 Disable castle element (1=floor, 2=front_door, 4=slope, 8=tower_front, 16=tower_left, 32=tower_right, 64=tower_back).\n\
142 Print the help.\n\n");
145 fprintf(stdout,
"\nERROR: Bad parameter [%s]\n", badparam);
148bool getOptions(
int argc,
const char **argv, std::string &ipath, std::string &configFile_depth,
149 std::string &modelFile_depth, std::string &initFile,
bool &displayFeatures,
bool &click_allowed,
150 bool &display,
bool &useOgre,
bool &showOgreConfigDialog,
bool &useScanline,
bool &computeCovariance,
151 bool &projectionError,
int &tracker_type_depth,
int &lastFrame,
int &disable_castle_faces)
162 configFile_depth = optarg_;
165 modelFile_depth = optarg_;
171 displayFeatures =
false;
174 click_allowed =
false;
186 showOgreConfigDialog =
true;
189 computeCovariance =
true;
192 projectionError =
true;
195 tracker_type_depth = atoi(optarg_);
198 lastFrame = atoi(optarg_);
201 disable_castle_faces = atoi(optarg_);
205 usage(argv[0],
nullptr);
208 usage(argv[0], optarg_);
213 if ((c == 1) || (c == -1)) {
215 usage(argv[0],
nullptr);
216 std::cerr <<
"ERROR: " << std::endl;
217 std::cerr <<
" Bad argument " << optarg_ << std::endl << std::endl;
224struct vpRealsenseIntrinsics_t
237void rs_deproject_pixel_to_point(
float point[3],
const vpRealsenseIntrinsics_t &intrin,
const float pixel[2],
float depth)
239 float x = (pixel[0] - intrin.ppx) / intrin.fx;
240 float y = (pixel[1] - intrin.ppy) / intrin.fy;
242 float r2 =
x *
x +
y *
y;
243 float f = 1 + intrin.coeffs[0] * r2 + intrin.coeffs[1] * r2 * r2 + intrin.coeffs[4] * r2 * r2 * r2;
244 float ux =
x * f + 2 * intrin.coeffs[2] *
x *
y + intrin.coeffs[3] * (r2 + 2 *
x *
x);
245 float uy =
y * f + 2 * intrin.coeffs[3] *
x *
y + intrin.coeffs[2] * (r2 + 2 *
y *
y);
256 vpImage<uint16_t> &I_depth_raw, std::vector<vpColVector> &pointcloud,
unsigned int &pointcloud_width,
257 unsigned int &pointcloud_height)
259#if defined(VISP_HAVE_DATASET)
260#if VISP_HAVE_DATASET_VERSION >= 0x030600
261 std::string ext(
"png");
263 std::string ext(
"pgm");
267 std::string ext(
"png");
273 std::cerr <<
"Cannot read: " << filename_image << std::endl;
281 std::ifstream file_depth(filename_depth.c_str(), std::ios::in | std::ios::binary);
282 if (!file_depth.is_open()) {
290 I_depth_raw.
resize(height, width);
292 uint16_t depth_value = 0;
293 for (
unsigned int i = 0;
i <
height;
i++) {
294 for (
unsigned int j = 0;
j <
width;
j++) {
296 I_depth_raw[
i][
j] = depth_value;
301 pointcloud_width =
width;
302 pointcloud_height =
height;
303 pointcloud.resize(
static_cast<size_t>(width * height));
307 vpRealsenseIntrinsics_t depth_intrinsic;
308 depth_intrinsic.ppx = 311.484558f;
309 depth_intrinsic.ppy = 246.283234f;
310 depth_intrinsic.fx = 476.053619f;
311 depth_intrinsic.fy = 476.053497f;
312 depth_intrinsic.coeffs[0] = 0.165056542f;
313 depth_intrinsic.coeffs[1] = -0.0508309528f;
314 depth_intrinsic.coeffs[2] = 0.00435937941f;
315 depth_intrinsic.coeffs[3] = 0.00541406544f;
316 depth_intrinsic.coeffs[4] = 0.250085592f;
318 for (
unsigned int i = 0;
i <
height;
i++) {
319 for (
unsigned int j = 0;
j <
width;
j++) {
322 float pixel[2] = {
static_cast<float>(
j),
static_cast<float>(i) };
323 rs_deproject_pixel_to_point(point, depth_intrinsic, pixel, scaled_depth);
326 data_3D[0] = point[0];
327 data_3D[1] = point[1];
328 data_3D[2] = point[2];
330 pointcloud[
static_cast<size_t>(
i *
width +
j)] = data_3D;
337void loadConfiguration(
vpMbTracker *
const tracker,
const std::string &
338#
if defined(VISP_HAVE_PUGIXML)
343#if defined(VISP_HAVE_PUGIXML)
358 cam.initPersProjWithoutDistortion(476.0536193848, 476.0534973145, 311.4845581055, 246.2832336426);
366 tracker->setNearClippingDistance(0.01);
367 tracker->setFarClippingDistance(2.0);
375std::vector<std::string> getCastleElementNames(
const int element)
377 std::vector<std::string> element_names;
380 element_names.push_back(
"floor");
382 element_names.push_back(
"front_door");
384 element_names.push_back(
"slope");
386 element_names.push_back(
"tower_front");
388 element_names.push_back(
"tower_left");
390 element_names.push_back(
"tower_right");
392 element_names.push_back(
"tower_back");
394 return element_names;
398int main(
int argc,
const char **argv)
401 std::string env_ipath;
402 std::string opt_ipath;
404 std::string opt_configFile_depth;
405 std::string opt_modelFile_depth;
406 std::string opt_initFile;
407 std::string initFile;
408 bool displayFeatures =
true;
409 bool opt_click_allowed =
true;
410 bool opt_display =
true;
411 bool useOgre =
false;
412 bool showOgreConfigDialog =
false;
413 bool useScanline =
false;
414 bool computeCovariance =
false;
415 bool projectionError =
false;
417#if defined(__mips__) || defined(__mips) || defined(mips) || defined(__MIPS__)
419 int opt_lastFrame = 5;
421 int opt_lastFrame = -1;
423 int disable_castle_faces = 0;
430 if (!env_ipath.empty())
434 if (!getOptions(argc, argv, opt_ipath, opt_configFile_depth, opt_modelFile_depth, opt_initFile, displayFeatures,
435 opt_click_allowed, opt_display, useOgre, showOgreConfigDialog, useScanline, computeCovariance,
436 projectionError, trackerType_depth, opt_lastFrame, disable_castle_faces)) {
441 if (opt_ipath.empty() && env_ipath.empty()) {
442 usage(argv[0],
nullptr);
443 std::cerr << std::endl <<
"ERROR:" << std::endl;
444 std::cerr <<
" Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
445 <<
" environment variable to specify the location of the " << std::endl
446 <<
" image path where test images are located." << std::endl
457 std::cerr <<
"ViSP-images does not contain the folder: " << dir_path <<
"!" << std::endl;
461 std::string configFile_depth;
462 if (!opt_configFile_depth.empty())
463 configFile_depth = opt_configFile_depth;
468 std::string modelFile_depth;
469 if (!opt_modelFile_depth.empty())
470 modelFile_depth = opt_modelFile_depth;
475 std::string vrml_ext =
".wrl";
477 (modelFile_depth.compare(modelFile_depth.length() - vrml_ext.length(), vrml_ext.length(), vrml_ext) == 0);
480#if defined(VISP_HAVE_COIN3D) && (COIN_MAJOR_VERSION == 2 || COIN_MAJOR_VERSION == 3 || COIN_MAJOR_VERSION == 4)
481 std::cout <<
"use_vrml: " << use_vrml << std::endl;
483 std::cerr <<
"Error: vrml model file is only supported if ViSP is "
484 "build with Coin3D 3rd party"
490 if (!opt_initFile.empty())
491 initFile = opt_initFile;
497 std::vector<vpColVector> pointcloud;
498 unsigned int pointcloud_width, pointcloud_height;
499 if (!
read_data(0, ipath, I, I_depth_raw, pointcloud, pointcloud_width, pointcloud_height)) {
500 std::cerr <<
"Cannot open sequence: " << ipath << std::endl;
507#if defined(VISP_HAVE_X11)
509#elif defined(VISP_HAVE_GDI)
511#elif defined(HAVE_OPENCV_HIGHGUI)
513#elif defined(VISP_HAVE_D3D9)
515#elif defined(VISP_HAVE_GTK)
521#if defined(VISP_HAVE_DISPLAY)
523 display.init(I_depth, 100, 100,
"Depth");
525 display2.
init(I,
I_depth.getWidth() + 100, 100,
"Image");
538 loadConfiguration(tracker, configFile_depth);
541 tracker->setDisplayFeatures(displayFeatures);
544 tracker->setOgreVisibilityTest(useOgre);
546 tracker->setOgreShowConfigDialog(showOgreConfigDialog);
549 tracker->setScanLineVisibilityTest(useScanline);
552 tracker->setCovarianceComputation(computeCovariance);
555 tracker->setProjectionErrorComputation(projectionError);
558 tracker->setProjectionErrorDisplay(
true);
559 tracker->setProjectionErrorDisplayArrowLength(30);
560 tracker->setProjectionErrorDisplayArrowThickness(2);
566 cam_color.initPersProjWithoutDistortion(615.1674804688, 615.1675415039, 312.1889953613, 243.4373779297);
568 std::string depth_M_color_filename =
571 std::ifstream depth_M_color_file(depth_M_color_filename.c_str());
576 if (opt_display && opt_click_allowed) {
587 if (opt_display && opt_click_allowed) {
595 vpHomogeneousMatrix cMoi(0.04431452054, 0.09294637757, 0.3357760654, -2.677922443, 0.121297639, -0.6028463357);
601 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
602 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
603 mapOfPointclouds[
"Camera"] = &pointcloud;
604 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
605 mapOfWidths[
"Camera"] = pointcloud_width;
606 mapOfHeights[
"Camera"] = pointcloud_height;
616 bool quit =
false, click =
false;
617 unsigned int frame_index = 0;
618 std::vector<double> time_vec;
619 while (
read_data(frame_index, ipath, I, I_depth_raw, pointcloud, pointcloud_width, pointcloud_height) && !quit &&
620 (opt_lastFrame > 0 ?
static_cast<int>(frame_index) <= opt_lastFrame :
true)) {
627 std::stringstream ss;
628 ss <<
"Num frame: " << frame_index;
633 if (frame_index == 10) {
634 std::cout <<
"----------Test reset tracker----------" << std::endl;
641 loadConfiguration(tracker, configFile_depth);
644 tracker->setOgreVisibilityTest(useOgre);
645 tracker->setScanLineVisibilityTest(useScanline);
646 tracker->setCovarianceComputation(computeCovariance);
647 tracker->setProjectionErrorComputation(projectionError);
653 if (frame_index == 20) {
654 cMo.buildFrom(0.05319520317, 0.09223511976, 0.3380095812, -2.71438192, 0.07141055397, -0.3810081638);
656 if (frame_index == 50) {
657 cMo.buildFrom(0.06865933578, 0.09494713501, 0.3260555142, -2.730027451, 0.03498390135, 0.01989831338);
659 std::cout <<
"Test set pose" << std::endl;
665 if (frame_index < 15 || frame_index >= 20) {
668 if (frame_index < 30 || frame_index >= 50) {
670 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
671 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
672 mapOfPointclouds[
"Camera"] = &pointcloud;
673 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
674 mapOfWidths[
"Camera"] = pointcloud_width;
675 mapOfHeights[
"Camera"] = pointcloud_height;
677 if (disable_castle_faces) {
678 std::vector<std::string> element_names = getCastleElementNames(disable_castle_faces);
679 std::cout <<
"Disable: ";
680 for (
size_t idx = 0;
idx < element_names.size();
idx++) {
681 std::cout << element_names[
idx];
682 if (idx + 1 < element_names.size())
690 std::cout << std::endl;
696 time_vec.push_back(t);
706 std::stringstream ss;
707 ss <<
"Computation time: " <<
t <<
" ms";
711 ss <<
"nb features: " <<
tracker->getError().getRows();
715 double projection_error =
tracker->computeCurrentProjectionError(I,
depth_M_color.inverse() * cMo, cam_color);
717 ss <<
"Projection error: " << projection_error;
722 if (opt_click_allowed && opt_display) {
741 if (computeCovariance) {
742 std::cout <<
"Covariance matrix: \n" <<
tracker->getCovarianceMatrix() << std::endl << std::endl;
745 if (projectionError) {
746 std::cout <<
"Projection error: " <<
tracker->getProjectionError() << std::endl << std::endl;
757 std::cout <<
"\nFinal poses, cMo:\n" <<
cMo << std::endl;
762 if (opt_click_allowed && !quit) {
772 std::cout <<
"Catch an exception: " <<
e << std::endl;
777#elif !(defined(VISP_HAVE_MODULE_MBT) && defined(VISP_HAVE_DISPLAY))
780 std::cout <<
"Cannot run this example: visp_mbt, visp_gui modules are required." << std::endl;
786 std::cout <<
"Cannot run this example: install Lapack, Eigen3 or OpenCV" << std::endl;
Generic class defining intrinsic camera parameters.
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...
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
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)
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.
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.
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.
@ ROBUST_FEATURE_ESTIMATION
Robust scheme to estimate the normal of the plane.
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()