00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "QGMMModel.h"
00020 #include "NumericLib.h"
00021
00022 using namespace std;
00023 using namespace Marsyas;
00024
00025
00026
00027
00028 QGMMModel::QGMMModel()
00029 {
00030 resetModel();
00031 }
00032
00033 QGMMModel::QGMMModel(const QGMMModel &a)
00034 {
00035 maxNrGSMixes_ = a.maxNrGSMixes_;
00036 nrGSMixes_ = a.nrGSMixes_;
00037 GSmixNrFrames_ = a.GSmixNrFrames_;
00038 GSmixCovMatrix_ = a.GSmixCovMatrix_;
00039 totalNrFrames_ = a.totalNrFrames_;
00040
00041 divergenceThres_ = a.divergenceThres_;
00042 }
00043 QGMMModel::~QGMMModel()
00044 {
00045
00046 }
00047
00048 void
00049 QGMMModel::resetModel()
00050 {
00051 maxNrGSMixes_ = 32;
00052 nrGSMixes_ = 0;
00053 GSmixNrFrames_.clear();
00054 GSmixCovMatrix_.clear();
00055 totalNrFrames_ = 0;
00056 divergenceThres_ = 0.50;
00057 }
00058
00059 realvec
00060 QGMMModel::updateCovModel(realvec C, mrs_natural N, realvec Cm, mrs_natural Nm)
00061 {
00062 C *= ((mrs_real)N / (mrs_real)(N+Nm));
00063 Cm *= ((mrs_real)Nm / (mrs_real)(N+Nm));
00064 C += Cm;
00065
00066 return C;
00067 }
00068
00069 void
00070 QGMMModel::updateModel(realvec &covMatrix, mrs_natural nrModelFrames)
00071 {
00072 static mrs_real meanDiv, count;
00073 static bool stopUpdate;
00074
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00095
00096
00097
00098 if(nrGSMixes_ == 0)
00099 {
00100 meanDiv = 0;
00101 count = 0;
00102 stopUpdate = false;
00103
00104 nrGSMixes_++;
00105 GSmixCovMatrix_.push_back(covMatrix);
00106 GSmixNrFrames_.push_back(nrModelFrames);
00107 totalNrFrames_ = nrModelFrames;
00108
00109 return;
00110 }
00111
00112 else
00113 {
00114 mrs_natural curMix = nrGSMixes_ - 1;
00115
00116
00117 realvec updatedModel = updateCovModel(GSmixCovMatrix_[curMix], GSmixNrFrames_[curMix],
00118 covMatrix, nrModelFrames);
00119
00120
00121 mrs_real divergenceShape = NumericLib::divergenceShape(GSmixCovMatrix_[curMix],updatedModel);
00122
00123
00124 meanDiv = meanDiv + 1/(count+1)*(divergenceShape - meanDiv);
00125 count++;
00126
00127
00128
00129 if (divergenceShape > meanDiv*divergenceThres_ && stopUpdate == false)
00130 {
00131 GSmixCovMatrix_[curMix] = updatedModel;
00132 GSmixNrFrames_[curMix] += nrModelFrames;
00133 totalNrFrames_ += nrModelFrames;
00134 }
00135
00136
00137 else
00138 {
00139 if (nrGSMixes_ < maxNrGSMixes_)
00140 {
00141 nrGSMixes_++;
00142 GSmixCovMatrix_.push_back(covMatrix);
00143 GSmixNrFrames_.push_back(nrModelFrames);
00144 totalNrFrames_ += nrModelFrames;
00145
00146 meanDiv = 0;
00147 count = 0;
00148 }
00149 else
00150 {
00151 stopUpdate = true;
00152 }
00153 }
00154 }
00155 }
00156
00157 mrs_real
00158 QGMMModel::deltaBIC(realvec C1, mrs_natural N1, realvec C2, mrs_natural N2, realvec C, mrs_real lambda)
00159 {
00160
00161 if(C1.getCols() != C2.getCols() && C1.getCols() != C.getCols() &&
00162 C1.getCols()!= C1.getRows())
00163 {
00164 MRSERR("QGMMModel:deltaBIC: matrices should all be squared and equal sized...");
00165 return MAXREAL;
00166 }
00167
00168 mrs_real res;
00169 mrs_real N = (mrs_real)(N1 + N2);
00170 mrs_real d = (mrs_real)C1.getCols();
00171
00172
00173 res = N * log(C.det());
00174 res -= (mrs_real)N1 * log(C1.det());
00175 res -= (mrs_real)N2 * log(C2.det());
00176 res *= 0.5f;
00177
00178 res -= 0.5f * lambda * (d + 0.5f*d*(d+1.0f))* log(N);
00179
00180 return res;
00181 }
00182
00183 mrs_real
00184 QGMMModel::BICdistance(realvec &covMatrix, mrs_natural Nframes, mrs_real lambda)
00185 {
00186 mrs_real wi;
00187 mrs_real res = 0;
00188
00189
00190
00191
00192
00193 for(mrs_natural i = 0; i < nrGSMixes_; ++i)
00194 {
00195 realvec combinedModel = updateCovModel(GSmixCovMatrix_[i],GSmixNrFrames_[i],
00196 covMatrix, Nframes);
00197
00198 wi = (mrs_real)GSmixNrFrames_[i]/(mrs_real)totalNrFrames_;
00199 res += wi * deltaBIC(GSmixCovMatrix_[i], GSmixNrFrames_[i], covMatrix, Nframes, combinedModel, lambda);
00200 }
00201
00202 return res;
00203 }