00001 #ifndef Impala_Core_Tracking_Classifier_h
00002 #define Impala_Core_Tracking_Classifier_h
00003
00004 #include "Core/Array/Arrays.h"
00005 #include "Core/Matrix/MatCovariance.h"
00006 #include "Core/Matrix/MatInverse.h"
00007 #include "Core/Matrix/MatMul.h"
00008 #include "Core/Array/MulVal.h"
00009 #include "Core/Array/Sub.h"
00010 #include "Core/Array/Add.h"
00011
00012 namespace Impala
00013 {
00014 namespace Core
00015 {
00016 namespace Tracking
00017 {
00018
00019 double
00020 Trace(const Array::Array2dScalarReal64* matrix)
00021 {
00022 const double* src = matrix->CPB();
00023 double trace = 0;
00024 int i;
00025 for(i=0 ; i<matrix->CW()*matrix->CH() ; i++)
00026 {
00027 trace += src[i];
00028 }
00029 return trace;
00030 }
00031
00045 class Classifier
00046 {
00047 public:
00048 Classifier(int size, int dimensionslity)
00049 :mDimensionality(dimensionslity)
00050 {
00051 CmdOptions& options = CmdOptions::GetInstance();
00052 mSize = size;
00053 mGamma = options.GetDouble("fore_back.classifier.gamma", 0.05);
00054 mLambdaFactor = options.GetDouble("fore_back.classifier.lambdafactor", 0.004);
00055 mObjectVectors = new Array::Array2dScalarReal64(mDimensionality, size, 0, 0);
00056 mClassifiers = new Array::Array2dScalarReal64(mDimensionality, size, 0, 0);
00057 mBackgroundMean = new Array::Array2dScalarReal64(mDimensionality, 1, 0, 0);
00058 mMatCovariance = new Array::Array2dScalarReal64(mDimensionality, mDimensionality, 0, 0);
00059 }
00060
00061 virtual ~Classifier()
00062 {
00063 delete mObjectVectors;
00064 delete mClassifiers;
00065 delete mBackgroundMean;
00066 delete mMatCovariance;
00067 }
00068
00071 void
00072 SetVec(const Array::Array2dScalarReal64& v, int index)
00073 {
00074 if(index >= mSize)
00075 std::cout << "[Classifier::SetVec] Classifier out of bounds" << std::endl;
00076 const double* vp = v.CPB(0,0);
00077 double* op = mObjectVectors->CPB(0,index);
00078 memcpy(op, vp, mDimensionality*sizeof(double));
00079 }
00080
00084 void
00085 UpdateVec(const Array::Array2dScalarReal64& v, int index)
00086 {
00087 if(index >= mSize)
00088 std::cout << "[Classifier::UpdateVec] Classifier out of bounds" << std::endl;
00089 const double* vp = v.CPB(0,0);
00090 double* op = mObjectVectors->CPB(0,index);
00091 for(int i=0 ; i<mDimensionality ; i++)
00092 {
00093 op[i] = op[i] * (1.0-mGamma) + vp[i] * mGamma;
00094 }
00095 }
00096
00097 void
00098 GetVector(int index, Array::Array2dScalarReal64& v)
00099 {
00100 double* vp = v.CPB(0, 0);
00101 double* op = mObjectVectors->CPB(0, index);
00102 memcpy(vp, op, mDimensionality*sizeof(double));
00103 }
00104
00105 void
00106 GetClassifiers(int index, Array::Array2dScalarReal64& v)
00107 {
00108 double* vp = v.CPB(0, 0);
00109 double* op = mClassifiers->CPB(0, index);
00110 memcpy(vp, op, mDimensionality*sizeof(double));
00111 }
00112
00114 void
00115 SetBackground(Array::Array2dScalarReal64& background)
00116 {
00117 delete mMatCovariance;
00118 mMatCovariance = Matrix::MatCovarianceExact(&background);
00119 MeanFromSamples(mBackgroundMean, &background);
00120 UpdateClassifiers();
00121 }
00122
00126 void
00127 Update(Array::Array2dScalarReal64& background)
00128 {
00129 UpdateBackGroundModel(background);
00130 UpdateClassifiers();
00131 }
00132
00133 void
00134 WriteSimpleDebug(std::ostream& stream)
00135 {
00136 stream << "[Classifier::WriteDebug]\n background";
00137 for(int i=0 ; i<mBackgroundMean->CW() ; i++)
00138 stream << " " << mBackgroundMean->Val(i,0);
00139 stream << "\n object vectors";
00140 for(int i=0 ; i<mObjectVectors->CH() ; i++)
00141 {
00142 stream << "\n ";
00143 for(int j=0 ; j<mObjectVectors->CW() ; j++)
00144 stream << " " << mObjectVectors->Val(i,j);
00145 }
00146 }
00147
00148 void
00149 WriteDebug(std::ostream& stream)
00150 {
00151 WriteSimpleDebug(stream);
00152 stream << "\n covariance matrix";
00153 for(int i=0 ; i<mMatCovariance->CH() ; i++)
00154 {
00155 stream << "\n ";
00156 for(int j=0 ; j<mMatCovariance->CW() ; j++)
00157 stream << " " << mMatCovariance->Val(i,j);
00158 }
00159 stream << std::endl;
00160 }
00161
00162
00163 private:
00164 double mGamma;
00165 double mLambdaFactor;
00166 int mSize;
00167 int mDimensionality;
00168
00169 Array::Array2dScalarReal64* mMatCovariance;
00170 Array::Array2dScalarReal64* mBackgroundMean;
00171 Array::Array2dScalarReal64* mObjectVectors;
00172 Array::Array2dScalarReal64* mClassifiers;
00173
00174 void
00175 UpdateBackGroundModel(Array::Array2dScalarReal64& background)
00176 {
00177
00178 Array::Array2dScalarReal64* temp =
00179 new Array::Array2dScalarReal64(mDimensionality, mDimensionality, 0, 0);
00180 MulVal(mMatCovariance, mMatCovariance, 1.-mGamma);
00181 MultiplyWithTranspose(temp, mBackgroundMean);
00182 AddMatrixWeighted(mMatCovariance, temp, 1.-mGamma);
00183
00184 MulVal(mBackgroundMean, mBackgroundMean, 1.-mGamma);
00185 Array::Array2dScalarReal64* mean =
00186 new Array::Array2dScalarReal64(mDimensionality, 1, 0, 0);
00187 MeanFromSamples(mean, &background);
00188 AddMatrixWeighted(mBackgroundMean, mean, mGamma);
00189 delete mean;
00190
00191 MultiplyWithTranspose(temp, mBackgroundMean);
00192 Sub(mMatCovariance, mMatCovariance, temp);
00193 SommateTransposeMultiplications(temp, &background);
00194 AddMatrixWeighted(mMatCovariance, temp, mGamma);
00195 delete temp;
00196 }
00197
00198 void
00199 UpdateClassifiers()
00200 {
00201
00202
00203 Array::Array2dScalarReal64* temp =
00204 new Array::Array2dScalarReal64(mDimensionality, mDimensionality, 0, 0);
00205 AddLambdaDiagonal(temp, mMatCovariance);
00206 Array::Array2dScalarReal64* Binverse = Matrix::MatInverse(temp);
00207 if(Binverse)
00208 {
00209 for(int i=0 ; i<mObjectVectors->CH() ; i++)
00210 {
00211
00212 Array::Array2dScalarReal64* vector =
00213 new Array::Array2dScalarReal64(1, mDimensionality, 0, 0);
00214 GetNormalisedObjectVector(vector,i);
00215
00216
00217 Array::Array2dScalarReal64* correlatedVector =
00218 Matrix::MatMul(Binverse, vector);
00219 double k_i = CrossProduct(vector, correlatedVector);
00220 k_i = 2. / (2.+k_i);
00221 SetClassifier(i, k_i, correlatedVector);
00222 delete correlatedVector;
00223 delete vector;
00224 }
00225 delete Binverse;
00226 }
00227 delete temp;
00228 }
00229
00230
00232 void
00233 MultiplyWithTranspose(Array::Array2dScalarReal64*& matrix,
00234 const Array::Array2dScalarReal64* vector)
00235 {
00236 const double* vec = vector->CPB();
00237 MultiplyWithTranspose(matrix, vec);
00238 }
00239
00241 void
00242 MultiplyWithTranspose(Array::Array2dScalarReal64*& matrix, const double* vec)
00243 {
00244 for(int i=0 ; i<matrix->CH() ; i++)
00245 {
00246 double* dst = matrix->CPB(0, i);
00247 for(int j=0 ; j<matrix->CW() ; j++)
00248 dst[j] = vec[i]*vec[j];
00249 }
00250 }
00251
00253 void
00254 AddMatrixWeighted(Array::Array2dScalarReal64*& matrix,
00255 const Array::Array2dScalarReal64* addmatrix, double weight)
00256 {
00257 double* dst = matrix->CPB();
00258 const double* src = addmatrix->CPB();
00259 for(int i=0 ; i<matrix->CW()*matrix->CH() ; i++)
00260 {
00261 dst[i] += src[i]*weight;
00262 }
00263 }
00264
00266 void
00267 MeanFromSamples(Array::Array2dScalarReal64*& mean,
00268 const Array::Array2dScalarReal64* samples)
00269 {
00270 double* dst = mean->CPB();
00271 int i;
00272 for(i=0 ; i<samples->CW() ; i++)
00273 dst[i] = 0;
00274 for(i=0 ; i<samples->CH() ; i++)
00275 {
00276 const double* src = samples->CPB(0, i);
00277 for(int j=0 ; j<samples->CW() ; j++)
00278 dst[j] += src[j];
00279 }
00280 for(i=0 ; i<samples->CW() ; i++)
00281 dst[i] /= samples->CH();
00282 }
00283
00285 void
00286 SommateTransposeMultiplications(Array::Array2dScalarReal64*& matrix,
00287 const Array::Array2dScalarReal64* samples)
00288 {
00289 double* dst = matrix->CPB();
00290 int i;
00291 for(i=0 ; i<matrix->CW()*matrix->CH() ; i++)
00292 dst[i] = 0;
00293
00294 Array::Array2dScalarReal64* temp =
00295 new Array::Array2dScalarReal64(mDimensionality, mDimensionality, 0, 0);
00296 for(i=0 ; i<samples->CH() ; i++)
00297 {
00298 const double* sample = samples->CPB(0,i);
00299 MultiplyWithTranspose(temp, sample);
00300 Array::Add(matrix, matrix, temp);
00301 }
00302 delete temp;
00303 for(i=0 ; i<matrix->CH()*matrix->CH() ; i++)
00304 dst[i] /= (double)samples->CH();
00305 }
00306
00307 void
00308 AddLambdaDiagonal(Array::Array2dScalarReal64*& matrixDst,
00309 const Array::Array2dScalarReal64* matrixSrc)
00310 {
00311
00312 double trace = Trace(matrixSrc) * mLambdaFactor;
00313 int i;
00314 for(i=0 ; i<matrixDst->CH() ; i++)
00315 {
00316 double* dst = matrixDst->CPB(0, i);
00317 const double* src = matrixSrc->CPB(0, i);
00318 for(int j=0 ; j<matrixDst->CW() ; j++)
00319 {
00320 dst[j] = src[j];
00321 if(i==j)
00322 dst[j] += trace;
00323 }
00324 }
00325 }
00326
00327 void
00328 GetNormalisedObjectVector(Array::Array2dScalarReal64*& vector, int index)
00329 {
00330 const double* object = mObjectVectors->CPB(0, index);
00331 const double* backMean = mBackgroundMean->CPB();
00332 double* dst = vector->CPB();
00333 for(int i=0 ; i<mDimensionality ; i++)
00334 {
00335 dst[i] = object[i] - backMean[i];
00336 }
00337 }
00338
00340 double
00341 CrossProduct(const Array::Array2dScalarReal64* vector1,
00342 const Array::Array2dScalarReal64* vector2)
00343 {
00344 const double* src1 = vector1->CPB();
00345 const double* src2 = vector1->CPB();
00346 double dst = 0;
00347 for(int i=0 ; i<mDimensionality ; i++)
00348 {
00349 dst += src1[i] * src2[i];
00350 }
00351 return dst;
00352 }
00353
00354 void
00355 SetClassifier(int index, double k_i,
00356 const Array::Array2dScalarReal64* correlatedVector)
00357 {
00358 const double* src = correlatedVector->CPB();
00359 double* dst = mClassifiers->CPB(0,index);
00360 for(int i=0 ; i<mDimensionality ; i++)
00361 {
00362 dst[i] = src[i] * k_i;
00363 }
00364 }
00365
00366 };
00367
00368 }
00369 }
00370 }
00371
00372 #endif //Impala_Core_Tracking_Classifier_h