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 VISP_HAVE_DATASET_VERSION >= 0x030600
278 std::string ext(
"png");
280 std::string ext(
"pgm");
283 std::stringstream ss;
284 ss << input_directory <<
"/image_";
285 ss << std::setfill(
'0') << std::setw(4);
289 std::string filename_image = ss.str();
291 std::cerr <<
"Cannot read: " << filename_image << std::endl;
298 ss << input_directory <<
"/depth_image_";
299 ss << std::setfill(
'0') << std::setw(4);
302 std::string filename_depth = ss.str();
304 std::ifstream file_depth(filename_depth.c_str(), std::ios::in | std::ios::binary);
305 if (!file_depth.is_open()) {
309 unsigned int height = 0, width = 0;
313 I_depth_raw.
resize(height, width);
315 uint16_t depth_value = 0;
316 for (
unsigned int i = 0; i < height; i++) {
317 for (
unsigned int j = 0; j < width; j++) {
319 I_depth_raw[i][j] = depth_value;
324 pointcloud_width = width;
325 pointcloud_height = height;
326 pointcloud.
resize((
size_t)width * height);
329 const float depth_scale = 0.000124986647f;
330 vpRealsenseIntrinsics_t depth_intrinsic;
331 depth_intrinsic.ppx = 311.484558f;
332 depth_intrinsic.ppy = 246.283234f;
333 depth_intrinsic.fx = 476.053619f;
334 depth_intrinsic.fy = 476.053497f;
335 depth_intrinsic.coeffs[0] = 0.165056542f;
336 depth_intrinsic.coeffs[1] = -0.0508309528f;
337 depth_intrinsic.coeffs[2] = 0.00435937941f;
338 depth_intrinsic.coeffs[3] = 0.00541406544f;
339 depth_intrinsic.coeffs[4] = 0.250085592f;
341 for (
unsigned int i = 0; i < height; i++) {
342 for (
unsigned int j = 0; j < width; j++) {
343 float scaled_depth = I_depth_raw[i][j] * depth_scale;
345 float pixel[2] = { (float)j, (
float)i };
346 rs_deproject_pixel_to_point(point, depth_intrinsic, pixel, scaled_depth);
349 data_3D[0] = point[0];
350 data_3D[1] = point[1];
351 data_3D[2] = point[2];
353 pointcloud[(size_t)(i * width + j)] = data_3D;
362 #
if defined(VISP_HAVE_PUGIXML)
367 #
if defined(VISP_HAVE_PUGIXML)
372 #if defined(VISP_HAVE_PUGIXML)
374 dynamic_cast<vpMbGenericTracker *
>(tracker)->loadConfigFile(configFile, configFile_depth);
389 #if defined(VISP_HAVE_MODULE_KLT) && defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
406 dynamic_cast<vpMbGenericTracker *
>(tracker)->setDepthNormalPclPlaneEstimationMethod(2);
407 dynamic_cast<vpMbGenericTracker *
>(tracker)->setDepthNormalPclPlaneEstimationRansacMaxIter(200);
408 dynamic_cast<vpMbGenericTracker *
>(tracker)->setDepthNormalPclPlaneEstimationRansacThreshold(0.001);
433 int main(
int argc,
const char **argv)
436 std::string env_ipath;
437 std::string opt_ipath;
439 std::string opt_configFile;
440 std::string opt_configFile_depth;
441 std::string opt_modelFile;
442 std::string opt_modelFile_depth;
443 std::string opt_initFile;
444 std::string initFile;
445 bool displayFeatures =
true;
446 bool opt_click_allowed =
true;
447 bool opt_display =
true;
448 bool useOgre =
false;
449 bool showOgreConfigDialog =
false;
450 bool useScanline =
false;
451 bool computeCovariance =
false;
452 bool projectionError =
false;
455 #if defined(__mips__) || defined(__mips) || defined(mips) || defined(__MIPS__)
457 int opt_lastFrame = 5;
459 int opt_lastFrame = -1;
467 if (!env_ipath.empty())
471 if (!getOptions(argc, argv, opt_ipath, opt_configFile, opt_configFile_depth, opt_modelFile, opt_modelFile_depth,
472 opt_initFile, displayFeatures, opt_click_allowed, opt_display, useOgre, showOgreConfigDialog,
473 useScanline, computeCovariance, projectionError, trackerType_image, trackerType_depth,
478 #if !(defined(VISP_HAVE_MODULE_KLT) && defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO))
479 if (trackerType_image == 2 || trackerType_image == 3) {
480 std::cout <<
"KLT features cannot be used: ViSP is not built with "
481 "KLT module or OpenCV imgproc and video modules are not available."
488 if (opt_ipath.empty() && env_ipath.empty()) {
489 usage(argv[0],
nullptr);
490 std::cerr << std::endl <<
"ERROR:" << std::endl;
491 std::cerr <<
" Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
492 <<
" environment variable to specify the location of the " << std::endl
493 <<
" image path where test images are located." << std::endl
504 std::cerr <<
"ViSP-images does not contain the folder: " << dir_path <<
"!" << std::endl;
508 std::string configFile, configFile_depth;
509 if (!opt_configFile.empty())
510 configFile = opt_configFile;
515 if (!opt_configFile_depth.empty())
516 configFile_depth = opt_configFile_depth;
521 std::string modelFile, modelFile_depth;
522 if (!opt_modelFile.empty())
523 modelFile = opt_modelFile;
525 #if defined(VISP_HAVE_COIN3D) && (COIN_MAJOR_VERSION == 2 || COIN_MAJOR_VERSION == 3 || COIN_MAJOR_VERSION == 4)
533 if (!opt_modelFile_depth.empty())
534 modelFile_depth = opt_modelFile_depth;
539 std::string vrml_ext =
".wrl";
541 (modelFile.compare(modelFile.length() - vrml_ext.length(), vrml_ext.length(), vrml_ext) == 0) ||
542 (modelFile_depth.compare(modelFile_depth.length() - vrml_ext.length(), vrml_ext.length(), vrml_ext) == 0);
545 #if defined(VISP_HAVE_COIN3D) && (COIN_MAJOR_VERSION == 2 || COIN_MAJOR_VERSION == 3 || COIN_MAJOR_VERSION == 4)
546 std::cout <<
"use_vrml: " << use_vrml << std::endl;
548 std::cerr <<
"Error: vrml model file is only supported if ViSP is "
549 "build with Coin3D 3rd party"
555 if (!opt_initFile.empty())
556 initFile = opt_initFile;
562 std::vector<vpColVector> pointcloud;
563 unsigned int pointcloud_width, pointcloud_height;
564 if (!read_data(0, ipath, I, I_depth_raw, pointcloud, pointcloud_width, pointcloud_height)) {
565 std::cerr <<
"Cannot open sequence: " << ipath << std::endl;
572 #if defined(VISP_HAVE_X11)
573 vpDisplayX display1, display2;
574 #elif defined(VISP_HAVE_GDI)
576 #elif defined(HAVE_OPENCV_HIGHGUI)
578 #elif defined(VISP_HAVE_D3D9)
580 #elif defined(VISP_HAVE_GTK)
586 #if defined(VISP_HAVE_DISPLAY)
589 display1.init(I, 100, 100,
"Test tracking (Left)");
591 "Test tracking (Right)");
599 std::vector<int> trackerTypes(2);
600 trackerTypes[0] = trackerType_image;
601 trackerTypes[1] = trackerType_depth;
607 loadConfiguration(tracker, configFile, configFile_depth);
610 std::string depth_M_color_filename =
613 std::ifstream depth_M_color_file(depth_M_color_filename.c_str());
614 depth_M_color.
load(depth_M_color_file);
615 std::map<std::string, vpHomogeneousMatrix> mapOfCameraTransformationMatrices;
616 mapOfCameraTransformationMatrices[
"Camera2"] = depth_M_color;
617 dynamic_cast<vpMbGenericTracker *
>(tracker)->setCameraTransformationMatrix(mapOfCameraTransformationMatrices);
641 if (opt_display && opt_click_allowed) {
652 if (opt_display && opt_click_allowed) {
653 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
654 mapOfImages[
"Camera1"] = &I;
655 mapOfImages[
"Camera2"] = &I_depth;
656 std::map<std::string, std::string> mapOfInitFiles;
657 mapOfInitFiles[
"Camera1"] = initFile;
660 dynamic_cast<vpMbGenericTracker *
>(tracker)->initClick(mapOfImages, mapOfInitFiles,
true);
666 vpHomogeneousMatrix c1Moi(0.06846423368, 0.09062570884, 0.3401096693, -2.671882598, 0.1174275908, -0.6011935263);
667 vpHomogeneousMatrix c2Moi(0.04431452054, 0.09294637757, 0.3357760654, -2.677922443, 0.121297639, -0.6028463357);
673 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
674 mapOfImages[
"Camera1"] = &I;
675 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
676 mapOfPointclouds[
"Camera2"] = &pointcloud;
677 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
678 mapOfWidths[
"Camera2"] = pointcloud_width;
679 mapOfHeights[
"Camera2"] = pointcloud_height;
681 dynamic_cast<vpMbGenericTracker *
>(tracker)->track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
690 bool quit =
false, click =
false;
691 unsigned int frame_index = 0;
692 std::vector<double> time_vec;
693 while (read_data(frame_index, ipath, I, I_depth_raw, pointcloud, pointcloud_width, pointcloud_height) && !quit &&
694 (opt_lastFrame > 0 ? (
int)frame_index <= opt_lastFrame :
true)) {
701 std::stringstream ss;
702 ss <<
"Num frame: " << frame_index;
707 if (frame_index == 10) {
708 std::cout <<
"----------Test reset tracker----------" << std::endl;
716 loadConfiguration(tracker, configFile, configFile_depth);
727 #if USE_SMALL_DATASET
728 if (frame_index == 20) {
729 c1Mo.
buildFrom(0.07734634051, 0.08993639906, 0.342344402, -2.708409543, 0.0669276477, -0.3798958303);
730 c2Mo.
buildFrom(0.05319520317, 0.09223511976, 0.3380095812, -2.71438192, 0.07141055397, -0.3810081638);
732 if (frame_index == 50) {
733 c1Mo.
buildFrom(0.09280663035, 0.09277655672, 0.330415149, -2.724431817, 0.0293932671, 0.02027966377);
734 c2Mo.
buildFrom(0.06865933578, 0.09494713501, 0.3260555142, -2.730027451, 0.03498390135, 0.01989831338);
736 std::cout <<
"Test set pose" << std::endl;
740 #if USE_SMALL_DATASET
742 if (frame_index < 15 || frame_index >= 20) {
745 if (frame_index < 30 || frame_index >= 50) {
747 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
748 mapOfImages[
"Camera1"] = &I;
749 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
750 mapOfPointclouds[
"Camera2"] = &pointcloud;
751 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
752 mapOfWidths[
"Camera2"] = pointcloud_width;
753 mapOfHeights[
"Camera2"] = pointcloud_height;
756 dynamic_cast<vpMbGenericTracker *
>(tracker)->track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
758 time_vec.push_back(t);
769 std::stringstream ss;
770 ss <<
"Computation time: " << t <<
" ms";
777 std::stringstream ss;
778 ss <<
"Features: edges " <<
dynamic_cast<vpMbGenericTracker *
>(tracker)->getNbFeaturesEdge() <<
", klt "
786 if (opt_click_allowed && opt_display) {
805 if (computeCovariance) {
806 std::cout <<
"Covariance matrix: \n" << tracker->
getCovarianceMatrix() << std::endl << std::endl;
809 if (projectionError) {
810 std::cout <<
"Projection error: " << tracker->
getProjectionError() << std::endl << std::endl;
821 std::cout <<
"\nFinal poses, c1Mo:\n" << c1Mo <<
"\nc2Mo:\n" << c2Mo << std::endl;
826 if (opt_click_allowed && !quit) {
836 std::cout <<
"Catch an exception: " << e << std::endl;
841 #elif !(defined(VISP_HAVE_MODULE_MBT) && defined(VISP_HAVE_DISPLAY))
844 std::cout <<
"Cannot run this example: visp_mbt, visp_gui modules are required." << std::endl;
850 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)
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()