Visual Servoing Platform  version 3.0.0
vpTemplateTrackerZNCCInverseCompositional.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2015 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  * Template tracker.
32  *
33  * Authors:
34  * Amaury Dame
35  * Aurelien Yol
36  * Fabien Spindler
37  *
38  *****************************************************************************/
39 #include <limits> // numeric_limits
40 
41 #include <visp3/tt/vpTemplateTrackerZNCCInverseCompositional.h>
42 #include <visp3/core/vpImageFilter.h>
43 
45  : vpTemplateTrackerZNCC(warp), compoInitialised(false),
46  evolRMS(0), x_pos(), y_pos(), threshold_RMS(1e-8), moydIrefdp()
47 {
48  useInverse=true;
49 }
50 
52 {
53  //std::cout<<"Initialise precomputed value of Compositionnal Inverse"<<std::endl;
54  int i,j;
55 
58 
59 
60  for(unsigned int point=0;point<templateSize;point++)
61  {
62  i=ptTemplate[point].y;
63  j=ptTemplate[point].x;
64 
65  X1[0]=j;X1[1]=i;
66  Warp->computeDenom(X1,p);
67  ptTemplate[point].dW=new double[nbParam];
68 
69  double dx=ptTemplate[point].dx;
70  double dy=ptTemplate[point].dy;
71  //std::cout<<ptTemplate[point].dx<<","<<ptTemplate[point].dy<<std::endl;
72 
73  Warp->getdW0(i,j,dy,dx,ptTemplate[point].dW);
74 
75  }
76  //vpTRACE("fin Comp Inverse");
77  compoInitialised=true;
78 }
79 
81 {
82  initCompInverse(I);
83 
84  if(blur)
88 
89  vpImage<double> dIxx,dIxy,dIyx,dIyy;
92 
95 
96  Warp->computeCoeff(p);
97  double Ic,dIcx=0.,dIcy=0.;
98  double Iref;
99  int i,j;
100  double i2,j2;
101  int Nbpoint=0;
102 
103  double moyIref=0;
104  double moyIc=0;
105  double denom=0;
107  vpMatrix moyd2Iref(nbParam,nbParam);moyd2Iref=0;
108 
109  for(unsigned int point=0;point<templateSize;point++)
110  {
111  i=ptTemplate[point].y;
112  j=ptTemplate[point].x;
113  X1[0]=j;X1[1]=i;
114  X2[0]=j;X2[1]=i;
115 
116  Warp->computeDenom(X1,p);
117 
118  j2=X2[0];i2=X2[1];
119 
120  if((i2>=0)&&(j2>=0)&&(i2<I.getHeight()-1)&&(j2<I.getWidth()-1))
121  {
122  Iref=ptTemplate[point].val;
123 
124  if(!blur)
125  Ic=I.getValue(i2,j2);
126  else
127  Ic=BI.getValue(i2,j2);
128 
129  Nbpoint++;
130  moyIref+=Iref;
131  moyIc+=Ic;
132 
133  for(unsigned int it=0;it<nbParam;it++)
134  moydIrefdp[it]+=ptTemplate[point].dW[it];
135 
136 
137  Warp->dWarp(X1,X2,p,dW);
138  double *tempt=new double[nbParam];
139  for(unsigned int it=0;it<nbParam;it++)
140  tempt[it]=dW[0][it]*dIcx+dW[1][it]*dIcy;
141  double d_Ixx=dIxx.getValue(i2,j2);
142  double d_Iyy=dIyy.getValue(i2,j2);
143  double d_Ixy=dIxy.getValue(i2,j2);
144 
145  for(unsigned int it=0;it<nbParam;it++)
146  for(unsigned int jt=0;jt<nbParam;jt++)
147  {
148  moyd2Iref[it][jt] +=(dW[0][it]*(dW[0][jt]*d_Ixx+dW[1][jt]*d_Ixy)
149  +dW[1][it]*(dW[0][jt]*d_Ixy+dW[1][jt]*d_Iyy));
150  }
151 
152  delete[] tempt;
153 
154 
155  }
156  }
157 
158  moyIref=moyIref/Nbpoint;
159  moydIrefdp=moydIrefdp/Nbpoint;
160  moyd2Iref=moyd2Iref/Nbpoint;
161  moyIc=moyIc/Nbpoint;
162  Hdesire=0;
163  double covarIref=0,covarIc=0;
164  double sIcIref=0;
165  vpColVector sIcdIref(nbParam);sIcdIref=0;
166  vpMatrix sIcd2Iref(nbParam,nbParam);sIcd2Iref=0;
167  vpMatrix sdIrefdIref(nbParam,nbParam);sdIrefdIref=0;
168  for(unsigned int point=0;point<templateSize;point++)
169  {
170  i=ptTemplate[point].y;
171  j=ptTemplate[point].x;
172  X1[0]=j;X1[1]=i;
173  X2[0]=j;X2[1]=i;
174 
175  Warp->computeDenom(X1,p);
176 
177  j2=X2[0];i2=X2[1];
178 
179  if((i2>=0)&&(j2>=0)&&(i2<I.getHeight()-1)&&(j2<I.getWidth()-1))
180  {
181  Iref=ptTemplate[point].val;
182 
183  if(!blur)
184  Ic=I.getValue(i2,j2);
185  else
186  Ic=BI.getValue(i2,j2);
187 
188  dIcx=dIx.getValue(i2,j2);
189  dIcy=dIy.getValue(i2,j2);
190 
191  Warp->dWarp(X1,X2,p,dW);
192 
193  double *tempt=new double[nbParam];
194  for(unsigned int it=0;it<nbParam;it++)
195  tempt[it]=dW[0][it]*dIcx+dW[1][it]*dIcy;
196 
197  double prodIc=(Ic-moyIc);
198 
199  double d_Ixx=dIxx.getValue(i2,j2);
200  double d_Iyy=dIyy.getValue(i2,j2);
201  double d_Ixy=dIxy.getValue(i2,j2);
202 
203  for(unsigned int it=0;it<nbParam;it++)
204  for(unsigned int jt=0;jt<nbParam;jt++)
205  {
206  sIcd2Iref[it][jt] +=prodIc*(dW[0][it]*(dW[0][jt]*d_Ixx+dW[1][jt]*d_Ixy)
207  +dW[1][it]*(dW[0][jt]*d_Ixy+dW[1][jt]*d_Iyy)-moyd2Iref[it][jt]);
208  sdIrefdIref[it][jt] +=(ptTemplate[point].dW[it]-moydIrefdp[it])*(ptTemplate[point].dW[jt]-moydIrefdp[jt]);
209  }
210 
211 
212  delete[] tempt;
213 
214  for(unsigned int it=0;it<nbParam;it++)
215  sIcdIref[it]+=prodIc*(ptTemplate[point].dW[it]-moydIrefdp[it]);
216 
217  covarIref+=(Iref-moyIref)*(Iref-moyIref);
218  covarIc+=(Ic-moyIc)*(Ic-moyIc);
219  sIcIref+=(Iref-moyIref)*(Ic-moyIc);
220  }
221 
222 
223  }
224  covarIref=sqrt(covarIref);
225  covarIc=sqrt(covarIc);
226 
227  denom=covarIref*covarIc;
228 
229  double NCC=sIcIref/denom;
230  //std::cout<<"NCC = "<<NCC<<std::endl;
231  vpColVector dcovarIref(nbParam);dcovarIref=-sIcdIref/covarIref;
232 
233  vpColVector dNCC(nbParam);dNCC=(sIcdIref/denom-NCC*dcovarIref/covarIref);
234  vpMatrix d2covarIref(nbParam,nbParam);
235  d2covarIref=-(sIcd2Iref-sdIrefdIref+dcovarIref*dcovarIref.t())/covarIref;
236 #ifdef APPROX_NCC
237  Hdesire=sIcd2Iref/denom;
238 #else
239  Hdesire=(sIcd2Iref-sdIrefdIref+dcovarIref*dcovarIref.t())/denom;
240 #endif
243  //std::cout<<"Hdesire = "<<Hdesire<<std::endl;
244 }
245 
247 {
248  if(blur)
250 
251  double erreur=0;
252  unsigned int Nbpoint=0;
253  vpColVector dpinv(nbParam);
254  double Ic;
255  double Iref;
256  unsigned int iteration=0;
257  int i,j;
258  double i2,j2;
259  initPosEvalRMS(p);
260  do
261  {
262  Nbpoint=0;
263  erreur=0;
264  G=0;
265  Warp->computeCoeff(p);
266  double moyIref=0;
267  double moyIc=0;
268  double denom=0;
269  for(unsigned int point=0;point<templateSize;point++)
270  {
271  i=ptTemplate[point].y;
272  j=ptTemplate[point].x;
273  X1[0]=j;X1[1]=i;
274 
275  Warp->computeDenom(X1,p);
276  Warp->warpX(X1,X2,p);
277 
278  j2=X2[0];i2=X2[1];
279  if((i2>=0)&&(j2>=0)&&(i2<I.getHeight()-1)&&(j2<I.getWidth()-1))
280  {
281  Iref=ptTemplate[point].val;
282 
283  if(!blur)
284  Ic=I.getValue(i2,j2);
285  else
286  Ic=BI.getValue(i2,j2);
287 
288  Nbpoint++;
289  moyIref+=Iref;
290  moyIc+=Ic;
291  }
292 
293 
294  }
295  if(Nbpoint > 0)
296  {
297  moyIref=moyIref/Nbpoint;
298  moyIc=moyIc/Nbpoint;
299  double sIcIref=0;
300  double covarIref=0,covarIc=0;
301  vpColVector sIcdIref(nbParam);sIcdIref=0;
302  vpColVector sIrefdIref(nbParam);sIrefdIref=0;
303 
304 
305  for(unsigned int point=0;point<templateSize;point++)
306  {
307  i=ptTemplate[point].y;
308  j=ptTemplate[point].x;
309  X1[0]=j;X1[1]=i;
310 
311  Warp->computeDenom(X1,p);
312  Warp->warpX(X1,X2,p);
313 
314  j2=X2[0];i2=X2[1];
315  if((i2>=0)&&(j2>=0)&&(i2<I.getHeight()-1)&&(j2<I.getWidth()-1))
316  {
317  Iref=ptTemplate[point].val;
318 
319  if(!blur)
320  Ic=I.getValue(i2,j2);
321  else
322  Ic=BI.getValue(i2,j2);
323 
324 
325  double prod=(Ic-moyIc);
326  for(unsigned int it=0;it<nbParam;it++)
327  sIcdIref[it]+=prod*(ptTemplate[point].dW[it]-moydIrefdp[it]);
328  for(unsigned int it=0;it<nbParam;it++)
329  sIrefdIref[it]+=(Iref-moyIref)*(ptTemplate[point].dW[it]-moydIrefdp[it]);
330 
331  double er=(Iref-Ic);
332  erreur+=(er*er);
333  //denom+=(Iref-moyIref)*(Iref-moyIref)*(Ic-moyIc)*(Ic-moyIc);
334  covarIref+=(Iref-moyIref)*(Iref-moyIref);
335  covarIc+=(Ic-moyIc)*(Ic-moyIc);
336  sIcIref+=(Iref-moyIref)*(Ic-moyIc);
337  }
338 
339 
340  }
341  covarIref=sqrt(covarIref);
342  covarIc=sqrt(covarIc);
343  denom=covarIref*covarIc;
344 
345  //if(denom==0.0)
346  if (std::fabs(denom) <= std::numeric_limits<double>::epsilon())
347  {
348  diverge=true;
349  }
350  else
351  {
352  double NCC=sIcIref/denom;
353  vpColVector dcovarIref(nbParam);dcovarIref=sIrefdIref/covarIref;
354  G=1.*(sIcdIref/denom-NCC*dcovarIref/covarIref);
355 
356 
357  try
358  {
359  dp=-1.*HLMdesireInverse*G;
360  }
361  catch(...)
362  {
363  std::cout<<"probleme inversion"<<std::endl;
364  break;
365  }
366 
367  Warp->getParamInverse(dp,dpinv);
368  Warp->pRondp(p,dpinv,p);
369 
370  computeEvalRMS(p);
371  }
372  }
373  else
374  diverge=true;
375 
376  iteration++;
377  }
378  while( (!diverge &&(evolRMS>threshold_RMS) && (iteration < iterationMax)));
379 
380  //std::cout<<"erreur "<<erreur<<std::endl;
381  nbIteration=iteration;
382 
384 }
385 
387 {
388  unsigned int nb_corners = zoneTracked->getNbTriangle() * 3;
389  x_pos.resize(nb_corners);
390  y_pos.resize(nb_corners);
391 
392  Warp->computeCoeff(p);
393  vpTemplateTrackerTriangle triangle;
394 
395  for(unsigned int i=0;i<zoneTracked->getNbTriangle();i++)
396  {
397  zoneTracked->getTriangle(i, triangle);
398  for (unsigned int j=0; j<3; j++) {
399  triangle.getCorner(j, X1[0], X1[1]);
400 
401  Warp->computeDenom(X1,p_);
402  Warp->warpX(X1,X2,p_);
403  x_pos[i*3+j]=X2[0];
404  y_pos[i*3+j]=X2[1];
405  }
406  }
407 }
408 
410 {
411  unsigned int nb_corners = zoneTracked->getNbTriangle() * 3;
412 
413  Warp->computeCoeff(p_);
414  evolRMS=0;
415  vpTemplateTrackerTriangle triangle;
416 
417  for(unsigned int i=0;i<zoneTracked->getNbTriangle();i++)
418  {
419  zoneTracked->getTriangle(i, triangle);
420  for (unsigned int j=0; j<3; j++) {
421  triangle.getCorner(j, X1[0], X1[1]);
422 
423  Warp->computeDenom(X1,p_);
424  Warp->warpX(X1,X2,p_);
425  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]);
426  x_pos[i*3+j]=X2[0];
427  y_pos[i*3+j]=X2[1];
428  }
429  }
430  evolRMS=evolRMS/nb_corners;
431 
432 }
433 
435 {
436 }
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:92
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:1148
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
vpImage< double > dIy
virtual void getdW0(const int &i, const int &j, const double &dy, const double &dx, double *dIdW)=0
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:152
vpTemplateTrackerWarp * Warp
static void computeHLM(const vpMatrix &H, const double &alpha, vpMatrix &HLM)
Definition: vpMatrix.cpp:3470
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:217