ViSP  2.10.0
vpTemplateTrackerZNCCInverseCompositional.cpp
1 /****************************************************************************
2  *
3  * $Id: vpTemplateTrackerZNCCInverseCompositional.cpp 5264 2015-02-04 13:49:55Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2014 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  * Description:
34  * Template tracker.
35  *
36  * Authors:
37  * Amaury Dame
38  * Aurelien Yol
39  * Fabien Spindler
40  *
41  *****************************************************************************/
42 #include <limits> // numeric_limits
43 
44 #include <visp/vpTemplateTrackerZNCCInverseCompositional.h>
45 #include <visp/vpImageFilter.h>
46 
48  : vpTemplateTrackerZNCC(warp), compoInitialised(false),
49  evolRMS(0), x_pos(), y_pos(), threshold_RMS(1e-8), moydIrefdp()
50 {
51  useInverse=true;
52 }
53 
55 {
56  //std::cout<<"Initialise precomputed value of Compositionnal Inverse"<<std::endl;
57  int i,j;
58 
61 
62 
63  for(unsigned int point=0;point<templateSize;point++)
64  {
65  i=ptTemplate[point].y;
66  j=ptTemplate[point].x;
67 
68  X1[0]=j;X1[1]=i;
69  Warp->computeDenom(X1,p);
70  ptTemplate[point].dW=new double[nbParam];
71 
72  double dx=ptTemplate[point].dx;
73  double dy=ptTemplate[point].dy;
74  //std::cout<<ptTemplate[point].dx<<","<<ptTemplate[point].dy<<std::endl;
75 
76  Warp->getdW0(i,j,dy,dx,ptTemplate[point].dW);
77 
78  }
79  //vpTRACE("fin Comp Inverse");
80  compoInitialised=true;
81 }
82 
84 {
85  initCompInverse(I);
86 
87  if(blur)
91 
92  vpImage<double> dIxx,dIxy,dIyx,dIyy;
95 
98 
99  Warp->computeCoeff(p);
100  double Ic,dIcx=0.,dIcy=0.;
101  double Iref;
102  int i,j;
103  double i2,j2;
104  int Nbpoint=0;
105 
106  double moyIref=0;
107  double moyIc=0;
108  double denom=0;
110  vpMatrix moyd2Iref(nbParam,nbParam);moyd2Iref=0;
111 
112  for(unsigned int point=0;point<templateSize;point++)
113  {
114  i=ptTemplate[point].y;
115  j=ptTemplate[point].x;
116  X1[0]=j;X1[1]=i;
117  X2[0]=j;X2[1]=i;
118 
119  Warp->computeDenom(X1,p);
120 
121  j2=X2[0];i2=X2[1];
122 
123  if((i2>=0)&&(j2>=0)&&(i2<I.getHeight()-1)&&(j2<I.getWidth()-1))
124  {
125  Iref=ptTemplate[point].val;
126 
127  if(!blur)
128  Ic=I.getValue(i2,j2);
129  else
130  Ic=BI.getValue(i2,j2);
131 
132  Nbpoint++;
133  moyIref+=Iref;
134  moyIc+=Ic;
135 
136  for(unsigned int it=0;it<nbParam;it++)
137  moydIrefdp[it]+=ptTemplate[point].dW[it];
138 
139 
140  Warp->dWarp(X1,X2,p,dW);
141  double *tempt=new double[nbParam];
142  for(unsigned int it=0;it<nbParam;it++)
143  tempt[it]=dW[0][it]*dIcx+dW[1][it]*dIcy;
144  double d_Ixx=dIxx.getValue(i2,j2);
145  double d_Iyy=dIyy.getValue(i2,j2);
146  double d_Ixy=dIxy.getValue(i2,j2);
147 
148  for(unsigned int it=0;it<nbParam;it++)
149  for(unsigned int jt=0;jt<nbParam;jt++)
150  {
151  moyd2Iref[it][jt] +=(dW[0][it]*(dW[0][jt]*d_Ixx+dW[1][jt]*d_Ixy)
152  +dW[1][it]*(dW[0][jt]*d_Ixy+dW[1][jt]*d_Iyy));
153  }
154 
155  delete[] tempt;
156 
157 
158  }
159  }
160 
161  moyIref=moyIref/Nbpoint;
162  moydIrefdp=moydIrefdp/Nbpoint;
163  moyd2Iref=moyd2Iref/Nbpoint;
164  moyIc=moyIc/Nbpoint;
165  Hdesire=0;
166  double covarIref=0,covarIc=0;
167  double sIcIref=0;
168  vpColVector sIcdIref(nbParam);sIcdIref=0;
169  vpMatrix sIcd2Iref(nbParam,nbParam);sIcd2Iref=0;
170  vpMatrix sdIrefdIref(nbParam,nbParam);sdIrefdIref=0;
171  for(unsigned int point=0;point<templateSize;point++)
172  {
173  i=ptTemplate[point].y;
174  j=ptTemplate[point].x;
175  X1[0]=j;X1[1]=i;
176  X2[0]=j;X2[1]=i;
177 
178  Warp->computeDenom(X1,p);
179 
180  j2=X2[0];i2=X2[1];
181 
182  if((i2>=0)&&(j2>=0)&&(i2<I.getHeight()-1)&&(j2<I.getWidth()-1))
183  {
184  Iref=ptTemplate[point].val;
185 
186  if(!blur)
187  Ic=I.getValue(i2,j2);
188  else
189  Ic=BI.getValue(i2,j2);
190 
191  dIcx=dIx.getValue(i2,j2);
192  dIcy=dIy.getValue(i2,j2);
193 
194  Warp->dWarp(X1,X2,p,dW);
195 
196  double *tempt=new double[nbParam];
197  for(unsigned int it=0;it<nbParam;it++)
198  tempt[it]=dW[0][it]*dIcx+dW[1][it]*dIcy;
199 
200  double prodIc=(Ic-moyIc);
201 
202  double d_Ixx=dIxx.getValue(i2,j2);
203  double d_Iyy=dIyy.getValue(i2,j2);
204  double d_Ixy=dIxy.getValue(i2,j2);
205 
206  for(unsigned int it=0;it<nbParam;it++)
207  for(unsigned int jt=0;jt<nbParam;jt++)
208  {
209  sIcd2Iref[it][jt] +=prodIc*(dW[0][it]*(dW[0][jt]*d_Ixx+dW[1][jt]*d_Ixy)
210  +dW[1][it]*(dW[0][jt]*d_Ixy+dW[1][jt]*d_Iyy)-moyd2Iref[it][jt]);
211  sdIrefdIref[it][jt] +=(ptTemplate[point].dW[it]-moydIrefdp[it])*(ptTemplate[point].dW[jt]-moydIrefdp[jt]);
212  }
213 
214 
215  delete[] tempt;
216 
217  for(unsigned int it=0;it<nbParam;it++)
218  sIcdIref[it]+=prodIc*(ptTemplate[point].dW[it]-moydIrefdp[it]);
219 
220  covarIref+=(Iref-moyIref)*(Iref-moyIref);
221  covarIc+=(Ic-moyIc)*(Ic-moyIc);
222  sIcIref+=(Iref-moyIref)*(Ic-moyIc);
223  }
224 
225 
226  }
227  covarIref=sqrt(covarIref);
228  covarIc=sqrt(covarIc);
229 
230  denom=covarIref*covarIc;
231 
232  double NCC=sIcIref/denom;
233  //std::cout<<"NCC = "<<NCC<<std::endl;
234  vpColVector dcovarIref(nbParam);dcovarIref=-sIcdIref/covarIref;
235 
236  vpColVector dNCC(nbParam);dNCC=(sIcdIref/denom-NCC*dcovarIref/covarIref);
237  vpMatrix d2covarIref(nbParam,nbParam);
238  d2covarIref=-(sIcd2Iref-sdIrefdIref+dcovarIref*dcovarIref.t())/covarIref;
239 #ifdef APPROX_NCC
240  Hdesire=sIcd2Iref/denom;
241 #else
242  Hdesire=(sIcd2Iref-sdIrefdIref+dcovarIref*dcovarIref.t())/denom;
243 #endif
246  //std::cout<<"Hdesire = "<<Hdesire<<std::endl;
247 }
248 
250 {
251  if(blur)
253 
254  double erreur=0;
255  unsigned int Nbpoint=0;
256  vpColVector dpinv(nbParam);
257  double Ic;
258  double Iref;
259  unsigned int iteration=0;
260  int i,j;
261  double i2,j2;
262  initPosEvalRMS(p);
263  do
264  {
265  Nbpoint=0;
266  erreur=0;
267  G=0;
268  Warp->computeCoeff(p);
269  double moyIref=0;
270  double moyIc=0;
271  double denom=0;
272  for(unsigned int point=0;point<templateSize;point++)
273  {
274  i=ptTemplate[point].y;
275  j=ptTemplate[point].x;
276  X1[0]=j;X1[1]=i;
277 
278  Warp->computeDenom(X1,p);
279  Warp->warpX(X1,X2,p);
280 
281  j2=X2[0];i2=X2[1];
282  if((i2>=0)&&(j2>=0)&&(i2<I.getHeight()-1)&&(j2<I.getWidth()-1))
283  {
284  Iref=ptTemplate[point].val;
285 
286  if(!blur)
287  Ic=I.getValue(i2,j2);
288  else
289  Ic=BI.getValue(i2,j2);
290 
291  Nbpoint++;
292  moyIref+=Iref;
293  moyIc+=Ic;
294  }
295 
296 
297  }
298  if(Nbpoint > 0)
299  {
300  moyIref=moyIref/Nbpoint;
301  moyIc=moyIc/Nbpoint;
302  double sIcIref=0;
303  double covarIref=0,covarIc=0;
304  vpColVector sIcdIref(nbParam);sIcdIref=0;
305  vpColVector sIrefdIref(nbParam);sIrefdIref=0;
306 
307 
308  for(unsigned int point=0;point<templateSize;point++)
309  {
310  i=ptTemplate[point].y;
311  j=ptTemplate[point].x;
312  X1[0]=j;X1[1]=i;
313 
314  Warp->computeDenom(X1,p);
315  Warp->warpX(X1,X2,p);
316 
317  j2=X2[0];i2=X2[1];
318  if((i2>=0)&&(j2>=0)&&(i2<I.getHeight()-1)&&(j2<I.getWidth()-1))
319  {
320  Iref=ptTemplate[point].val;
321 
322  if(!blur)
323  Ic=I.getValue(i2,j2);
324  else
325  Ic=BI.getValue(i2,j2);
326 
327 
328  double prod=(Ic-moyIc);
329  for(unsigned int it=0;it<nbParam;it++)
330  sIcdIref[it]+=prod*(ptTemplate[point].dW[it]-moydIrefdp[it]);
331  for(unsigned int it=0;it<nbParam;it++)
332  sIrefdIref[it]+=(Iref-moyIref)*(ptTemplate[point].dW[it]-moydIrefdp[it]);
333 
334  double er=(Iref-Ic);
335  erreur+=(er*er);
336  //denom+=(Iref-moyIref)*(Iref-moyIref)*(Ic-moyIc)*(Ic-moyIc);
337  covarIref+=(Iref-moyIref)*(Iref-moyIref);
338  covarIc+=(Ic-moyIc)*(Ic-moyIc);
339  sIcIref+=(Iref-moyIref)*(Ic-moyIc);
340  }
341 
342 
343  }
344  covarIref=sqrt(covarIref);
345  covarIc=sqrt(covarIc);
346  denom=covarIref*covarIc;
347 
348  //if(denom==0.0)
349  if (std::fabs(denom) <= std::numeric_limits<double>::epsilon())
350  {
351  diverge=true;
352  }
353  else
354  {
355  double NCC=sIcIref/denom;
356  vpColVector dcovarIref(nbParam);dcovarIref=sIrefdIref/covarIref;
357  G=1.*(sIcdIref/denom-NCC*dcovarIref/covarIref);
358 
359 
360  try
361  {
362  dp=-1.*HLMdesireInverse*G;
363  }
364  catch(...)
365  {
366  std::cout<<"probleme inversion"<<std::endl;
367  break;
368  }
369 
370  Warp->getParamInverse(dp,dpinv);
371  Warp->pRondp(p,dpinv,p);
372 
373  computeEvalRMS(p);
374  }
375  }
376  else
377  diverge=true;
378 
379  iteration++;
380  }
381  while( (!diverge &&(evolRMS>threshold_RMS) && (iteration < iterationMax)));
382 
383  //std::cout<<"erreur "<<erreur<<std::endl;
384  nbIteration=iteration;
385 
387 }
388 
390 {
391  unsigned int nb_corners = zoneTracked->getNbTriangle() * 3;
392  x_pos.resize(nb_corners);
393  y_pos.resize(nb_corners);
394 
395  Warp->computeCoeff(p);
396  vpTemplateTrackerTriangle triangle;
397 
398  for(unsigned int i=0;i<zoneTracked->getNbTriangle();i++)
399  {
400  zoneTracked->getTriangle(i, triangle);
401  for (unsigned int j=0; j<3; j++) {
402  triangle.getCorner(j, X1[0], X1[1]);
403 
404  Warp->computeDenom(X1,p_);
405  Warp->warpX(X1,X2,p_);
406  x_pos[i*3+j]=X2[0];
407  y_pos[i*3+j]=X2[1];
408  }
409  }
410 }
411 
413 {
414  unsigned int nb_corners = zoneTracked->getNbTriangle() * 3;
415 
416  Warp->computeCoeff(p_);
417  evolRMS=0;
418  vpTemplateTrackerTriangle triangle;
419 
420  for(unsigned int i=0;i<zoneTracked->getNbTriangle();i++)
421  {
422  zoneTracked->getTriangle(i, triangle);
423  for (unsigned int j=0; j<3; j++) {
424  triangle.getCorner(j, X1[0], X1[1]);
425 
426  Warp->computeDenom(X1,p_);
427  Warp->warpX(X1,X2,p_);
428  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]);
429  x_pos[i*3+j]=X2[0];
430  y_pos[i*3+j]=X2[1];
431  }
432  }
433  evolRMS=evolRMS/nb_corners;
434 
435 }
436 
438 {
439 }
Definition of the vpMatrix class.
Definition: vpMatrix.h:98
void getTriangle(unsigned int i, vpTemplateTrackerTriangle &T) const
unsigned int getWidth() const
Definition: vpImage.h:161
static void getGradX(const vpImage< unsigned char > &I, vpImage< double > &dIx)
vpTemplateTrackerPoint * ptTemplate
static void getGradY(const vpImage< unsigned char > &I, vpImage< double > &dIy)
virtual void warpX(const int &i, const int &j, double &i2, double &j2, const vpColVector &ParamM)=0
Type getValue(double i, double j) const
Definition: vpImage.h:1068
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
virtual void getParamInverse(const vpColVector &ParamM, vpColVector &ParamMinv) const =0
unsigned int templateSize
unsigned int iterationMax
virtual void pRondp(const vpColVector &p1, const vpColVector &p2, vpColVector &pres) const =0
unsigned int getNbTriangle() const
static void filter(const vpImage< double > &I, vpImage< double > &Iu, vpImage< double > &Iv, const vpMatrix &M)
vpImage< double > dIx
vpRowVector t() const
Transpose of a vector.
vpImage< double > dIy
virtual void getdW0(const int &i, const int &j, const double &dy, const double &dx, double *dIdW)=0
unsigned int nbIteration
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
vpMatrix inverseByLU() const
vpTemplateTrackerZone * zoneTracked
unsigned int getHeight() const
Definition: vpImage.h:152
vpTemplateTrackerWarp * Warp
static void computeHLM(const vpMatrix &H, const double &alpha, vpMatrix &HLM)
Definition: vpMatrix.cpp:4320
virtual void dWarp(const vpColVector &X1, const vpColVector &X2, const vpColVector &ParamM, vpMatrix &dW)=0
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpColVector.h:98