44 #include <visp3/core/vpConfig.h> 46 #if defined(VISP_HAVE_MODULE_MBT) && defined(VISP_HAVE_DISPLAY) 48 #include <visp3/core/vpDebug.h> 49 #include <visp3/core/vpHomogeneousMatrix.h> 50 #include <visp3/core/vpIoTools.h> 51 #include <visp3/core/vpMath.h> 52 #include <visp3/gui/vpDisplayD3D.h> 53 #include <visp3/gui/vpDisplayGDI.h> 54 #include <visp3/gui/vpDisplayGTK.h> 55 #include <visp3/gui/vpDisplayOpenCV.h> 56 #include <visp3/gui/vpDisplayX.h> 57 #include <visp3/io/vpImageIo.h> 58 #include <visp3/io/vpParseArgv.h> 59 #include <visp3/io/vpVideoReader.h> 60 #include <visp3/mbt/vpMbGenericTracker.h> 62 #define GETOPTARGS "x:X:m:M:i:n:dchfolwvpt:T:e:" 65 #define USE_SMALL_DATASET 1 // small depth dataset in ViSP-images 69 void usage(
const char *name,
const char *badparam)
72 Example of tracking with vpGenericTracker.\n\ 75 %s [-i <test image path>] [-x <config file>] [-X <config file depth>]\n\ 76 [-m <model name>] [-M <model name depth>] [-n <initialisation file base name>]\n\ 77 [-f] [-c] [-d] [-h] [-o] [-w] [-l] [-v] [-p]\n\ 78 [-t <tracker type>] [-T <tracker type>] [-e <last frame index>]\n", name);
82 -i <input image path> \n\ 83 Set image input path.\n\ 84 These images come from ViSP-images-x.y.z.tar.gz available \n\ 85 on the ViSP website.\n\ 86 Setting the VISP_INPUT_IMAGE_PATH environment\n\ 87 variable produces the same behavior than using\n\ 91 Set the config file (the xml file) to use.\n\ 92 The config file is used to specify the parameters of the tracker.\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.\n\ 100 The model can either be a vrml model (.wrl) or a .cao file.\n\ 103 Specify the name of the file of the model for the depth sensor.\n\ 104 The model can either be a vrml model (.wrl) or a .cao file.\n\ 106 -n <initialisation file base name> \n\ 107 Base name of the initialisation file. The file will be 'base_name'.init .\n\ 108 This base name is also used for the optional picture specifying where to \n\ 109 click (a .ppm picture).\n\ 112 Turn off the display of the the moving edges and Klt points. \n\ 115 Turn off the display.\n\ 118 Disable the mouse click. Useful to automate the \n\ 119 execution of this program without human intervention.\n\ 122 Use Ogre3D for visibility tests\n\ 125 When Ogre3D is enable [-o] show Ogre3D configuration dialog that allows to set the renderer.\n\ 128 Use the scanline for visibility tests.\n\ 131 Compute covariance matrix.\n\ 134 Compute gradient projection error.\n\ 137 Set tracker type (<1 (Edge)>, <2 (KLT)>, <3 (both)>) for color sensor.\n\ 140 Set tracker type (<4 (Depth normal)>, <8 (Depth dense)>, <12 (both)>) for depth sensor.\n\ 142 -e <last frame index>\n\ 143 Specify the index of the last frame. Once reached, the tracking is stopped.\n\ 146 Print the help.\n\n");
149 fprintf(stdout,
"\nERROR: Bad parameter [%s]\n", badparam);
152 bool getOptions(
int argc,
const char **argv, std::string &ipath, std::string &configFile, std::string &configFile_depth,
153 std::string &modelFile, std::string &modelFile_depth, std::string &initFile,
bool &displayFeatures,
154 bool &click_allowed,
bool &display,
bool &useOgre,
bool &showOgreConfigDialog,
bool &useScanline,
155 bool &computeCovariance,
bool &projectionError,
int &trackerType,
int &tracker_type_depth,
167 configFile = optarg_;
170 configFile_depth = optarg_;
176 modelFile_depth = optarg_;
182 displayFeatures =
false;
185 click_allowed =
false;
197 showOgreConfigDialog =
true;
200 computeCovariance =
true;
203 projectionError =
true;
206 trackerType = atoi(optarg_);
209 tracker_type_depth = atoi(optarg_);
212 lastFrame = atoi(optarg_);
215 usage(argv[0], NULL);
220 usage(argv[0], optarg_);
226 if ((c == 1) || (c == -1)) {
228 usage(argv[0], NULL);
229 std::cerr <<
"ERROR: " << std::endl;
230 std::cerr <<
" Bad argument " << optarg_ << std::endl << std::endl;
237 struct rs_intrinsics {
249 void rs_deproject_pixel_to_point(
float point[3],
const rs_intrinsics &intrin,
const float pixel[2],
float depth)
251 float x = (pixel[0] - intrin.ppx) / intrin.fx;
252 float y = (pixel[1] - intrin.ppy) / intrin.fy;
254 float r2 = x * x + y * y;
255 float f = 1 + intrin.coeffs[0] * r2 + intrin.coeffs[1] * r2 * r2 + intrin.coeffs[4] * r2 * r2 * r2;
256 float ux = x * f + 2 * intrin.coeffs[2] * x * y + intrin.coeffs[3] * (r2 + 2 * x * x);
257 float uy = y * f + 2 * intrin.coeffs[3] * x * y + intrin.coeffs[2] * (r2 + 2 * y * y);
262 point[0] = depth * x;
263 point[1] = depth * y;
268 vpImage<uint16_t> &I_depth_raw, std::vector<vpColVector> &pointcloud,
unsigned int &pointcloud_width,
269 unsigned int &pointcloud_height)
274 std::stringstream ss;
275 ss << input_directory <<
"/image_%04d.pgm";
276 sprintf(buffer, ss.str().c_str(), cpt);
277 std::string filename_image = buffer;
280 std::cerr <<
"Cannot read: " << filename_image << std::endl;
287 ss << input_directory <<
"/depth_image_%04d.bin";
288 sprintf(buffer, ss.str().c_str(), cpt);
289 std::string filename_depth = buffer;
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 rs_intrinsics 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;
349 #
if defined(VISP_HAVE_XML2) && USE_XML
354 #
if defined(VISP_HAVE_XML2) && USE_XML
359 #if defined(VISP_HAVE_XML2) && USE_XML 361 dynamic_cast<vpMbGenericTracker *
>(tracker)->loadConfigFile(configFile, configFile_depth);
375 #if defined(VISP_HAVE_MODULE_KLT) && (defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x020100)) 392 dynamic_cast<vpMbGenericTracker *
>(tracker)->setDepthNormalPclPlaneEstimationMethod(2);
393 dynamic_cast<vpMbGenericTracker *
>(tracker)->setDepthNormalPclPlaneEstimationRansacMaxIter(200);
394 dynamic_cast<vpMbGenericTracker *
>(tracker)->setDepthNormalPclPlaneEstimationRansacThreshold(0.001);
419 int main(
int argc,
const char **argv)
424 vpMbtTukeyEstimator<double> tukey_estimator;
425 std::vector<double> residues;
426 residues.push_back(0.5);
427 residues.push_back(0.1);
428 residues.push_back(0.15);
429 residues.push_back(0.14);
430 residues.push_back(0.12);
431 std::vector<double> weights(5, 1);
433 tukey_estimator.MEstimator(residues, weights, 1e-3);
435 for (
size_t i = 0; i < weights.size(); i++) {
436 std::cout <<
"residues[" << i <<
"]=" << residues[i] <<
" ; weights[i" << i <<
"]=" << weights[i] << std::endl;
438 std::cout << std::endl;
442 vpMbtTukeyEstimator<float> tukey_estimator;
443 std::vector<float> residues;
444 residues.push_back(0.5f);
445 residues.push_back(0.1f);
446 residues.push_back(0.15f);
447 residues.push_back(0.14f);
448 residues.push_back(0.12f);
449 std::vector<float> weights(5, 1);
451 tukey_estimator.MEstimator(residues, weights, (
float)1e-3);
453 for (
size_t i = 0; i < weights.size(); i++) {
454 std::cout <<
"residues[" << i <<
"]=" << residues[i] <<
" ; weights[i" << i <<
"]=" << weights[i] << std::endl;
456 std::cout << std::endl;
461 std::string env_ipath;
462 std::string opt_ipath;
464 std::string opt_configFile;
465 std::string opt_configFile_depth;
466 std::string opt_modelFile;
467 std::string opt_modelFile_depth;
468 std::string opt_initFile;
469 std::string initFile;
470 bool displayFeatures =
true;
471 bool opt_click_allowed =
true;
472 bool opt_display =
true;
473 bool useOgre =
false;
474 bool showOgreConfigDialog =
false;
475 bool useScanline =
false;
476 bool computeCovariance =
false;
477 bool projectionError =
false;
480 #if defined(__mips__) || defined(__mips) || defined(mips) || defined(__MIPS__) 482 int opt_lastFrame = 5;
484 int opt_lastFrame = -1;
492 if (!env_ipath.empty())
496 if (!getOptions(argc, argv, opt_ipath, opt_configFile, opt_configFile_depth, opt_modelFile, opt_modelFile_depth,
497 opt_initFile, displayFeatures, opt_click_allowed, opt_display, useOgre, showOgreConfigDialog,
498 useScanline, computeCovariance, projectionError, trackerType_image, trackerType_depth,
503 #if !defined(VISP_HAVE_MODULE_KLT) || (!defined(VISP_HAVE_OPENCV) || (VISP_HAVE_OPENCV_VERSION < 0x020100)) 504 if (trackerType_image == 2) {
505 std::cout <<
"KLT only features cannot be used: ViSP is not built with " 506 "KLT module or OpenCV is not available." 513 if (opt_ipath.empty() && env_ipath.empty()) {
514 usage(argv[0], NULL);
515 std::cerr << std::endl <<
"ERROR:" << std::endl;
516 std::cerr <<
" Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
517 <<
" environment variable to specify the location of the " << std::endl
518 <<
" image path where test images are located." << std::endl
529 std::cerr <<
"ViSP-images does not contain the folder: " << dir_path <<
"!" << std::endl;
533 std::string configFile, configFile_depth;
534 if (!opt_configFile.empty())
535 configFile = opt_configFile;
540 if (!opt_configFile_depth.empty())
541 configFile_depth = opt_configFile_depth;
546 std::string modelFile, modelFile_depth;
547 if (!opt_modelFile.empty())
548 modelFile = opt_modelFile;
550 #if defined(VISP_HAVE_COIN3D) && (COIN_MAJOR_VERSION == 2 || COIN_MAJOR_VERSION == 3 || COIN_MAJOR_VERSION == 4) 558 if (!opt_modelFile_depth.empty())
559 modelFile_depth = opt_modelFile_depth;
564 std::string vrml_ext =
".wrl";
566 (modelFile.compare(modelFile.length() - vrml_ext.length(), vrml_ext.length(), vrml_ext) == 0) ||
567 (modelFile_depth.compare(modelFile_depth.length() - vrml_ext.length(), vrml_ext.length(), vrml_ext) == 0);
570 #if defined(VISP_HAVE_COIN3D) && (COIN_MAJOR_VERSION == 2 || COIN_MAJOR_VERSION == 3 || COIN_MAJOR_VERSION == 4) 571 std::cout <<
"use_vrml: " << use_vrml << std::endl;
573 std::cerr <<
"Error: vrml model file is only supported if ViSP is " 574 "build with Coin3D 3rd party" 580 if (!opt_initFile.empty())
581 initFile = opt_initFile;
587 std::vector<vpColVector> pointcloud;
588 unsigned int pointcloud_width, pointcloud_height;
589 if (!read_data(0, ipath, I, I_depth_raw, pointcloud, pointcloud_width, pointcloud_height)) {
590 std::cerr <<
"Cannot open sequence: " << ipath << std::endl;
597 #if defined VISP_HAVE_X11 599 #elif defined VISP_HAVE_GDI 601 #elif defined VISP_HAVE_OPENCV 603 #elif defined VISP_HAVE_D3D9 605 #elif defined VISP_HAVE_GTK 611 #if defined(VISP_HAVE_DISPLAY) 614 display1.
init(I, 100, 100,
"Test tracking (Left)");
616 "Test tracking (Right)");
624 std::vector<int> trackerTypes(2);
625 trackerTypes[0] = trackerType_image;
626 trackerTypes[1] = trackerType_depth;
632 loadConfiguration(tracker, configFile, configFile_depth);
635 std::string depth_M_color_filename =
638 std::ifstream depth_M_color_file(depth_M_color_filename.c_str());
639 depth_M_color.
load(depth_M_color_file);
640 std::map<std::string, vpHomogeneousMatrix> mapOfCameraTransformationMatrices;
641 mapOfCameraTransformationMatrices[
"Camera2"] = depth_M_color;
642 dynamic_cast<vpMbGenericTracker *
>(tracker)->setCameraTransformationMatrix(mapOfCameraTransformationMatrices);
666 if (opt_display && opt_click_allowed) {
677 if (opt_display && opt_click_allowed) {
678 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
679 mapOfImages[
"Camera1"] = &I;
680 mapOfImages[
"Camera2"] = &I_depth;
681 std::map<std::string, std::string> mapOfInitFiles;
682 mapOfInitFiles[
"Camera1"] = initFile;
685 dynamic_cast<vpMbGenericTracker *
>(tracker)->initClick(mapOfImages, mapOfInitFiles,
true);
690 vpHomogeneousMatrix c1Moi(0.06846423368, 0.09062570884, 0.3401096693, -2.671882598, 0.1174275908, -0.6011935263);
691 vpHomogeneousMatrix c2Moi(0.04431452054, 0.09294637757, 0.3357760654, -2.677922443, 0.121297639, -0.6028463357);
697 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
698 mapOfImages[
"Camera1"] = &I;
699 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
700 mapOfPointclouds[
"Camera2"] = &pointcloud;
701 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
702 mapOfWidths[
"Camera2"] = pointcloud_width;
703 mapOfHeights[
"Camera2"] = pointcloud_height;
705 dynamic_cast<vpMbGenericTracker *
>(tracker)->track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
714 bool quit =
false, click =
false;
715 unsigned int frame_index = 0;
716 std::vector<double> time_vec;
717 while (read_data(frame_index, ipath, I, I_depth_raw, pointcloud, pointcloud_width, pointcloud_height) && !quit &&
718 (opt_lastFrame > 0 ? (
int)frame_index <= opt_lastFrame :
true)) {
725 std::stringstream ss;
726 ss <<
"Num frame: " << frame_index;
731 if (frame_index == 10) {
732 std::cout <<
"----------Test reset tracker----------" << std::endl;
740 loadConfiguration(tracker, configFile, configFile_depth);
751 #if USE_SMALL_DATASET 752 if (frame_index == 20) {
753 c1Mo.
buildFrom(0.07734634051, 0.08993639906, 0.342344402, -2.708409543, 0.0669276477, -0.3798958303);
754 c2Mo.
buildFrom(0.05319520317, 0.09223511976, 0.3380095812, -2.71438192, 0.07141055397, -0.3810081638);
756 if (frame_index == 50) {
757 c1Mo.
buildFrom(0.09280663035, 0.09277655672, 0.330415149, -2.724431817, 0.0293932671, 0.02027966377);
758 c2Mo.
buildFrom(0.06865933578, 0.09494713501, 0.3260555142, -2.730027451, 0.03498390135, 0.01989831338);
760 std::cout <<
"Test set pose" << std::endl;
764 #if USE_SMALL_DATASET 766 if (frame_index < 15 || frame_index >= 20) {
769 if (frame_index < 30 || frame_index >= 50) {
771 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
772 mapOfImages[
"Camera1"] = &I;
773 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
774 mapOfPointclouds[
"Camera2"] = &pointcloud;
775 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
776 mapOfWidths[
"Camera2"] = pointcloud_width;
777 mapOfHeights[
"Camera2"] = pointcloud_height;
780 dynamic_cast<vpMbGenericTracker *
>(tracker)->track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
782 time_vec.push_back(t);
793 std::stringstream ss;
794 ss <<
"Computation time: " << t <<
" ms";
803 if (opt_click_allowed && opt_display) {
822 if (computeCovariance) {
823 std::cout <<
"Covariance matrix: \n" << tracker->
getCovarianceMatrix() << std::endl << std::endl;
826 if (projectionError) {
827 std::cout <<
"Projection error: " << tracker->
getProjectionError() << std::endl << std::endl;
838 std::cout <<
"\nFinal poses, c1Mo:\n" << c1Mo <<
"\nc2Mo:\n" << c2Mo << std::endl;
843 if (opt_click_allowed && !quit) {
850 #if defined(VISP_HAVE_XML2) && USE_XML 856 #if defined(VISP_HAVE_COIN3D) && (COIN_MAJOR_VERSION >= 2) 865 std::cout <<
"Catch an exception: " << e << std::endl;
873 std::cerr <<
"visp_mbt, visp_gui modules and OpenCV are required to run " virtual void setDisplayFeatures(const bool displayF)
virtual void setCovarianceComputation(const bool &flag)
virtual void setOgreShowConfigDialog(const bool showConfigDialog)
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static double getStdev(const std::vector< double > &v, const bool useBesselCorrection=false)
void setHarrisFreeParameter(double harris_k)
virtual unsigned int getClipping() const
virtual void setAngleDisappear(const double &a)
Implementation of an homogeneous matrix and operations on such kind of matrices.
void setMaskNumber(const unsigned int &a)
virtual void setDownScalingFactor(unsigned int scale)
static double getMedian(const std::vector< double > &v)
static const vpColor darkRed
Display for windows using GDI (available on any windows 32 platform).
void setMaxFeatures(const int maxCount)
void setSampleStep(const double &s)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
void setMinDistance(double minDistance)
error that can be emited by ViSP classes.
Real-time 6D object pose tracking using its CAD model.
virtual void resetTracker()=0
static void flush(const vpImage< unsigned char > &I)
void load(std::ifstream &f)
VISP_EXPORT double measureTimeMs()
void setMu1(const double &mu_1)
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
void setQuality(double qualityLevel)
void initPersProjWithoutDistortion(const double px, const double py, const double u0, const double v0)
static double getMean(const std::vector< double > &v)
Display for windows using Direct3D 3rd party. Thus to enable this class Direct3D should be installed...
void setMaskSize(const unsigned int &a)
static void display(const vpImage< unsigned char > &I)
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
virtual double getProjectionError() const
Generic class defining intrinsic camera parameters.
Main methods for a model-based tracker.
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
void resize(const unsigned int h, const unsigned int w)
resize the image : Image initialization
virtual void setAngleAppear(const double &a)
unsigned int getRows() const
void setPyramidLevels(const int pyrMaxLevel)
void buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)
static double rad(double deg)
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="")
void setMu2(const double &mu_2)
void setWindowSize(const int winSize)
virtual void setOgreVisibilityTest(const bool &v)
static void read(vpImage< unsigned char > &I, const std::string &filename)
Implementation of column vector and the associated operations.
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))
unsigned int getDownScalingFactor()
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented in OpenCV. Thus to enable this ...
void setBlockSize(const int blockSize)
void setThreshold(const double &t)
virtual void setScanLineVisibilityTest(const bool &v)
virtual void setClipping(const unsigned int &flags)
void setRange(const unsigned int &r)
virtual void setFarClippingDistance(const double &dist)
static void createDepthHistogram(const vpImage< uint16_t > &src_depth, vpImage< vpRGBa > &dest_rgba)
virtual void setProjectionErrorComputation(const bool &flag)
virtual vpColVector getError() const =0
virtual void setNearClippingDistance(const double &dist)
virtual vpMatrix getCovarianceMatrix() const