Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpTemplateTrackerMIForwardAdditional.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
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 http://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  * Example of template tracking.
32  *
33  * Authors:
34  * Amaury Dame
35  * Aurelien Yol
36  * Fabien Spindler
37  *
38  *****************************************************************************/
39 
40 #include <visp3/tt_mi/vpTemplateTrackerMIForwardAdditional.h>
41 
42 #ifdef VISP_HAVE_OPENMP
43 #include <omp.h>
44 #endif
45 
47  : vpTemplateTrackerMI(_warp), minimizationMethod(USE_NEWTON), evolRMS(0), x_pos(NULL), y_pos(NULL),
48  threshold_RMS(0), p_prec(), G_prec(), KQuasiNewton()
49 {
50  evolRMS = 0;
51  x_pos = y_pos = NULL;
52  useCompositionnal=false;
53  threshold_RMS=1e-20;
54  minimizationMethod=USE_NEWTON;
55 }
56 
58 {
59  //std::cout<<"Initialise Hessian at Desired position..."<<std::endl;
60 
61  dW=0;
62 
63  int Nbpoint=0;
64 
65  if(blur)
69 
70  double Tij;
71  double IW,dx,dy;
72  int cr,ct;
73  double er,et;
74 
75  Nbpoint=0;
76 
78  Warp->computeCoeff(p);
79  for(unsigned int point=0;point<templateSize;point++)
80  {
81  int i=ptTemplate[point].y;
82  int j=ptTemplate[point].x;
83  X1[0]=j;X1[1]=i;
84  X2[0]=j;X2[1]=i;
85 
86  Warp->computeDenom(X1,p);
87  Warp->warpX(X1,X2,p);
88 
89  double j2=X2[0];
90  double i2=X2[1];
91 
92  if((i2>=0)&&(j2>=0)&&(i2<I.getHeight()-1)&&(j2<I.getWidth()-1))
93  {
94  Nbpoint++;
95  Tij=ptTemplate[point].val;
96  if(!blur)
97  IW=I.getValue(i2,j2);
98  else
99  IW=BI.getValue(i2,j2);
100 
101  dx=1.*dIx.getValue(i2,j2)*(Nc-1)/255.;
102  dy=1.*dIy.getValue(i2,j2)*(Nc-1)/255.;
103 
104  ct=(int)((IW*(Nc-1))/255.);
105  cr=(int)((Tij*(Nc-1))/255.);
106  et=(IW*(Nc-1))/255.-ct;
107  er=((double)Tij*(Nc-1))/255.-cr;
108  //std::cout<<"test"<<std::endl;
109  Warp->dWarp(X1,X2,p,dW);
110 
111  double *tptemp=new double[nbParam];
112  for(unsigned int it=0;it<nbParam;it++)
113  tptemp[it] =dW[0][it]*dx+dW[1][it]*dy;
114 
116  vpTemplateTrackerMIBSpline::PutTotPVBsplineNoSecond(PrtTout, cr, er, ct, et, Nc, tptemp, nbParam, bspline);
118  vpTemplateTrackerMIBSpline::PutTotPVBspline(PrtTout, cr, er, ct, et, Nc, tptemp, nbParam, bspline);
119 
120  delete[] tptemp;
121  }
122  }
123 
124  if(Nbpoint>0)
125  {
126  double MI;
127  computeProba(Nbpoint);
128  computeMI(MI);
130 
131 
132  // double conditionnement=GetConditionnement(Hdesire);
133  // std::cout<<"conditionnement : "<<conditionnement<<std::endl;
135  try
136  {
138  }
139  catch(vpException &e)
140  {
141  //std::cerr<<"probleme inversion"<<std::endl;
142  throw(e);
143  }
144  //std::cout<<"Hdesire = "<<Hdesire<<std::endl;
145  //std::cout<<"\tEnd initialisation..."<<std::endl;
146  }
147 
148 }
149 
151 {
152  dW=0;
153 
154  //double erreur=0;
155  int Nbpoint=0;
156  if(blur)
160 
161  double MI=0,MIprec=-1000;
162 
164 
165  double alpha=2.;
166 
167  unsigned int iteration=0;
168 
169  initPosEvalRMS(p);
170  do
171  {
172  if(iteration%5==0)
174  Nbpoint=0;
175  MIprec=MI;
176  MI=0;
177  //erreur=0;
178 
180 
181  Warp->computeCoeff(p);
182 #ifdef VISP_HAVE_OPENMP
183  int nthreads = omp_get_num_procs() ;
184  //std::cout << "file: " __FILE__ << " line: " << __LINE__ << " function: " << __FUNCTION__ << " nthread: " << nthreads << std::endl;
185  omp_set_num_threads(nthreads);
186 #pragma omp parallel for default(shared)
187 #endif
188  for(int point=0;point<(int)templateSize;point++)
189  {
190  int i=ptTemplate[point].y;
191  int j=ptTemplate[point].x;
192  X1[0]=j;X1[1]=i;
193 
194  Warp->computeDenom(X1,p);
195  Warp->warpX(X1,X2,p);
196 
197  double j2=X2[0];
198  double i2=X2[1];
199 
200  if((i2>=0)&&(j2>=0)&&(i2<I.getHeight()-1)&&(j2<I.getWidth()-1))
201  {
202  Nbpoint++;
203  double Tij=ptTemplate[point].val;
204  double IW;
205  if(!blur)
206  IW=I.getValue(i2,j2);
207  else
208  IW=BI.getValue(i2,j2);
209 
210  double dx=1.*dIx.getValue(i2,j2)*(Nc-1)/255.;
211  double dy=1.*dIy.getValue(i2,j2)*(Nc-1)/255.;
212 
213  int ct=(int)((IW*(Nc-1))/255.);
214  int cr=(int)((Tij*(Nc-1))/255.);
215  double et=(IW*(Nc-1))/255.-ct;
216  double er=((double)Tij*(Nc-1))/255.-cr;
217 
218  //calcul de l'erreur
219  //erreur+=(Tij-IW)*(Tij-IW);
220 
221  //Calcul de l'histogramme joint par interpolation bilinÈaire (Bspline ordre 1)
222  Warp->dWarp(X1,X2,p,dW);
223 
224  //double *tptemp=temp;
225  double *tptemp=new double[nbParam];;
226  for(unsigned int it=0;it<nbParam;it++)
227  tptemp[it] =(dW[0][it]*dx+dW[1][it]*dy);
228  //*tptemp++ =dW[0][it]*dIWx+dW[1][it]*dIWy;
229  //std::cout<<cr<<" "<<ct<<" ; ";
231  vpTemplateTrackerMIBSpline::PutTotPVBsplineNoSecond(PrtTout, cr, er, ct, et, Nc, tptemp, nbParam, bspline);
233  vpTemplateTrackerMIBSpline::PutTotPVBspline(PrtTout, cr, er, ct, et, Nc, tptemp, nbParam, bspline);
234 
235  delete[] tptemp;
236  }
237  }
238 
239  if(Nbpoint==0)
240  {
241  //std::cout<<"plus de point dans template suivi"<<std::endl;
242  diverge=true;
243  MI=0;
245  throw(vpTrackingException(vpTrackingException::notEnoughPointError, "No points in the template"));
246  }
247  else
248  {
249  computeProba(Nbpoint);
250  computeMI(MI);
251  //std::cout<<iteration<<"\tMI= "<<MI<<std::endl;
252  computeHessien(H);
253  computeGradient();
254 
256  try
257  {
258  switch(hessianComputation)
259  {
262  break;
264  if(HLM.cond()>HLMdesire.cond())
266  else
267  dp=gain*0.2*HLM.inverseByLU()*G;
268  break;
269  default:
270  dp=gain*0.2*HLM.inverseByLU()*G;
271  break;
272  }
273  }
274  catch(vpException &e)
275  {
276  //std::cerr<<"probleme inversion"<<std::endl;
278  throw(e);
279  }
280  }
281 
282  switch(minimizationMethod)
283  {
285  {
286  vpColVector p_test_LMA(nbParam);
288  p_test_LMA=p-100000.1*dp;
289  else
290  p_test_LMA=p+1.*dp;
291  MI=-getCost(I,p);
292  double MI_LMA=-getCost(I,p_test_LMA);
293  if(MI_LMA>MI)
294  {
295  p=p_test_LMA;
296  lambda=(lambda/10.<1e-6)?lambda/10.:1e-6;
297  }
298  else
299  {
300  lambda=(lambda*10.<1e6)?1e6:lambda*10.;
301  }
302  }
303  break;
305  {
306  dp=-gain*6.0*G;
307  if(useBrent)
308  {
309  alpha=2.;
310  computeOptimalBrentGain(I,p,-MI,dp,alpha);
311  dp=alpha*dp;
312  }
313  p+=1.*dp;
314  break;
315  }
316 
318  {
319  if(iterationGlobale!=0)
320  {
321  vpColVector s_quasi=p-p_prec;
322  vpColVector y_quasi=G-G_prec;
323  double s_scal_y=s_quasi.t()*y_quasi;
324  //if(s_scal_y!=0)//BFGS
325  // KQuasiNewton=KQuasiNewton-(s_quasi*y_quasi.t()*KQuasiNewton+KQuasiNewton*y_quasi*s_quasi.t())/s_scal_y+(1.+y_quasi.t()*(KQuasiNewton*y_quasi)/s_scal_y)*s_quasi*s_quasi.t()/s_scal_y;
326  //if(s_scal_y!=0)//DFP
327  if(std::fabs(s_scal_y) > std::numeric_limits<double>::epsilon())
328  KQuasiNewton=KQuasiNewton+0.001*(s_quasi*s_quasi.t()/s_scal_y-KQuasiNewton*y_quasi*y_quasi.t()*KQuasiNewton/(y_quasi.t()*KQuasiNewton*y_quasi));
329  }
330  dp=-KQuasiNewton*G;
331  p_prec=p;
332  G_prec=G;
333  p-=1.01*dp;
334  }
335  break;
336 
337  default:
338  {
340  dp=-0.1*dp;
341  if(useBrent)
342  {
343  alpha=2.;
344  computeOptimalBrentGain(I,p,-MI,dp,alpha);
345  //std::cout<<alpha<<std::endl;
346  dp=alpha*dp;
347  }
348 
349  p+=1.*dp;
350  break;
351  }
352  }
353 
354  computeEvalRMS(p);
355  iteration++;
357 
358  }
359  while( (std::fabs(MI-MIprec) > std::fabs(MI)*std::numeric_limits<double>::epsilon()) &&(iteration< iterationMax)&&(evolRMS>threshold_RMS) );
360  //while( (MI!=MIprec) &&(iteration< iterationMax)&&(evolRMS>threshold_RMS) );
361  if(Nbpoint==0) {
362  //std::cout<<"plus de point dans template suivi"<<std::endl;
364  throw(vpTrackingException(vpTrackingException::notEnoughPointError, "No points in the template"));
365  }
366 
367  nbIteration=iteration;
370  {
371  MI_postEstimation = -1;
372  }
374 }
375 
377 {
378  unsigned int nb_corners = zoneTracked->getNbTriangle() * 3;
379  x_pos=new double[nb_corners];
380  y_pos=new double[nb_corners];
381 
382  Warp->computeCoeff(pw);
383  vpTemplateTrackerTriangle triangle;
384 
385  for(unsigned int i=0;i<zoneTracked->getNbTriangle();i++)
386  {
387  zoneTracked->getTriangle(i, triangle);
388  for (unsigned int j=0; j<3; j++) {
389  triangle.getCorner(j, X1[0], X1[1]);
390 
391  Warp->computeDenom(X1,pw);
392  Warp->warpX(X1,X2,pw);
393  x_pos[i*3+j]=X2[0];
394  y_pos[i*3+j]=X2[1];
395  }
396  }
397 }
398 
400 {
401  unsigned int nb_corners = zoneTracked->getNbTriangle() * 3;
402 
403  Warp->computeCoeff(pw);
404  evolRMS=0;
405  vpTemplateTrackerTriangle triangle;
406 
407  for(unsigned int i=0;i<zoneTracked->getNbTriangle();i++)
408  {
409  zoneTracked->getTriangle(i, triangle);
410  for (unsigned int j=0; j<3; j++) {
411  triangle.getCorner(j, X1[0], X1[1]);
412 
413  Warp->computeDenom(X1,pw);
414  Warp->warpX(X1,X2,pw);
415  evolRMS+=(x_pos[i*3+j]-X2[0])*(x_pos[i*3+j]-X2[0])+(y_pos[i*3+j]-X2[1])*(y_pos[i*3+j]-X2[1]);
416  x_pos[i*3+j]=X2[0];
417  y_pos[i*3+j]=X2[1];
418  }
419  }
420  evolRMS=evolRMS/nb_corners;
421 }
422 
424 {
425  delete[] x_pos;
426  delete[] y_pos;
427 }
void computeHessien(vpMatrix &H)
void getTriangle(unsigned int i, vpTemplateTrackerTriangle &T) const
unsigned int getWidth() const
Definition: vpImage.h:226
void trackNoPyr(const vpImage< unsigned char > &I)
vpTemplateTrackerPoint * ptTemplate
virtual void warpX(const int &i, const int &j, double &i2, double &j2, const vpColVector &ParamM)=0
void computeOptimalBrentGain(const vpImage< unsigned char > &I, vpColVector &tp, double tMI, vpColVector &direction, double &alpha)
error that can be emited by ViSP classes.
Definition: vpException.h:73
Type getValue(double i, double j) const
Definition: vpImage.h:1477
vpColVector getCorner(unsigned int i) const
static void getGradYGauss2D(const vpImage< unsigned char > &I, vpImage< double > &dIy, const double *gaussianKernel, const double *gaussianDerivativeKernel, unsigned int size)
static void getGradXGauss2D(const vpImage< unsigned char > &I, vpImage< double > &dIx, const double *gaussianKernel, const double *gaussianDerivativeKernel, unsigned int size)
vpImage< double > BI
vpHessienApproximationType ApproxHessian
double cond() const
Definition: vpMatrix.cpp:3500
unsigned int templateSize
unsigned int iterationMax
Error that can be emited by the vpTracker class and its derivates.
double getCost(const vpImage< unsigned char > &I, const vpColVector &tp)
unsigned int getNbTriangle() const
vpImage< double > dIx
void computeMI(double &MI)
vpRowVector t() const
vpImage< double > dIy
unsigned int iterationGlobale
unsigned int nbIteration
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
vpMatrix inverseByLU() const
vpTemplateTrackerZone * zoneTracked
unsigned int getHeight() const
Definition: vpImage.h:175
static void filter(const vpImage< double > &I, vpImage< double > &Iu, vpImage< double > &Iv, const vpMatrix &M, const bool convolve=false)
void initHessienDesired(const vpImage< unsigned char > &I)
vpTemplateTrackerWarp * Warp
static void computeHLM(const vpMatrix &H, const double &alpha, vpMatrix &HLM)
Definition: vpMatrix.cpp:3525
void computeProba(int &nbpoint)
virtual void dWarp(const vpColVector &X1, const vpColVector &X2, const vpColVector &ParamM, vpMatrix &dW)=0
vpHessienType hessianComputation