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 Trace(const Array::Array2dScalarReal64* matrix)
00020 {
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
00032
00033
00034
00035
00036 class Classifier
00037 {
00038 public:
00039 Classifier(int size, int dimensionslity)
00040 :mDimensionality(dimensionslity)
00041 {
00042 CmdOptions& options = CmdOptions::GetInstance();
00043 mSize = size;
00044 mGamma = options.GetDouble("fore_back.classifier.gamma", 0.05);
00045 mLambdaFactor = options.GetDouble("fore_back.classifier.lambdafactor", 0.004);
00046 mObjectVectors = new Array::Array2dScalarReal64(mDimensionality, size, 0, 0);
00047 mClassifiers = new Array::Array2dScalarReal64(mDimensionality, size, 0, 0);
00048 mBackgroundMean = new Array::Array2dScalarReal64(mDimensionality, 1, 0, 0);
00049 mMatCovariance = new Array::Array2dScalarReal64(mDimensionality, mDimensionality, 0, 0);
00050 }
00051
00052 virtual ~Classifier()
00053 {
00054 delete mObjectVectors;
00055 delete mClassifiers;
00056 delete mBackgroundMean;
00057 delete mMatCovariance;
00058 }
00059
00060 void SetVec(const Array::Array2dScalarReal64& v, int index)
00061 {
00062 if(index >= mSize)
00063 std::cout << "[Classifier::SetVec] Classifier out of bounds" << std::endl;
00064 const double* vp = v.CPB(0,0);
00065 double* op = mObjectVectors->CPB(0,index);
00066 memcpy(op, vp, mDimensionality*sizeof(double));
00067 }
00068
00069 void UpdateVec(const Array::Array2dScalarReal64& v, int index)
00070 {
00071 if(index >= mSize)
00072 std::cout << "[Classifier::UpdateVec] Classifier out of bounds" << std::endl;
00073 const double* vp = v.CPB(0,0);
00074 double* op = mObjectVectors->CPB(0,index);
00075 for(int i=0 ; i<mDimensionality ; i++)
00076 {
00077 op[i] = op[i] * (1.0-mGamma) + vp[i] * mGamma;
00078 }
00079 }
00080
00081 void GetVector(int index, Array::Array2dScalarReal64& v)
00082 {
00083 double* vp = v.CPB(0, 0);
00084 double* op = mObjectVectors->CPB(0, index);
00085 memcpy(vp, op, mDimensionality*sizeof(double));
00086 }
00087
00088 void GetClassifiers(int index, Array::Array2dScalarReal64& v)
00089 {
00090 double* vp = v.CPB(0, 0);
00091 double* op = mClassifiers->CPB(0, index);
00092 memcpy(vp, op, mDimensionality*sizeof(double));
00093 }
00094
00095 void SetBackground(Array::Array2dScalarReal64& background)
00096 {
00097 delete mMatCovariance;
00098 mMatCovariance = Matrix::MatCovarianceExact(&background);
00099 MeanFromSamples(mBackgroundMean, &background);
00100 UpdateClassifiers();
00101 }
00102
00103 void Update(Array::Array2dScalarReal64& background)
00104 {
00105 UpdateBackGroundModel(background);
00106 UpdateClassifiers();
00107 }
00108
00109 void WriteSimpleDebug(std::ostream& stream)
00110 {
00111 stream << "[Classifier::WriteDebug]\n background";
00112 for(int i=0 ; i<mBackgroundMean->CW() ; i++)
00113 stream << " " << mBackgroundMean->Val(i,0);
00114 stream << "\n object vectors";
00115 for(int i=0 ; i<mObjectVectors->CH() ; i++)
00116 {
00117 stream << "\n ";
00118 for(int j=0 ; j<mObjectVectors->CW() ; j++)
00119 stream << " " << mObjectVectors->Val(i,j);
00120 }
00121 }
00122
00123 void WriteDebug(std::ostream& stream)
00124 {
00125 WriteSimpleDebug(stream);
00126 stream << "\n covariance matrix";
00127 for(int i=0 ; i<mMatCovariance->CH() ; i++)
00128 {
00129 stream << "\n ";
00130 for(int j=0 ; j<mMatCovariance->CW() ; j++)
00131 stream << " " << mMatCovariance->Val(i,j);
00132 }
00133 stream << std::endl;
00134 }
00135
00136
00137 private:
00138 double mGamma;
00139 double mLambdaFactor;
00140 int mSize;
00141 int mDimensionality;
00142
00143 Array::Array2dScalarReal64* mMatCovariance;
00144 Array::Array2dScalarReal64* mBackgroundMean;
00145 Array::Array2dScalarReal64* mObjectVectors;
00146 Array::Array2dScalarReal64* mClassifiers;
00147
00148 void UpdateBackGroundModel(Array::Array2dScalarReal64& background)
00149 {
00150
00151 Array::Array2dScalarReal64* temp = new Array::Array2dScalarReal64(mDimensionality, mDimensionality, 0, 0);
00152 MulVal(mMatCovariance, mMatCovariance, 1.-mGamma);
00153 MultiplyWithTranspose(temp, mBackgroundMean);
00154 AddMatrixWeighted(mMatCovariance, temp, 1.-mGamma);
00155
00156 MulVal(mBackgroundMean, mBackgroundMean, 1.-mGamma);
00157 Array::Array2dScalarReal64* mean = new Array::Array2dScalarReal64(mDimensionality, 1, 0, 0);
00158 MeanFromSamples(mean, &background);
00159 AddMatrixWeighted(mBackgroundMean, mean, mGamma);
00160 delete mean;
00161
00162 MultiplyWithTranspose(temp, mBackgroundMean);
00163 Sub(mMatCovariance, mMatCovariance, temp);
00164 SommateTransposeMultiplications(temp, &background);
00165 AddMatrixWeighted(mMatCovariance, temp, mGamma);
00166 delete temp;
00167 }
00168
00169 void UpdateClassifiers()
00170 {
00171
00172
00173 Array::Array2dScalarReal64* temp = new Array::Array2dScalarReal64(mDimensionality, mDimensionality, 0, 0);
00174 AddLambdaDiagonal(temp, mMatCovariance);
00175 Array::Array2dScalarReal64* Binverse = Matrix::MatInverse(temp);
00176 if(Binverse)
00177 {
00178 for(int i=0 ; i<mObjectVectors->CH() ; i++)
00179 {
00180
00181 Array::Array2dScalarReal64* vector = new Array::Array2dScalarReal64(1, mDimensionality, 0, 0);
00182 GetNormalisedObjectVector(vector,i);
00183
00184 Array::Array2dScalarReal64* correlatedVector = Matrix::MatMul(Binverse, vector);
00185 double k_i = CrossProduct(vector, correlatedVector);
00186 k_i = 2. / (2.+k_i);
00187 SetClassifier(i, k_i, correlatedVector);
00188 delete correlatedVector;
00189 delete vector;
00190 }
00191 delete Binverse;
00192 }
00193 delete temp;
00194 }
00195
00196
00197 void MultiplyWithTranspose(Array::Array2dScalarReal64*& matrix, const Array::Array2dScalarReal64* vector)
00198 {
00199 const double* vec = vector->CPB();
00200 MultiplyWithTranspose(matrix, vec);
00201 }
00202
00203 void MultiplyWithTranspose(Array::Array2dScalarReal64*& matrix, const double* vec)
00204 {
00205 for(int i=0 ; i<matrix->CH() ; i++)
00206 {
00207 double* dst = matrix->CPB(0, i);
00208 for(int j=0 ; j<matrix->CW() ; j++)
00209 dst[j] = vec[i]*vec[j];
00210 }
00211 }
00212
00213 void AddMatrixWeighted(Array::Array2dScalarReal64*& matrix, const Array::Array2dScalarReal64* addmatrix, double weight)
00214 {
00215 double* dst = matrix->CPB();
00216 const double* src = addmatrix->CPB();
00217 for(int i=0 ; i<matrix->CW()*matrix->CH() ; i++)
00218 {
00219 dst[i] += src[i]*weight;
00220 }
00221 }
00222
00223 void MeanFromSamples(Array::Array2dScalarReal64*& mean, const Array::Array2dScalarReal64* samples)
00224 {
00225 double* dst = mean->CPB();
00226 int i;
00227 for(i=0 ; i<samples->CW() ; i++)
00228 dst[i] = 0;
00229 for(i=0 ; i<samples->CH() ; i++)
00230 {
00231 const double* src = samples->CPB(0, i);
00232 for(int j=0 ; j<samples->CW() ; j++)
00233 dst[j] += src[j];
00234 }
00235 for(i=0 ; i<samples->CW() ; i++)
00236 dst[i] /= samples->CH();
00237 }
00238
00239 void SommateTransposeMultiplications(Array::Array2dScalarReal64*& matrix, const Array::Array2dScalarReal64* samples)
00240 {
00241 double* dst = matrix->CPB();
00242 int i;
00243 for(i=0 ; i<matrix->CW()*matrix->CH() ; i++)
00244 dst[i] = 0;
00245
00246 Array::Array2dScalarReal64* temp = new Array::Array2dScalarReal64(mDimensionality, mDimensionality, 0, 0);
00247 for(i=0 ; i<samples->CH() ; i++)
00248 {
00249 const double* sample = samples->CPB(0,i);
00250 MultiplyWithTranspose(temp, sample);
00251 Array::Add(matrix, matrix, temp);
00252 }
00253 delete temp;
00254 for(i=0 ; i<matrix->CH()*matrix->CH() ; i++)
00255 dst[i] /= (double)samples->CH();
00256 }
00257
00258 void AddLambdaDiagonal(Array::Array2dScalarReal64*& matrixDst, const Array::Array2dScalarReal64* matrixSrc)
00259 {
00260
00261 double trace = Trace(matrixSrc) * mLambdaFactor;
00262 int i;
00263 for(i=0 ; i<matrixDst->CH() ; i++)
00264 {
00265 double* dst = matrixDst->CPB(0, i);
00266 const double* src = matrixSrc->CPB(0, i);
00267 for(int j=0 ; j<matrixDst->CW() ; j++)
00268 {
00269 dst[j] = src[j];
00270 if(i==j)
00271 dst[j] += trace;
00272 }
00273 }
00274 }
00275
00276 void GetNormalisedObjectVector(Array::Array2dScalarReal64*& vector, int index)
00277 {
00278 const double* object = mObjectVectors->CPB(0, index);
00279 const double* backMean = mBackgroundMean->CPB();
00280 double* dst = vector->CPB();
00281 for(int i=0 ; i<mDimensionality ; i++)
00282 {
00283 dst[i] = object[i] - backMean[i];
00284 }
00285 }
00286
00287 double CrossProduct(const Array::Array2dScalarReal64* vector1, const Array::Array2dScalarReal64* vector2)
00288 {
00289 const double* src1 = vector1->CPB();
00290 const double* src2 = vector1->CPB();
00291 double dst = 0;
00292 for(int i=0 ; i<mDimensionality ; i++)
00293 {
00294 dst += src1[i] * src2[i];
00295 }
00296 return dst;
00297 }
00298
00299 void SetClassifier(int index, double k_i, const Array::Array2dScalarReal64* correlatedVector)
00300 {
00301 const double* src = correlatedVector->CPB();
00302 double* dst = mClassifiers->CPB(0,index);
00303 for(int i=0 ; i<mDimensionality ; i++)
00304 {
00305 dst[i] = src[i] * k_i;
00306 }
00307 }
00308
00309 };
00310
00311 }
00312 }
00313 }
00314
00315 #endif //Impala_Core_Tracking_Classifier_h