Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpMbKltTracker.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Model based tracker using only KLT
32 */
33
34#include <visp3/core/vpImageConvert.h>
35#include <visp3/core/vpDebug.h>
36#include <visp3/core/vpTrackingException.h>
37#include <visp3/core/vpVelocityTwistMatrix.h>
38#include <visp3/mbt/vpMbKltTracker.h>
39#include <visp3/mbt/vpMbtXmlGenericParser.h>
40
41#if defined(VISP_HAVE_MODULE_KLT) && defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
42
43#if defined(__APPLE__) && defined(__MACH__) // Apple OSX and iOS (Darwin)
44#include <TargetConditionals.h> // To detect OSX or IOS using TARGET_OS_IPHONE or TARGET_OS_IOS macro
45#endif
46
48
49#ifndef DOXYGEN_SHOULD_SKIP_THIS
50namespace
51{
71vpMatrix homography2collineation(const vpMatrix &H, const vpCameraParameters &cam)
72{
73 vpMatrix G(3, 3);
74 double px = cam.get_px();
75 double py = cam.get_py();
76 double u0 = cam.get_u0();
77 double v0 = cam.get_v0();
78 double one_over_px = cam.get_px_inverse();
79 double one_over_py = cam.get_py_inverse();
80 double h00 = H[0][0], h01 = H[0][1], h02 = H[0][2];
81 double h10 = H[1][0], h11 = H[1][1], h12 = H[1][2];
82 double h20 = H[2][0], h21 = H[2][1], h22 = H[2][2];
83
84 double A = h00 * px + u0 * h20;
85 double B = h01 * px + u0 * h21;
86 double C = h02 * px + u0 * h22;
87 double D = h10 * py + v0 * h20;
88 double E = h11 * py + v0 * h21;
89 double F = h12 * py + v0 * h22;
90
91 G[0][0] = A * one_over_px;
92 G[1][0] = D * one_over_px;
93 G[2][0] = h20 * one_over_px;
94
95 G[0][1] = B * one_over_py;
96 G[1][1] = E * one_over_py;
97 G[2][1] = h21 * one_over_py;
98
99 double u0_one_over_px = u0 * one_over_px;
100 double v0_one_over_py = v0 * one_over_py;
101
102 G[0][2] = -A * u0_one_over_px - B * v0_one_over_py + C;
103 G[1][2] = -D * u0_one_over_px - E * v0_one_over_py + F;
104 G[2][2] = -h20 * u0_one_over_px - h21 * v0_one_over_py + h22;
105
106 return G;
107}
108} // namespace
109
110#endif // DOXYGEN_SHOULD_SKIP_THIS
111
113 :
117{
118 tracker.setTrackerId(1);
119 tracker.setUseHarris(1);
120 tracker.setMaxFeatures(10000);
121 tracker.setWindowSize(5);
122 tracker.setQuality(0.01);
123 tracker.setMinDistance(5);
124 tracker.setHarrisFreeParameter(0.01);
125 tracker.setBlockSize(3);
126 tracker.setPyramidLevels(3);
127
128#ifdef VISP_HAVE_OGRE
129 faces.getOgreContext()->setWindowName("MBT Klt");
130#endif
131
132 m_lambda = 0.8;
133 m_maxIter = 200;
134}
135
141{
142 // delete the Klt Polygon features
143 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
144 vpMbtDistanceKltPoints *kltpoly = *it;
145 if (kltpoly != nullptr) {
146 delete kltpoly;
147 }
148 kltpoly = nullptr;
149 }
150 kltPolygons.clear();
151
152 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
153 ++it) {
154 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
155 if (kltPolyCylinder != nullptr) {
156 delete kltPolyCylinder;
157 }
158 kltPolyCylinder = nullptr;
159 }
160 kltCylinders.clear();
161
162 // delete the structures used to display circles
163 for (std::list<vpMbtDistanceCircle *>::const_iterator it = circles_disp.begin(); it != circles_disp.end(); ++it) {
164 vpMbtDistanceCircle *ci = *it;
165 if (ci != nullptr) {
166 delete ci;
167 }
168 ci = nullptr;
169 }
170
171 circles_disp.clear();
172}
173
175{
176 if (!modelInitialised) {
177 throw vpException(vpException::fatalError, "model not initialized");
178 }
179
180 bool reInitialisation = false;
181 if (!useOgre)
182 faces.setVisible(I.getWidth(), I.getHeight(), m_cam, m_cMo, angleAppears, angleDisappears, reInitialisation);
183 else {
184#ifdef VISP_HAVE_OGRE
185 if (!faces.isOgreInitialised()) {
186 faces.setBackgroundSizeOgre(I.getHeight(), I.getWidth());
187 faces.setOgreShowConfigDialog(ogreShowConfigDialog);
188 faces.initOgre(m_cam);
189 // Turn off Ogre config dialog display for the next call to this
190 // function since settings are saved in the ogre.cfg file and used
191 // during the next call
192 ogreShowConfigDialog = false;
193 }
194
195 faces.setVisibleOgre(I.getWidth(), I.getHeight(), m_cam, m_cMo, angleAppears, angleDisappears, reInitialisation);
196
197#else
198 faces.setVisible(I.getWidth(), I.getHeight(), m_cam, m_cMo, angleAppears, angleDisappears, reInitialisation);
199#endif
200 }
201 reinit(I);
202}
203
205{
206 c0Mo = m_cMo;
207 ctTc0.eye();
208
210
211 m_cam.computeFov(I.getWidth(), I.getHeight());
212
213 if (useScanLine) {
214 faces.computeClippedPolygons(m_cMo, m_cam);
215 faces.computeScanLineRender(m_cam, I.getWidth(), I.getHeight());
216 }
217
218 // mask
219 cv::Mat mask(static_cast<int>(I.getRows()), static_cast<int>(I.getCols()), CV_8UC1, cv::Scalar(0));
220
221 vpMbtDistanceKltPoints *kltpoly;
222 vpMbtDistanceKltCylinder *kltPolyCylinder;
223 if (useScanLine) {
224 vpImageConvert::convert(faces.getMbScanLineRenderer().getMask(), mask);
225 }
226 else {
227 unsigned char val = 255 /* - i*15*/;
228 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
229 kltpoly = *it;
230 if (kltpoly->polygon->isVisible() && kltpoly->isTracked() && kltpoly->polygon->getNbPoint() > 2) {
231 // need to changeFrame when reinit() is called by postTracking
232 // other solution is
233 kltpoly->polygon->changeFrame(m_cMo);
234 kltpoly->polygon->computePolygonClipped(m_cam); // Might not be necessary when scanline is activated
235 kltpoly->updateMask(mask, val, maskBorder);
236 }
237 }
238
239 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
240 ++it) {
241 kltPolyCylinder = *it;
242
243 if (kltPolyCylinder->isTracked()) {
244 for (unsigned int k = 0; k < kltPolyCylinder->listIndicesCylinderBBox.size(); k++) {
245 unsigned int indCylBBox = static_cast<unsigned int>(kltPolyCylinder->listIndicesCylinderBBox[k]);
246 if (faces[indCylBBox]->isVisible() && faces[indCylBBox]->getNbPoint() > 2u) {
247 faces[indCylBBox]->computePolygonClipped(m_cam); // Might not be necessary when scanline is activated
248 }
249 }
250
251 kltPolyCylinder->updateMask(mask, val, maskBorder);
252 }
253 }
254 }
255
256 tracker.initTracking(cur, mask);
257 // tracker.track(cur); // AY: Not sure to be usefull but makes sure that
258 // the points are valid for tracking and avoid too fast reinitialisations.
259 // vpCTRACE << "init klt. detected " << tracker.getNbFeatures() << "
260 // points" << std::endl;
261
262 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
263 kltpoly = *it;
264 if (kltpoly->polygon->isVisible() && kltpoly->isTracked() && kltpoly->polygon->getNbPoint() > 2) {
265 kltpoly->init(tracker, m_mask);
266 }
267 }
268
269 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
270 ++it) {
271 kltPolyCylinder = *it;
272
273 if (kltPolyCylinder->isTracked())
274 kltPolyCylinder->init(tracker, m_cMo);
275 }
276}
277
283{
284 m_cMo.eye();
285
286 // delete the Klt Polygon features
287 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
288 vpMbtDistanceKltPoints *kltpoly = *it;
289 if (kltpoly != nullptr) {
290 delete kltpoly;
291 }
292 kltpoly = nullptr;
293 }
294 kltPolygons.clear();
295
296 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
297 ++it) {
298 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
299 if (kltPolyCylinder != nullptr) {
300 delete kltPolyCylinder;
301 }
302 kltPolyCylinder = nullptr;
303 }
304 kltCylinders.clear();
305
306 // delete the structures used to display circles
307 for (std::list<vpMbtDistanceCircle *>::const_iterator it = circles_disp.begin(); it != circles_disp.end(); ++it) {
308 vpMbtDistanceCircle *ci = *it;
309 if (ci != nullptr) {
310 delete ci;
311 }
312 ci = nullptr;
313 }
314
315 circles_disp.clear();
316
318 firstInitialisation = true;
319 computeCovariance = false;
320
321 tracker.setTrackerId(1);
322 tracker.setUseHarris(1);
323
324 tracker.setMaxFeatures(10000);
325 tracker.setWindowSize(5);
326 tracker.setQuality(0.01);
327 tracker.setMinDistance(5);
328 tracker.setHarrisFreeParameter(0.01);
329 tracker.setBlockSize(3);
330 tracker.setPyramidLevels(3);
331
334
336
337 maskBorder = 5;
338 threshold_outlier = 0.5;
339 percentGood = 0.6;
340
341 m_lambda = 0.8;
342 m_maxIter = 200;
343
344 faces.reset();
345
347
348 useScanLine = false;
349
350#ifdef VISP_HAVE_OGRE
351 useOgre = false;
352#endif
353}
354
363std::vector<vpImagePoint> vpMbKltTracker::getKltImagePoints() const
364{
365 std::vector<vpImagePoint> kltPoints;
366 for (unsigned int i = 0; i < static_cast<unsigned int>(tracker.getNbFeatures()); i++) {
367 long id;
368 float x_tmp, y_tmp;
369 tracker.getFeature(static_cast<int>(i), id, x_tmp, y_tmp);
370 kltPoints.push_back(vpImagePoint(y_tmp, x_tmp));
371 }
372
373 return kltPoints;
374}
375
384std::map<int, vpImagePoint> vpMbKltTracker::getKltImagePointsWithId() const
385{
386 std::map<int, vpImagePoint> kltPoints;
387 for (unsigned int i = 0; i < static_cast<unsigned int>(tracker.getNbFeatures()); i++) {
388 long id;
389 float x_tmp, y_tmp;
390 tracker.getFeature(static_cast<int>(i), id, x_tmp, y_tmp);
391#ifdef TARGET_OS_IPHONE
392 kltPoints[static_cast<int>(id)] = vpImagePoint(y_tmp, x_tmp);
393#else
394 kltPoints[id] = vpImagePoint(y_tmp, x_tmp);
395#endif
396 }
397
398 return kltPoints;
399}
400
407{
408 tracker.setMaxFeatures(t.getMaxFeatures());
409 tracker.setWindowSize(t.getWindowSize());
410 tracker.setQuality(t.getQuality());
411 tracker.setMinDistance(t.getMinDistance());
412 tracker.setHarrisFreeParameter(t.getHarrisFreeParameter());
413 tracker.setBlockSize(t.getBlockSize());
414 tracker.setPyramidLevels(t.getPyramidLevels());
415}
416
423{
424 // for (unsigned int i = 0; i < faces.size(); i += 1){
425 // faces[i]->setCameraParameters(camera);
426 // }
427
428 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
429 vpMbtDistanceKltPoints *kltpoly = *it;
430 kltpoly->setCameraParameters(cam);
431 }
432
433 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
434 ++it) {
435 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
436 kltPolyCylinder->setCameraParameters(cam);
437 }
438
439 m_cam = cam;
440}
441
442void vpMbKltTracker::setPose(const vpImage<unsigned char> *const I, const vpImage<vpRGBa> *const I_color,
443 const vpHomogeneousMatrix &cdMo)
444{
445 if (I_color) {
446 vpImageConvert::convert(*I_color, m_I);
447 }
448
449 if (!kltCylinders.empty()) {
450 std::cout << "WARNING: Cannot set pose when model contains cylinder(s). "
451 "This feature is not implemented yet."
452 << std::endl;
453 std::cout << "Tracker will be reinitialized with the given pose." << std::endl;
454 m_cMo = cdMo;
455 if (I) {
456 init(*I);
457 }
458 else {
459 init(m_I);
460 }
461 }
462 else {
463 vpMbtDistanceKltPoints *kltpoly;
464
465 std::vector<cv::Point2f> init_pts;
466 std::vector<long> init_ids;
467 std::vector<cv::Point2f> guess_pts;
468
469 vpHomogeneousMatrix cdMc = cdMo * m_cMo.inverse();
470 vpHomogeneousMatrix cMcd = cdMc.inverse();
471
472 vpRotationMatrix cdRc;
474
475 cdMc.extract(cdRc);
476 cdMc.extract(cdtc);
477
478 // unsigned int nbCur = 0;
479
480 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
481 kltpoly = *it;
482
483 if (kltpoly->polygon->isVisible() && kltpoly->polygon->getNbPoint() > 2) {
484 kltpoly->polygon->changeFrame(cdMo);
485
486 // Get the normal to the face at the current state cMo
487 vpPlane plan(kltpoly->polygon->p[0], kltpoly->polygon->p[1], kltpoly->polygon->p[2]);
488 plan.changeFrame(cMcd);
489
490 vpColVector Nc = plan.getNormal();
491 Nc.normalize();
492
493 double invDc = 1.0 / plan.getD();
494
495 // Create the homography
496 vpMatrix cdHc;
497 vpGEMM(cdtc, Nc, -invDc, cdRc, 1.0, cdHc, VP_GEMM_B_T);
498 cdHc /= cdHc[2][2];
499
500 // Compute homography in the pixel space cdGc = K * cdHc * K^{-1}
501 vpMatrix cdGc = homography2collineation(cdHc, m_cam);
502
503 // Points displacement
504 std::map<int, vpImagePoint>::const_iterator iter = kltpoly->getCurrentPoints().begin();
505 // nbCur+= (unsigned int)kltpoly->getCurrentPoints().size();
506 for (; iter != kltpoly->getCurrentPoints().end(); ++iter) {
507#ifdef TARGET_OS_IPHONE
508 if (std::find(init_ids.begin(), init_ids.end(), (long)(kltpoly->getCurrentPointsInd())[static_cast<int>(iter->first)]) !=
509 init_ids.end())
510#else
511 if (std::find(init_ids.begin(), init_ids.end(),
512 (long)(kltpoly->getCurrentPointsInd())[static_cast<size_t>(iter->first)]) != init_ids.end())
513#endif
514 {
515 // KLT point already processed (a KLT point can exist in another
516 // vpMbtDistanceKltPoints due to possible overlapping faces)
517 continue;
518 }
519
520 vpColVector cdp(3);
521 cdp[0] = iter->second.get_j();
522 cdp[1] = iter->second.get_i();
523 cdp[2] = 1.0;
524
525 cv::Point2f p(static_cast<float>(cdp[0]), static_cast<float>(cdp[1]));
526 init_pts.push_back(p);
527#ifdef TARGET_OS_IPHONE
528 init_ids.push_back(static_cast<size_t>(kltpoly->getCurrentPointsInd()[static_cast<int>(iter->first)]));
529#else
530 init_ids.push_back(static_cast<size_t>(kltpoly->getCurrentPointsInd()[static_cast<size_t>(iter->first)]));
531#endif
532
533 double p_mu_t_2 = cdp[0] * cdGc[2][0] + cdp[1] * cdGc[2][1] + cdGc[2][2];
534
535 if (fabs(p_mu_t_2) < std::numeric_limits<double>::epsilon()) {
536 cdp[0] = 0.0;
537 cdp[1] = 0.0;
538 throw vpException(vpException::divideByZeroError, "the depth of the point is calculated to zero");
539 }
540
541 cdp[0] = (cdp[0] * cdGc[0][0] + cdp[1] * cdGc[0][1] + cdGc[0][2]) / p_mu_t_2;
542 cdp[1] = (cdp[0] * cdGc[1][0] + cdp[1] * cdGc[1][1] + cdGc[1][2]) / p_mu_t_2;
543
544 // Set value to the KLT tracker
545 cv::Point2f p_guess(static_cast<float>(cdp[0]), static_cast<float>(cdp[1]));
546 guess_pts.push_back(p_guess);
547 }
548 }
549 }
550
551 if (I) {
553 }
554 else {
556 }
557
558 tracker.setInitialGuess(init_pts, guess_pts, init_ids);
559
560 bool reInitialisation = false;
561 if (!useOgre) {
562 if (I) {
563 faces.setVisible(I->getWidth(), I->getHeight(), m_cam, cdMo, angleAppears, angleDisappears, reInitialisation);
564 }
565 else {
566 faces.setVisible(m_I.getWidth(), m_I.getHeight(), m_cam, cdMo, angleAppears, angleDisappears, reInitialisation);
567 }
568 }
569 else {
570#ifdef VISP_HAVE_OGRE
571 if (I) {
572 faces.setVisibleOgre(I->getWidth(), I->getHeight(), m_cam, cdMo, angleAppears, angleDisappears,
573 reInitialisation);
574 }
575 else {
576 faces.setVisibleOgre(m_I.getWidth(), m_I.getHeight(), m_cam, cdMo, angleAppears, angleDisappears,
577 reInitialisation);
578 }
579#else
580 if (I) {
581 faces.setVisible(I->getWidth(), I->getHeight(), m_cam, cdMo, angleAppears, angleDisappears, reInitialisation);
582 }
583 else {
584 faces.setVisible(m_I.getWidth(), m_I.getHeight(), m_cam, cdMo, angleAppears, angleDisappears, reInitialisation);
585 }
586#endif
587 }
588
589 m_cam.computeFov(I ? I->getWidth() : m_I.getWidth(), I ? I->getHeight() : m_I.getHeight());
590
591 if (useScanLine) {
592 faces.computeClippedPolygons(cdMo, m_cam);
593 faces.computeScanLineRender(m_cam, I ? I->getWidth() : m_I.getWidth(), I ? I->getHeight() : m_I.getHeight());
594 }
595
596 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
597 kltpoly = *it;
598 if (kltpoly->polygon->isVisible() && kltpoly->polygon->getNbPoint() > 2) {
600 kltpoly->init(tracker, m_mask);
601 }
602 }
603
604 m_cMo = cdMo;
605 c0Mo = m_cMo;
606 ctTc0.eye();
607 }
608}
609
620{
621 vpMbKltTracker::setPose(&I, nullptr, cdMo);
622}
623
634{
635 vpMbKltTracker::setPose(nullptr, &I_color, cdMo);
636}
637
645{
647 kltPoly->setCameraParameters(m_cam);
648 kltPoly->polygon = &polygon;
649 kltPoly->hiddenface = &faces;
650 kltPoly->useScanLine = useScanLine;
651 kltPolygons.push_back(kltPoly);
652}
653
660{
662 kltPoly->setCameraParameters(m_cam);
663 kltPoly->polygon = &polygon;
664 kltPoly->hiddenface = &faces;
665 kltPoly->useScanLine = useScanLine;
666 kltPolygons.push_back(kltPoly);
667}
668
676{
678 tracker.track(cur);
679
680 m_nbInfos = 0;
681 m_nbFaceUsed = 0;
682 // for (unsigned int i = 0; i < faces.size(); i += 1){
683 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
684 vpMbtDistanceKltPoints *kltpoly = *it;
685 if (kltpoly->polygon->isVisible() && kltpoly->isTracked() && kltpoly->polygon->getNbPoint() > 2) {
687 // faces[i]->ransac();
688 if (kltpoly->hasEnoughPoints()) {
689 m_nbInfos += kltpoly->getCurrentNumberPoints();
690 m_nbFaceUsed++;
691 }
692 }
693 }
694
695 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
696 ++it) {
697 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
698
699 if (kltPolyCylinder->isTracked()) {
700 kltPolyCylinder->computeNbDetectedCurrent(tracker);
701 if (kltPolyCylinder->hasEnoughPoints()) {
702 m_nbInfos += kltPolyCylinder->getCurrentNumberPoints();
703 m_nbFaceUsed++;
704 }
705 }
706 }
707}
708
713{
714 // # For a better Post Tracking, tracker should reinitialize if so faces
715 // don't have enough points but are visible. # Here we are not doing it for
716 // more speed performance.
717 bool reInitialisation = false;
718
719 unsigned int initialNumber = 0;
720 unsigned int currentNumber = 0;
721 unsigned int shift = 0;
722 // for (unsigned int i = 0; i < faces.size(); i += 1){
723 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
724 vpMbtDistanceKltPoints *kltpoly = *it;
725 if (kltpoly->polygon->isVisible() && kltpoly->isTracked() && kltpoly->polygon->getNbPoint() > 2) {
726 initialNumber += kltpoly->getInitialNumberPoint();
727 if (kltpoly->hasEnoughPoints()) {
728 vpSubColVector sub_w(w, shift, 2 * kltpoly->getCurrentNumberPoints());
729 shift += 2 * kltpoly->getCurrentNumberPoints();
730 kltpoly->removeOutliers(sub_w, threshold_outlier);
731
732 currentNumber += kltpoly->getCurrentNumberPoints();
733 }
734 // else{
735 // reInitialisation = true;
736 // break;
737 // }
738 }
739 }
740
741 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
742 ++it) {
743 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
744
745 if (kltPolyCylinder->isTracked()) {
746 initialNumber += kltPolyCylinder->getInitialNumberPoint();
747 if (kltPolyCylinder->hasEnoughPoints()) {
748 vpSubColVector sub_w(w, shift, 2 * kltPolyCylinder->getCurrentNumberPoints());
749 shift += 2 * kltPolyCylinder->getCurrentNumberPoints();
750 kltPolyCylinder->removeOutliers(sub_w, threshold_outlier);
751
752 currentNumber += kltPolyCylinder->getCurrentNumberPoints();
753 }
754 }
755 }
756
757 // if(!reInitialisation){
758 double value = percentGood * static_cast<double>(initialNumber);
759 if (static_cast<double>(currentNumber) < value) {
760 // std::cout << "Too many point disappear : " << initialNumber << "/"
761 // << currentNumber << std::endl;
762 reInitialisation = true;
763 }
764 else {
765 if (!useOgre)
766 faces.setVisible(I.getWidth(), I.getHeight(), m_cam, m_cMo, angleAppears, angleDisappears, reInitialisation);
767 else {
768#ifdef VISP_HAVE_OGRE
769 faces.setVisibleOgre(I.getWidth(), I.getHeight(), m_cam, m_cMo, angleAppears, angleDisappears, reInitialisation);
770#else
771 faces.setVisible(I.getWidth(), I.getHeight(), m_cam, m_cMo, angleAppears, angleDisappears, reInitialisation);
772#endif
773 }
774 }
775 // }
776
777 if (reInitialisation)
778 return true;
779
780 return false;
781}
782
787{
788 vpMatrix L_true; // interaction matrix without weighting
789 vpMatrix LVJ_true;
790 vpColVector v; // "speed" for VVS
791
792 vpMatrix LTL;
793 vpColVector LTR;
794 vpHomogeneousMatrix cMoPrev;
795 vpHomogeneousMatrix ctTc0_Prev;
796 vpColVector error_prev;
797 double mu = m_initialMu;
798
799 double normRes = 0;
800 double normRes_1 = -1;
801 unsigned int iter = 0;
802
803 bool isoJoIdentity = m_isoJoIdentity; // Backup since it can be modified if L is not full rank
804 if (isoJoIdentity)
805 oJo.eye();
806
808
809 while ((static_cast<int>((normRes - normRes_1) * 1e8) != 0) && (iter < m_maxIter)) {
811
812 bool reStartFromLastIncrement = false;
813 computeVVSCheckLevenbergMarquardt(iter, m_error_klt, error_prev, cMoPrev, mu, reStartFromLastIncrement);
814 if (reStartFromLastIncrement) {
815 ctTc0 = ctTc0_Prev;
816 }
817
818 if (!reStartFromLastIncrement) {
820
821 if (computeCovariance) {
822 L_true = m_L_klt;
823 if (!isoJoIdentity) {
825 cVo.buildFrom(m_cMo);
826 LVJ_true = (m_L_klt * cVo * oJo);
827 }
828 }
829
830 normRes_1 = normRes;
831 normRes = 0.0;
832
833 for (unsigned int i = 0; i < m_error_klt.getRows(); i++) {
835 normRes += m_weightedError_klt[i];
836 }
837
838 if ((iter == 0) || m_computeInteraction) {
839 for (unsigned int i = 0; i < m_error_klt.getRows(); i++) {
840 for (unsigned int j = 0; j < 6; j++) {
841 m_L_klt[i][j] *= m_w_klt[i];
842 }
843 }
844 }
845
847
848 cMoPrev = m_cMo;
849 ctTc0_Prev = ctTc0;
851 m_cMo = ctTc0 * c0Mo;
852 } // endif(!reStartFromLastIncrement)
853
854 iter++;
855 }
856
858}
859
861{
862 unsigned int nbFeatures = 2 * m_nbInfos;
863
864 m_L_klt.resize(nbFeatures, 6, false, false);
865 m_error_klt.resize(nbFeatures, false);
866
867 m_weightedError_klt.resize(nbFeatures, false);
868 m_w_klt.resize(nbFeatures, false);
869 m_w_klt = 1;
870
871 m_robust_klt.setMinMedianAbsoluteDeviation(2 / m_cam.get_px());
872}
873
875{
876 unsigned int shift = 0;
877 vpHomography H;
878
879 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
880 vpMbtDistanceKltPoints *kltpoly = *it;
881 if (kltpoly->polygon->isVisible() && kltpoly->isTracked() && kltpoly->polygon->getNbPoint() > 2 &&
882 kltpoly->hasEnoughPoints()) {
883 vpSubColVector subR(m_error_klt, shift, 2 * kltpoly->getCurrentNumberPoints());
884 vpSubMatrix subL(m_L_klt, shift, 0, 2 * kltpoly->getCurrentNumberPoints(), 6);
885
886 try {
887 kltpoly->computeHomography(ctTc0, H);
888 kltpoly->computeInteractionMatrixAndResidu(subR, subL);
889 }
890 catch (...) {
891 throw vpTrackingException(vpTrackingException::fatalError, "Cannot compute interaction matrix");
892 }
893
894 shift += 2 * kltpoly->getCurrentNumberPoints();
895 }
896 }
897
898 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
899 ++it) {
900 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
901
902 if (kltPolyCylinder->isTracked() && kltPolyCylinder->hasEnoughPoints()) {
903 vpSubColVector subR(m_error_klt, shift, 2 * kltPolyCylinder->getCurrentNumberPoints());
904 vpSubMatrix subL(m_L_klt, shift, 0, 2 * kltPolyCylinder->getCurrentNumberPoints(), 6);
905
906 try {
907 kltPolyCylinder->computeInteractionMatrixAndResidu(ctTc0, subR, subL);
908 }
909 catch (...) {
910 throw vpTrackingException(vpTrackingException::fatalError, "Cannot compute interaction matrix");
911 }
912
913 shift += 2 * kltPolyCylinder->getCurrentNumberPoints();
914 }
915 }
916}
917
926{
927 preTracking(I);
928
929 if (m_nbInfos < 4 || m_nbFaceUsed == 0) {
930 throw vpTrackingException(vpTrackingException::notEnoughPointError, "Error: not enough features");
931 }
932
933 computeVVS();
934
935 if (postTracking(I, m_w_klt))
936 reinit(I);
937
938 if (displayFeatures) {
940 }
941}
942
951{
954
955 if (m_nbInfos < 4 || m_nbFaceUsed == 0) {
956 throw vpTrackingException(vpTrackingException::notEnoughPointError, "Error: not enough features");
957 }
958
959 computeVVS();
960
962 reinit(m_I);
963}
964
1008void vpMbKltTracker::loadConfigFile(const std::string &configFile, bool verbose)
1009{
1010#if defined(VISP_HAVE_PUGIXML)
1011// Load projection error config
1012 vpMbTracker::loadConfigFile(configFile, verbose);
1013
1015 xmlp.setVerbose(verbose);
1016 xmlp.setKltMaxFeatures(10000);
1017 xmlp.setKltWindowSize(5);
1018 xmlp.setKltQuality(0.01);
1019 xmlp.setKltMinDistance(5);
1020 xmlp.setKltHarrisParam(0.01);
1021 xmlp.setKltBlockSize(3);
1022 xmlp.setKltPyramidLevels(3);
1026
1027 try {
1028 if (verbose) {
1029 std::cout << " *********** Parsing XML for MBT KLT Tracker ************ " << std::endl;
1030 }
1031 xmlp.parse(configFile.c_str());
1032 }
1033 catch (...) {
1034 vpERROR_TRACE("Can't open XML file \"%s\"\n ", configFile.c_str());
1035 throw vpException(vpException::ioError, "problem to parse configuration file.");
1036 }
1037
1038 vpCameraParameters camera;
1039 xmlp.getCameraParameters(camera);
1040 setCameraParameters(camera);
1041
1042 tracker.setMaxFeatures(static_cast<int>(xmlp.getKltMaxFeatures()));
1043 tracker.setWindowSize(static_cast<int>(xmlp.getKltWindowSize()));
1044 tracker.setQuality(xmlp.getKltQuality());
1045 tracker.setMinDistance(xmlp.getKltMinDistance());
1046 tracker.setHarrisFreeParameter(xmlp.getKltHarrisParam());
1047 tracker.setBlockSize(static_cast<int>(xmlp.getKltBlockSize()));
1048 tracker.setPyramidLevels(static_cast<int>(xmlp.getKltPyramidLevels()));
1052
1053 // if(useScanLine)
1054 faces.getMbScanLineRenderer().setMaskBorder(maskBorder);
1055
1056 if (xmlp.hasNearClippingDistance())
1058
1059 if (xmlp.hasFarClippingDistance())
1061
1062 if (xmlp.getFovClipping())
1064
1065 useLodGeneral = xmlp.getLodState();
1068
1070 if (this->getNbPolygon() > 0) {
1075 }
1076#else
1077 (void)configFile;
1078 (void)verbose;
1079 throw(vpException(vpException::ioError, "vpMbKltTracker::loadConfigFile() needs pugixml built-in 3rdparty"));
1080#endif
1081}
1082
1095 const vpCameraParameters &cam, const vpColor &col, unsigned int thickness,
1096 bool displayFullModel)
1097{
1098 std::vector<std::vector<double> > models =
1099 vpMbKltTracker::getModelForDisplay(I.getWidth(), I.getHeight(), cMo, cam, displayFullModel);
1100
1101 for (size_t i = 0; i < models.size(); i++) {
1102 if (vpMath::equal(models[i][0], 0)) {
1103 vpImagePoint ip1(models[i][1], models[i][2]);
1104 vpImagePoint ip2(models[i][3], models[i][4]);
1105 vpDisplay::displayLine(I, ip1, ip2, col, thickness);
1106 }
1107 else if (vpMath::equal(models[i][0], 1)) {
1108 vpImagePoint center(models[i][1], models[i][2]);
1109 double n20 = models[i][3];
1110 double n11 = models[i][4];
1111 double n02 = models[i][5];
1112 vpDisplay::displayEllipse(I, center, n20, n11, n02, true, col, thickness);
1113 }
1114 }
1115
1116 if (displayFeatures) {
1117 for (size_t i = 0; i < m_featuresToBeDisplayedKlt.size(); i++) {
1121
1123 double id = m_featuresToBeDisplayedKlt[i][5];
1124 std::stringstream ss;
1125 ss << id;
1126 vpDisplay::displayText(I, ip2, ss.str(), vpColor::red);
1127 }
1128 }
1129 }
1130
1131#ifdef VISP_HAVE_OGRE
1132 if (useOgre)
1133 faces.displayOgre(cMo);
1134#endif
1135}
1136
1149 const vpColor &col, unsigned int thickness, bool displayFullModel)
1150{
1151 std::vector<std::vector<double> > models =
1152 vpMbKltTracker::getModelForDisplay(I.getWidth(), I.getHeight(), cMo, cam, displayFullModel);
1153
1154 for (size_t i = 0; i < models.size(); i++) {
1155 if (vpMath::equal(models[i][0], 0)) {
1156 vpImagePoint ip1(models[i][1], models[i][2]);
1157 vpImagePoint ip2(models[i][3], models[i][4]);
1158 vpDisplay::displayLine(I, ip1, ip2, col, thickness);
1159 }
1160 else if (vpMath::equal(models[i][0], 1)) {
1161 vpImagePoint center(models[i][1], models[i][2]);
1162 double n20 = models[i][3];
1163 double n11 = models[i][4];
1164 double n02 = models[i][5];
1165 vpDisplay::displayEllipse(I, center, n20, n11, n02, true, col, thickness);
1166 }
1167 }
1168
1169 if (displayFeatures) {
1170 for (size_t i = 0; i < m_featuresToBeDisplayedKlt.size(); i++) {
1174
1176 double id = m_featuresToBeDisplayedKlt[i][5];
1177 std::stringstream ss;
1178 ss << id;
1179 vpDisplay::displayText(I, ip2, ss.str(), vpColor::red);
1180 }
1181 }
1182 }
1183
1184#ifdef VISP_HAVE_OGRE
1185 if (useOgre)
1186 faces.displayOgre(cMo);
1187#endif
1188}
1189
1190std::vector<std::vector<double> > vpMbKltTracker::getFeaturesForDisplayKlt()
1191{
1192 std::vector<std::vector<double> > features;
1193
1194 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
1195 vpMbtDistanceKltPoints *kltpoly = *it;
1196
1197 if (kltpoly->hasEnoughPoints() && kltpoly->polygon->isVisible() && kltpoly->isTracked()) {
1198 std::vector<std::vector<double> > currentFeatures = kltpoly->getFeaturesForDisplay();
1199 features.insert(features.end(), currentFeatures.begin(), currentFeatures.end());
1200 }
1201 }
1202
1203 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
1204 ++it) {
1205 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
1206
1207 if (kltPolyCylinder->isTracked() && kltPolyCylinder->hasEnoughPoints()) {
1208 std::vector<std::vector<double> > currentFeatures = kltPolyCylinder->getFeaturesForDisplay();
1209 features.insert(features.end(), currentFeatures.begin(), currentFeatures.end());
1210 }
1211 }
1212
1213 return features;
1214}
1215
1231std::vector<std::vector<double> > vpMbKltTracker::getModelForDisplay(unsigned int width, unsigned int height,
1232 const vpHomogeneousMatrix &cMo,
1233 const vpCameraParameters &cam,
1234 bool displayFullModel)
1235{
1236 std::vector<std::vector<double> > models;
1237
1238 vpCameraParameters c = cam;
1239
1240 if (clippingFlag > 3) // Contains at least one FOV constraint
1241 c.computeFov(width, height);
1242
1243 // vpMbtDistanceKltPoints *kltpoly;
1244 // vpMbtDistanceKltCylinder *kltPolyCylinder;
1245
1246 // Previous version 12/08/2015
1247 // for(std::list<vpMbtDistanceKltPoints*>::const_iterator
1248 // it=kltPolygons.begin(); it!=kltPolygons.end(); ++it){
1249 // kltpoly = *it;
1250 // kltpoly->polygon->changeFrame(cMo_);
1251 // kltpoly->polygon->computePolygonClipped(c);
1252 // }
1253 faces.computeClippedPolygons(cMo, c);
1254
1255 if (useScanLine && !displayFullModel)
1256 faces.computeScanLineRender(m_cam, width, height);
1257
1258 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
1259 vpMbtDistanceKltPoints *kltpoly = *it;
1260 std::vector<std::vector<double> > modelLines = kltpoly->getModelForDisplay(cam, displayFullModel);
1261 models.insert(models.end(), modelLines.begin(), modelLines.end());
1262 }
1263
1264 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
1265 ++it) {
1266 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
1267 std::vector<std::vector<double> > modelLines = kltPolyCylinder->getModelForDisplay(cMo, cam);
1268 models.insert(models.end(), modelLines.begin(), modelLines.end());
1269 }
1270
1271 for (std::list<vpMbtDistanceCircle *>::const_iterator it = circles_disp.begin(); it != circles_disp.end(); ++it) {
1272 vpMbtDistanceCircle *displayCircle = *it;
1273 std::vector<double> paramsCircle = displayCircle->getModelForDisplay(cMo, cam, displayFullModel);
1274 if (!paramsCircle.empty()) {
1275 models.push_back(paramsCircle);
1276 }
1277 }
1278
1279 return models;
1280}
1281
1289{
1290 unsigned int nbTotalPoints = 0;
1291 // for (unsigned int i = 0; i < faces.size(); i += 1){
1292 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
1293 vpMbtDistanceKltPoints *kltpoly = *it;
1294 if (kltpoly->polygon->isVisible() && kltpoly->isTracked() && kltpoly->polygon->getNbPoint() > 2 &&
1295 kltpoly->hasEnoughPoints()) {
1296 nbTotalPoints += kltpoly->getCurrentNumberPoints();
1297 }
1298 }
1299
1300 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
1301 ++it) {
1302 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
1303 if (kltPolyCylinder->isTracked() && kltPolyCylinder->hasEnoughPoints())
1304 nbTotalPoints += kltPolyCylinder->getCurrentNumberPoints();
1305 }
1306
1307 if (nbTotalPoints < 10) {
1308 std::cerr << "test tracking failed (too few points to realize a good tracking)." << std::endl;
1310 "test tracking failed (too few points to realize a good tracking).");
1311 }
1312}
1313
1324void vpMbKltTracker::initCylinder(const vpPoint &p1, const vpPoint &p2, double radius, int idFace,
1325 const std::string &name)
1326{
1327 (void)name;
1329 kltPoly->setCameraParameters(m_cam);
1330
1331 kltPoly->buildFrom(p1, p2, radius);
1332
1333 // Add the Cylinder BBox to the list of polygons
1334 kltPoly->listIndicesCylinderBBox.push_back(idFace + 1);
1335 kltPoly->listIndicesCylinderBBox.push_back(idFace + 2);
1336 kltPoly->listIndicesCylinderBBox.push_back(idFace + 3);
1337 kltPoly->listIndicesCylinderBBox.push_back(idFace + 4);
1338
1339 kltPoly->hiddenface = &faces;
1340 kltPoly->useScanLine = useScanLine;
1341 kltCylinders.push_back(kltPoly);
1342}
1343
1355void vpMbKltTracker::initCircle(const vpPoint &p1, const vpPoint &p2, const vpPoint &p3, double radius, int idFace,
1356 const std::string &name)
1357{
1358 (void)idFace;
1359 addCircle(p1, p2, p3, radius, name);
1360}
1361
1372void vpMbKltTracker::addCircle(const vpPoint &p1, const vpPoint &p2, const vpPoint &p3, double radius,
1373 const std::string &name)
1374{
1375 bool already_here = false;
1376
1377 // for(std::list<vpMbtDistanceCircle*>::const_iterator
1378 // it=circles_disp.begin(); it!=circles_disp[i].end(); ++it){
1379 // ci = *it;
1380 // if((samePoint(*(ci->p1),P1) && samePoint(*(ci->p2),P2) &&
1381 // samePoint(*(ci->p3),P3)) ||
1382 // (samePoint(*(ci->p1),P1) && samePoint(*(ci->p2),P3) &&
1383 // samePoint(*(ci->p3),P2)) ){
1384 // already_here = (std::fabs(ci->radius - r) <
1385 // std::numeric_limits<double>::epsilon() * vpMath::maximum(ci->radius,
1386 // r));
1387 // }
1388 // }
1389
1390 if (!already_here) {
1392
1394 ci->setName(name);
1395 ci->buildFrom(p1, p2, p3, radius);
1396 circles_disp.push_back(ci);
1397 }
1398}
1399
1412void vpMbKltTracker::reInitModel(const vpImage<unsigned char> &I, const std::string &cad_name,
1413 const vpHomogeneousMatrix &cMo, bool verbose, const vpHomogeneousMatrix &T)
1414{
1415 m_cMo.eye();
1416
1417 firstInitialisation = true;
1418
1419 // delete the Klt Polygon features
1420 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
1421 vpMbtDistanceKltPoints *kltpoly = *it;
1422 if (kltpoly != nullptr) {
1423 delete kltpoly;
1424 }
1425 kltpoly = nullptr;
1426 }
1427 kltPolygons.clear();
1428
1429 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
1430 ++it) {
1431 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
1432 if (kltPolyCylinder != nullptr) {
1433 delete kltPolyCylinder;
1434 }
1435 kltPolyCylinder = nullptr;
1436 }
1437 kltCylinders.clear();
1438
1439 // delete the structures used to display circles
1440 for (std::list<vpMbtDistanceCircle *>::const_iterator it = circles_disp.begin(); it != circles_disp.end(); ++it) {
1441 vpMbtDistanceCircle *ci = *it;
1442 if (ci != nullptr) {
1443 delete ci;
1444 }
1445 ci = nullptr;
1446 }
1447
1448 faces.reset();
1449
1450 loadModel(cad_name, verbose, T);
1451 initFromPose(I, cMo);
1452}
1453
1461void vpMbKltTracker::setUseKltTracking(const std::string &name, const bool &useKltTracking)
1462{
1463 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
1464 vpMbtDistanceKltPoints *kltpoly = *it;
1465 if (kltpoly->polygon->getName() == name) {
1466 kltpoly->setTracked(useKltTracking);
1467 }
1468 }
1469}
1470END_VISP_NAMESPACE
1471#elif !defined(VISP_BUILD_SHARED_LIBS)
1472// Work around to avoid warning: libvisp_mbt.a(vpMbKltTracker.cpp.o) has no symbols
1473void dummy_vpMbKltTracker() { }
1474#endif // VISP_HAVE_OPENCV
Generic class defining intrinsic camera parameters.
void computeFov(const unsigned int &w, const unsigned int &h)
Implementation of column vector and the associated operations.
vpColVector & normalize()
Class to define RGB colors available for display functionalities.
Definition vpColor.h:157
static const vpColor red
Definition vpColor.h:198
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1, bool segment=true)
static void displayEllipse(const vpImage< unsigned char > &I, const vpImagePoint &center, const double &coef1, const double &coef2, const double &coef3, bool use_normalized_centered_moments, const vpColor &color, unsigned int thickness=1, bool display_center=false, bool display_arc=false)
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
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:60
@ ioError
I/O error.
Definition vpException.h:67
@ fatalError
Fatal error.
Definition vpException.h:72
@ divideByZeroError
Division by zero.
Definition vpException.h:70
static vpHomogeneousMatrix direct(const vpColVector &v)
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpHomogeneousMatrix inverse() const
void extract(vpRotationMatrix &R) const
Implementation of an homography and operations on homographies.
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition of the vpImage class member functions.
Definition vpImage.h:131
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented in OpenCV. Thus to enable this ...
Definition vpKltOpencv.h:83
static double rad(double deg)
Definition vpMath.h:129
static bool equal(double x, double y, double threshold=0.001)
Definition vpMath.h:470
static double deg(double rad)
Definition vpMath.h:119
Implementation of a matrix and operations on matrices.
Definition vpMatrix.h:175
std::list< vpMbtDistanceKltCylinder * > kltCylinders
virtual void reInitModel(const vpImage< unsigned char > &I, const std::string &cad_name, const vpHomogeneousMatrix &cMo, bool verbose=false, const vpHomogeneousMatrix &T=vpHomogeneousMatrix())
vpColVector m_error_klt
(s - s*)
vpHomogeneousMatrix c0Mo
Initial pose.
void addCircle(const vpPoint &p1, const vpPoint &p2, const vpPoint &p3, double radius, const std::string &name="")
vpHomogeneousMatrix ctTc0
std::list< vpMbtDistanceKltPoints * > kltPolygons
virtual void initCircle(const vpPoint &, const vpPoint &, const vpPoint &, double, int, const std::string &name="") VP_OVERRIDE
virtual void setKltOpencv(const vpKltOpencv &t)
void resetTracker() VP_OVERRIDE
virtual void computeVVSInteractionMatrixAndResidu() VP_OVERRIDE
cv::Mat cur
Temporary OpenCV image for fast conversion.
void setCameraParameters(const vpCameraParameters &cam) VP_OVERRIDE
std::map< int, vpImagePoint > getKltImagePointsWithId() const
virtual std::vector< std::vector< double > > getModelForDisplay(unsigned int width, unsigned int height, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, bool displayFullModel=false) VP_OVERRIDE
std::list< vpMbtDistanceCircle * > circles_disp
Vector of the circles used here only to display the full model.
vpColVector m_weightedError_klt
Weighted error.
virtual ~vpMbKltTracker()
vpKltOpencv tracker
Points tracker.
virtual std::vector< std::vector< double > > getFeaturesForDisplayKlt()
virtual void init(const vpImage< unsigned char > &I) VP_OVERRIDE
void preTracking(const vpImage< unsigned char > &I)
virtual void initCylinder(const vpPoint &, const vpPoint &, double, int, const std::string &name="") VP_OVERRIDE
virtual void initFaceFromCorners(vpMbtPolygon &polygon) VP_OVERRIDE
unsigned int m_nbInfos
virtual void computeVVSInit() VP_OVERRIDE
bool postTracking(const vpImage< unsigned char > &I, vpColVector &w)
vpRobust m_robust_klt
Robust.
virtual void reinit(const vpImage< unsigned char > &I)
virtual void setPose(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cdMo) VP_OVERRIDE
std::vector< vpImagePoint > getKltImagePoints() const
unsigned int maskBorder
Erosion of the mask.
unsigned int m_nbFaceUsed
vpColVector m_w_klt
Robust weights.
std::vector< std::vector< double > > m_featuresToBeDisplayedKlt
Display features.
vpMatrix m_L_klt
Interaction matrix.
void setUseKltTracking(const std::string &name, const bool &useKltTracking)
virtual void display(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, const vpColor &col, unsigned int thickness=1, bool displayFullModel=false) VP_OVERRIDE
virtual void initFaceFromLines(vpMbtPolygon &polygon) VP_OVERRIDE
virtual void track(const vpImage< unsigned char > &I) VP_OVERRIDE
virtual void testTracking() VP_OVERRIDE
virtual void loadConfigFile(const std::string &configFile, bool verbose=true) VP_OVERRIDE
double m_lambda
Gain of the virtual visual servoing stage.
bool modelInitialised
double minLineLengthThresholdGeneral
Minimum line length threshold for LOD mode (general setting).
virtual void setMinLineLengthThresh(double minLineLengthThresh, const std::string &name="")
vpImage< unsigned char > m_I
Grayscale image buffer, used when passing color images.
bool useLodGeneral
True if LOD mode is enabled.
double minPolygonAreaThresholdGeneral
Minimum polygon area threshold for LOD mode (general setting).
bool m_computeInteraction
vpMatrix oJo
The Degrees of Freedom to estimate.
virtual void setMinPolygonAreaThresh(double minPolygonAreaThresh, const std::string &name="")
double m_initialMu
Initial Mu for Levenberg Marquardt optimization loop.
vpHomogeneousMatrix m_cMo
The current pose.
virtual void computeVVSCheckLevenbergMarquardt(unsigned int iter, vpColVector &error, const vpColVector &m_error_prev, const vpHomogeneousMatrix &cMoPrev, double &mu, bool &reStartFromLastIncrement, vpColVector *const w=nullptr, const vpColVector *const m_w_prev=nullptr)
vpCameraParameters m_cam
The camera parameters.
bool useOgre
Use Ogre3d for global visibility tests.
virtual void computeVVSWeights(vpRobust &robust, const vpColVector &error, vpColVector &w)
vpMbHiddenFaces< vpMbtPolygon > faces
Set of faces describing the object.
virtual void setLod(bool useLod, const std::string &name="")
virtual void computeCovarianceMatrixVVS(const bool isoJoIdentity, const vpColVector &w_true, const vpHomogeneousMatrix &cMoPrev, const vpMatrix &L_true, const vpMatrix &LVJ_true, const vpColVector &error)
vpMbtOptimizationMethod m_optimizationMethod
Optimization method used.
virtual void computeVVSPoseEstimation(const bool isoJoIdentity, unsigned int iter, vpMatrix &L, vpMatrix &LTL, vpColVector &R, const vpColVector &error, vpColVector &error_prev, vpColVector &LTR, double &mu, vpColVector &v, const vpColVector *const w=nullptr, vpColVector *const m_w_prev=nullptr)
bool displayFeatures
If true, the features are displayed.
virtual void loadModel(const std::string &modelFile, bool verbose=false, const vpHomogeneousMatrix &od_M_o=vpHomogeneousMatrix())
double angleDisappears
Angle used to detect a face disappearance.
virtual unsigned int getNbPolygon() const
virtual void setNearClippingDistance(const double &dist)
bool applyLodSettingInConfig
virtual void setFarClippingDistance(const double &dist)
bool m_isoJoIdentity
Boolean to know if oJo is identity (for fast computation).
bool useScanLine
Use Scanline for global visibility tests.
virtual void setClipping(const unsigned int &flags)
double angleAppears
Angle used to detect a face appearance.
const vpImage< bool > * m_mask
Mask used to disable tracking on a part of image.
virtual void initFromPose(const vpImage< unsigned char > &I, const std::string &initFile)
bool computeCovariance
Flag used to specify if the covariance matrix has to be computed or not.
unsigned int m_maxIter
Maximum number of iterations of the virtual visual servoing stage.
bool ogreShowConfigDialog
unsigned int clippingFlag
Flags specifying which clipping to used.
virtual void loadConfigFile(const std::string &configFile, bool verbose=true)
Manage a circle used in the model-based tracker.
void setCameraParameters(const vpCameraParameters &camera)
void buildFrom(const vpPoint &_p1, const vpPoint &_p2, const vpPoint &_p3, double r)
std::vector< double > getModelForDisplay(const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, bool displayFullModel=false)
void setName(const std::string &circle_name)
Implementation of a polygon of the model containing points of interest. It is used by the model-based...
virtual void setCameraParameters(const vpCameraParameters &_cam)
void buildFrom(const vpPoint &p1, const vpPoint &p2, const double &r)
void removeOutliers(const vpColVector &weight, const double &threshold_outlier)
unsigned int computeNbDetectedCurrent(const vpKltOpencv &_tracker)
std::vector< std::vector< double > > getFeaturesForDisplay()
void computeInteractionMatrixAndResidu(const vpHomogeneousMatrix &cMc0, vpColVector &_R, vpMatrix &_J)
bool useScanLine
Use scanline rendering.
void updateMask(cv::Mat &mask, unsigned char _nb=255, unsigned int _shiftBorder=0)
void init(const vpKltOpencv &_tracker, const vpHomogeneousMatrix &cMo)
std::vector< std::vector< double > > getModelForDisplay(const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam)
unsigned int getCurrentNumberPoints() const
std::vector< int > listIndicesCylinderBBox
Pointer to the polygon that define a face.
vpMbHiddenFaces< vpMbtPolygon > * hiddenface
Pointer to the list of faces.
unsigned int getInitialNumberPoint() const
Implementation of a polygon of the model containing points of interest. It is used by the model-based...
void updateMask(cv::Mat &mask, unsigned char _nb=255, unsigned int _shiftBorder=0)
bool useScanLine
Use scanline rendering.
void computeInteractionMatrixAndResidu(vpColVector &_R, vpMatrix &_J)
unsigned int computeNbDetectedCurrent(const vpKltOpencv &_tracker, const vpImage< bool > *mask=nullptr)
std::vector< std::vector< double > > getFeaturesForDisplay()
vpMbHiddenFaces< vpMbtPolygon > * hiddenface
Pointer to the list of faces.
void init(const vpKltOpencv &_tracker, const vpImage< bool > *mask=nullptr)
virtual void setCameraParameters(const vpCameraParameters &_cam)
unsigned int getCurrentNumberPoints() const
std::vector< std::vector< double > > getModelForDisplay(const vpCameraParameters &cam, bool displayFullModel=false)
vpMbtPolygon * polygon
Pointer to the polygon that define a face.
std::map< int, int > & getCurrentPointsInd()
unsigned int getInitialNumberPoint() const
void removeOutliers(const vpColVector &weight, const double &threshold_outlier)
std::map< int, vpImagePoint > & getCurrentPoints()
void computeHomography(const vpHomogeneousMatrix &_cTc0, vpHomography &cHc0)
void setTracked(const bool &track)
Implementation of a polygon of the model used by the model-based tracker.
std::string getName() const
virtual bool isVisible(const vpHomogeneousMatrix &cMo, double alpha, const bool &modulo=false, const vpCameraParameters &cam=vpCameraParameters(), unsigned int width=0, unsigned int height=0)
Parse an Xml file to extract configuration parameters of a mbtConfig object.
unsigned int getKltMaxFeatures() const
void setKltMinDistance(const double &mD)
unsigned int getKltBlockSize() const
void getCameraParameters(vpCameraParameters &cam) const
void setKltMaskBorder(const unsigned int &mb)
double getLodMinLineLengthThreshold() const
unsigned int getKltMaskBorder() const
void setAngleDisappear(const double &adisappear)
void setKltPyramidLevels(const unsigned int &pL)
void setKltWindowSize(const unsigned int &w)
void setKltMaxFeatures(const unsigned int &mF)
void setAngleAppear(const double &aappear)
void setKltBlockSize(const unsigned int &bs)
void setKltHarrisParam(const double &hp)
void parse(const std::string &filename)
void setKltQuality(const double &q)
unsigned int getKltPyramidLevels() const
unsigned int getKltWindowSize() const
double getLodMinPolygonAreaThreshold() const
This class defines the container for a plane geometrical structure.
Definition vpPlane.h:56
void changeFrame(const vpHomogeneousMatrix &cMo)
Definition vpPlane.cpp:465
double getD() const
Definition vpPlane.h:106
vpColVector getNormal() const
Definition vpPlane.cpp:311
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
Definition vpPoint.h:79
void changeFrame(const vpHomogeneousMatrix &cMo)
unsigned int getNbPoint() const
vpPoint * p
corners in the object frame
Definition vpPolygon3D.h:79
void computePolygonClipped(const vpCameraParameters &cam=vpCameraParameters())
Implementation of a rotation matrix and operations on such kind of matrices.
Definition of the vpSubMatrix class that provides a mask on a vpMatrix. All properties of vpMatrix ar...
Definition vpSubMatrix.h:57
Error that can be emitted by the vpTracker class and its derivatives.
@ notEnoughPointError
Not enough point to track.
@ fatalError
Tracker fatal error.
Class that consider the case of a translation vector.
vpVelocityTwistMatrix & buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)
#define vpERROR_TRACE
Definition vpDebug.h:423