36 #include <visp3/core/vpImageConvert.h>
37 #include <visp3/core/vpDebug.h>
38 #include <visp3/core/vpTrackingException.h>
39 #include <visp3/core/vpVelocityTwistMatrix.h>
40 #include <visp3/mbt/vpMbKltTracker.h>
41 #include <visp3/mbt/vpMbtXmlGenericParser.h>
43 #if defined(VISP_HAVE_MODULE_KLT) && defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
45 #if defined(__APPLE__) && defined(__MACH__)
46 #include <TargetConditionals.h>
51 #ifndef DOXYGEN_SHOULD_SKIP_THIS
82 double h00 = H[0][0], h01 = H[0][1], h02 = H[0][2];
83 double h10 = H[1][0], h11 = H[1][1], h12 = H[1][2];
84 double h20 = H[2][0], h21 = H[2][1], h22 = H[2][2];
86 double A = h00 * px + u0 * h20;
87 double B = h01 * px + u0 * h21;
88 double C = h02 * px + u0 * h22;
89 double D = h10 * py + v0 * h20;
90 double E = h11 * py + v0 * h21;
91 double F = h12 * py + v0 * h22;
93 G[0][0] = A * one_over_px;
94 G[1][0] = D * one_over_px;
95 G[2][0] = h20 * one_over_px;
97 G[0][1] = B * one_over_py;
98 G[1][1] = E * one_over_py;
99 G[2][1] = h21 * one_over_py;
101 double u0_one_over_px = u0 * one_over_px;
102 double v0_one_over_py = v0 * one_over_py;
104 G[0][2] = -A * u0_one_over_px - B * v0_one_over_py + C;
105 G[1][2] = -D * u0_one_over_px - E * v0_one_over_py + F;
106 G[2][2] = -h20 * u0_one_over_px - h21 * v0_one_over_py + h22;
114 vpMbKltTracker::vpMbKltTracker()
116 cur(), c0Mo(), firstInitialisation(true), maskBorder(5), threshold_outlier(0.5), percentGood(0.6), ctTc0(), tracker(),
117 kltPolygons(), kltCylinders(), circles_disp(), m_nbInfos(0), m_nbFaceUsed(0), m_L_klt(), m_error_klt(), m_w_klt(),
118 m_weightedError_klt(), m_robust_klt(), m_featuresToBeDisplayedKlt()
120 tracker.setTrackerId(1);
121 tracker.setUseHarris(1);
122 tracker.setMaxFeatures(10000);
123 tracker.setWindowSize(5);
124 tracker.setQuality(0.01);
125 tracker.setMinDistance(5);
126 tracker.setHarrisFreeParameter(0.01);
127 tracker.setBlockSize(3);
128 tracker.setPyramidLevels(3);
130 #ifdef VISP_HAVE_OGRE
131 faces.getOgreContext()->setWindowName(
"MBT Klt");
142 vpMbKltTracker::~vpMbKltTracker()
145 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
146 vpMbtDistanceKltPoints *kltpoly = *it;
147 if (kltpoly !=
nullptr) {
154 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
156 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
157 if (kltPolyCylinder !=
nullptr) {
158 delete kltPolyCylinder;
160 kltPolyCylinder =
nullptr;
162 kltCylinders.clear();
165 for (std::list<vpMbtDistanceCircle *>::const_iterator it = circles_disp.begin(); it != circles_disp.end(); ++it) {
173 circles_disp.clear();
178 if (!modelInitialised) {
182 bool reInitialisation =
false;
184 faces.setVisible(I.
getWidth(), I.
getHeight(), m_cam, m_cMo, angleAppears, angleDisappears, reInitialisation);
186 #ifdef VISP_HAVE_OGRE
187 if (!faces.isOgreInitialised()) {
189 faces.setOgreShowConfigDialog(ogreShowConfigDialog);
190 faces.initOgre(m_cam);
194 ogreShowConfigDialog =
false;
197 faces.setVisibleOgre(I.
getWidth(), I.
getHeight(), m_cam, m_cMo, angleAppears, angleDisappears, reInitialisation);
200 faces.setVisible(I.
getWidth(), I.
getHeight(), m_cam, m_cMo, angleAppears, angleDisappears, reInitialisation);
216 faces.computeClippedPolygons(m_cMo, m_cam);
221 cv::Mat mask((
int)I.
getRows(), (
int)I.
getCols(), CV_8UC1, cv::Scalar(0));
223 vpMbtDistanceKltPoints *kltpoly;
224 vpMbtDistanceKltCylinder *kltPolyCylinder;
229 unsigned char val = 255 ;
230 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
232 if (kltpoly->polygon->isVisible() && kltpoly->isTracked() && kltpoly->polygon->getNbPoint() > 2) {
235 kltpoly->polygon->changeFrame(m_cMo);
236 kltpoly->polygon->computePolygonClipped(m_cam);
237 kltpoly->updateMask(mask, val, maskBorder);
241 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
243 kltPolyCylinder = *it;
245 if (kltPolyCylinder->isTracked()) {
246 for (
unsigned int k = 0; k < kltPolyCylinder->listIndicesCylinderBBox.size(); k++) {
247 unsigned int indCylBBox = (
unsigned int)kltPolyCylinder->listIndicesCylinderBBox[k];
248 if (faces[indCylBBox]->isVisible() && faces[indCylBBox]->getNbPoint() > 2u) {
249 faces[indCylBBox]->computePolygonClipped(m_cam);
253 kltPolyCylinder->updateMask(mask, val, maskBorder);
258 tracker.initTracking(cur, mask);
264 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
266 if (kltpoly->polygon->isVisible() && kltpoly->isTracked() && kltpoly->polygon->getNbPoint() > 2) {
267 kltpoly->init(tracker, m_mask);
271 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
273 kltPolyCylinder = *it;
275 if (kltPolyCylinder->isTracked())
276 kltPolyCylinder->init(tracker, m_cMo);
284 void vpMbKltTracker::resetTracker()
289 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
290 vpMbtDistanceKltPoints *kltpoly = *it;
291 if (kltpoly !=
nullptr) {
298 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
300 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
301 if (kltPolyCylinder !=
nullptr) {
302 delete kltPolyCylinder;
304 kltPolyCylinder =
nullptr;
306 kltCylinders.clear();
309 for (std::list<vpMbtDistanceCircle *>::const_iterator it = circles_disp.begin(); it != circles_disp.end(); ++it) {
317 circles_disp.clear();
319 m_computeInteraction =
true;
320 firstInitialisation =
true;
321 computeCovariance =
false;
323 tracker.setTrackerId(1);
324 tracker.setUseHarris(1);
326 tracker.setMaxFeatures(10000);
327 tracker.setWindowSize(5);
328 tracker.setQuality(0.01);
329 tracker.setMinDistance(5);
330 tracker.setHarrisFreeParameter(0.01);
331 tracker.setBlockSize(3);
332 tracker.setPyramidLevels(3);
340 threshold_outlier = 0.5;
352 #ifdef VISP_HAVE_OGRE
365 std::vector<vpImagePoint> vpMbKltTracker::getKltImagePoints()
const
367 std::vector<vpImagePoint> kltPoints;
368 for (
unsigned int i = 0; i < static_cast<unsigned int>(tracker.getNbFeatures()); i++) {
371 tracker.getFeature((
int)i, id, x_tmp, y_tmp);
386 std::map<int, vpImagePoint> vpMbKltTracker::getKltImagePointsWithId()
const
388 std::map<int, vpImagePoint> kltPoints;
389 for (
unsigned int i = 0; i < static_cast<unsigned int>(tracker.getNbFeatures()); i++) {
392 tracker.getFeature((
int)i, id, x_tmp, y_tmp);
393 #ifdef TARGET_OS_IPHONE
408 void vpMbKltTracker::setKltOpencv(
const vpKltOpencv &t)
430 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
431 vpMbtDistanceKltPoints *kltpoly = *it;
432 kltpoly->setCameraParameters(cam);
435 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
437 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
438 kltPolyCylinder->setCameraParameters(cam);
451 if (!kltCylinders.empty()) {
452 std::cout <<
"WARNING: Cannot set pose when model contains cylinder(s). "
453 "This feature is not implemented yet."
455 std::cout <<
"Tracker will be reinitialized with the given pose." << std::endl;
465 vpMbtDistanceKltPoints *kltpoly;
467 std::vector<cv::Point2f> init_pts;
468 std::vector<long> init_ids;
469 std::vector<cv::Point2f> guess_pts;
482 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
485 if (kltpoly->polygon->isVisible() && kltpoly->polygon->getNbPoint() > 2) {
486 kltpoly->polygon->changeFrame(cdMo);
489 vpPlane plan(kltpoly->polygon->p[0], kltpoly->polygon->p[1], kltpoly->polygon->p[2]);
490 plan.changeFrame(cMcd);
495 double invDc = 1.0 / plan.getD();
499 vpGEMM(cdtc, Nc, -invDc, cdRc, 1.0, cdHc, VP_GEMM_B_T);
503 vpMatrix cdGc = homography2collineation(cdHc, m_cam);
506 std::map<int, vpImagePoint>::const_iterator iter = kltpoly->getCurrentPoints().begin();
508 for (; iter != kltpoly->getCurrentPoints().end(); ++iter) {
509 #ifdef TARGET_OS_IPHONE
510 if (std::find(init_ids.begin(), init_ids.end(), (
long)(kltpoly->getCurrentPointsInd())[(
int)iter->first]) !=
513 if (std::find(init_ids.begin(), init_ids.end(),
514 (
long)(kltpoly->getCurrentPointsInd())[(
size_t)iter->first]) != init_ids.end())
523 cdp[0] = iter->second.get_j();
524 cdp[1] = iter->second.get_i();
527 cv::Point2f p((
float)cdp[0], (
float)cdp[1]);
528 init_pts.push_back(p);
529 #ifdef TARGET_OS_IPHONE
530 init_ids.push_back((
size_t)(kltpoly->getCurrentPointsInd())[(
int)iter->first]);
532 init_ids.push_back((
size_t)(kltpoly->getCurrentPointsInd())[(
size_t)iter->first]);
535 double p_mu_t_2 = cdp[0] * cdGc[2][0] + cdp[1] * cdGc[2][1] + cdGc[2][2];
537 if (fabs(p_mu_t_2) < std::numeric_limits<double>::epsilon()) {
543 cdp[0] = (cdp[0] * cdGc[0][0] + cdp[1] * cdGc[0][1] + cdGc[0][2]) / p_mu_t_2;
544 cdp[1] = (cdp[0] * cdGc[1][0] + cdp[1] * cdGc[1][1] + cdGc[1][2]) / p_mu_t_2;
547 cv::Point2f p_guess((
float)cdp[0], (
float)cdp[1]);
548 guess_pts.push_back(p_guess);
560 tracker.setInitialGuess(init_pts, guess_pts, init_ids);
562 bool reInitialisation =
false;
565 faces.setVisible(I->
getWidth(), I->
getHeight(), m_cam, cdMo, angleAppears, angleDisappears, reInitialisation);
568 faces.setVisible(m_I.getWidth(), m_I.getHeight(), m_cam, cdMo, angleAppears, angleDisappears, reInitialisation);
572 #ifdef VISP_HAVE_OGRE
574 faces.setVisibleOgre(I->
getWidth(), I->
getHeight(), m_cam, cdMo, angleAppears, angleDisappears,
578 faces.setVisibleOgre(m_I.getWidth(), m_I.getHeight(), m_cam, cdMo, angleAppears, angleDisappears,
583 faces.setVisible(I->
getWidth(), I->
getHeight(), m_cam, cdMo, angleAppears, angleDisappears, reInitialisation);
586 faces.setVisible(m_I.getWidth(), m_I.getHeight(), m_cam, cdMo, angleAppears, angleDisappears, reInitialisation);
591 m_cam.computeFov(I ? I->
getWidth() : m_I.getWidth(), I ? I->
getHeight() : m_I.getHeight());
594 faces.computeClippedPolygons(cdMo, m_cam);
595 faces.computeScanLineRender(m_cam, I ? I->
getWidth() : m_I.getWidth(), I ? I->
getHeight() : m_I.getHeight());
598 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
600 if (kltpoly->polygon->isVisible() && kltpoly->polygon->getNbPoint() > 2) {
601 kltpoly->polygon->computePolygonClipped(m_cam);
602 kltpoly->init(tracker, m_mask);
623 vpMbKltTracker::setPose(&I,
nullptr, cdMo);
637 vpMbKltTracker::setPose(
nullptr, &I_color, cdMo);
646 void vpMbKltTracker::initFaceFromCorners(
vpMbtPolygon &polygon)
648 vpMbtDistanceKltPoints *kltPoly =
new vpMbtDistanceKltPoints();
649 kltPoly->setCameraParameters(m_cam);
650 kltPoly->polygon = &polygon;
651 kltPoly->hiddenface = &faces;
652 kltPoly->useScanLine = useScanLine;
653 kltPolygons.push_back(kltPoly);
661 void vpMbKltTracker::initFaceFromLines(
vpMbtPolygon &polygon)
663 vpMbtDistanceKltPoints *kltPoly =
new vpMbtDistanceKltPoints();
664 kltPoly->setCameraParameters(m_cam);
665 kltPoly->polygon = &polygon;
666 kltPoly->hiddenface = &faces;
667 kltPoly->useScanLine = useScanLine;
668 kltPolygons.push_back(kltPoly);
685 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
686 vpMbtDistanceKltPoints *kltpoly = *it;
687 if (kltpoly->polygon->isVisible() && kltpoly->isTracked() && kltpoly->polygon->getNbPoint() > 2) {
688 kltpoly->computeNbDetectedCurrent(tracker, m_mask);
690 if (kltpoly->hasEnoughPoints()) {
691 m_nbInfos += kltpoly->getCurrentNumberPoints();
697 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
699 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
701 if (kltPolyCylinder->isTracked()) {
702 kltPolyCylinder->computeNbDetectedCurrent(tracker);
703 if (kltPolyCylinder->hasEnoughPoints()) {
704 m_nbInfos += kltPolyCylinder->getCurrentNumberPoints();
719 bool reInitialisation =
false;
721 unsigned int initialNumber = 0;
722 unsigned int currentNumber = 0;
723 unsigned int shift = 0;
725 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
726 vpMbtDistanceKltPoints *kltpoly = *it;
727 if (kltpoly->polygon->isVisible() && kltpoly->isTracked() && kltpoly->polygon->getNbPoint() > 2) {
728 initialNumber += kltpoly->getInitialNumberPoint();
729 if (kltpoly->hasEnoughPoints()) {
730 vpSubColVector sub_w(w, shift, 2 * kltpoly->getCurrentNumberPoints());
731 shift += 2 * kltpoly->getCurrentNumberPoints();
732 kltpoly->removeOutliers(sub_w, threshold_outlier);
734 currentNumber += kltpoly->getCurrentNumberPoints();
743 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
745 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
747 if (kltPolyCylinder->isTracked()) {
748 initialNumber += kltPolyCylinder->getInitialNumberPoint();
749 if (kltPolyCylinder->hasEnoughPoints()) {
750 vpSubColVector sub_w(w, shift, 2 * kltPolyCylinder->getCurrentNumberPoints());
751 shift += 2 * kltPolyCylinder->getCurrentNumberPoints();
752 kltPolyCylinder->removeOutliers(sub_w, threshold_outlier);
754 currentNumber += kltPolyCylinder->getCurrentNumberPoints();
760 double value = percentGood * (double)initialNumber;
761 if ((
double)currentNumber < value) {
764 reInitialisation =
true;
768 faces.setVisible(I.
getWidth(), I.
getHeight(), m_cam, m_cMo, angleAppears, angleDisappears, reInitialisation);
770 #ifdef VISP_HAVE_OGRE
771 faces.setVisibleOgre(I.
getWidth(), I.
getHeight(), m_cam, m_cMo, angleAppears, angleDisappears, reInitialisation);
773 faces.setVisible(I.
getWidth(), I.
getHeight(), m_cam, m_cMo, angleAppears, angleDisappears, reInitialisation);
779 if (reInitialisation)
788 void vpMbKltTracker::computeVVS()
799 double mu = m_initialMu;
802 double normRes_1 = -1;
803 unsigned int iter = 0;
805 bool isoJoIdentity = m_isoJoIdentity;
809 vpMbKltTracker::computeVVSInit();
811 while (((
int)((normRes - normRes_1) * 1e8) != 0) && (iter < m_maxIter)) {
812 vpMbKltTracker::computeVVSInteractionMatrixAndResidu();
814 bool reStartFromLastIncrement =
false;
815 computeVVSCheckLevenbergMarquardt(iter, m_error_klt, error_prev, cMoPrev, mu, reStartFromLastIncrement);
816 if (reStartFromLastIncrement) {
820 if (!reStartFromLastIncrement) {
823 if (computeCovariance) {
825 if (!isoJoIdentity) {
828 LVJ_true = (m_L_klt * cVo * oJo);
835 for (
unsigned int i = 0; i < m_error_klt.getRows(); i++) {
836 m_weightedError_klt[i] = m_error_klt[i] * m_w_klt[i];
837 normRes += m_weightedError_klt[i];
840 if ((iter == 0) || m_computeInteraction) {
841 for (
unsigned int i = 0; i < m_error_klt.getRows(); i++) {
842 for (
unsigned int j = 0; j < 6; j++) {
843 m_L_klt[i][j] *= m_w_klt[i];
848 computeVVSPoseEstimation(m_isoJoIdentity, iter, m_L_klt, LTL, m_weightedError_klt, m_error_klt, error_prev, LTR, mu, v);
853 m_cMo = ctTc0 * c0Mo;
859 computeCovarianceMatrixVVS(m_isoJoIdentity, m_w_klt, cMoPrev, L_true, LVJ_true, m_error_klt);
862 void vpMbKltTracker::computeVVSInit()
864 unsigned int nbFeatures = 2 * m_nbInfos;
866 m_L_klt.resize(nbFeatures, 6,
false,
false);
867 m_error_klt.resize(nbFeatures,
false);
869 m_weightedError_klt.resize(nbFeatures,
false);
870 m_w_klt.resize(nbFeatures,
false);
873 m_robust_klt.setMinMedianAbsoluteDeviation(2 / m_cam.get_px());
876 void vpMbKltTracker::computeVVSInteractionMatrixAndResidu()
878 unsigned int shift = 0;
881 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
882 vpMbtDistanceKltPoints *kltpoly = *it;
883 if (kltpoly->polygon->isVisible() && kltpoly->isTracked() && kltpoly->polygon->getNbPoint() > 2 &&
884 kltpoly->hasEnoughPoints()) {
885 vpSubColVector subR(m_error_klt, shift, 2 * kltpoly->getCurrentNumberPoints());
886 vpSubMatrix subL(m_L_klt, shift, 0, 2 * kltpoly->getCurrentNumberPoints(), 6);
889 kltpoly->computeHomography(ctTc0, H);
890 kltpoly->computeInteractionMatrixAndResidu(subR, subL);
896 shift += 2 * kltpoly->getCurrentNumberPoints();
900 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
902 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
904 if (kltPolyCylinder->isTracked() && kltPolyCylinder->hasEnoughPoints()) {
905 vpSubColVector subR(m_error_klt, shift, 2 * kltPolyCylinder->getCurrentNumberPoints());
906 vpSubMatrix subL(m_L_klt, shift, 0, 2 * kltPolyCylinder->getCurrentNumberPoints(), 6);
909 kltPolyCylinder->computeInteractionMatrixAndResidu(ctTc0, subR, subL);
915 shift += 2 * kltPolyCylinder->getCurrentNumberPoints();
931 if (m_nbInfos < 4 || m_nbFaceUsed == 0) {
937 if (postTracking(I, m_w_klt))
940 if (displayFeatures) {
941 m_featuresToBeDisplayedKlt = getFeaturesForDisplayKlt();
957 if (m_nbInfos < 4 || m_nbFaceUsed == 0) {
963 if (postTracking(m_I, m_w_klt))
1010 void vpMbKltTracker::loadConfigFile(
const std::string &configFile,
bool verbose)
1012 #if defined(VISP_HAVE_PUGIXML)
1017 xmlp.setVerbose(verbose);
1018 xmlp.setKltMaxFeatures(10000);
1019 xmlp.setKltWindowSize(5);
1020 xmlp.setKltQuality(0.01);
1021 xmlp.setKltMinDistance(5);
1022 xmlp.setKltHarrisParam(0.01);
1023 xmlp.setKltBlockSize(3);
1024 xmlp.setKltPyramidLevels(3);
1025 xmlp.setKltMaskBorder(maskBorder);
1027 xmlp.setAngleDisappear(
vpMath::deg(angleDisappears));
1031 std::cout <<
" *********** Parsing XML for MBT KLT Tracker ************ " << std::endl;
1033 xmlp.parse(configFile.c_str());
1036 vpERROR_TRACE(
"Can't open XML file \"%s\"\n ", configFile.c_str());
1041 xmlp.getCameraParameters(camera);
1042 setCameraParameters(camera);
1044 tracker.setMaxFeatures((
int)xmlp.getKltMaxFeatures());
1045 tracker.setWindowSize((
int)xmlp.getKltWindowSize());
1046 tracker.setQuality(xmlp.getKltQuality());
1047 tracker.setMinDistance(xmlp.getKltMinDistance());
1048 tracker.setHarrisFreeParameter(xmlp.getKltHarrisParam());
1049 tracker.setBlockSize((
int)xmlp.getKltBlockSize());
1050 tracker.setPyramidLevels((
int)xmlp.getKltPyramidLevels());
1051 maskBorder = xmlp.getKltMaskBorder();
1052 angleAppears =
vpMath::rad(xmlp.getAngleAppear());
1053 angleDisappears =
vpMath::rad(xmlp.getAngleDisappear());
1056 faces.getMbScanLineRenderer().setMaskBorder(maskBorder);
1058 if (xmlp.hasNearClippingDistance())
1059 setNearClippingDistance(xmlp.getNearClippingDistance());
1061 if (xmlp.hasFarClippingDistance())
1062 setFarClippingDistance(xmlp.getFarClippingDistance());
1064 if (xmlp.getFovClipping())
1067 useLodGeneral = xmlp.getLodState();
1068 minLineLengthThresholdGeneral = xmlp.getLodMinLineLengthThreshold();
1069 minPolygonAreaThresholdGeneral = xmlp.getLodMinPolygonAreaThreshold();
1071 applyLodSettingInConfig =
false;
1072 if (this->getNbPolygon() > 0) {
1073 applyLodSettingInConfig =
true;
1074 setLod(useLodGeneral);
1075 setMinLineLengthThresh(minLineLengthThresholdGeneral);
1076 setMinPolygonAreaThresh(minPolygonAreaThresholdGeneral);
1098 bool displayFullModel)
1100 std::vector<std::vector<double> > models =
1101 vpMbKltTracker::getModelForDisplay(I.
getWidth(), I.
getHeight(), cMo, cam, displayFullModel);
1103 for (
size_t i = 0; i < models.size(); i++) {
1111 double n20 = models[i][3];
1112 double n11 = models[i][4];
1113 double n02 = models[i][5];
1118 if (displayFeatures) {
1119 for (
size_t i = 0; i < m_featuresToBeDisplayedKlt.size(); i++) {
1121 vpImagePoint ip1(m_featuresToBeDisplayedKlt[i][1], m_featuresToBeDisplayedKlt[i][2]);
1124 vpImagePoint ip2(m_featuresToBeDisplayedKlt[i][3], m_featuresToBeDisplayedKlt[i][4]);
1125 double id = m_featuresToBeDisplayedKlt[i][5];
1126 std::stringstream ss;
1133 #ifdef VISP_HAVE_OGRE
1135 faces.displayOgre(cMo);
1151 const vpColor &col,
unsigned int thickness,
bool displayFullModel)
1153 std::vector<std::vector<double> > models =
1154 vpMbKltTracker::getModelForDisplay(I.
getWidth(), I.
getHeight(), cMo, cam, displayFullModel);
1156 for (
size_t i = 0; i < models.size(); i++) {
1164 double n20 = models[i][3];
1165 double n11 = models[i][4];
1166 double n02 = models[i][5];
1171 if (displayFeatures) {
1172 for (
size_t i = 0; i < m_featuresToBeDisplayedKlt.size(); i++) {
1174 vpImagePoint ip1(m_featuresToBeDisplayedKlt[i][1], m_featuresToBeDisplayedKlt[i][2]);
1177 vpImagePoint ip2(m_featuresToBeDisplayedKlt[i][3], m_featuresToBeDisplayedKlt[i][4]);
1178 double id = m_featuresToBeDisplayedKlt[i][5];
1179 std::stringstream ss;
1186 #ifdef VISP_HAVE_OGRE
1188 faces.displayOgre(cMo);
1192 std::vector<std::vector<double> > vpMbKltTracker::getFeaturesForDisplayKlt()
1194 std::vector<std::vector<double> > features;
1196 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
1197 vpMbtDistanceKltPoints *kltpoly = *it;
1199 if (kltpoly->hasEnoughPoints() && kltpoly->polygon->isVisible() && kltpoly->isTracked()) {
1200 std::vector<std::vector<double> > currentFeatures = kltpoly->getFeaturesForDisplay();
1201 features.insert(features.end(), currentFeatures.begin(), currentFeatures.end());
1205 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
1207 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
1209 if (kltPolyCylinder->isTracked() && kltPolyCylinder->hasEnoughPoints()) {
1210 std::vector<std::vector<double> > currentFeatures = kltPolyCylinder->getFeaturesForDisplay();
1211 features.insert(features.end(), currentFeatures.begin(), currentFeatures.end());
1233 std::vector<std::vector<double> > vpMbKltTracker::getModelForDisplay(
unsigned int width,
unsigned int height,
1236 bool displayFullModel)
1238 std::vector<std::vector<double> > models;
1242 if (clippingFlag > 3)
1255 faces.computeClippedPolygons(cMo, c);
1257 if (useScanLine && !displayFullModel)
1258 faces.computeScanLineRender(m_cam, width, height);
1260 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
1261 vpMbtDistanceKltPoints *kltpoly = *it;
1262 std::vector<std::vector<double> > modelLines = kltpoly->getModelForDisplay(cam, displayFullModel);
1263 models.insert(models.end(), modelLines.begin(), modelLines.end());
1266 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
1268 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
1269 std::vector<std::vector<double> > modelLines = kltPolyCylinder->getModelForDisplay(cMo, cam);
1270 models.insert(models.end(), modelLines.begin(), modelLines.end());
1273 for (std::list<vpMbtDistanceCircle *>::const_iterator it = circles_disp.begin(); it != circles_disp.end(); ++it) {
1275 std::vector<double> paramsCircle = displayCircle->
getModelForDisplay(cMo, cam, displayFullModel);
1276 if (!paramsCircle.empty()) {
1277 models.push_back(paramsCircle);
1290 void vpMbKltTracker::testTracking()
1292 unsigned int nbTotalPoints = 0;
1294 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
1295 vpMbtDistanceKltPoints *kltpoly = *it;
1296 if (kltpoly->polygon->isVisible() && kltpoly->isTracked() && kltpoly->polygon->getNbPoint() > 2 &&
1297 kltpoly->hasEnoughPoints()) {
1298 nbTotalPoints += kltpoly->getCurrentNumberPoints();
1302 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
1304 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
1305 if (kltPolyCylinder->isTracked() && kltPolyCylinder->hasEnoughPoints())
1306 nbTotalPoints += kltPolyCylinder->getCurrentNumberPoints();
1309 if (nbTotalPoints < 10) {
1310 std::cerr <<
"test tracking failed (too few points to realize a good tracking)." << std::endl;
1312 "test tracking failed (too few points to realize a good tracking).");
1326 void vpMbKltTracker::initCylinder(
const vpPoint &p1,
const vpPoint &p2,
double radius,
int idFace,
1327 const std::string & )
1329 vpMbtDistanceKltCylinder *kltPoly =
new vpMbtDistanceKltCylinder();
1330 kltPoly->setCameraParameters(m_cam);
1332 kltPoly->buildFrom(p1, p2, radius);
1335 kltPoly->listIndicesCylinderBBox.push_back(idFace + 1);
1336 kltPoly->listIndicesCylinderBBox.push_back(idFace + 2);
1337 kltPoly->listIndicesCylinderBBox.push_back(idFace + 3);
1338 kltPoly->listIndicesCylinderBBox.push_back(idFace + 4);
1340 kltPoly->hiddenface = &faces;
1341 kltPoly->useScanLine = useScanLine;
1342 kltCylinders.push_back(kltPoly);
1356 void vpMbKltTracker::initCircle(
const vpPoint &p1,
const vpPoint &p2,
const vpPoint &p3,
double radius,
int ,
1357 const std::string &name)
1359 addCircle(p1, p2, p3, radius, name);
1371 const std::string &name)
1373 bool already_here =
false;
1388 if (!already_here) {
1394 circles_disp.push_back(ci);
1415 firstInitialisation =
true;
1418 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
1419 vpMbtDistanceKltPoints *kltpoly = *it;
1420 if (kltpoly !=
nullptr) {
1425 kltPolygons.clear();
1427 for (std::list<vpMbtDistanceKltCylinder *>::const_iterator it = kltCylinders.begin(); it != kltCylinders.end();
1429 vpMbtDistanceKltCylinder *kltPolyCylinder = *it;
1430 if (kltPolyCylinder !=
nullptr) {
1431 delete kltPolyCylinder;
1433 kltPolyCylinder =
nullptr;
1435 kltCylinders.clear();
1438 for (std::list<vpMbtDistanceCircle *>::const_iterator it = circles_disp.begin(); it != circles_disp.end(); ++it) {
1440 if (ci !=
nullptr) {
1448 loadModel(cad_name, verbose, T);
1449 initFromPose(I, cMo);
1459 void vpMbKltTracker::setUseKltTracking(
const std::string &name,
const bool &useKltTracking)
1461 for (std::list<vpMbtDistanceKltPoints *>::const_iterator it = kltPolygons.begin(); it != kltPolygons.end(); ++it) {
1462 vpMbtDistanceKltPoints *kltpoly = *it;
1463 if (kltpoly->polygon->getName() == name) {
1464 kltpoly->setTracked(useKltTracking);
1469 #elif !defined(VISP_BUILD_SHARED_LIBS)
1471 void dummy_vpMbKltTracker() { };
void vpGEMM(const vpArray2D< double > &A, const vpArray2D< double > &B, const double &alpha, const vpArray2D< double > &C, const double &beta, vpArray2D< double > &D, const unsigned int &ops=0)
Generic class defining intrinsic camera parameters.
void computeFov(const unsigned int &w, const unsigned int &h)
double get_px_inverse() const
double get_py_inverse() const
Implementation of column vector and the associated operations.
vpColVector & normalize()
Class to define RGB colors available for display functionalities.
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 ¢er, 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.
@ divideByZeroError
Division by zero.
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 ...
unsigned int getWidth() const
unsigned int getCols() const
unsigned int getHeight() const
unsigned int getRows() const
void init(unsigned int h, unsigned int w, Type value)
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented in OpenCV. Thus to enable this ...
double getQuality() const
int getMaxFeatures() const
Get the list of lost feature.
int getWindowSize() const
Get the window size used to refine the corner locations.
double getHarrisFreeParameter() const
Get the free parameter of the Harris detector.
double getMinDistance() const
int getBlockSize() const
Get the size of the averaging block used to track the features.
int getPyramidLevels() const
Get the list of features id.
static double rad(double deg)
static bool equal(double x, double y, double threshold=0.001)
static double deg(double rad)
Implementation of a matrix and operations on matrices.
virtual void computeVVSWeights(vpRobust &robust, const vpColVector &error, vpColVector &w)
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 used by the model-based tracker.
Parse an Xml file to extract configuration parameters of a mbtConfig object.
This class defines the container for a plane geometrical structure.
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
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...
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)