39 #include <visp3/core/vpException.h>
40 #include <visp3/tt_mi/vpTemplateTrackerMI.h>
41 #include <visp3/tt_mi/vpTemplateTrackerMIBSpline.h>
81 :
vpTemplateTracker(_warp), hessianComputation(USE_HESSIEN_NORMAL), ApproxHessian(HESSIAN_NEW), lambda(0), temp(nullptr),
82 Prt(nullptr), dPrt(nullptr), Pt(nullptr), Pr(nullptr), d2Prt(nullptr), PrtTout(nullptr), dprtemp(nullptr), PrtD(nullptr), dPrtD(nullptr),
83 influBspline(0), bspline(3), Nc(8), Ncb(0), d2Ix(), d2Iy(), d2Ixy(), MI_preEstimation(0), MI_postEstimation(0),
84 NMI_preEstimation(0), NMI_postEstimation(0), covarianceMatrix(), computeCovariance(false)
105 Pt =
new double[
Ncb];
106 Pr =
new double[
Ncb];
141 Pt =
new double[
Ncb];
142 Pr =
new double[
Ncb];
153 unsigned int Ncb_ = (
unsigned int)
Ncb;
154 unsigned int Nc_ = (
unsigned int)
Nc;
155 unsigned int influBspline_ = (
unsigned int)
influBspline;
157 memset(
Prt, 0, Ncb_ * Ncb_ *
sizeof(
double));
158 memset(
PrtD, 0, Nc_ * Nc_ * influBspline_ *
sizeof(
double));
160 Warp->computeCoeff(tp);
161 for (
unsigned int point = 0; point <
templateSize; point++) {
165 Warp->computeDenom(
X1, tp);
170 if ((i2 >= 0) && (j2 >= 0) && (i2 < I.
getHeight() - 1) && (j2 < I.
getWidth() - 1)) {
179 double Nc_1 = (
Nc - 1.) / 255.;
180 double IW_Nc = IW * Nc_1;
181 double Tij_Nc = Tij * Nc_1;
182 int cr =
static_cast<int>(IW_Nc);
183 int ct =
static_cast<int>(Tij_Nc);
184 double er = IW_Nc - cr;
185 double et = Tij_Nc - ct;
189 vpTemplateTrackerMIBSpline::PutPVBsplineD(
PrtD, cr, er, ct, et,
Nc, 1.,
bspline);
196 for (
int r = 0; r <
Nc; r++)
197 for (
int t = 0; t <
Nc; t++) {
202 Prt[r2 *
Ncb + t2] += *pt;
210 for (
unsigned int r = 0; r < Ncb_; r++) {
211 for (
unsigned int t = 0; t < Ncb_; t++) {
212 Prt[r * Ncb_ + t] /= Nbpoint;
216 memset(
Pr, 0, Ncb_ *
sizeof(
double));
217 memset(
Pt, 0, Ncb_ *
sizeof(
double));
218 for (
unsigned int r = 0; r < Ncb_; r++) {
219 for (
unsigned int t = 0; t < Ncb_; t++) {
220 Pr[r] +=
Prt[r * Ncb_ + t];
221 Pt[r] +=
Prt[t * Ncb_ + r];
225 for (
unsigned int r = 0; r < Ncb_; r++) {
226 if (std::fabs(
Pr[r]) > std::numeric_limits<double>::epsilon()) {
227 MI -=
Pr[r] * log(
Pr[r]);
229 if (std::fabs(
Pt[r]) > std::numeric_limits<double>::epsilon()) {
230 MI -=
Pt[r] * log(
Pt[r]);
232 for (
unsigned int t = 0; t < Ncb_; t++) {
233 unsigned int r_Ncb_t_ = r * Ncb_ + t;
234 if (std::fabs(
Prt[r_Ncb_t_]) > std::numeric_limits<double>::epsilon()) {
235 MI +=
Prt[r_Ncb_t_] * log(
Prt[r_Ncb_t_]);
255 double Prt_[256][256];
257 memset(Pr_, 0, 256 *
sizeof(
double));
258 memset(Pt_, 0, 256 *
sizeof(
double));
259 memset(Prt_, 0, 256 * 256 *
sizeof(
double));
261 for (
unsigned int point = 0; point <
templateSize; point++) {
265 Warp->computeDenom(
X1, tp);
270 if ((i2 >= 0) && (j2 >= 0) && (i2 < I.
getHeight() - 1) && (j2 < I.
getWidth() - 1)) {
273 int Tij_ =
static_cast<int>(Tij);
275 IW = I[(int)i2][(
int)j2];
280 int IW_ =
static_cast<int>(IW);
289 for (
int r = 0; r < 256; r++) {
292 if (std::fabs(Pr_[r]) > std::numeric_limits<double>::epsilon()) {
293 MI -= Pr_[r] * log(Pr_[r]);
295 if (std::fabs(Pt_[r]) > std::numeric_limits<double>::epsilon()) {
296 MI -= Pt_[r] * log(Pt_[r]);
298 for (
int t = 0; t < 256; t++) {
299 Prt_[r][t] /= Nbpoint;
300 if (std::fabs(Prt_[r][t]) > std::numeric_limits<double>::epsilon()) {
301 denom -= (Prt_[r][t] * log(Prt_[r][t]));
306 if (std::fabs(denom) > std::numeric_limits<double>::epsilon())
341 unsigned int Nc_ =
static_cast<unsigned int>(
Nc);
342 unsigned int Ncb_ =
static_cast<unsigned int>(
Ncb);
343 unsigned int bspline_ =
static_cast<unsigned int>(
bspline);
345 for (
unsigned int r = 0; r < Nc_; r++) {
346 for (
unsigned int t = 0; t < Nc_; t++) {
347 for (
unsigned int r2 = 0; r2 < bspline_; r2++) {
348 unsigned int r2_r_Ncb_ = (r2 + r) * Ncb_;
349 for (
unsigned int t2 = 0; t2 < bspline_; t2++) {
350 unsigned int t2_t_ = t2 + t;
351 unsigned int r2_r_Ncb_t2_t_nbParam_ = (r2_r_Ncb_ + t2_t_) *
nbParam;
352 Prt[r2_r_Ncb_ + t2_t_] += *pt++;
353 for (
unsigned int ip = 0; ip <
nbParam; ip++) {
354 dPrt[r2_r_Ncb_t2_t_nbParam_ + ip] += *pt++;
355 unsigned int ip_nbParam_ = ip *
nbParam;
356 for (
unsigned int it = 0; it <
nbParam; it++) {
357 d2Prt[r2_r_Ncb_t2_t_nbParam_ *
nbParam + ip_nbParam_ + it] += *pt++;
368 unsigned int indd, indd2;
370 for (
volatile int i = 0; i <
Ncb *
Ncb; i++) {
371 Prt[i] =
Prt[i] / nbpoint;
372 for (
unsigned int j = 0; j <
nbParam; j++) {
373 dPrt[indd] /= nbpoint;
375 for (
unsigned int k = 0; k <
nbParam; k++) {
376 d2Prt[indd2] /= nbpoint;
385 unsigned int Ncb_ = (
unsigned int)
Ncb;
388 memset(
Pr, 0, Ncb_ *
sizeof(
double));
389 memset(
Pt, 0, Ncb_ *
sizeof(
double));
390 for (
unsigned int r = 0; r < Ncb_; r++) {
391 unsigned int r_Nbc_ = r * Ncb_;
392 for (
unsigned int t = 0; t < Ncb_; t++) {
393 Pr[r] +=
Prt[r_Nbc_ + t];
394 Pt[r] +=
Prt[r + Ncb_ * t];
399 for (
unsigned int r = 0; r < Ncb_; r++) {
400 if (std::fabs(
Pr[r]) > std::numeric_limits<double>::epsilon()) {
401 MI -=
Pr[r] * log(
Pr[r]);
403 if (std::fabs(
Pt[r]) > std::numeric_limits<double>::epsilon()) {
404 MI -=
Pt[r] * log(
Pt[r]);
406 unsigned int r_Nbc_ = r * Ncb_;
407 for (
unsigned int t = 0; t < Ncb_; t++) {
408 unsigned int r_Nbc_t_ = r_Nbc_ + t;
409 if (std::fabs(
Prt[r_Nbc_t_]) > std::numeric_limits<double>::epsilon()) {
410 MI +=
Prt[r_Nbc_t_] * log(
Prt[r_Nbc_t_]);
418 double seuilevitinf = 1e-200;
421 unsigned int Ncb_ =
static_cast<unsigned int>(
Ncb);
424 for (
unsigned int t = 0; t < Ncb_; t++) {
425 if (
Pt[t] > seuilevitinf) {
426 for (
unsigned int r = 0; r < Ncb_; r++) {
427 if (
Prt[r * Ncb_ + t] > seuilevitinf) {
428 unsigned int r_Ncb_t_ = r * Ncb_ + t;
429 unsigned int r_Ncb_t_nbParam_ = r_Ncb_t_ *
nbParam;
430 for (
unsigned int it = 0; it <
nbParam; it++) {
434 dtemp = 1. + log(
Prt[r * Ncb_ + t] /
Pt[t]);
436 double Prt_Pt_ = 1. /
Prt[r_Ncb_t_] - 1. /
Pt[t];
437 unsigned int r_Ncb_t_nbParam2_ = r_Ncb_t_ * nbParam2;
438 for (
unsigned int it = 0; it <
nbParam; it++) {
439 unsigned int r_Ncb_t_nbParam2_it_nbParam_ = r_Ncb_t_nbParam2_ + it *
nbParam;
440 for (
unsigned int jt = 0; jt <
nbParam; jt++) {
445 Hessian[it][jt] +=
d2Prt[r_Ncb_t_nbParam2_it_nbParam_ + jt] * dtemp;
458 double seuilevitinf = 1e-200;
459 double u = 0, v = 0, B = 0;
468 for (
unsigned int i = 0; i <
nbParam; i++) {
474 std::fill(
m_du.begin(),
m_du.end(), 0);
475 std::fill(
m_dv.begin(),
m_dv.end(), 0);
476 std::fill(
m_A.begin(),
m_A.end(), 0);
477 std::fill(
m_dB.begin(),
m_dB.end(), 0);
478 for (
unsigned int it = 0; it <
nbParam; it++) {
479 std::fill(
m_d2u[0].begin(),
m_d2u[0].end(), 0);
480 std::fill(
m_d2v[0].begin(),
m_d2v[0].end(), 0);
481 std::fill(
m_dA[0].begin(),
m_dA[0].end(), 0);
486 unsigned int Ncb_ =
static_cast<unsigned int>(
Ncb);
489 for (
unsigned int t = 0; t < Ncb_; t++) {
490 if (
Pt[t] > seuilevitinf) {
491 for (
unsigned int r = 0; r < Ncb_; r++) {
492 unsigned int r_Ncb_t_ = r * Ncb_ + t;
493 if (
Prt[r_Ncb_t_] > seuilevitinf) {
494 unsigned int r_Ncb_t_nbParam_ = r_Ncb_t_ *
nbParam;
495 for (
unsigned int it = 0; it <
nbParam; it++) {
499 double log_Pt_Pr_ = log(
Pt[t] *
Pr[r]);
500 double log_Prt_ = log(
Prt[r_Ncb_t_]);
502 u +=
Prt[r_Ncb_t_] * log_Pt_Pr_;
504 v +=
Prt[r_Ncb_t_] * log_Prt_;
506 double log_Prt_1_ = 1 + log(
Prt[r_Ncb_t_]);
507 for (
unsigned int it = 0; it <
nbParam; it++) {
513 double Prt_ = 1.0 /
Prt[r_Ncb_t_];
514 unsigned int r_Ncb_t_nbParam2_ = r_Ncb_t_ * nbParam2;
515 for (
unsigned int it = 0; it <
nbParam; it++) {
517 unsigned int r_Ncb_t_nbParam2_it_nbParam_ = r_Ncb_t_nbParam2_ + it *
nbParam;
518 for (
unsigned int jt = 0; jt <
nbParam; jt++) {
519 unsigned int r_Ncb_t_nbParam2_it_nbParam_jt_ = r_Ncb_t_nbParam2_it_nbParam_ + jt;
520 m_d2u[it][jt] +=
d2Prt[r_Ncb_t_nbParam2_it_nbParam_jt_] * log_Pt_Pr_ + dprtemp_it2_;
521 m_d2v[it][jt] +=
d2Prt[r_Ncb_t_nbParam2_it_nbParam_jt_] * log_Prt_1_ + dprtemp_it2_;
531 for (
unsigned int it = 0; it <
nbParam; it++) {
536 double A_it_dB_it_ =
m_A[it] *
m_dB[it];
537 for (
unsigned int jt = 0; jt <
nbParam; jt++) {
541 Hessian[it][jt] = (
m_dA[it][jt] * B - A_it_dB_it_) / B2;
548 double seuilevitinf = 1e-200;
550 unsigned int Ncb_ =
static_cast<unsigned int>(
Ncb);
552 for (
unsigned int t = 0; t < Ncb_; t++) {
553 if (
Pt[t] > seuilevitinf) {
554 for (
unsigned int r = 0; r < Ncb_; r++) {
555 unsigned int r_Ncb_t_ = r * Ncb_ + t;
556 if (
Prt[r_Ncb_t_] > seuilevitinf) {
557 unsigned int r_Ncb_t_nbParam_ = r_Ncb_t_ *
nbParam;
558 for (
unsigned int it = 0; it <
nbParam; it++) {
562 dtemp = 1. + log(
Prt[r_Ncb_t_] /
Pt[t]);
564 for (
unsigned int it = 0; it <
nbParam; it++) {
575 unsigned int Ncb_ =
static_cast<unsigned int>(
Ncb);
576 unsigned int Nc_ =
static_cast<unsigned int>(
Nc);
577 unsigned int influBspline_ =
static_cast<unsigned int>(
influBspline);
579 unsigned int Ncb2_ = Ncb_ * Ncb_ *
sizeof(double);
580 unsigned int Ncb2_nbParam_ = Ncb2_ *
nbParam;
581 unsigned int Ncb2_nbParam2_ = Ncb2_nbParam_ *
nbParam;
583 memset(
Prt, 0, Ncb2_);
584 memset(
dPrt, 0, Ncb2_nbParam_);
585 memset(
d2Prt, 0, Ncb2_nbParam2_);
591 unsigned int tNcb =
static_cast<unsigned int>(nc + bspline_);
592 unsigned int tinfluBspline =
static_cast<unsigned int>(bspline_ * bspline_);
593 unsigned int nc_ =
static_cast<unsigned int>(nc);
595 double *tPrtD =
new double[nc_ * nc_ * tinfluBspline];
596 double *tPrt =
new double[tNcb * tNcb];
597 double *tPr =
new double[tNcb];
598 double *tPt =
new double[tNcb];
601 volatile int Nbpoint = 0;
607 memset(tPrt, 0, tNcb * tNcb *
sizeof(
double));
608 memset(tPrtD, 0, nc_ * nc_ * tinfluBspline *
sizeof(
double));
610 Warp->computeCoeff(tp);
611 for (
unsigned int point = 0; point <
templateSize; point++) {
615 Warp->computeDenom(
X1, tp);
620 if ((i2 >= 0) && (j2 >= 0) && (i2 < I.
getHeight() - 1) && (j2 < I.
getWidth()) - 1) {
629 int cr =
static_cast<int>((IW * (nc - 1)) / 255.);
630 int ct =
static_cast<int>((Tij * (nc - 1)) / 255.);
631 double er = (IW * (nc - 1)) / 255. - cr;
632 double et = (Tij * (nc - 1)) / 255. - ct;
636 vpTemplateTrackerMIBSpline::PutPVBsplineD(tPrtD, cr, er, ct, et, nc, 1., bspline_);
640 int tNcb_ = (int)tNcb;
641 int tinfluBspline_ = (int)tinfluBspline;
642 for (
int r = 0; r < nc; r++)
643 for (
int t = 0; t < nc; t++) {
644 for (
volatile int i = 0; i < tinfluBspline_; i++) {
646 r2 = r + i / bspline_;
647 t2 = t + i % bspline_;
648 tPrt[r2 * tNcb_ + t2] += *pt;
663 for (
unsigned int r = 0; r < tNcb; r++)
664 for (
unsigned int t = 0; t < tNcb; t++)
665 tPrt[r * tNcb + t] = tPrt[r * tNcb + t] / Nbpoint;
667 memset(tPr, 0, tNcb *
sizeof(
double));
668 for (
unsigned int r = 0; r < tNcb; r++) {
669 for (
unsigned int t = 0; t < tNcb; t++)
670 tPr[r] += tPrt[r * tNcb + t];
674 memset(tPt, 0, (
size_t)(tNcb *
sizeof(
double)));
675 for (
unsigned int t = 0; t < tNcb; t++) {
676 for (
unsigned int r = 0; r < tNcb; r++)
677 tPt[t] += tPrt[r * tNcb + t];
679 for (
unsigned int r = 0; r < tNcb; r++)
680 if (std::fabs(tPr[r]) > std::numeric_limits<double>::epsilon())
681 MI -= tPr[r] * log(tPr[r]);
683 for (
unsigned int t = 0; t < tNcb; t++)
684 if (std::fabs(tPt[t]) > std::numeric_limits<double>::epsilon())
685 MI -= tPt[t] * log(tPt[t]);
687 for (
unsigned int r = 0; r < tNcb; r++)
688 for (
unsigned int t = 0; t < tNcb; t++)
689 if (std::fabs(tPrt[r * tNcb + t]) > std::numeric_limits<double>::epsilon())
690 MI += tPrt[r * tNcb + t] * log(tPrt[r * tNcb + t]);
709 volatile int Nbpoint = 0;
710 unsigned int Tij, IW;
716 Warp->computeCoeff(tp);
717 for (
unsigned int point = 0; point <
templateSize; point++) {
721 Warp->computeDenom(
X1, tp);
726 if ((i2 >= 0) && (j2 >= 0) && (i2 < I.
getHeight() - 1) && (j2 < I.
getWidth()) - 1) {
731 IW =
static_cast<unsigned int>(I.
getValue(i2, j2));
733 IW =
static_cast<unsigned int>(GaussI.
getValue(i2, j2));
744 Prt256 = Prt256 / Nbpoint;
745 Pr256 = Pr256 / Nbpoint;
746 Pt256 = Pt256 / Nbpoint;
750 for (
unsigned int t = 0; t < 256; t++) {
751 for (
unsigned int r = 0; r < 256; r++) {
752 if (std::fabs(Prt256[r][t]) > std::numeric_limits<double>::epsilon())
753 MI += Prt256[r][t] * log(Prt256[r][t]);
755 if (std::fabs(Pt256[t]) > std::numeric_limits<double>::epsilon())
756 MI += -Pt256[t] * log(Pt256[t]);
757 if (std::fabs(Pr256[t]) > std::numeric_limits<double>::epsilon())
758 MI += -Pr256[t] * log(Pr256[t]);
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Implementation of column vector and the associated operations.
void resize(unsigned int i, bool flagNullify=true)
error that can be emitted by ViSP classes.
@ divideByZeroError
Division by zero.
static void filter(const vpImage< ImageType > &I, vpImage< FilterType > &If, const vpArray2D< FilterType > &M, bool convolve=false, const vpImage< bool > *p_mask=nullptr)
unsigned int getWidth() const
Type getValue(unsigned int i, unsigned int j) const
unsigned int getHeight() const
Implementation of a matrix and operations on matrices.
vpHessienApproximationType ApproxHessian
void computeHessienNormalized(vpMatrix &H)
std::vector< std::vector< double > > m_d2v
vpHessienType hessianComputation
double getCost(const vpImage< unsigned char > &I, const vpColVector &tp) VP_OVERRIDE
void computeMI(double &MI)
std::vector< double > m_dB
std::vector< double > m_du
void computeProba(int &nbpoint)
vpTemplateTrackerMI()
Default constructor.
virtual ~vpTemplateTrackerMI() VP_OVERRIDE
void computeHessien(vpMatrix &H)
std::vector< double > m_dv
std::vector< std::vector< double > > m_d2u
double getNormalizedCost(const vpImage< unsigned char > &I, const vpColVector &tp)
std::vector< std::vector< double > > m_dA
double getMI256(const vpImage< unsigned char > &I, const vpColVector &tp)
std::vector< double > m_A
void setBspline(const vpBsplineType &newbs)
virtual void warpX(const int &v1, const int &u1, double &v2, double &u2, const vpColVector &p)=0
vpTemplateTrackerPoint * ptTemplate
vpTemplateTrackerWarp * Warp
unsigned int templateSize
Error that can be emitted by the vpTracker class and its derivatives.
@ notEnoughPointError
Not enough point to track.