29 #include "TrackerBaseInterface.hh"
32 #include <Base/Common/BIASpragma.hh>
57 os <<
"unkown rejection type "<<(int)rt;
68 os <<
"TRACKER_SUCCESS";
71 os <<
"TRACKER_NOSTRUCTURE";
74 os <<
"TRACKER_OUTOFIMAGE";
77 os <<
"TRACKER_TOOMANYITER";
80 os <<
"TRACKER_OUTOFROI";
83 os <<
"TRACKER_MEANABSDIF";
86 os <<
"TRACKER_IGNOREPOINT";
92 os <<
"TRACKER_ODDAFFINEWARP";
95 os <<
"TRACKER_ERRORINCREASED";
98 os <<
"unkown tracker result code "<<(int)res;
109 template <
class StorageType>
137 template <
class StorageType>
143 template <
class StorageType>
155 unsigned ytlx, ytly, ybrx, ybry;
157 unsigned 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);
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);
181 bool resize = (_HalfWinSize != _LastHalfWinSize);
183 Resize_(_HalfWinSize);
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;
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");
200 BIASASSERT(_HalfWinSize>0);
201 BIASASSERT(_maxy1>_miny1 && _maxx1>_minx1);
202 BIASASSERT(_maxy2>_miny2 && _maxx2>_minx2);
204 _ComputeFilteredImages =
false;
207 template <
class StorageType>
219 _ComputeFilteredImages =
true;
221 LOWPASS_FILTERMASK_SEPARABLE : LOWPASS_FILTERMASK;
223 GRAD_FILTERMASK_SEPARABLE : GRAD_FILTERMASK;
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);
255 _LowpassWindowExtraSize = (m-1)/2;
257 _minx1 = _HalfWinSize + _LowpassWindowExtraSize + 2;
258 _maxx1 = im1.
GetWidth() - _HalfWinSize - _LowpassWindowExtraSize - 2;
259 _miny1 = _HalfWinSize + _LowpassWindowExtraSize + 2;
260 _maxy1 = im1.
GetHeight() - _HalfWinSize - _LowpassWindowExtraSize - 2;
262 _minx2 = _HalfWinSize + _LowpassWindowExtraSize + 2;
263 _maxx2 = im2.
GetWidth() - _HalfWinSize - _LowpassWindowExtraSize - 2;
264 _miny2 = _HalfWinSize + _LowpassWindowExtraSize + 2;
265 _maxy2 = im2.
GetHeight() - _HalfWinSize - _LowpassWindowExtraSize - 2;
273 _LowpassFilter = LOWPASS_BINOMIAL3X3;
280 _LowpassFilter = LOWPASS_BINOMIAL3X3;
288 _GradXFilter = GRAD_SOBEL3X3;
296 _GradXFilter = GRAD_SOBEL3X3;
304 _GradYFilter = GRAD_SOBEL3X3;
311 _GradYFilter = GRAD_SOBEL3X3;
314 bool resize = (_HalfWinSize != _LastHalfWinSize);
316 Resize_(_HalfWinSize);
320 template <
class StorageType>
323 KLT_TYPE& error,
int &iter,
324 KLT_TYPE& residuumMAD, KLT_TYPE& residuumMSD,
335 if (_HalfWinSize != _LastHalfWinSize){
336 Resize_(_HalfWinSize);
345 int result = Track_(p1vec, p2vec, tracked, error, iter,
346 AffinePred.
NormFrobenius()<1e-10 ?
id : AffinePred, affineResult);
354 if (AffineResult != NULL)
356 *AffineResult = affineResult;
360 EvaluateResult_(residuumMAD, residuumMSD, cov);
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,
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());
388 for (
unsigned int i = 0; i < num; i++)
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);
396 switch(_RejectionType)
399 RejectMAD_(residuiMAD, res);
402 RejectX84_(residuiMSD, residuiMAD, res);
405 RejectX84_(residuiMSD, residuiMAD, res);
409 BIASERR(
"unknown rejection method " << _RejectionType);
415 cerr <<
"TrackerBaseInterface tracking took "<<timer.
GetRealTime()<<
" us\n";
424 template <
class StorageType>
433 KLT_TYPE* cov = CovMatrix.
GetData();
435 KLT_TYPE *f1=_bl1.GetData(), *f2=_bl2.GetData(), *end = f1+_WinSize*_WinSize;
438 KLT_TYPE tmp_res=0.0;
441 if ((*f1 == TRACKERBASE_INVALID_PIXEL) ||
442 (*f2 == TRACKERBASE_INVALID_PIXEL)) {
447 tmp_res = *f1++ - *f2++;
448 msd += tmp_res * tmp_res;
449 mad += fabs(tmp_res);
457 double sigmasquared = DBL_MAX;
459 sigmasquared = msd / (double)(validpixels - 3);
462 msd /= KLT_TYPE(validpixels);
463 mad /= KLT_TYPE(validpixels);
471 cov[0] = _gyy * _idet * sigmasquared;
472 cov[1] = cov[2]= -_gxy * _idet * sigmasquared;
473 cov[3] = _gxx * _idet * sigmasquared;
492 cerr <<
"TrackerBaseInterface::EvaluateResult_ took "<<timer.
GetRealTime()<<
" us = "
497 template <
class StorageType>
499 RejectMAD_(std::vector<KLT_TYPE>& sad, std::vector<int>& res)
501 KLT_TYPE thresh=_MaxResiduumMAD;
502 unsigned num = res.size();
504 for (
unsigned i=0; i<num; i++){
512 template <
class StorageType>
514 RejectX84_(std::vector<KLT_TYPE>& ssd, std::vector<KLT_TYPE>& sad,
515 std::vector<int>& res)
526 vector<KLT_TYPE> _ssd_residui;
527 KLT_TYPE _median_ssd_residui;
530 vector<KLT_TYPE> _diff_from_median;
534 vector<KLT_TYPE> _all_diff_from_median;
536 _ssd_residui.reserve(num);
537 _diff_from_median.reserve(num);
538 _all_diff_from_median.resize(num);
541 for (
int i=0; i<num; i++){
543 _ssd_residui.push_back(ssd[i]);
548 unsigned num2=_ssd_residui.size();
553 BIASCDOUT(D_TRACKERB_REJECT,
"using "<<num2
554 <<
" valid residuis for median calculation"<<endl);
557 BIASERR(
"no valid residui!");
563 _median_ssd_residui = _Median.
GetMedian();
568 BIASCDOUT(D_TRACKERB_REJECT,
"median residuum is "<<_median_ssd_residui
571 for (
unsigned i=0; i<num2; i++){
572 _diff_from_median.push_back(fabs(_ssd_residui[i] - _median_ssd_residui));
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 "
582 BIASCDOUT(D_TRACKERB_REJECT,
"x84 threshold is "<<threshold<<endl);
585 for (
int i=0; i<num; i++){
590 _all_diff_from_median[i] = ssd[i] - _median_ssd_residui;
592 if (_RejectionType ==
RT_X84M) {
594 if ((res[i]>=0 && (_all_diff_from_median[i] > threshold))
595 &&(sad[i] > _MaxResiduumMAD)){
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);
602 (_all_diff_from_median[i] < threshold)){
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);
610 if (res[i]>=0 && (_all_diff_from_median[i] > threshold)){
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);
617 (_all_diff_from_median[i] < threshold)){
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);
625 BIASCDOUT(D_TRACKERB_REJECT,
"rejected "<<rejected<<
" points "<<endl);
628 if (rejected>num2/2){
629 cout <<
"rejected more than half of tracks ("<<rejected<<
" of "<<num2
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;
637 sort(_ssd_residui.begin(), _ssd_residui.end());
638 sort(_diff_from_median.begin(), _diff_from_median.end());
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;
652 cerr <<
"TrackerBase::Rejectx86 took "<<timer.
GetRealTime()
658 template <
class StorageType>
666 KLT_TYPE sum = (KLT_TYPE)0;
667 for (
int i = 0; i < (int)vert.
Size(); i++)
669 for (
int j = 0; j < (int)horz.
Size(); j++)
671 sum += (KLT_TYPE)fabs(vert[i] * horz[j]);
679 KLT_TYPE sum = (KLT_TYPE)0;
680 for (
int i = 0; i < (int)kernel.
GetRows(); i++)
682 for (
int j = 0; j < (int)kernel.
GetCols(); j++)
684 sum += (KLT_TYPE)fabs(kernel[i][j]);
699 #ifdef BUILD_IMAGE_INT
702 #ifdef BUILD_IMAGE_CHAR
705 #ifdef BUILD_IMAGE_SHORT
708 #ifdef BUILD_IMAGE_USHORT
711 #ifdef BUILD_IMAGE_UINT
714 #ifdef BUILD_IMAGE_DOUBLE
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
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
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...
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
Matrix< T > & newsize(Subscript M, Subscript N)
bool _AffineBrightnessInvariance
compute brightness "invariant"
unsigned int Size() const
length of the vector
Image< StorageType > * _gradim2x
unsigned int GetWidth() const
Image< StorageType > * _im1
const Vector< FM_FLOAT > * GetSepfh() const
returns pointer to horiz float vector for sep.
success (error < maxerror)
ROI * GetROI()
Returns a pointer to the roi object.
unsigned int GetRows() const
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.
affine warp seems degenerated
input point was at infinity
unsigned int GetHeight() const
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.
The image template class for specific storage types.
T * GetData()
get the pointer to the data array of the matrix (for faster direct memeory access) ...
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 "size" as Image of other type
is a 'fixed size' quadratic matrix of dim.
point is rejected by X84/X84M
std::ostream & operator<<(std::ostream &os, const Array2D< T > &arg)
int _HalfWinSize
use support window of size 2*hws+1
bool _ComputeFilteredImages
class Vector3 contains a Vector of fixed dim.
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
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)
virtual ~TrackerBaseInterface()
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)).
A filter mask (or a kernel) used for convolution.
Image< StorageType > * _im2
error increased from last iteration
class TimeMeasure contains functions for timing real time and cpu time.
Image< StorageType > * _gradim1x
class BIASGeometryBase_EXPORT HomgPoint2D
maxiter is reached and error is above maxerror