Visual Servoing Platform version 3.6.0
Loading...
Searching...
No Matches
tutorial-mb-generic-tracker-full.cpp
1
2#include <visp3/core/vpIoTools.h>
3#include <visp3/gui/vpDisplayGDI.h>
4#include <visp3/gui/vpDisplayOpenCV.h>
5#include <visp3/gui/vpDisplayX.h>
6#include <visp3/gui/vpPlot.h>
8#include <visp3/mbt/vpMbGenericTracker.h>
10#include <visp3/io/vpVideoReader.h>
11#include <visp3/io/vpVideoWriter.h>
12
13int main(int argc, char **argv)
14{
15#if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_VIDEOIO) && defined(HAVE_OPENCV_HIGHGUI)
16 std::string opt_videoname = "model/teabox/teabox.mp4";
17 std::string opt_modelname = "model/teabox/teabox.cao";
18 int opt_tracker = 0;
19 int opt_video_first_frame = -1;
20 int opt_downscale_img = 1;
21 bool opt_verbose = false;
22 bool opt_plot = true;
23 bool opt_display_scale_auto = false;
24 vpColVector opt_dof_to_estimate(6, 1.); // Here we consider 6 dof estimation
25 std::string opt_save;
26 unsigned int thickness = 2;
27
29 vpDisplay *display = NULL;
30 vpPlot *plot = NULL;
31 vpVideoWriter *writer = NULL;
32
33 try {
34 for (int i = 0; i < argc; i++) {
35 if (std::string(argv[i]) == "--video") {
36 opt_videoname = std::string(argv[++i]);
37 }
38 else if (std::string(argv[i]) == "--video-first-frame") {
39 opt_video_first_frame = std::atoi(argv[++i]);
40 }
41 else if (std::string(argv[i]) == "--model") {
42 opt_modelname = std::string(argv[++i]);
43 }
44 else if (std::string(argv[i]) == "--tracker") {
45 opt_tracker = atoi(argv[++i]);
46 }
47 else if (std::string(argv[i]) == "--downscale-img") {
48 opt_downscale_img = std::atoi(argv[++i]);
49 }
50 else if (std::string(argv[i]) == "--save") {
51 opt_save = std::string(argv[++i]);
52 }
53 else if (std::string(argv[i]) == "--plot") {
54 opt_plot = true;
55 }
56 else if (std::string(argv[i]) == "--dof") {
57 for (int j = 0; j < 6; j++) {
58 int val = std::atoi(argv[++i]);
59 if (val == 0 || val == 1) {
60 opt_dof_to_estimate[j] = val;
61 }
62 else {
63 std::cout << "Error: wrong value after --dof option. Authorized values are 0 or 1 for each 6 dof to estimate." << std::endl;
64 return EXIT_FAILURE;
65 }
66 }
67 }
68 else if (std::string(argv[i]) == "--display-scale-auto") {
69 opt_display_scale_auto = true;
70 }
71 else if (std::string(argv[i]) == "--verbose" || std::string(argv[i]) == "-v") {
72 opt_verbose = true;
73 }
74 else if (std::string(argv[i]) == "--help" || std::string(argv[i]) == "-h") {
75 std::cout << "\nSYNOPSIS " << std::endl
76 << argv[0]
77 << " [--video <video name>]"
78 << " [--video-first-frame <image index>"
79 << " [--model <model name>"
80 << " [--tracker <0=egde|1=keypoint|2=hybrid>]"
81 << " [--downscale-img <scale factor>]"
82 << " [--dof <0/1 0/1 0/1 0/1 0/1 0/1>]"
83 << " [--save <video>]"
84 << " [--display-scale-auto]"
85 << " [--plot]"
86 << " [--verbose,-v]"
87 << " [--help,-h]"
88 << std::endl;
89 std::cout << "\nOPTIONS " << std::endl
90 << " --video <video name>" << std::endl
91 << " Input video name." << std::endl
92 << " Default: model/teabox/teabox.mp4" << std::endl
93 << std::endl
94 << " --video-first-frame <image index>" << std::endl
95 << " Index of the first image to process." << std::endl
96 << " Set to -1 to process the first image of the video." << std::endl
97 << " Default: -1" << std::endl
98 << std::endl
99 << " --model <model name>" << std::endl
100 << " CAD model filename. Supported formats are .cao and .wrl." << std::endl
101 << " To use wrl format, ViSP need to be built with Coin3D third-party." << std::endl
102 << " Default: model/teabox/teabox.cao" << std::endl
103 << std::endl
104 << " --tracker <0=egde|1=keypoint|2=hybrid>" << std::endl
105 << " Tracker type:" << std::endl
106 << " - when 0: use only moving-edges" << std::endl
107 << " - when 1: use only KLT keypoints" << std::endl
108 << " - when 2: use hybrid scheme, moving-edges and KLT keypoints." << std::endl
109 << " Default: 0" << std::endl
110 << std::endl
111 << " --downscale-img <scale factor>" << std::endl
112 << " Downscale input image width and height by this factor." << std::endl
113 << " When set to 1, image not down scaled. When set to 2, image width" << std::endl
114 << " and height is divided by 2." << std::endl
115 << " Default: 1" << std::endl
116 << std::endl
117 << " --dof <0/1 0/1 0/1 0/1 0/1 0/1>" << std::endl
118 << " 6-dim vector of 0 and 1 to indicate which dof [tx ty tz rx ry rz]" << std::endl
119 << " has to be estimated." << std::endl
120 << " When set to 1 the dof is estimated. When rather set to 0 the dof" << std::endl
121 << " is not estimated. It's value is the one from the initialisation." << std::endl
122 << " Default: 1 1 1 1 1 1 (to estimate all 6 dof)" << std::endl
123 << std::endl
124 << " --save <video>" << std::endl
125 << " Name of the saved image sequence that contains tracking results in overlay." << std::endl
126 << " When the name contains a folder like in the next example, the folder" << std::endl
127 << " is created if it doesn't exist."
128 << " Example: \"result/image-%04d.png\"." << std::endl
129 << std::endl
130 << " --display-scale-auto" << std::endl
131 << " Enable display window auto scaling to ensure that the image is fully" << std::endl
132 << " visible on the screen. Useful for large images." << std::endl
133 << " Note that this option doesn't affect the size of the processed images." << std::endl
134 << std::endl
135 << " --plot" << std::endl
136 << " Open a window that plots the estimated pose evolution." << std::endl
137 << std::endl
138 << " --verbose, -v" << std::endl
139 << " Enable verbose mode." << std::endl
140 << std::endl
141 << " --help, -h" << std::endl
142 << " Display this helper message." << std::endl
143 << std::endl;
144 return EXIT_SUCCESS;
145 }
146 }
147 std::string parentname = vpIoTools::getParent(opt_modelname);
148 std::string objectname = vpIoTools::getNameWE(opt_modelname);
149
150 if (!parentname.empty())
151 objectname = parentname + "/" + objectname;
152
153 std::cout << " *********** Tracker config ************ " << std::endl;
154 std::cout << "Video name : " << opt_videoname << std::endl;
155 std::cout << "Tracker cad model file : " << objectname << ".[cao or wrl]" << std::endl;
156 std::cout << "Tracker init file : " << objectname << ".init" << std::endl;
157 std::cout << "Tracker optional init image: " << objectname << ".[png,ppm,jpg]" << std::endl;
158 if (opt_downscale_img > 1) {
159 std::cout << "Downscale image factor : " << opt_downscale_img << std::endl;
160 }
161 std::cout << "Dof to estimate : " << opt_dof_to_estimate.t() << std::endl;
162
163 // Create output folder if needed
164 if (!opt_save.empty()) {
165 std::string parent = vpIoTools::getParent(opt_save);
166 if (!parent.empty()) {
167 std::cout << "Create output directory: " << parent << std::endl;
169 }
170 }
171
178
180 g.setFileName(opt_videoname);
181 if (opt_video_first_frame > 0) {
182 g.setFirstFrameIndex(static_cast<unsigned int>(opt_video_first_frame));
183 }
184 if (opt_downscale_img > 1) {
185 g.open(Ivideo);
186 Ivideo.subsample(opt_downscale_img, opt_downscale_img, I);
187 }
188 else {
189 g.open(I);
190 }
191
193 if (!opt_save.empty()) {
194 writer = new vpVideoWriter();
195 writer->setFileName(opt_save);
196 writer->open(O);
197 }
198
199#if defined(VISP_HAVE_X11)
200 display = new vpDisplayX;
201#elif defined(VISP_HAVE_GDI)
202 display = new vpDisplayGDI;
203#elif defined(HAVE_OPENCV_HIGHGUI)
204 display = new vpDisplayOpenCV;
205#endif
206 if (opt_display_scale_auto) {
207 display->setDownScalingFactor(vpDisplay::SCALE_AUTO);
208 }
209 display->init(I, 100, 100, "Model-based tracker");
210
211 if (opt_plot) {
212 plot = new vpPlot(2, 700, 700, display->getWindowXPosition() + I.getWidth() / display->getDownScalingFactor() + 30, display->getWindowYPosition(), "Estimated pose");
213 plot->initGraph(0, 3); // Translation
214 plot->setTitle(0, "Translation [m]");
215 plot->setColor(0, 0, vpColor::red);
216 plot->setColor(0, 1, vpColor::green);
217 plot->setColor(0, 2, vpColor::blue);
218 plot->initGraph(1, 3); // Attitude
219 plot->setTitle(1, "Attitude thetaU [deg]");
220 plot->setColor(1, 0, vpColor::red);
221 plot->setColor(1, 1, vpColor::green);
222 plot->setColor(1, 2, vpColor::blue);
223 }
224
226 vpMbGenericTracker tracker;
227 if (opt_tracker == 0)
229#if defined(VISP_HAVE_MODULE_KLT) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
230 else if (opt_tracker == 1)
232 else
234#else
235 else {
236 std::cout << "klt and hybrid model-based tracker are not available since visp_klt module is not available. "
237 "In CMakeGUI turn visp_klt module ON, configure and build ViSP again."
238 << std::endl;
239 return EXIT_FAILURE;
240 }
241#endif
243
244 bool usexml = false;
246 if (vpIoTools::checkFilename(objectname + ".xml")) {
247 std::cout << "Tracker config file : " << objectname + ".xml" << std::endl;
248 tracker.loadConfigFile(objectname + ".xml");
249 usexml = true;
250 }
252
253 if (!usexml) {
255 if (opt_tracker == 0 || opt_tracker == 2) {
257 vpMe me;
258 me.setMaskSize(5);
259 me.setMaskNumber(180);
260 me.setRange(8);
262 me.setThreshold(20);
263 me.setMu1(0.5);
264 me.setMu2(0.5);
265 me.setSampleStep(4);
266 tracker.setMovingEdge(me);
268 }
269
270#if defined(VISP_HAVE_MODULE_KLT) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
271 if (opt_tracker == 1 || opt_tracker == 2) {
273 vpKltOpencv klt_settings;
274 klt_settings.setMaxFeatures(300);
275 klt_settings.setWindowSize(5);
276 klt_settings.setQuality(0.015);
277 klt_settings.setMinDistance(8);
278 klt_settings.setHarrisFreeParameter(0.01);
279 klt_settings.setBlockSize(3);
280 klt_settings.setPyramidLevels(3);
281 tracker.setKltOpencv(klt_settings);
282 tracker.setKltMaskBorder(5);
284 }
285#endif
286
288 tracker.setAngleAppear(vpMath::rad(70));
289 tracker.setAngleDisappear(vpMath::rad(80));
292 tracker.setNearClippingDistance(0.1);
293 tracker.setFarClippingDistance(100.0);
298
301 cam.initPersProjWithoutDistortion(839.21470, 839.44555, 325.66776, 243.69727);
302 tracker.setCameraParameters(cam);
305 }
306
309 tracker.setOgreVisibilityTest(false);
310 tracker.setOgreShowConfigDialog(false);
313 tracker.setScanLineVisibilityTest(true);
316
318 if (vpIoTools::checkFilename(objectname + ".cao"))
319 tracker.loadModel(objectname + ".cao");
322 else if (vpIoTools::checkFilename(objectname + ".wrl"))
323 tracker.loadModel(objectname + ".wrl");
326 tracker.setDisplayFeatures(true);
328
330
331 if (opt_dof_to_estimate != 1.) {
332 tracker.setEstimatedDoF(opt_dof_to_estimate);
333 }
334
337 tracker.getCameraParameters(cam);
338 std::cout << "Camera parameters: \n" << cam << std::endl;
340
341 std::cout << "Initialize tracker on image size: " << I.getWidth() << " x " << I.getHeight() << std::endl;
342
344 tracker.initClick(I, objectname + ".init", true);
346
347 while (!g.end()) {
348 if (opt_downscale_img > 1) {
349 g.acquire(Ivideo);
350 Ivideo.subsample(opt_downscale_img, opt_downscale_img, I);
351 }
352 else {
353 g.acquire(I);
354 }
355 std::stringstream ss;
356 ss << "Process image " << g.getFrameIndex();
357 if (opt_verbose) {
358 std::cout << "-- " << ss.str() << std::endl;
359 }
362 tracker.track(I);
365 tracker.getPose(cMo);
368 tracker.display(I, cMo, cam, vpColor::red, thickness);
370 vpDisplay::displayFrame(I, cMo, cam, 0.025, vpColor::none, thickness);
371 vpDisplay::displayText(I, 20 * display->getDownScalingFactor(), 10 * display->getDownScalingFactor(), "A click to exit...", vpColor::red);
372 vpDisplay::displayText(I, 40 * display->getDownScalingFactor(), 10 * display->getDownScalingFactor(), ss.str(), vpColor::red);
373 {
374 std::stringstream ss;
375 ss << "Features";
377 ss << " edge: " << tracker.getNbFeaturesEdge();
378 }
379#if defined(VISP_HAVE_MODULE_KLT) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
381 ss << " klt: " << tracker.getNbFeaturesKlt();
382 }
383#endif
384 vpDisplay::displayText(I, 60 * display->getDownScalingFactor(), 10 * display->getDownScalingFactor(), ss.str(), vpColor::red);
385 if (opt_verbose) {
386 std::cout << ss.str() << std::endl;
387 std::cout << "cMo:\n" << cMo << std::endl;
388 }
389 }
390 {
391 double proj_error = tracker.computeCurrentProjectionError(I, cMo, cam);
392 std::stringstream ss;
393 ss << "Projection error: " << std::setprecision(2) << proj_error << " deg";
394 vpDisplay::displayText(I, 80 * display->getDownScalingFactor(), 10 * display->getDownScalingFactor(), ss.str(), vpColor::red);
395 if (opt_verbose) {
396 std::cout << ss.str() << std::endl;
397 }
398 }
400
401 if (opt_plot) {
404 vpColVector c_tu_o_deg = vpMath::deg(c_tu_o);
405 plot->plot(0, g.getFrameIndex(), c_t_o);
406 plot->plot(1, g.getFrameIndex(), c_tu_o_deg);
407 }
408
409 if (!opt_save.empty()) {
411 writer->saveFrame(O);
412 }
413
414 if (vpDisplay::getClick(I, false))
415 break;
416 }
418 }
419 catch (const vpException &e) {
420 std::cout << "Catch a ViSP exception: " << e << std::endl;
422 }
423#ifdef VISP_HAVE_OGRE
424 catch (Ogre::Exception &e) {
425 std::cout << "Catch an Ogre exception: " << e.getDescription() << std::endl;
427 }
428#endif
430 delete display;
431 if (opt_plot) {
432 delete plot;
433 }
434 if (writer) {
435 delete writer;
436 }
438#else
439 (void)argc;
440 (void)argv;
441 std::cout << "Install OpenCV and rebuild ViSP to use this example." << std::endl;
442#endif
443 return EXIT_SUCCESS;
444}
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 red
Definition vpColor.h:211
static const vpColor none
Definition vpColor.h:223
static const vpColor blue
Definition vpColor.h:217
static const vpColor green
Definition vpColor.h:214
Display for windows using GDI (available on any windows 32 platform).
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="")
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition vpDisplayX.h:132
Class that defines generic functionalities for display.
Definition vpDisplay.h:173
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
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 getImage(const vpImage< unsigned char > &Is, vpImage< vpRGBa > &Id)
static void flush(const vpImage< unsigned char > &I)
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.
Definition vpException.h:59
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpRotationMatrix getRotationMatrix() const
vpTranslationVector getTranslationVector() const
Definition of the vpImage class member functions.
Definition vpImage.h:135
void subsample(unsigned int v_scale, unsigned int h_scale, vpImage< Type > &sampled) const
Definition vpImage.h:1466
static bool checkFilename(const std::string &filename)
static void makeDirectory(const std::string &dirname)
static std::string getNameWE(const std::string &pathname)
static std::string getParent(const std::string &pathname)
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented in OpenCV. Thus to enable this ...
Definition vpKltOpencv.h:73
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)
Definition vpMath.h:116
static double deg(double rad)
Definition vpMath.h:106
Real-time 6D object pose tracking using its CAD model.
virtual void setCameraParameters(const vpCameraParameters &camera)
virtual void getPose(vpHomogeneousMatrix &cMo) const
virtual void setDisplayFeatures(bool displayF)
virtual int getTrackerType() const
virtual void setKltMaskBorder(const unsigned int &e)
virtual unsigned int getNbFeaturesEdge() const
virtual void setOgreShowConfigDialog(bool showConfigDialog)
virtual void setGoodMovingEdgesRatioThreshold(double threshold)
virtual void setAngleAppear(const double &a)
virtual void setNearClippingDistance(const double &dist)
virtual unsigned int getNbFeaturesKlt() const
virtual void getCameraParameters(vpCameraParameters &camera) const
virtual void setAngleDisappear(const double &a)
virtual void setMovingEdge(const vpMe &me)
virtual void setScanLineVisibilityTest(const bool &v)
virtual void setKltOpencv(const vpKltOpencv &t)
virtual void getClipping(unsigned int &clippingFlag1, unsigned int &clippingFlag2) const
virtual void setTrackerType(int type)
virtual void initClick(const vpImage< unsigned char > &I1, const vpImage< unsigned char > &I2, const std::string &initFile1, const std::string &initFile2, bool displayHelp=false, const vpHomogeneousMatrix &T1=vpHomogeneousMatrix(), const vpHomogeneousMatrix &T2=vpHomogeneousMatrix())
virtual void setFarClippingDistance(const double &dist)
virtual double computeCurrentProjectionError(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &_cMo, const vpCameraParameters &_cam)
virtual void setClipping(const unsigned int &flags)
virtual void loadConfigFile(const std::string &configFile, bool verbose=true)
virtual void setOgreVisibilityTest(const bool &v)
virtual void loadModel(const std::string &modelFile, bool verbose=false, const vpHomogeneousMatrix &T=vpHomogeneousMatrix())
virtual void display(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, const vpColor &col, unsigned int thickness=1, bool displayFullModel=false)
virtual void track(const vpImage< unsigned char > &I)
virtual void setEstimatedDoF(const vpColVector &v)
Definition vpMe.h:122
void setMu1(const double &mu_1)
Definition vpMe.h:353
void setSampleStep(const double &s)
Definition vpMe.h:390
void setRange(const unsigned int &r)
Definition vpMe.h:383
void setLikelihoodThresholdType(const vpLikelihoodThresholdType likelihood_threshold_type)
Definition vpMe.h:445
void setMaskSize(const unsigned int &a)
Definition vpMe.cpp:452
void setMu2(const double &mu_2)
Definition vpMe.h:360
@ NORMALIZED_THRESHOLD
Easy-to-use normalized likelihood threshold corresponding to the minimal luminance contrast to consid...
Definition vpMe.h:132
void setMaskNumber(const unsigned int &a)
Definition vpMe.cpp:445
void setThreshold(const double &t)
Definition vpMe.h:435
This class enables real time drawing of 2D or 3D graphics. An instance of the class open a window whi...
Definition vpPlot.h:113
void initGraph(unsigned int graphNum, unsigned int curveNbr)
Definition vpPlot.cpp:202
void plot(unsigned int graphNum, unsigned int curveNum, double x, double y)
Definition vpPlot.cpp:269
void setColor(unsigned int graphNum, unsigned int curveNum, vpColor color)
Definition vpPlot.cpp:245
void setTitle(unsigned int graphNum, const std::string &title)
Definition vpPlot.cpp:503
Implementation of a rotation vector as axis-angle minimal representation.
Class that consider the case of a translation vector.
Class that enables to manipulate easily a video file or a sequence of images. As it inherits from the...
void acquire(vpImage< vpRGBa > &I)
void open(vpImage< vpRGBa > &I)
void setFileName(const std::string &filename)
void setFirstFrameIndex(const long first_frame)
long getFrameIndex() const
Class that enables to write easily a video file or a sequence of images.
void saveFrame(vpImage< vpRGBa > &I)
void setFileName(const std::string &filename)
void open(vpImage< vpRGBa > &I)