Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
TrackerBaseInterface.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS),
3 however, it contains other contributions.
4 For these marked parts a different license may apply, please read
5 the documentation of the marked parts for further details.
6 For the rest of this file read the following:
7 
8 Copyright (C) 2003-2009 (see file CONTACT for details)
9  Multimediale Systeme der Informationsverarbeitung
10  Institut fuer Informatik
11  Christian-Albrechts-Universitaet Kiel
12 
13 
14 BIAS is free software; you can redistribute it and/or modify
15 it under the terms of the GNU Lesser General Public License as published by
16 the Free Software Foundation; either version 2.1 of the License, or
17 (at your option) any later version.
18 
19 BIAS is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU Lesser General Public License for more details.
23 
24 You should have received a copy of the GNU Lesser General Public License
25 along with BIAS; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 */
28 
29 #include "TrackerBaseInterface.hh"
30 #include <algorithm>
31 
32 #include <Base/Common/BIASpragma.hh>
33 
34 using namespace BIAS;
35 using namespace std;
36 
37 //////////////////////////////////////////////////////////////////////////
38 // operators
39 //////////////////////////////////////////////////////////////////////////
40 
41 ostream& BIAS::operator<<(ostream& os, const enum ERejectionType& rt)
42 {
43  switch (rt){
44  case RT_Invalid:
45  os << "invalid";
46  break;
47  case RT_MAD:
48  os << "RT_MAD";
49  break;
50  case RT_X84:
51  os << "RT_X84";
52  break;
53  case RT_X84M:
54  os << "RT_X84M";
55  break;
56  default:
57  os << "unkown rejection type "<<(int)rt;
58  break;
59  }
60  return os;
61 }
62 
63 
64 ostream& BIAS::operator<<(std::ostream& os, const enum ETrackerResult& res)
65 {
66  switch (res){
67  case TRACKER_SUCCESS:
68  os << "TRACKER_SUCCESS";
69  break;
71  os << "TRACKER_NOSTRUCTURE";
72  break;
73  case TRACKER_OUTOFIMAGE:
74  os << "TRACKER_OUTOFIMAGE";
75  break;
77  os << "TRACKER_TOOMANYITER";
78  break;
79  case TRACKER_OUTOFROI:
80  os << "TRACKER_OUTOFROI";
81  break;
82  case TRACKER_MEANABSDIF:
83  os << "TRACKER_MEANABSDIF";
84  break;
86  os << "TRACKER_IGNOREPOINT";
87  break;
88  case TRACKER_X84:
89  os << "TRACKER_X84";
90  break;
92  os << "TRACKER_ODDAFFINEWARP";
93  break;
95  os << "TRACKER_ERRORINCREASED";
96  break;
97  default:
98  os << "unkown tracker result code "<<(int)res;
99  break;
100  }
101  return os;
102 }
103 
104 
105 //////////////////////////////////////////////////////////////////////////
106 // implementation
107 //////////////////////////////////////////////////////////////////////////
108 
109 template <class StorageType>
112  : Debug()
113 {
114  _HalfWinSize = 3;
115  _WinSize = 2 * _HalfWinSize + 1;
116  _MaxIterations = 10;
117  _MaxError = 0.01;
118  _MaxResiduumMAD = 10.0;
120 
121  _im1 = NULL;
122  _gradim1x = NULL;
123  _gradim1y = NULL;
124 
125  _im2 = NULL;
126  _gradim2x = NULL;
127  _gradim2y = NULL;
128 
129  _ComputeFilteredImages = false;
130 
131  _maxx1 = _maxy1 = _minx1 = _miny1 = 0;
132  _maxx2 = _maxy2 = _minx2 = _miny2 = 0;
133  _LastHalfWinSize = 0;
135 }
136 
137 template <class StorageType>
140 {
141 }
142 
143 template <class StorageType>
146  Image<StorageType>& gradx1, Image<StorageType>& grady1,
147  Image<StorageType>& gradx2, Image<StorageType>& grady2)
148 {
149  BIASASSERT(im2.SamePixelAndChannelCount(im1));
150  BIASASSERT(gradx1.SamePixelAndChannelCount(im1));
151  BIASASSERT(grady1.SamePixelAndChannelCount(im1));
152  BIASASSERT(gradx2.SamePixelAndChannelCount(im1));
153  BIASASSERT(grady2.SamePixelAndChannelCount(im1));
154 
155  unsigned ytlx, ytly, ybrx, ybry;
156  grady1.GetROI()->GetCorners(ytlx, ytly, ybrx, ybry);
157  unsigned xtlx, xtly, xbrx, xbry;
158  gradx1.GetROI()->GetCorners(xtlx, xtly, xbrx, xbry);
159  unsigned minx1, miny1, maxx1, maxy1;
160  minx1=(ytlx>xtlx)?(ytlx):(xtlx);
161  miny1=(ytly>xtly)?(ytly):(xtly);
162  maxx1=(ybrx<xbrx)?(ybrx):(xbrx);
163  maxy1=(ybry<xbry)?(ybry):(xbry);
164 
165  grady2.GetROI()->GetCorners(ytlx, ytly, ybrx, ybry);
166  gradx2.GetROI()->GetCorners(xtlx, xtly, xbrx, xbry);
167  unsigned minx2, miny2, maxx2, maxy2;
168  minx2=(ytlx>xtlx)?(ytlx):(xtlx);
169  miny2=(ytly>xtly)?(ytly):(xtly);
170  maxx2=(ybrx<xbrx)?(ybrx):(xbrx);
171  maxy2=(ybry<xbry)?(ybry):(xbry);
172 
173  _im1 = &im1;
174  _im2 = &im2;
175 
176  _gradim1x = &gradx1;
177  _gradim2x = &gradx2;
178  _gradim1y = &grady1;
179  _gradim2y = &grady2;
180 
181  bool resize = (_HalfWinSize != _LastHalfWinSize);
182  if (resize) {
183  Resize_(_HalfWinSize);
184  }
185 
186  _minx1=minx1+_HalfWinSize+1;
187  _miny1=miny1+_HalfWinSize+1;
188  _maxx1=maxx1-_HalfWinSize-1;
189  _maxy1=maxy1-_HalfWinSize-1;
190  _minx2=minx2+_HalfWinSize+1;
191  _miny2=miny2+_HalfWinSize+1;
192  _maxx2=maxx2-_HalfWinSize-1;
193  _maxy2=maxy2-_HalfWinSize-1;
194 
195  BIASCDOUT(D_TRACKERB_INIT, "tracking roi im1 : ( "<<_minx1<<", "<<_miny1
196  <<") <--> ( "<<_maxx1<<", "<<_maxy1<<")\n");
197  BIASCDOUT(D_TRACKERB_INIT, "tracking roi im2 : ( "<<_minx2<<", "<<_miny2
198  <<") <--> ( "<<_maxx2<<", "<<_maxy2<<")\n");
199 
200  BIASASSERT(_HalfWinSize>0);
201  BIASASSERT(_maxy1>_miny1 && _maxx1>_minx1);
202  BIASASSERT(_maxy2>_miny2 && _maxx2>_minx2);
203 
204  _ComputeFilteredImages = false;
205 }
206 
207 template <class StorageType>
210  FilterMask& lowpass_mask, FilterMask& gradx_mask,
211  FilterMask& grady_mask)
212 {
213  BIASASSERT(im2.SamePixelAndChannelCount(im1));
214 
215  _im1 = &im1;
216  _im2 = &im2;
217 
218  // initialize filter configuration
219  _ComputeFilteredImages = true;
220  _LowpassFilter = lowpass_mask.IsSeparable() ?
221  LOWPASS_FILTERMASK_SEPARABLE : LOWPASS_FILTERMASK;
222  _GradXFilter = gradx_mask.IsSeparable() ?
223  GRAD_FILTERMASK_SEPARABLE : GRAD_FILTERMASK;
224  _GradYFilter = grady_mask.IsSeparable() ?
225  GRAD_FILTERMASK_SEPARABLE : GRAD_FILTERMASK;
226  _LowpassMask = lowpass_mask;
227  _GradXMask = gradx_mask;
228  _GradYMask = grady_mask;
229  _LowpassMaskSum = ComputeMaskSum(lowpass_mask);
230  _GradXMaskSum = ComputeMaskSum(gradx_mask);
231  _GradYMaskSum = ComputeMaskSum(grady_mask);
232 
233  // compute required additional size for lowpass filtered window.
234  unsigned int m = 0;
235  if (gradx_mask.IsSeparable())
236  {
237  m = max(m, gradx_mask.GetSepfh()->Size());
238  m = max(m, gradx_mask.GetSepfv()->Size());
239  }
240  else
241  {
242  m = max(m, gradx_mask.GetKernelf()->GetRows());
243  m = max(m, gradx_mask.GetKernelf()->GetCols());
244  }
245  if (grady_mask.IsSeparable())
246  {
247  m = max(m, grady_mask.GetSepfh()->Size());
248  m = max(m, grady_mask.GetSepfv()->Size());
249  }
250  else
251  {
252  m = max(m, grady_mask.GetKernelf()->GetRows());
253  m = max(m, grady_mask.GetKernelf()->GetCols());
254  }
255  _LowpassWindowExtraSize = (m-1)/2;
256 
257  _minx1 = _HalfWinSize + _LowpassWindowExtraSize + 2;
258  _maxx1 = im1.GetWidth() - _HalfWinSize - _LowpassWindowExtraSize - 2;
259  _miny1 = _HalfWinSize + _LowpassWindowExtraSize + 2;
260  _maxy1 = im1.GetHeight() - _HalfWinSize - _LowpassWindowExtraSize - 2;
261 
262  _minx2 = _HalfWinSize + _LowpassWindowExtraSize + 2;
263  _maxx2 = im2.GetWidth() - _HalfWinSize - _LowpassWindowExtraSize - 2;
264  _miny2 = _HalfWinSize + _LowpassWindowExtraSize + 2;
265  _maxy2 = im2.GetHeight() - _HalfWinSize - _LowpassWindowExtraSize - 2;
266 
267 
268  // check if optimized lowpass filter can be used.
269  if (lowpass_mask.IsSeparable() &&
270  *lowpass_mask.GetSepfh() == Vector3<FM_FLOAT>(1, 2, 1) &&
271  *lowpass_mask.GetSepfv() == Vector3<FM_FLOAT>(1, 2, 1))
272  {
273  _LowpassFilter = LOWPASS_BINOMIAL3X3;
274  }
275  if (!lowpass_mask.IsSeparable() &&
276  lowpass_mask.GetKernelf()->GetRows() == 3 &&
277  lowpass_mask.GetKernelf()->GetCols() == 3 &&
278  *lowpass_mask.GetKernelf() == Matrix<float>(Matrix3x3<FM_FLOAT>(1,2,1,2,4,2,1,2,1)))
279  {
280  _LowpassFilter = LOWPASS_BINOMIAL3X3;
281  }
282 
283  // check if optimized gradient x filter can be used.
284  if (gradx_mask.IsSeparable() &&
285  *gradx_mask.GetSepfh() == Vector3<FM_FLOAT>(-1,0,1) &&
286  *gradx_mask.GetSepfv() == Vector3<FM_FLOAT>(1,2,1))
287  {
288  _GradXFilter = GRAD_SOBEL3X3;
289  }
290 
291  if (!gradx_mask.IsSeparable() &&
292  gradx_mask.GetKernelf()->GetRows() == 3 &&
293  gradx_mask.GetKernelf()->GetCols() == 3 &&
294  *gradx_mask.GetKernelf() == Matrix<float>(Matrix3x3<FM_FLOAT>(-1,0,1,-2,0,2,-1,0,1)))
295  {
296  _GradXFilter = GRAD_SOBEL3X3;
297  }
298 
299  // check if optimized gradient y filter can be used.
300  if (grady_mask.IsSeparable() &&
301  *grady_mask.GetSepfh() == Vector3<FM_FLOAT>(1,2,1) &&
302  *grady_mask.GetSepfv() == Vector3<FM_FLOAT>(-1,0,1))
303  {
304  _GradYFilter = GRAD_SOBEL3X3;
305  }
306  if (!grady_mask.IsSeparable() &&
307  grady_mask.GetKernelf()->GetRows() == 3 &&
308  grady_mask.GetKernelf()->GetCols() == 3 &&
309  *grady_mask.GetKernelf() == Matrix<float>(Matrix3x3<FM_FLOAT>(-1,-2,-1,0,0,0,1,2,1)))
310  {
311  _GradYFilter = GRAD_SOBEL3X3;
312  }
313 
314  bool resize = (_HalfWinSize != _LastHalfWinSize);
315  if (resize) {
316  Resize_(_HalfWinSize);
317  }
318 }
319 
320 template <class StorageType>
322 Track(HomgPoint2D& p1, HomgPoint2D& p2, HomgPoint2D& p2tracked,
323  KLT_TYPE& error, int &iter,
324  KLT_TYPE& residuumMAD, KLT_TYPE& residuumMSD,
325  Matrix<KLT_TYPE>& cov,
326  const Matrix2x2<KLT_TYPE>& AffinePred,
327  Matrix2x2<KLT_TYPE>* AffineResult)
328 {
329  // don't track points with w != 1
330  if (p1[2] != 1.0)
331  {
332  return TRACKER_IGNOREPOINT;
333  }
334 
335  if (_HalfWinSize != _LastHalfWinSize){
336  Resize_(_HalfWinSize);
337  }
338 
339  // run specialized Track_
340  Vector2<KLT_TYPE> p1vec(p1[0], p1[1]);
341  Vector2<KLT_TYPE> p2vec(p2[0], p2[1]);
342  Vector2<KLT_TYPE> tracked;
343  Matrix2x2<KLT_TYPE> affineResult(MatrixIdentity);
345  int result = Track_(p1vec, p2vec, tracked, error, iter,
346  AffinePred.NormFrobenius()<1e-10 ? id : AffinePred, affineResult);
347  if (result != 0)
348  {
349  return result;
350  }
351 
352  // fill output parameters
353  p2tracked = HomgPoint2D(tracked[0], tracked[1]);
354  if (AffineResult != NULL)
355  {
356  *AffineResult = affineResult;
357  }
358 
359  // evaluate result
360  EvaluateResult_(residuumMAD, residuumMSD, cov);
361 
362  return 0;
363 }
364 
365 
366 template <class StorageType>
368 Track(std::vector<HomgPoint2D>& p1, std::vector<HomgPoint2D>& p2,
369  std::vector<HomgPoint2D>& p2tracked, std::vector<KLT_TYPE>& error,
370  std::vector<int>& numiter, std::vector<KLT_TYPE>& residuiMAD,
371  std::vector<KLT_TYPE>& residuiMSD, std::vector<int>& res,
372  std::vector<Matrix<KLT_TYPE> >& cov,
373  const std::vector<Matrix2x2<KLT_TYPE> >& AffinePred,
374  std::vector<Matrix2x2<KLT_TYPE> >* AffineResult)
375 {
376 #ifdef TIMING
377  TimeMeasure timer;
378  timer.Start();
379 #endif
380 
381  const unsigned num=p1.size();
382  BIASASSERT(num==p2.size() && num==p2tracked.size() && num==error.size());
383  BIASASSERT(num==numiter.size() && num==res.size() && num==residuiMSD.size()&&
384  num==residuiMAD.size() && num==cov.size());
385  BIASASSERT(num>0);
386 
387  // track points
388  for (unsigned int i = 0; i < num; i++)
389  {
390  res[i] = Track(p1[i], p2[i], p2tracked[i], error[i], numiter[i],
391  residuiMAD[i], residuiMSD[i], cov[i],
392  AffinePred[i], AffineResult ? &(*AffineResult)[i] : NULL);
393  }
394 
395  // reject points
396  switch(_RejectionType)
397  {
398  case RT_MAD:
399  RejectMAD_(residuiMAD, res);
400  break;
401  case RT_X84:
402  RejectX84_(residuiMSD, residuiMAD, res);
403  break;
404  case RT_X84M:
405  RejectX84_(residuiMSD, residuiMAD, res);
406  break;
407  case RT_Invalid:break; // rejection disabled ...
408  default:
409  BIASERR("unknown rejection method " << _RejectionType);
410  break;
411  }
412 
413 #ifdef TIMING
414  timer.Stop();
415  cerr << "TrackerBaseInterface tracking took "<<timer.GetRealTime()<<" us\n";
416 #endif
417 }
418 
419 
420 ///////////////////////////////////////////////////////////////////
421 // tracking
422 ///////////////////////////////////////////////////////////////////
423 
424 template <class StorageType>
426 EvaluateResult_(KLT_TYPE& mad, KLT_TYPE& msd, Matrix<KLT_TYPE>& CovMatrix)
427 {
428 #ifdef TIMING
429  TimeMeasure timer;
430  timer.Start();
431 #endif
432  CovMatrix.newsize(2, 2);
433  KLT_TYPE* cov = CovMatrix.GetData();
434 
435  KLT_TYPE *f1=_bl1.GetData(), *f2=_bl2.GetData(), *end = f1+_WinSize*_WinSize;
436  mad = 0.0;
437  msd = 0.0;
438  KLT_TYPE tmp_res=0.0;
439  int validpixels = 0;
440  while (f1<end){
441  if ((*f1 == TRACKERBASE_INVALID_PIXEL) ||
442  (*f2 == TRACKERBASE_INVALID_PIXEL)) {
443  f1++;
444  f2++;
445  continue;
446  }
447  tmp_res = *f1++ - *f2++;
448  msd += tmp_res * tmp_res;
449  mad += fabs(tmp_res);
450  validpixels++;
451  }
452 
453  // now calculate the covariance matrix
454  // see Reinhards dissertation page 67, equation 5.9
455  // this is the inverse of the matrix
456  // the reference variance is sigma
457  double sigmasquared = DBL_MAX;
458  if (validpixels>3) {
459  sigmasquared = msd / (double)(validpixels - 3);
460 
461  // compute mean squared difference
462  msd /= KLT_TYPE(validpixels);
463  mad /= KLT_TYPE(validpixels);
464  } else {
465  msd = DBL_MAX;
466  mad = DBL_MAX;
467  }
468  // the inverse of the structure tensor matrix is given by
469  // 1/det * | _gyy -_gxy|
470  // |-_gxy _gxx|
471  cov[0] = _gyy * _idet * sigmasquared;
472  cov[1] = cov[2]= -_gxy * _idet * sigmasquared;
473  cov[3] = _gxx * _idet * sigmasquared;
474 // #ifdef BIAS_DEBUG
475 // cout << "mad "<<mad<<" sigmasq "<<sigmasquared<<" cov[0][0] "<<cov[0]
476 // <<" cov[1][1] "<<cov[3];
477 // double meanx=0.0, meany=0.0;
478 // for (int x=0; x<7; x++){
479 // for (int y=0; y<7; y++){
480 // meanx+=fabs(_gx1[y][x]);
481 // meany+=fabs(_gy1[y][x]);
482 // }
483 // }
484 // meanx/=49.0;
485 // meany/=49.0;
486 // cout <<" gx: "<<meanx <<" gy: "<<meany<<" idet "<<_idet<<" _gxx "
487 // <<_gxx<<" _gyy "<<_gyy<<endl;
488 // #endif
489 
490 #ifdef TIMING
491  timer.Stop();
492  cerr << "TrackerBaseInterface::EvaluateResult_ took "<<timer.GetRealTime()<<" us = "
493  <<timer.GetCycleCount()<<" cycles\n";
494 #endif
495 }
496 
497 template <class StorageType>
499 RejectMAD_(std::vector<KLT_TYPE>& sad, std::vector<int>& res)
500 {
501  KLT_TYPE thresh=_MaxResiduumMAD;
502  unsigned num = res.size();
503 
504  for (unsigned i=0; i<num; i++){
505  if (res[i]>=TRACKER_SUCCESS && sad[i]>=thresh){
506  res[i]=TRACKER_MEANABSDIF;
507  }
508  }
509  return 0;
510 }
511 
512 template <class StorageType>
514 RejectX84_(std::vector<KLT_TYPE>& ssd, std::vector<KLT_TYPE>& sad,
515  std::vector<int>& res)
516 {
517 #ifdef TIMING
518  TimeMeasure timer;
519  timer.Start();
520 #endif
521  int num=ssd.size();
522 
523  Median1D<KLT_TYPE> _Median; // median calculation class
524 
525  // sum of sq. grey value diff only for points where tracking succeeded
526  vector<KLT_TYPE> _ssd_residui;
527  KLT_TYPE _median_ssd_residui; // median of _ssd_residui
528 
529  // _diff_from_median = fabs(_ssd_residui - _median_ssd_residui)
530  vector<KLT_TYPE> _diff_from_median;
531 
532  // same as _diff_from_median but also for points where tracking was not
533  // sucessfull
534  vector<KLT_TYPE> _all_diff_from_median;
535 
536  _ssd_residui.reserve(num);
537  _diff_from_median.reserve(num);
538  _all_diff_from_median.resize(num);
539 
540  // remove all points where tracking failed
541  for (int i=0; i<num; i++){
542  if (res[i]>=TRACKER_SUCCESS){
543  _ssd_residui.push_back(ssd[i]);
544  } else {
545 
546  }
547  }
548  unsigned num2=_ssd_residui.size();
549  if (num2==0) {
550  // no points -> no x84 decision, return
551  return 0;
552  }
553  BIASCDOUT(D_TRACKERB_REJECT, "using "<<num2
554  <<" valid residuis for median calculation"<<endl);
555 #ifdef BIAS_DEBUG
556  if (num2==0){
557  BIASERR("no valid residui!");
558  BIASBREAK;
559  }
560 #endif
561 
562  _Median.Compute(_ssd_residui);
563  _median_ssd_residui = _Median.GetMedian();
564 
565 
566 
567 
568  BIASCDOUT(D_TRACKERB_REJECT,"median residuum is "<<_median_ssd_residui
569  <<endl);
570 
571  for (unsigned i=0; i<num2; i++){
572  _diff_from_median.push_back(fabs(_ssd_residui[i] - _median_ssd_residui));
573  // BIASCDOUT(D_TRACKERB_REJECT, setw(4)<<i<<" residuum "<<setprecision(2)
574  // <<setw(10)<<_ssd_residui[i]<<"\tdiff_from_median "
575  // <<setprecision(2)<<setw(10)<<_diff_from_median[i]<<endl);
576  }
577 
578  _Median.Compute(_diff_from_median);
579  KLT_TYPE threshold = 5.2 * _Median.GetMedian();
580  BIASCDOUT(D_TRACKERB_REJECT, "median of diff from median is "
581  <<_Median.GetMedian()<<endl);
582  BIASCDOUT(D_TRACKERB_REJECT, "x84 threshold is "<<threshold<<endl);
583 
584  unsigned rejected=0;
585  for (int i=0; i<num; i++){
586  // do we want to reject point which are TOO good ?
587  // _all_diff_from_median[i] = fabs(ssd[i] - _median_ssd_residui);
588  // keep good points (diff<0) which are outside the interval median+-sigma
589  // because they are very close to zero error.
590  _all_diff_from_median[i] = ssd[i] - _median_ssd_residui;
591 
592  if (_RejectionType == RT_X84M) {
593  //X84M: keeps all features with sad <= _MaxResiduumMAD
594  if ((res[i]>=0 && (_all_diff_from_median[i] > threshold))
595  &&(sad[i] > _MaxResiduumMAD)){
596  res[i]=TRACKER_X84;
597  BIASCDOUT(D_TRACKERB_REJECT, "rejecting point "<<setw(4)<<i
598  <<": sad = "<<sad[i]<<"/"<<_MaxResiduumMAD<<" diff from median "<<fixed<<right
599  <<setprecision(2)<<setw(10)<<_all_diff_from_median[i]<<endl);
600  rejected++;
601  } else if (res[i]==TRACKER_MEANABSDIF &&
602  (_all_diff_from_median[i] < threshold)){
603  res[i]=0;
604  BIASCDOUT(D_TRACKERB_REJECT, "accepting point "<<setw(4)<<i
605  <<": sad = "<<sad[i]<<" diff from median "<<fixed<<right
606  <<setprecision(2)<<setw(10)<<_all_diff_from_median[i]<<endl);
607  }
608  } else {
609  //standard X84
610  if (res[i]>=0 && (_all_diff_from_median[i] > threshold)){
611  res[i]=TRACKER_X84;
612  BIASCDOUT(D_TRACKERB_REJECT, "rejecting point "<<setw(4)<<i
613  <<": diff from median "<<fixed<<right<<setprecision(2)
614  <<setw(10)<<_all_diff_from_median[i]<<endl);
615  rejected++;
616  } else if (res[i]==TRACKER_MEANABSDIF &&
617  (_all_diff_from_median[i] < threshold)){
618  res[i]=0;
619  BIASCDOUT(D_TRACKERB_REJECT, "accepting point "<<setw(4)<<i
620  <<": diff from median "<<fixed<<right<<setprecision(2)
621  <<setw(10)<<_all_diff_from_median[i]<<endl);
622  }
623  }
624  }
625  BIASCDOUT(D_TRACKERB_REJECT, "rejected "<<rejected<<" points "<<endl);
626 
627 #ifdef BIAS_DEBUG
628  if (rejected>num2/2){
629  cout << "rejected more than half of tracks ("<<rejected<<" of "<<num2
630  <<")aborting\n";
631  for (unsigned i=0; i<num2; i++){
632  cout << setw(4)<<i<<" residuum "<<setprecision(4)<<setw(10)<<fixed
633  <<right<<_ssd_residui[i]<<"\tdiff_from_median "<<setprecision(4)
634  <<setw(10)<<fixed<<right<<_diff_from_median[i]<<endl;
635  }
636 
637  sort(_ssd_residui.begin(), _ssd_residui.end());
638  sort(_diff_from_median.begin(), _diff_from_median.end());
639  cout << "sorted\n";
640  for (unsigned i=0; i<num2; i++){
641  cout << setw(4)<<i<<" residuum "<<setprecision(4)<<setw(10)<<fixed
642  <<right<<_ssd_residui[i]<<"\tdiff_from_median "<<setprecision(4)
643  <<setw(10)<<fixed<<right<<_diff_from_median[i]<<endl;
644  }
645 
646  BIASABORT;
647  }
648 #endif
649 
650 #ifdef TIMING
651  timer.Stop();
652  cerr << "TrackerBase::Rejectx86 took "<<timer.GetRealTime()
653  <<" us = "<<timer.GetCycleCount()<<" cycles \n";
654 #endif
655  return 0;
656 }
657 
658 template <class StorageType>
661 {
662  if (mask.IsSeparable())
663  {
664  const Vector<FM_FLOAT>& vert = *mask.GetSepfv();
665  const Vector<FM_FLOAT>& horz = *mask.GetSepfh();
666  KLT_TYPE sum = (KLT_TYPE)0;
667  for (int i = 0; i < (int)vert.Size(); i++)
668  {
669  for (int j = 0; j < (int)horz.Size(); j++)
670  {
671  sum += (KLT_TYPE)fabs(vert[i] * horz[j]);
672  }
673  }
674  return sum;
675  }
676  else
677  {
678  const Matrix<FM_FLOAT>& kernel = *mask.GetKernelf();
679  KLT_TYPE sum = (KLT_TYPE)0;
680  for (int i = 0; i < (int)kernel.GetRows(); i++)
681  {
682  for (int j = 0; j < (int)kernel.GetCols(); j++)
683  {
684  sum += (KLT_TYPE)fabs(kernel[i][j]);
685  }
686  }
687  return sum;
688  }
689 }
690 
691 //////////////////////////////////////////////////////////////////////////
692 // instantiation
693 //////////////////////////////////////////////////////////////////////////
694 namespace BIAS{
696 template class TrackerBaseInterface<float>;
697 
698 // fill in instances as required
699 #ifdef BUILD_IMAGE_INT
700 template class TrackerBaseInterface<int>;
701 #endif
702 #ifdef BUILD_IMAGE_CHAR
703 template class TrackerBaseInterface<char>;
704 #endif
705 #ifdef BUILD_IMAGE_SHORT
706 template class TrackerBaseInterface<short>;
707 #endif
708 #ifdef BUILD_IMAGE_USHORT
710 #endif
711 #ifdef BUILD_IMAGE_UINT
712 template class TrackerBaseInterface<unsigned int>;
713 #endif
714 #ifdef BUILD_IMAGE_DOUBLE
715 #endif
716 }
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
Definition: HomgPoint2D.hh:67
DataType GetMedian() const
Return computed median.
Definition: Median1D.hh:56
void Init(Image< StorageType > &im1, Image< StorageType > &im2, Image< StorageType > &gradx1, Image< StorageType > &grady1, Image< StorageType > &gradx2, Image< StorageType > &grady2)
Prepare for tracking with prefiltered images.
bool IsSeparable() const
checks if the kernel is separable
Definition: FilterMask.hh:136
void GetCorners(unsigned &UpperLeftX, unsigned &UpperLeftY, unsigned &LowerRightX, unsigned &LowerRightY) const
Return the region of interest, by saving the coordinates within the variables defined by the paramete...
Definition: ROI.hh:443
point slid out of image
Base class for the different tracking algorithms, defining the interfaces for the tracking functions...
int _RejectionType
The rejection type: RT_MAD,RT_X84 or RT_X84M.
const Matrix< FM_FLOAT > * GetKernelf() const
returns pointer to float filter mask
Definition: FilterMask.hh:116
Computes the median and p-quantile of a vector.
Definition: Median1D.hh:41
Matrix< T > & newsize(Subscript M, Subscript N)
Definition: cmat.h:269
bool _AffineBrightnessInvariance
compute brightness &quot;invariant&quot;
unsigned int Size() const
length of the vector
Definition: Vector.hh:143
Image< StorageType > * _gradim2x
unsigned int GetWidth() const
Definition: ImageBase.hh:312
const Vector< FM_FLOAT > * GetSepfh() const
returns pointer to horiz float vector for sep.
Definition: FilterMask.hh:128
success (error &lt; maxerror)
ROI * GetROI()
Returns a pointer to the roi object.
Definition: ImageBase.hh:615
unsigned int GetRows() const
Definition: Matrix.hh:202
no spatial structure is present
KLT_TYPE _MaxError
iteration stops if position refinement is less than *_MaxError
Image< StorageType > * _gradim2y
int Track(HomgPoint2D &p1, HomgPoint2D &p2, HomgPoint2D &p2tracked, KLT_TYPE &error, int &iter, KLT_TYPE &residuumMAD, KLT_TYPE &residuumMSD, Matrix< KLT_TYPE > &cov, const Matrix2x2< KLT_TYPE > &AffinePred=Matrix2x2< KLT_TYPE >(MatrixIdentity), Matrix2x2< KLT_TYPE > *AffineResult=NULL)
Calculates correspondence from image1 to image2.
void Compute(const std::vector< DataType > &vec)
Compute median and store sorted vector internally.
Definition: Median1D.cpp:32
affine warp seems degenerated
input point was at infinity
unsigned int GetHeight() const
Definition: ImageBase.hh:319
virtual void EvaluateResult_(KLT_TYPE &mad, KLT_TYPE &msd, Matrix< KLT_TYPE > &cov)
Uses bl1, _bl2, _gxx, _gxy and _gyy to calculate the residui and covariance matrix and must hence be ...
const Vector< FM_FLOAT > * GetSepfv() const
returns pointer to vertical float vector for sep.
Definition: FilterMask.hh:132
The image template class for specific storage types.
Definition: Image.hh:78
T * GetData()
get the pointer to the data array of the matrix (for faster direct memeory access) ...
Definition: Matrix.hh:185
int RejectX84_(std::vector< KLT_TYPE > &ssd, std::vector< KLT_TYPE > &sad, std::vector< int > &res)
bool SamePixelAndChannelCount(const ImageBase &Image) const
checks if data area has same &quot;size&quot; as Image of other type
Definition: ImageBase.hh:73
is a &#39;fixed size&#39; quadratic matrix of dim.
Definition: Matrix.hh:54
point is rejected by X84/X84M
std::ostream & operator<<(std::ostream &os, const Array2D< T > &arg)
Definition: Array2D.hh:260
int _HalfWinSize
use support window of size 2*hws+1
class Vector3 contains a Vector of fixed dim.
Definition: Matrix.hh:53
double GetCycleCount() const
return number of cycles between all subsequent calls to Start() and Stop() since last call to Reset()...
double GetRealTime() const
return real time (=wall time clock) in usec JW For Win32: real-time is measured differently from user...
unsigned int GetCols() const
Definition: Matrix.hh:204
matrix class with arbitrary size, indexing is row major.
int RejectMAD_(std::vector< KLT_TYPE > &sad, std::vector< int > &res)
Image< StorageType > * _gradim1y
int _MaxIterations
iteration stops after _MaxIterations
KLT_TYPE ComputeMaskSum(const FilterMask &mask)
KLT_TYPE _MaxResiduumMAD
outlier rejection via MAD and
a point lies outside of valid region in images
point was rejected by MAD criterion
double NormFrobenius() const
Return Frobenius norm = sqrt(trace(A^t * A)).
Definition: Matrix.hh:897
A filter mask (or a kernel) used for convolution.
Definition: FilterMask.hh:61
error increased from last iteration
class TimeMeasure contains functions for timing real time and cpu time.
Definition: TimeMeasure.hh:111
Image< StorageType > * _gradim1x
class BIASGeometryBase_EXPORT HomgPoint2D
maxiter is reached and error is above maxerror