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:X:m:M:i:n:dchfolwvpt:T:e:"
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>] [-X <config file depth>]\n\
78 [-m <model name>] [-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>] [-T <tracker type>] [-e <last frame index>]\n",
85 -i <input image path> \n\
86 Set image input path.\n\
87 These images come from visp-images-x.y.z.tar.gz available \n\
88 on the ViSP website.\n\
89 Setting the VISP_INPUT_IMAGE_PATH environment\n\
90 variable produces the same behavior than using\n\
94 Set the config file (the xml file) to use.\n\
95 The config file is used to specify the parameters of the tracker.\n\
98 Set the config file (the xml file) to use for the depth sensor.\n\
99 The config file is used to specify the parameters of the tracker.\n\
102 Specify the name of the file of the model.\n\
103 The model can either be a vrml model (.wrl) or a .cao file.\n\
106 Specify the name of the file of the model for the depth sensor.\n\
107 The model can either be a vrml model (.wrl) or a .cao file.\n\
109 -n <initialisation file base name> \n\
110 Base name of the initialisation file. The file will be 'base_name'.init .\n\
111 This base name is also used for the optional picture specifying where to \n\
112 click (a .ppm picture).\n\
115 Turn off the display of the the moving edges and Klt points. \n\
118 Turn off the display.\n\
121 Disable the mouse click. Useful to automate the \n\
122 execution of this program without human intervention.\n\
125 Use Ogre3D for visibility tests\n\
128 When Ogre3D is enable [-o] show Ogre3D configuration dialog that allows to set the renderer.\n\
131 Use the scanline for visibility tests.\n\
134 Compute covariance matrix.\n\
137 Compute gradient projection error.\n\
140 Set tracker type (<1 (Edge)>, <2 (KLT)>, <3 (both)>) for color sensor.\n\
143 Set tracker type (<4 (Depth normal)>, <8 (Depth dense)>, <12 (both)>) for depth sensor.\n\
145 -e <last frame index>\n\
146 Specify the index of the last frame. Once reached, the tracking is stopped.\n\
149 Print the help.\n\n");
152 fprintf(stdout,
"\nERROR: Bad parameter [%s]\n", badparam);
155bool getOptions(
int argc,
const char **argv, std::string &ipath, std::string &configFile, std::string &configFile_depth,
156 std::string &modelFile, std::string &modelFile_depth, std::string &initFile,
bool &displayFeatures,
157 bool &click_allowed,
bool &display,
bool &useOgre,
bool &showOgreConfigDialog,
bool &useScanline,
158 bool &computeCovariance,
bool &projectionError,
int &trackerType,
int &tracker_type_depth,
170 configFile = optarg_;
173 configFile_depth = optarg_;
179 modelFile_depth = optarg_;
185 displayFeatures =
false;
188 click_allowed =
false;
200 showOgreConfigDialog =
true;
203 computeCovariance =
true;
206 projectionError =
true;
209 trackerType = atoi(optarg_);
212 tracker_type_depth = atoi(optarg_);
215 lastFrame = atoi(optarg_);
218 usage(argv[0],
nullptr);
222 usage(argv[0], optarg_);
227 if ((c == 1) || (c == -1)) {
229 usage(argv[0],
nullptr);
230 std::cerr <<
"ERROR: " << std::endl;
231 std::cerr <<
" Bad argument " << optarg_ << std::endl << std::endl;
238struct vpRealsenseIntrinsics_t
251void rs_deproject_pixel_to_point(
float point[3],
const vpRealsenseIntrinsics_t &intrin,
const float pixel[2],
float depth)
253 float x = (pixel[0] - intrin.ppx) / intrin.fx;
254 float y = (pixel[1] - intrin.ppy) / intrin.fy;
256 float r2 =
x *
x +
y *
y;
257 float f = 1 + intrin.coeffs[0] * r2 + intrin.coeffs[1] * r2 * r2 + intrin.coeffs[4] * r2 * r2 * r2;
258 float ux =
x * f + 2 * intrin.coeffs[2] *
x *
y + intrin.coeffs[3] * (r2 + 2 *
x *
x);
259 float uy =
y * f + 2 * intrin.coeffs[3] *
x *
y + intrin.coeffs[2] * (r2 + 2 *
y *
y);
270 vpImage<uint16_t> &I_depth_raw, std::vector<vpColVector> &pointcloud,
unsigned int &pointcloud_width,
271 unsigned int &pointcloud_height)
273#if defined(VISP_HAVE_DATASET)
274#if VISP_HAVE_DATASET_VERSION >= 0x030600
275 std::string ext(
"png");
277 std::string ext(
"pgm");
281 std::string ext(
"png");
286 std::cerr <<
"Cannot read: " << filename_image << std::endl;
293 std::ifstream file_depth(filename_depth.c_str(), std::ios::in | std::ios::binary);
294 if (!file_depth.is_open()) {
302 I_depth_raw.
resize(height, width);
304 uint16_t depth_value = 0;
305 for (
unsigned int i = 0;
i <
height;
i++) {
306 for (
unsigned int j = 0;
j <
width;
j++) {
308 I_depth_raw[
i][
j] = depth_value;
313 pointcloud_width =
width;
314 pointcloud_height =
height;
315 pointcloud.resize(
static_cast<size_t>(width * height));
319 vpRealsenseIntrinsics_t depth_intrinsic;
320 depth_intrinsic.ppx = 311.484558f;
321 depth_intrinsic.ppy = 246.283234f;
322 depth_intrinsic.fx = 476.053619f;
323 depth_intrinsic.fy = 476.053497f;
324 depth_intrinsic.coeffs[0] = 0.165056542f;
325 depth_intrinsic.coeffs[1] = -0.0508309528f;
326 depth_intrinsic.coeffs[2] = 0.00435937941f;
327 depth_intrinsic.coeffs[3] = 0.00541406544f;
328 depth_intrinsic.coeffs[4] = 0.250085592f;
330 for (
unsigned int i = 0;
i <
height;
i++) {
331 for (
unsigned int j = 0;
j <
width;
j++) {
334 float pixel[2] = {
static_cast<float>(
j),
static_cast<float>(i) };
335 rs_deproject_pixel_to_point(point, depth_intrinsic, pixel, scaled_depth);
338 data_3D[0] = point[0];
339 data_3D[1] = point[1];
340 data_3D[2] = point[2];
342 pointcloud[
static_cast<size_t>(
i *
width +
j)] = data_3D;
351#
if defined(VISP_HAVE_PUGIXML)
356#
if defined(VISP_HAVE_PUGIXML)
361#if defined(VISP_HAVE_PUGIXML)
378#if defined(VISP_HAVE_MODULE_KLT) && defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
412 tracker->setNearClippingDistance(0.01);
413 tracker->setFarClippingDistance(2.0);
422int main(
int argc,
const char **argv)
425 std::string env_ipath;
426 std::string opt_ipath;
428 std::string opt_configFile;
429 std::string opt_configFile_depth;
430 std::string opt_modelFile;
431 std::string opt_modelFile_depth;
432 std::string opt_initFile;
433 std::string initFile;
434 bool displayFeatures =
true;
435 bool opt_click_allowed =
true;
436 bool opt_display =
true;
437 bool useOgre =
false;
438 bool showOgreConfigDialog =
false;
439 bool useScanline =
false;
440 bool computeCovariance =
false;
441 bool projectionError =
false;
444#if defined(__mips__) || defined(__mips) || defined(mips) || defined(__MIPS__)
446 int opt_lastFrame = 5;
448 int opt_lastFrame = -1;
456 if (!env_ipath.empty())
460 if (!getOptions(argc, argv, opt_ipath, opt_configFile, opt_configFile_depth, opt_modelFile, opt_modelFile_depth,
461 opt_initFile, displayFeatures, opt_click_allowed, opt_display, useOgre, showOgreConfigDialog,
462 useScanline, computeCovariance, projectionError, trackerType_image, trackerType_depth,
467#if !(defined(VISP_HAVE_MODULE_KLT) && defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO))
468 if (trackerType_image == 2 || trackerType_image == 3) {
469 std::cout <<
"KLT features cannot be used: ViSP is not built with "
470 "KLT module or OpenCV imgproc and video modules are not available."
477 if (opt_ipath.empty() && env_ipath.empty()) {
478 usage(argv[0],
nullptr);
479 std::cerr << std::endl <<
"ERROR:" << std::endl;
480 std::cerr <<
" Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
481 <<
" environment variable to specify the location of the " << std::endl
482 <<
" image path where test images are located." << std::endl
493 std::cerr <<
"ViSP-images does not contain the folder: " << dir_path <<
"!" << std::endl;
497 std::string configFile, configFile_depth;
498 if (!opt_configFile.empty())
499 configFile = opt_configFile;
504 if (!opt_configFile_depth.empty())
505 configFile_depth = opt_configFile_depth;
510 std::string modelFile, modelFile_depth;
511 if (!opt_modelFile.empty())
512 modelFile = opt_modelFile;
514#if defined(VISP_HAVE_COIN3D) && (COIN_MAJOR_VERSION == 2 || COIN_MAJOR_VERSION == 3 || COIN_MAJOR_VERSION == 4)
522 if (!opt_modelFile_depth.empty())
523 modelFile_depth = opt_modelFile_depth;
528 std::string vrml_ext =
".wrl";
530 (modelFile.compare(modelFile.length() - vrml_ext.length(), vrml_ext.length(), vrml_ext) == 0) ||
531 (modelFile_depth.compare(modelFile_depth.length() - vrml_ext.length(), vrml_ext.length(), vrml_ext) == 0);
534#if defined(VISP_HAVE_COIN3D) && (COIN_MAJOR_VERSION == 2 || COIN_MAJOR_VERSION == 3 || COIN_MAJOR_VERSION == 4)
535 std::cout <<
"use_vrml: " << use_vrml << std::endl;
537 std::cerr <<
"Error: vrml model file is only supported if ViSP is "
538 "build with Coin3D 3rd party"
544 if (!opt_initFile.empty())
545 initFile = opt_initFile;
551 std::vector<vpColVector> pointcloud;
552 unsigned int pointcloud_width, pointcloud_height;
553 if (!
read_data(0, ipath, I, I_depth_raw, pointcloud, pointcloud_width, pointcloud_height)) {
554 std::cerr <<
"Cannot open sequence: " << ipath << std::endl;
561#if defined(VISP_HAVE_X11)
563#elif defined(VISP_HAVE_GDI)
565#elif defined(HAVE_OPENCV_HIGHGUI)
567#elif defined(VISP_HAVE_D3D9)
569#elif defined(VISP_HAVE_GTK)
575#if defined(VISP_HAVE_DISPLAY)
578 display1.
init(I, 100, 100,
"Test tracking (Left)");
580 "Test tracking (Right)");
588 std::vector<int> trackerTypes(2);
589 trackerTypes[0] = trackerType_image;
590 trackerTypes[1] = trackerType_depth;
596 loadConfiguration(tracker, configFile, configFile_depth);
599 std::string depth_M_color_filename =
602 std::ifstream depth_M_color_file(depth_M_color_filename.c_str());
604 std::map<std::string, vpHomogeneousMatrix> mapOfCameraTransformationMatrices;
605 mapOfCameraTransformationMatrices[
"Camera2"] =
depth_M_color;
610 tracker->setDisplayFeatures(displayFeatures);
613 tracker->setOgreVisibilityTest(useOgre);
615 tracker->setOgreShowConfigDialog(showOgreConfigDialog);
618 tracker->setScanLineVisibilityTest(useScanline);
621 tracker->setCovarianceComputation(computeCovariance);
624 tracker->setProjectionErrorComputation(projectionError);
630 if (opt_display && opt_click_allowed) {
641 if (opt_display && opt_click_allowed) {
642 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
643 mapOfImages[
"Camera1"] = &I;
644 mapOfImages[
"Camera2"] = &
I_depth;
645 std::map<std::string, std::string> mapOfInitFiles;
646 mapOfInitFiles[
"Camera1"] = initFile;
655 vpHomogeneousMatrix c1Moi(0.06846423368, 0.09062570884, 0.3401096693, -2.671882598, 0.1174275908, -0.6011935263);
656 vpHomogeneousMatrix c2Moi(0.04431452054, 0.09294637757, 0.3357760654, -2.677922443, 0.121297639, -0.6028463357);
662 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
663 mapOfImages[
"Camera1"] = &I;
664 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
665 mapOfPointclouds[
"Camera2"] = &pointcloud;
666 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
667 mapOfWidths[
"Camera2"] = pointcloud_width;
668 mapOfHeights[
"Camera2"] = pointcloud_height;
679 bool quit =
false, click =
false;
680 unsigned int frame_index = 0;
681 std::vector<double> time_vec;
682 while (
read_data(frame_index, ipath, I, I_depth_raw, pointcloud, pointcloud_width, pointcloud_height) && !quit &&
683 (opt_lastFrame > 0 ?
static_cast<int>(frame_index) <= opt_lastFrame :
true)) {
690 std::stringstream ss;
691 ss <<
"Num frame: " << frame_index;
696 if (frame_index == 10) {
697 std::cout <<
"----------Test reset tracker----------" << std::endl;
705 loadConfiguration(tracker, configFile, configFile_depth);
708 tracker->setOgreVisibilityTest(useOgre);
709 tracker->setScanLineVisibilityTest(useScanline);
710 tracker->setCovarianceComputation(computeCovariance);
711 tracker->setProjectionErrorComputation(projectionError);
717 if (frame_index == 20) {
718 c1Mo.
buildFrom(0.07734634051, 0.08993639906, 0.342344402, -2.708409543, 0.0669276477, -0.3798958303);
719 c2Mo.
buildFrom(0.05319520317, 0.09223511976, 0.3380095812, -2.71438192, 0.07141055397, -0.3810081638);
721 if (frame_index == 50) {
722 c1Mo.
buildFrom(0.09280663035, 0.09277655672, 0.330415149, -2.724431817, 0.0293932671, 0.02027966377);
723 c2Mo.
buildFrom(0.06865933578, 0.09494713501, 0.3260555142, -2.730027451, 0.03498390135, 0.01989831338);
725 std::cout <<
"Test set pose" << std::endl;
731 if (frame_index < 15 || frame_index >= 20) {
734 if (frame_index < 30 || frame_index >= 50) {
736 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
737 mapOfImages[
"Camera1"] = &I;
738 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
739 mapOfPointclouds[
"Camera2"] = &pointcloud;
740 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
741 mapOfWidths[
"Camera2"] = pointcloud_width;
742 mapOfHeights[
"Camera2"] = pointcloud_height;
747 time_vec.push_back(t);
758 std::stringstream ss;
759 ss <<
"Computation time: " <<
t <<
" ms";
763 ss <<
"nb features: " <<
tracker->getError().getRows();
766 std::stringstream ss;
775 if (opt_click_allowed && opt_display) {
794 if (computeCovariance) {
795 std::cout <<
"Covariance matrix: \n" <<
tracker->getCovarianceMatrix() << std::endl << std::endl;
798 if (projectionError) {
799 std::cout <<
"Projection error: " <<
tracker->getProjectionError() << std::endl << std::endl;
810 std::cout <<
"\nFinal poses, c1Mo:\n" << c1Mo <<
"\nc2Mo:\n" << c2Mo << std::endl;
815 if (opt_click_allowed && !quit) {
825 std::cout <<
"Catch an exception: " <<
e << std::endl;
830#elif !(defined(VISP_HAVE_MODULE_MBT) && defined(VISP_HAVE_DISPLAY))
833 std::cout <<
"Cannot run this example: visp_mbt, visp_gui modules are required." << std::endl;
839 std::cout <<
"Cannot run this example: install Lapack, Eigen3 or OpenCV" << std::endl;
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.
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)
Definition of the vpImage class member functions.
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
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.
@ 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)
read_data(CameraParameters|None cam_depth, ImageGray I, rs.pipeline pipe)
VISP_EXPORT double measureTimeMs()