00001 #ifndef Impala_Core_Array_Trait_FuncKalman_h
00002 #define Impala_Core_Array_Trait_FuncKalman_h
00003
00004 #include <deque>
00005
00006 namespace Impala
00007 {
00008 namespace Core
00009 {
00010 namespace Array
00011 {
00012 namespace Element
00013 {
00014
00015 inline double EuclidDistSquare(const Vec3Real64& p1, const Vec3Real64& p2)
00016 {
00017 double t,d;
00018 t = p1.X() - p2.X();
00019 d = t*t;
00020 t = p1.Y() - p2.Y();
00021 d += t*t;
00022 t = p1.Z() - p2.Z();
00023 d += t*t;
00024 return d;
00025 }
00026
00027 }
00028
00029 namespace Trait
00030 {
00031
00040 class FuncKalman
00041 {
00042 private:
00043 Array2dScalarUInt8* mOutCounter;
00044 std::deque<double> mPastResiduals;
00045 double mOutlierTreshold;
00046 public:
00047 double mSigmaI, mSigmaW, mSigmaG;
00048 double mAlpha, mBeta, mGamma, mN_omax, mK, mPixelCount;
00049 int mOutliers;
00050 double mResidualThisFrame,mResidualAvrg;
00051 bool mInitialised,mOcclusion;
00052
00053 typedef Pattern::TagTransVar TransVarianceCategory;
00054 typedef Pattern::TagCallValue CallCategory;
00055 typedef Vec3Int32 DstArithT;
00056 typedef Vec3Int32 SrcArithT;
00057
00061 FuncKalman(int w, int h)
00062 {
00063
00064 mAlpha = 2.5;
00065 mBeta = 1.1;
00066 mGamma = 0.4;
00067 mN_omax = 20;
00068 mK = 20;
00069
00070 mOutCounter = 0;
00071 Reset(w,h);
00072 }
00073
00083 void Reset(int w, int h)
00084 {
00085 if(mOutCounter)
00086 delete mOutCounter;
00087 mOutCounter = new Array2dScalarUInt8(w,h,0,0);
00088 int i;
00089 for(i=0 ; i<w*h ; i++)
00090 mOutCounter->mData[i] = 0;
00091
00092 mOutlierTreshold = 196608;
00093 mSigmaI = mSigmaW = 0;
00094 mSigmaG = 1;
00095 mPastResiduals.clear();
00096 mResidualThisFrame = 0;
00097 mPixelCount = 0;
00098 mOutliers = 0;
00099 mInitialised = false;
00100 mOcclusion = false;
00101 }
00102
00107 Vec3Real64
00108 doIt(const Vec3Real64& p1, const Vec3Real64& p2, int x, int y)
00109 {
00110 double r2;
00111 r2 = EuclidDistSquare(p1,p2);
00112
00113
00114 mResidualThisFrame += r2;
00115 mPixelCount++;
00116
00117 if(r2 < mOutlierTreshold)
00118 {
00119 mOutCounter->mData[y*mOutCounter->CW() + x] = 0;
00120
00121 return (p1*mSigmaI + p2*mSigmaG) / (mSigmaI+mSigmaG);
00122 }
00123 else
00124 {
00125 mOutliers++;
00126 if(mOcclusion)
00127 return p1;
00128 else
00129 {
00130 if(mOutCounter->mData[y*mOutCounter->CW() + x] >= mN_omax)
00131 {
00132 mOutCounter->mData[y*mOutCounter->CW() + x] = 0;
00133 return p2;
00134 }
00135 else
00136 {
00137 mOutCounter->mData[y*mOutCounter->CW() + x]++;
00138 return p1;
00139 }
00140 }
00141 }
00142 }
00143
00147 void InitialiseSigma()
00148 {
00149
00150 mSigmaW = 0;
00151 mSigmaI = 0.5*mResidualAvrg;
00152 mSigmaG = 0.5*mResidualAvrg;
00153 mInitialised = true;
00154 }
00155
00158 void UpdateKalman()
00159 {
00160
00161 mResidualThisFrame /= mPixelCount;
00162 mResidualThisFrame *= mBeta;
00163 if(mResidualThisFrame == 0)
00164 mResidualThisFrame = 1;
00165
00166 if(mPixelCount * mGamma > mOutliers)
00167 {
00168 mOcclusion = false;
00169 ComputeResiduals();
00170 if(!mInitialised)
00171 InitialiseSigma();
00172
00173 mSigmaG = (mSigmaG*mSigmaI)/(mSigmaG+mSigmaI);
00174
00175 mSigmaW = mResidualAvrg - mSigmaI - mSigmaG;
00176
00177
00178 if(mSigmaW<0)
00179 mSigmaW = 0;
00180
00181 mSigmaG += mSigmaW;
00182 }
00183 else
00184 {
00185 if(!mOcclusion)
00186 {
00187
00188 mSigmaG -= mSigmaW;
00189 }
00190 mOcclusion = true;
00191 }
00192 mPixelCount = 0;
00193 mOutliers = 0;
00194 }
00195
00196 void ComputeResiduals()
00197 {
00198
00199 mPastResiduals.push_back(mResidualThisFrame);
00200 mResidualThisFrame = 0;
00201 mResidualAvrg = 0;
00202 std::deque<double>::iterator i;
00203 for(i=mPastResiduals.begin() ; i!=mPastResiduals.end() ; i++)
00204 {
00205 mResidualAvrg += *i;
00206 }
00207 mResidualAvrg /= mPastResiduals.size();
00208 mOutlierTreshold = mResidualAvrg * mAlpha;
00209 while(mPastResiduals.size() > mK)
00210 mPastResiduals.pop_front();
00211 }
00212
00213 };
00214
00215
00220 class FuncKalmanColor
00221 {
00222 private:
00223 Array2dScalarUInt8* mOutCounter;
00224 std::deque<double> mPastResiduals[3];
00225 double mOutlierTreshold;
00226 public:
00227 double mSigmaI[3], mSigmaW[3], mSigmaG[3];
00228 double mChi2, mGamma, mN_omax, mK, mPixelCount;
00229 int mOutliers;
00230 double mResidualThisFrame[3], mResidualAvrg[3];
00231 bool mInitialised, mOcclusion;
00232
00233 typedef Pattern::TagTransVar TransVarianceCategory;
00234 typedef Pattern::TagCallPointer CallCategory;
00235 typedef Vec3Int32 DstArithT;
00236 typedef Vec3Int32 SrcArithT;
00237
00241 FuncKalmanColor()
00242 {
00243 CmdOptions& options = CmdOptions::GetInstance();
00244
00245 mChi2 = options.GetDouble("appearance_kalman.kalman.chi^2", 13);
00246 mGamma = options.GetDouble("appearance_kalman.kalman.gamma", 0.3);
00247 mN_omax = options.GetDouble("appearance_kalman.kalman.N_omax", 40);
00248 mK = options.GetDouble("appearance_kalman.kalman.K", 20);
00249
00250 mOutCounter = 0;
00251 Reset(0,0);
00252 }
00253
00263 void Reset(int w, int h)
00264 {
00265 if(mOutCounter)
00266 delete mOutCounter;
00267 mOutCounter = new Array2dScalarUInt8(w,h,0,0);
00268 int i;
00269 for(i=0 ; i<w*h ; i++)
00270 mOutCounter->mData[i] = 0;
00271
00272 mOutlierTreshold = 196608;
00273 for(i=0 ; i<3 ; i++)
00274 {
00275 mSigmaI[i] = 0;
00276 mSigmaW[i] = 0;
00277 mSigmaG[i] = 1;
00278 mPastResiduals[i].clear();
00279 mResidualThisFrame[i] = 0;
00280 }
00281 mPixelCount = 0;
00282 mOutliers = 0;
00283 mInitialised = false;
00284 mOcclusion = false;
00285 }
00286
00290 double MahalanobisDist(double* p1, double* p2)
00291 {
00292 double r, err=0;
00293 for(int i=0 ; i<3 ; i++)
00294 {
00295 r = p1[i] - p2[i];
00296 err += r*r/(mSigmaG[i]+mSigmaI[i]);
00297 mResidualThisFrame[i] += r*r;
00298 }
00299 return err;
00300 }
00301
00306 void
00307 DoIt(double* out, double* p1, double* p2, int x, int y)
00308 {
00309 double err;
00310 err = MahalanobisDist(p1,p2);
00311
00312 mPixelCount++;
00313
00314 if(err < mChi2 || !mInitialised)
00315 {
00316 mOutCounter->mData[y*mOutCounter->CW() + x] = 0;
00317
00318 for(int i=0 ; i<3 ; i++)
00319 out[i] = (p1[i] * mSigmaI[i] + p2[i] * mSigmaG[i]) / (mSigmaI[i]+mSigmaG[i]);
00320 return;
00321 }
00322 else
00323 {
00324 mOutliers++;
00325 if(mOcclusion)
00326 {
00327 for(int i=0 ; i<3 ; i++)
00328 out[i] = p1[i];
00329 return;
00330 }
00331 else
00332 {
00333 if(mOutCounter->mData[y*mOutCounter->CW() + x] >= mN_omax)
00334 {
00335 mOutCounter->mData[y*mOutCounter->CW() + x] = 0;
00336 for(int i=0 ; i<3 ; i++)
00337 out[i] = p2[i];
00338 return;
00339 }
00340 else
00341 {
00342 mOutCounter->mData[y*mOutCounter->CW() + x]++;
00343 for(int i=0 ; i<3 ; i++)
00344 out[i] = p1[i];
00345 return;
00346 }
00347 }
00348 }
00349 }
00350
00354 void InitialiseSigma()
00355 {
00356 for(int i=0 ; i<3 ; i++)
00357 {
00358
00359 mSigmaW[i] = 0;
00360 mSigmaI[i] = 0.5*mResidualAvrg[i];
00361 mSigmaG[i] = 0.5*mResidualAvrg[i];
00362 }
00363 mInitialised = true;
00364 }
00365
00368 void UpdateKalman()
00369 {
00370 int i;
00371 for(i=0 ; i<3 ; i++)
00372 {
00373
00374 mResidualThisFrame[i] /= mPixelCount;
00375 if(mResidualThisFrame[i] == 0)
00376 mResidualThisFrame[i] = 1;
00377 }
00378
00379 if(mPixelCount * mGamma > mOutliers)
00380 {
00381 mOcclusion = false;
00382 ComputeResiduals();
00383 if(!mInitialised)
00384 InitialiseSigma();
00385 for(i=0 ; i<3 ; i++)
00386 {
00387
00388 mSigmaG[i] = (mSigmaG[i]*mSigmaI[i])/(mSigmaG[i]+mSigmaI[i]);
00389
00390 mSigmaW[i] = mResidualAvrg[i] - mSigmaI[i] - mSigmaG[i];
00391
00392
00393 if(mSigmaW[i]<0)
00394 mSigmaW[i] = 0;
00395
00396 mSigmaG[i] += mSigmaW[i];
00397 }
00398 }
00399 else
00400 {
00401 if(!mOcclusion)
00402 {
00403
00404 for(i=0 ; i<3 ; i++)
00405 mSigmaG[i] -= mSigmaW[i];
00406 }
00407 mOcclusion = true;
00408
00409
00410
00411
00412
00413
00414 for(i=0 ; i<3 ; i++)
00415 mSigmaG[i] *= 1.15;
00416
00417 }
00418 mPixelCount = 0;
00419 mOutliers = 0;
00420 }
00421
00422 void ComputeResiduals()
00423 {
00424
00425 for(int i=0 ; i<3 ; i++)
00426 {
00427 mPastResiduals[i].push_back(mResidualThisFrame[i]);
00428 mResidualThisFrame[i] = 0;
00429 mResidualAvrg[i] = 0;
00430 std::deque<double>::iterator it;
00431 for(it=mPastResiduals[i].begin() ; it!=mPastResiduals[i].end() ; it++)
00432 {
00433 mResidualAvrg[i] += *it;
00434 }
00435 mResidualAvrg[i] /= mPastResiduals[i].size();
00436 mOutlierTreshold = mResidualAvrg[i];
00437 while(mPastResiduals[i].size() > mK)
00438 mPastResiduals[i].pop_front();
00439 }
00440 }
00441 };
00442
00443
00444
00451 class FuncBpoRobustMahalanobis
00452 {
00453 public:
00454 typedef Pattern::TagTransInVar TransVarianceCategory;
00455 typedef Pattern::TagCallPointer CallCategory;
00456
00457 typedef Vec3Int32 DstArithT;
00458 typedef Vec3Int32 Src1ArithT;
00459 typedef Vec3Int32 Src2ArithT;
00460
00461 double mSigma[3];
00462 double mError;
00463 double mChi;
00464
00465 FuncBpoRobustMahalanobis()
00466 {
00467 mSigma[0] = mSigma[1] = mSigma[2] = 1;
00468 mError = 0;
00469 mChi = 3.5;
00470 }
00471
00472 void
00473 DoIt(double* res, double* p1, double* p2)
00474 {
00475 double r, err=0;
00476 for(int i=0 ; i<3 ; i++)
00477 {
00478 r = p1[i] - p2[i];
00479 err += r*r/(mSigma[i]);
00480 }
00481
00482
00483 if(err < mChi)
00484 {
00485 double r = 0.5 * err * err;
00486 res[0] = res[1] = res[2] = r;
00487 mError += r;
00488 }
00489 else
00490 {
00491 double r = mChi*(err - mChi/2);
00492 res[0] = res[1] = res[2] = r;
00493 mError += r;
00494 }
00495 }
00496 };
00497
00498 }
00499 }
00500 }
00501 }
00502
00503 #endif //Impala_Core_Array_Trait_FuncKalman_h