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;
297 file_depth.read((
char *)(&height),
sizeof(height));
298 file_depth.read((
char *)(&width),
sizeof(width));
299 I_depth_raw.
resize(height, width);
301 uint16_t depth_value = 0;
302 for (
unsigned int i = 0; i < height; i++) {
303 for (
unsigned int j = 0; j < width; j++) {
304 file_depth.read((
char *)(&depth_value),
sizeof(depth_value));
305 I_depth_raw[i][j] = depth_value;
310 pointcloud_width = width;
311 pointcloud_height = height;
312 pointcloud.
resize((
size_t)width * height);
315 const float depth_scale = 0.000124986647f;
316 rs_intrinsics depth_intrinsic;
317 depth_intrinsic.ppx = 311.484558f;
318 depth_intrinsic.ppy = 246.283234f;
319 depth_intrinsic.fx = 476.053619f;
320 depth_intrinsic.fy = 476.053497f;
321 depth_intrinsic.coeffs[0] = 0.165056542f;
322 depth_intrinsic.coeffs[1] = -0.0508309528f;
323 depth_intrinsic.coeffs[2] = 0.00435937941f;
324 depth_intrinsic.coeffs[3] = 0.00541406544f;
325 depth_intrinsic.coeffs[4] = 0.250085592f;
327 for (
unsigned int i = 0; i < height; i++) {
328 for (
unsigned int j = 0; j < width; j++) {
329 float scaled_depth = I_depth_raw[i][j] * depth_scale;
331 float pixel[2] = {(float)j, (
float)i};
332 rs_deproject_pixel_to_point(point, depth_intrinsic, pixel, scaled_depth);
335 data_3D[0] = point[0];
336 data_3D[1] = point[1];
337 data_3D[2] = point[2];
339 pointcloud[(size_t)(i * width + j)] = data_3D;
348 #
if defined(VISP_HAVE_XML2) && USE_XML
353 #
if defined(VISP_HAVE_XML2) && USE_XML
358 #if defined(VISP_HAVE_XML2) && USE_XML 360 dynamic_cast<vpMbGenericTracker *
>(tracker)->loadConfigFile(configFile, configFile_depth);
374 #if defined(VISP_HAVE_MODULE_KLT) && (defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x020100)) 391 dynamic_cast<vpMbGenericTracker *
>(tracker)->setDepthNormalPclPlaneEstimationMethod(2);
392 dynamic_cast<vpMbGenericTracker *
>(tracker)->setDepthNormalPclPlaneEstimationRansacMaxIter(200);
393 dynamic_cast<vpMbGenericTracker *
>(tracker)->setDepthNormalPclPlaneEstimationRansacThreshold(0.001);
418 int main(
int argc,
const char **argv)
423 vpMbtTukeyEstimator<double> tukey_estimator;
424 std::vector<double> residues;
425 residues.push_back(0.5);
426 residues.push_back(0.1);
427 residues.push_back(0.15);
428 residues.push_back(0.14);
429 residues.push_back(0.12);
430 std::vector<double> weights(5, 1);
432 tukey_estimator.MEstimator(residues, weights, 1e-3);
434 for (
size_t i = 0; i < weights.size(); i++) {
435 std::cout <<
"residues[" << i <<
"]=" << residues[i] <<
" ; weights[i" << i <<
"]=" << weights[i] << std::endl;
437 std::cout << std::endl;
441 vpMbtTukeyEstimator<float> tukey_estimator;
442 std::vector<float> residues;
443 residues.push_back(0.5f);
444 residues.push_back(0.1f);
445 residues.push_back(0.15f);
446 residues.push_back(0.14f);
447 residues.push_back(0.12f);
448 std::vector<float> weights(5, 1);
450 tukey_estimator.MEstimator(residues, weights, (
float)1e-3);
452 for (
size_t i = 0; i < weights.size(); i++) {
453 std::cout <<
"residues[" << i <<
"]=" << residues[i] <<
" ; weights[i" << i <<
"]=" << weights[i] << std::endl;
455 std::cout << std::endl;
460 std::string env_ipath;
461 std::string opt_ipath;
463 std::string opt_configFile;
464 std::string opt_configFile_depth;
465 std::string opt_modelFile;
466 std::string opt_modelFile_depth;
467 std::string opt_initFile;
468 std::string initFile;
469 bool displayFeatures =
true;
470 bool opt_click_allowed =
true;
471 bool opt_display =
true;
472 bool useOgre =
false;
473 bool showOgreConfigDialog =
false;
474 bool useScanline =
false;
475 bool computeCovariance =
false;
476 bool projectionError =
false;
479 int opt_lastFrame = -1;
486 if (!env_ipath.empty())
490 if (!getOptions(argc, argv, opt_ipath, opt_configFile, opt_configFile_depth, opt_modelFile, opt_modelFile_depth,
491 opt_initFile, displayFeatures, opt_click_allowed, opt_display, useOgre, showOgreConfigDialog,
492 useScanline, computeCovariance, projectionError, trackerType_image, trackerType_depth,
497 #if !defined(VISP_HAVE_MODULE_KLT) || (!defined(VISP_HAVE_OPENCV) || (VISP_HAVE_OPENCV_VERSION < 0x020100)) 498 if (trackerType_image == 2) {
499 std::cout <<
"KLT only features cannot be used: ViSP is not built with " 500 "KLT module or OpenCV is not available." 507 if (opt_ipath.empty() && env_ipath.empty()) {
508 usage(argv[0], NULL);
509 std::cerr << std::endl <<
"ERROR:" << std::endl;
510 std::cerr <<
" Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
511 <<
" environment variable to specify the location of the " << std::endl
512 <<
" image path where test images are located." << std::endl
523 std::cerr <<
"ViSP-images does not contain the folder: " << dir_path <<
"!" << std::endl;
527 std::string configFile, configFile_depth;
528 if (!opt_configFile.empty())
529 configFile = opt_configFile;
534 if (!opt_configFile_depth.empty())
535 configFile_depth = opt_configFile_depth;
540 std::string modelFile, modelFile_depth;
541 if (!opt_modelFile.empty())
542 modelFile = opt_modelFile;
544 #if defined(VISP_HAVE_COIN3D) && (COIN_MAJOR_VERSION == 2 || COIN_MAJOR_VERSION == 3 || COIN_MAJOR_VERSION == 4) 552 if (!opt_modelFile_depth.empty())
553 modelFile_depth = opt_modelFile_depth;
558 std::string vrml_ext =
".wrl";
560 (modelFile.compare(modelFile.length() - vrml_ext.length(), vrml_ext.length(), vrml_ext) == 0) ||
561 (modelFile_depth.compare(modelFile_depth.length() - vrml_ext.length(), vrml_ext.length(), vrml_ext) == 0);
564 #if defined(VISP_HAVE_COIN3D) && (COIN_MAJOR_VERSION == 2 || COIN_MAJOR_VERSION == 3 || COIN_MAJOR_VERSION == 4) 565 std::cout <<
"use_vrml: " << use_vrml << std::endl;
567 std::cerr <<
"Error: vrml model file is only supported if ViSP is " 568 "build with Coin3D 3rd party" 574 if (!opt_initFile.empty())
575 initFile = opt_initFile;
581 std::vector<vpColVector> pointcloud;
582 unsigned int pointcloud_width, pointcloud_height;
583 if (!read_data(0, ipath, I, I_depth_raw, pointcloud, pointcloud_width, pointcloud_height)) {
584 std::cerr <<
"Cannot open sequence: " << ipath << std::endl;
591 #if defined VISP_HAVE_X11 593 #elif defined VISP_HAVE_GDI 595 #elif defined VISP_HAVE_OPENCV 597 #elif defined VISP_HAVE_D3D9 599 #elif defined VISP_HAVE_GTK 605 #if (defined VISP_HAVE_DISPLAY) 608 display1.
init(I, 100, 100,
"Test tracking (Left)");
610 "Test tracking (Right)");
618 std::vector<int> trackerTypes(2);
619 trackerTypes[0] = trackerType_image;
620 trackerTypes[1] = trackerType_depth;
625 loadConfiguration(tracker, configFile, configFile_depth);
628 std::string depth_M_color_filename =
631 std::ifstream depth_M_color_file(depth_M_color_filename.c_str());
632 depth_M_color.
load(depth_M_color_file);
633 std::map<std::string, vpHomogeneousMatrix> mapOfCameraTransformationMatrices;
634 mapOfCameraTransformationMatrices[
"Camera2"] = depth_M_color;
635 dynamic_cast<vpMbGenericTracker *
>(tracker)->setCameraTransformationMatrix(mapOfCameraTransformationMatrices);
659 if (opt_display && opt_click_allowed) {
670 if (opt_display && opt_click_allowed) {
671 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
672 mapOfImages[
"Camera1"] = &I;
673 mapOfImages[
"Camera2"] = &I_depth;
674 std::map<std::string, std::string> mapOfInitFiles;
675 mapOfInitFiles[
"Camera1"] = initFile;
678 dynamic_cast<vpMbGenericTracker *
>(tracker)->initClick(mapOfImages, mapOfInitFiles,
true);
683 vpHomogeneousMatrix c1Moi(0.06846423368, 0.09062570884, 0.3401096693, -2.671882598, 0.1174275908, -0.6011935263);
684 vpHomogeneousMatrix c2Moi(0.04431452054, 0.09294637757, 0.3357760654, -2.677922443, 0.121297639, -0.6028463357);
690 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
691 mapOfImages[
"Camera1"] = &I;
692 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
693 mapOfPointclouds[
"Camera2"] = &pointcloud;
694 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
695 mapOfWidths[
"Camera2"] = pointcloud_width;
696 mapOfHeights[
"Camera2"] = pointcloud_height;
698 dynamic_cast<vpMbGenericTracker *
>(tracker)->track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
707 bool quit =
false, click =
false;
708 unsigned int frame_index = 0;
709 std::vector<double> time_vec;
710 while (read_data(frame_index, ipath, I, I_depth_raw, pointcloud, pointcloud_width, pointcloud_height) && !quit &&
711 (opt_lastFrame > 0 ? (
int)frame_index <= opt_lastFrame :
true)) {
718 std::stringstream ss;
719 ss <<
"Num frame: " << frame_index;
724 if (frame_index == 10) {
725 std::cout <<
"----------Test reset tracker----------" << std::endl;
733 loadConfiguration(tracker, configFile, configFile_depth);
744 #if USE_SMALL_DATASET 745 if (frame_index == 20) {
746 c1Mo.
buildFrom(0.07734634051, 0.08993639906, 0.342344402, -2.708409543, 0.0669276477, -0.3798958303);
747 c2Mo.
buildFrom(0.05319520317, 0.09223511976, 0.3380095812, -2.71438192, 0.07141055397, -0.3810081638);
749 if (frame_index == 50) {
750 c1Mo.
buildFrom(0.09280663035, 0.09277655672, 0.330415149, -2.724431817, 0.0293932671, 0.02027966377);
751 c2Mo.
buildFrom(0.06865933578, 0.09494713501, 0.3260555142, -2.730027451, 0.03498390135, 0.01989831338);
753 std::cout <<
"Test set pose" << std::endl;
757 #if USE_SMALL_DATASET 759 if (frame_index < 15 || frame_index >= 20) {
762 if (frame_index < 30 || frame_index >= 50) {
764 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
765 mapOfImages[
"Camera1"] = &I;
766 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
767 mapOfPointclouds[
"Camera2"] = &pointcloud;
768 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
769 mapOfWidths[
"Camera2"] = pointcloud_width;
770 mapOfHeights[
"Camera2"] = pointcloud_height;
773 dynamic_cast<vpMbGenericTracker *
>(tracker)->track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
775 time_vec.push_back(t);
786 std::stringstream ss;
787 ss <<
"Computation time: " << t <<
" ms";
792 if (opt_click_allowed) {
811 if (computeCovariance) {
812 std::cout <<
"Covariance matrix: \n" << tracker->
getCovarianceMatrix() << std::endl << std::endl;
815 if (projectionError) {
816 std::cout <<
"Projection error: " << tracker->
getProjectionError() << std::endl << std::endl;
825 std::cout <<
"\nFinal poses, c1Mo:\n" << c1Mo <<
"\nc2Mo:\n" << c2Mo << std::endl;
830 if (opt_click_allowed && !quit) {
837 #if defined(VISP_HAVE_XML2) && USE_XML 843 #if defined(VISP_HAVE_COIN3D) && (COIN_MAJOR_VERSION == 2 || COIN_MAJOR_VERSION == 3 || COIN_MAJOR_VERSION == 4) 852 std::cout <<
"Catch an exception: " << e << std::endl;
860 std::cerr <<
"visp_mbt, visp_gui modules and OpenCV are required to run " virtual unsigned int getClipping() const
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 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...
virtual double getProjectionError() const
void setMinDistance(double minDistance)
error that can be emited by ViSP classes.
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...
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)
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()
virtual vpMatrix getCovarianceMatrix() const
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 void setNearClippingDistance(const double &dist)