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:X:m:M:i:n:dchfolwvpt:T:e:"
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>] [-X <config file depth>]\n\
80 [-m <model name>] [-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>] [-T <tracker type>] [-e <last frame index>]\n",
87 -i <input image path> \n\
88 Set image input path.\n\
89 These images come from visp-images-x.y.z.tar.gz available \n\
90 on the ViSP website.\n\
91 Setting the VISP_INPUT_IMAGE_PATH environment\n\
92 variable produces the same behavior than using\n\
96 Set the config file (the xml file) to use.\n\
97 The config file is used to specify the parameters of the tracker.\n\
100 Set the config file (the xml file) to use for the depth sensor.\n\
101 The config file is used to specify the parameters of the tracker.\n\
104 Specify the name of the file of the model.\n\
105 The model can either be a vrml model (.wrl) or a .cao file.\n\
108 Specify the name of the file of the model for the depth sensor.\n\
109 The model can either be a vrml model (.wrl) or a .cao file.\n\
111 -n <initialisation file base name> \n\
112 Base name of the initialisation file. The file will be 'base_name'.init .\n\
113 This base name is also used for the optional picture specifying where to \n\
114 click (a .ppm picture).\n\
117 Turn off the display of the the moving edges and Klt points. \n\
120 Turn off the display.\n\
123 Disable the mouse click. Useful to automate the \n\
124 execution of this program without human intervention.\n\
127 Use Ogre3D for visibility tests\n\
130 When Ogre3D is enable [-o] show Ogre3D configuration dialog that allows to set the renderer.\n\
133 Use the scanline for visibility tests.\n\
136 Compute covariance matrix.\n\
139 Compute gradient projection error.\n\
142 Set tracker type (<1 (Edge)>, <2 (KLT)>, <3 (both)>) for color sensor.\n\
145 Set tracker type (<4 (Depth normal)>, <8 (Depth dense)>, <12 (both)>) for depth sensor.\n\
147 -e <last frame index>\n\
148 Specify the index of the last frame. Once reached, the tracking is stopped.\n\
151 Print the help.\n\n");
154 fprintf(stdout,
"\nERROR: Bad parameter [%s]\n", badparam);
157 bool getOptions(
int argc,
const char **argv, std::string &ipath, std::string &configFile, std::string &configFile_depth,
158 std::string &modelFile, std::string &modelFile_depth, std::string &initFile,
bool &displayFeatures,
159 bool &click_allowed,
bool &display,
bool &useOgre,
bool &showOgreConfigDialog,
bool &useScanline,
160 bool &computeCovariance,
bool &projectionError,
int &trackerType,
int &tracker_type_depth,
172 configFile = optarg_;
175 configFile_depth = optarg_;
181 modelFile_depth = optarg_;
187 displayFeatures =
false;
190 click_allowed =
false;
202 showOgreConfigDialog =
true;
205 computeCovariance =
true;
208 projectionError =
true;
211 trackerType = atoi(optarg_);
214 tracker_type_depth = atoi(optarg_);
217 lastFrame = atoi(optarg_);
220 usage(argv[0],
nullptr);
225 usage(argv[0], optarg_);
231 if ((c == 1) || (c == -1)) {
233 usage(argv[0],
nullptr);
234 std::cerr <<
"ERROR: " << std::endl;
235 std::cerr <<
" Bad argument " << optarg_ << std::endl << std::endl;
242 struct vpRealsenseIntrinsics_t
255 void rs_deproject_pixel_to_point(
float point[3],
const vpRealsenseIntrinsics_t &intrin,
const float pixel[2],
float depth)
257 float x = (pixel[0] - intrin.ppx) / intrin.fx;
258 float y = (pixel[1] - intrin.ppy) / intrin.fy;
260 float r2 = x * x + y * y;
261 float f = 1 + intrin.coeffs[0] * r2 + intrin.coeffs[1] * r2 * r2 + intrin.coeffs[4] * r2 * r2 * r2;
262 float ux = x * f + 2 * intrin.coeffs[2] * x * y + intrin.coeffs[3] * (r2 + 2 * x * x);
263 float uy = y * f + 2 * intrin.coeffs[3] * x * y + intrin.coeffs[2] * (r2 + 2 * y * y);
268 point[0] = depth * x;
269 point[1] = depth * y;
274 vpImage<uint16_t> &I_depth_raw, std::vector<vpColVector> &pointcloud,
unsigned int &pointcloud_width,
275 unsigned int &pointcloud_height)
277 #if defined(VISP_HAVE_DATASET)
278 #if VISP_HAVE_DATASET_VERSION >= 0x030600
279 std::string ext(
"png");
281 std::string ext(
"pgm");
285 std::string ext(
"png");
288 std::stringstream ss;
289 ss << input_directory <<
"/image_";
290 ss << std::setfill(
'0') << std::setw(4);
294 std::string filename_image = ss.str();
296 std::cerr <<
"Cannot read: " << filename_image << std::endl;
303 ss << input_directory <<
"/depth_image_";
304 ss << std::setfill(
'0') << std::setw(4);
307 std::string filename_depth = ss.str();
309 std::ifstream file_depth(filename_depth.c_str(), std::ios::in | std::ios::binary);
310 if (!file_depth.is_open()) {
314 unsigned int height = 0, width = 0;
318 I_depth_raw.
resize(height, width);
320 uint16_t depth_value = 0;
321 for (
unsigned int i = 0; i < height; i++) {
322 for (
unsigned int j = 0; j < width; j++) {
324 I_depth_raw[i][j] = depth_value;
329 pointcloud_width = width;
330 pointcloud_height = height;
331 pointcloud.
resize((
size_t)width * height);
334 const float depth_scale = 0.000124986647f;
335 vpRealsenseIntrinsics_t depth_intrinsic;
336 depth_intrinsic.ppx = 311.484558f;
337 depth_intrinsic.ppy = 246.283234f;
338 depth_intrinsic.fx = 476.053619f;
339 depth_intrinsic.fy = 476.053497f;
340 depth_intrinsic.coeffs[0] = 0.165056542f;
341 depth_intrinsic.coeffs[1] = -0.0508309528f;
342 depth_intrinsic.coeffs[2] = 0.00435937941f;
343 depth_intrinsic.coeffs[3] = 0.00541406544f;
344 depth_intrinsic.coeffs[4] = 0.250085592f;
346 for (
unsigned int i = 0; i < height; i++) {
347 for (
unsigned int j = 0; j < width; j++) {
348 float scaled_depth = I_depth_raw[i][j] * depth_scale;
350 float pixel[2] = { (float)j, (
float)i };
351 rs_deproject_pixel_to_point(point, depth_intrinsic, pixel, scaled_depth);
354 data_3D[0] = point[0];
355 data_3D[1] = point[1];
356 data_3D[2] = point[2];
358 pointcloud[(size_t)(i * width + j)] = data_3D;
367 #
if defined(VISP_HAVE_PUGIXML)
372 #
if defined(VISP_HAVE_PUGIXML)
377 #if defined(VISP_HAVE_PUGIXML)
379 dynamic_cast<vpMbGenericTracker *
>(tracker)->loadConfigFile(configFile, configFile_depth);
394 #if defined(VISP_HAVE_MODULE_KLT) && defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
411 dynamic_cast<vpMbGenericTracker *
>(tracker)->setDepthNormalPclPlaneEstimationMethod(2);
412 dynamic_cast<vpMbGenericTracker *
>(tracker)->setDepthNormalPclPlaneEstimationRansacMaxIter(200);
413 dynamic_cast<vpMbGenericTracker *
>(tracker)->setDepthNormalPclPlaneEstimationRansacThreshold(0.001);
438 int main(
int argc,
const char **argv)
441 std::string env_ipath;
442 std::string opt_ipath;
444 std::string opt_configFile;
445 std::string opt_configFile_depth;
446 std::string opt_modelFile;
447 std::string opt_modelFile_depth;
448 std::string opt_initFile;
449 std::string initFile;
450 bool displayFeatures =
true;
451 bool opt_click_allowed =
true;
452 bool opt_display =
true;
453 bool useOgre =
false;
454 bool showOgreConfigDialog =
false;
455 bool useScanline =
false;
456 bool computeCovariance =
false;
457 bool projectionError =
false;
460 #if defined(__mips__) || defined(__mips) || defined(mips) || defined(__MIPS__)
462 int opt_lastFrame = 5;
464 int opt_lastFrame = -1;
472 if (!env_ipath.empty())
476 if (!getOptions(argc, argv, opt_ipath, opt_configFile, opt_configFile_depth, opt_modelFile, opt_modelFile_depth,
477 opt_initFile, displayFeatures, opt_click_allowed, opt_display, useOgre, showOgreConfigDialog,
478 useScanline, computeCovariance, projectionError, trackerType_image, trackerType_depth,
483 #if !(defined(VISP_HAVE_MODULE_KLT) && defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO))
484 if (trackerType_image == 2 || trackerType_image == 3) {
485 std::cout <<
"KLT features cannot be used: ViSP is not built with "
486 "KLT module or OpenCV imgproc and video modules are not available."
493 if (opt_ipath.empty() && env_ipath.empty()) {
494 usage(argv[0],
nullptr);
495 std::cerr << std::endl <<
"ERROR:" << std::endl;
496 std::cerr <<
" Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
497 <<
" environment variable to specify the location of the " << std::endl
498 <<
" image path where test images are located." << std::endl
509 std::cerr <<
"ViSP-images does not contain the folder: " << dir_path <<
"!" << std::endl;
513 std::string configFile, configFile_depth;
514 if (!opt_configFile.empty())
515 configFile = opt_configFile;
520 if (!opt_configFile_depth.empty())
521 configFile_depth = opt_configFile_depth;
526 std::string modelFile, modelFile_depth;
527 if (!opt_modelFile.empty())
528 modelFile = opt_modelFile;
530 #if defined(VISP_HAVE_COIN3D) && (COIN_MAJOR_VERSION == 2 || COIN_MAJOR_VERSION == 3 || COIN_MAJOR_VERSION == 4)
538 if (!opt_modelFile_depth.empty())
539 modelFile_depth = opt_modelFile_depth;
544 std::string vrml_ext =
".wrl";
546 (modelFile.compare(modelFile.length() - vrml_ext.length(), vrml_ext.length(), vrml_ext) == 0) ||
547 (modelFile_depth.compare(modelFile_depth.length() - vrml_ext.length(), vrml_ext.length(), vrml_ext) == 0);
550 #if defined(VISP_HAVE_COIN3D) && (COIN_MAJOR_VERSION == 2 || COIN_MAJOR_VERSION == 3 || COIN_MAJOR_VERSION == 4)
551 std::cout <<
"use_vrml: " << use_vrml << std::endl;
553 std::cerr <<
"Error: vrml model file is only supported if ViSP is "
554 "build with Coin3D 3rd party"
560 if (!opt_initFile.empty())
561 initFile = opt_initFile;
567 std::vector<vpColVector> pointcloud;
568 unsigned int pointcloud_width, pointcloud_height;
569 if (!read_data(0, ipath, I, I_depth_raw, pointcloud, pointcloud_width, pointcloud_height)) {
570 std::cerr <<
"Cannot open sequence: " << ipath << std::endl;
577 #if defined(VISP_HAVE_X11)
579 #elif defined(VISP_HAVE_GDI)
581 #elif defined(HAVE_OPENCV_HIGHGUI)
583 #elif defined(VISP_HAVE_D3D9)
585 #elif defined(VISP_HAVE_GTK)
591 #if defined(VISP_HAVE_DISPLAY)
594 display1.
init(I, 100, 100,
"Test tracking (Left)");
596 "Test tracking (Right)");
604 std::vector<int> trackerTypes(2);
605 trackerTypes[0] = trackerType_image;
606 trackerTypes[1] = trackerType_depth;
612 loadConfiguration(tracker, configFile, configFile_depth);
615 std::string depth_M_color_filename =
618 std::ifstream depth_M_color_file(depth_M_color_filename.c_str());
619 depth_M_color.
load(depth_M_color_file);
620 std::map<std::string, vpHomogeneousMatrix> mapOfCameraTransformationMatrices;
621 mapOfCameraTransformationMatrices[
"Camera2"] = depth_M_color;
622 dynamic_cast<vpMbGenericTracker *
>(tracker)->setCameraTransformationMatrix(mapOfCameraTransformationMatrices);
646 if (opt_display && opt_click_allowed) {
657 if (opt_display && opt_click_allowed) {
658 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
659 mapOfImages[
"Camera1"] = &I;
660 mapOfImages[
"Camera2"] = &I_depth;
661 std::map<std::string, std::string> mapOfInitFiles;
662 mapOfInitFiles[
"Camera1"] = initFile;
665 dynamic_cast<vpMbGenericTracker *
>(tracker)->initClick(mapOfImages, mapOfInitFiles,
true);
671 vpHomogeneousMatrix c1Moi(0.06846423368, 0.09062570884, 0.3401096693, -2.671882598, 0.1174275908, -0.6011935263);
672 vpHomogeneousMatrix c2Moi(0.04431452054, 0.09294637757, 0.3357760654, -2.677922443, 0.121297639, -0.6028463357);
678 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
679 mapOfImages[
"Camera1"] = &I;
680 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
681 mapOfPointclouds[
"Camera2"] = &pointcloud;
682 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
683 mapOfWidths[
"Camera2"] = pointcloud_width;
684 mapOfHeights[
"Camera2"] = pointcloud_height;
686 dynamic_cast<vpMbGenericTracker *
>(tracker)->track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
695 bool quit =
false, click =
false;
696 unsigned int frame_index = 0;
697 std::vector<double> time_vec;
698 while (read_data(frame_index, ipath, I, I_depth_raw, pointcloud, pointcloud_width, pointcloud_height) && !quit &&
699 (opt_lastFrame > 0 ? (
int)frame_index <= opt_lastFrame :
true)) {
706 std::stringstream ss;
707 ss <<
"Num frame: " << frame_index;
712 if (frame_index == 10) {
713 std::cout <<
"----------Test reset tracker----------" << std::endl;
721 loadConfiguration(tracker, configFile, configFile_depth);
732 #if USE_SMALL_DATASET
733 if (frame_index == 20) {
734 c1Mo.
buildFrom(0.07734634051, 0.08993639906, 0.342344402, -2.708409543, 0.0669276477, -0.3798958303);
735 c2Mo.
buildFrom(0.05319520317, 0.09223511976, 0.3380095812, -2.71438192, 0.07141055397, -0.3810081638);
737 if (frame_index == 50) {
738 c1Mo.
buildFrom(0.09280663035, 0.09277655672, 0.330415149, -2.724431817, 0.0293932671, 0.02027966377);
739 c2Mo.
buildFrom(0.06865933578, 0.09494713501, 0.3260555142, -2.730027451, 0.03498390135, 0.01989831338);
741 std::cout <<
"Test set pose" << std::endl;
745 #if USE_SMALL_DATASET
747 if (frame_index < 15 || frame_index >= 20) {
750 if (frame_index < 30 || frame_index >= 50) {
752 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
753 mapOfImages[
"Camera1"] = &I;
754 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
755 mapOfPointclouds[
"Camera2"] = &pointcloud;
756 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
757 mapOfWidths[
"Camera2"] = pointcloud_width;
758 mapOfHeights[
"Camera2"] = pointcloud_height;
761 dynamic_cast<vpMbGenericTracker *
>(tracker)->track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
763 time_vec.push_back(t);
774 std::stringstream ss;
775 ss <<
"Computation time: " << t <<
" ms";
782 std::stringstream ss;
783 ss <<
"Features: edges " <<
dynamic_cast<vpMbGenericTracker *
>(tracker)->getNbFeaturesEdge() <<
", klt "
791 if (opt_click_allowed && opt_display) {
810 if (computeCovariance) {
811 std::cout <<
"Covariance matrix: \n" << tracker->
getCovarianceMatrix() << std::endl << std::endl;
814 if (projectionError) {
815 std::cout <<
"Projection error: " << tracker->
getProjectionError() << std::endl << std::endl;
826 std::cout <<
"\nFinal poses, c1Mo:\n" << c1Mo <<
"\nc2Mo:\n" << c2Mo << std::endl;
831 if (opt_click_allowed && !quit) {
841 std::cout <<
"Catch an exception: " << e << std::endl;
846 #elif !(defined(VISP_HAVE_MODULE_MBT) && defined(VISP_HAVE_DISPLAY))
849 std::cout <<
"Cannot run this example: visp_mbt, visp_gui modules are required." << std::endl;
855 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...
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)
unsigned int getDownScalingFactor()
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)
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
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented in OpenCV. Thus to enable this ...
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)
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 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 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 setAngleAppear(const double &a)
virtual unsigned int getClipping() const
@ ROBUST_FEATURE_ESTIMATION
Robust scheme to estimate the normal of the plane.
void setMu1(const double &mu_1)
void setRange(const unsigned int &range)
void setLikelihoodThresholdType(const vpLikelihoodThresholdType likelihood_threshold_type)
void setMaskNumber(const unsigned int &mask_number)
void setThreshold(const double &threshold)
void setSampleStep(const double &sample_step)
void setMaskSize(const unsigned int &mask_size)
void setMu2(const double &mu_2)
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
VISP_EXPORT double measureTimeMs()