00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #if !defined(ALIZE_EnergyDetector_cpp)
00056 #define ALIZE_EnergyDetector_cpp
00057
00058 #include <iostream>
00059 #include <fstream>
00060 #include <cassert>
00061 #include <cmath>
00062 #include <liatools.h>
00063 #include "SegTools.h"
00064 #include "EnergyDetector.h"
00065
00066 #define DirectInterpolation 1
00067
00068 using namespace alize;
00069 using namespace std;
00070
00071
00072 void plotEnergyDistrib(MixtureGD &mixt)
00073 {
00074 unsigned long distribCount = mixt.getDistribCount();
00075 cout << "EnergyModel"<<endl;
00076 for (unsigned long c=0; c<distribCount; c++)
00077 cout << "Component["<<c<<"] Mean["<<mixt.getDistrib(c).getMean(0)<<
00078 "] Cov["<<mixt.getDistrib(c).getCov(0)<<"] Weight["<<mixt.weight(c)<<"]"<<endl;
00079 }
00080
00081
00082 unsigned long findMaxEnergyDistrib(MixtureGD &mixt)
00083 {
00084 unsigned long distribCount = mixt.getDistribCount();
00085 unsigned long cmpMax=0;
00086 for (unsigned long c=1; c<distribCount; c++)
00087 if (mixt.getDistrib(c).getMean(0)>mixt.getDistrib(cmpMax).getMean(0))
00088 cmpMax=c;
00089 if (verbose) cout << "Highest component["<<cmpMax<<"] Mean["<<mixt.getDistrib(cmpMax).getMean(0)<<
00090 "] Cov["<<mixt.getDistrib(cmpMax).getCov(0)<<"] Weight["<<mixt.weight(cmpMax)<<"]"<<endl;
00091 return cmpMax;
00092 }
00093
00094 unsigned long findMinEnergyDistrib(MixtureGD &mixt)
00095 {
00096 unsigned long distribCount = mixt.getDistribCount();
00097 unsigned long cmpMin=0;
00098 for (unsigned long c=1; c<distribCount; c++)
00099 if (mixt.getDistrib(c).getMean(0)<mixt.getDistrib(cmpMin).getMean(0))
00100 cmpMin=c;
00101 if (verbose) cout << "Lowest component["<<cmpMin<<"] Mean["<<mixt.getDistrib(cmpMin).getMean(0)<<
00102 "] Cov["<<mixt.getDistrib(cmpMin).getCov(0)<<"] Weight["<<mixt.weight(cmpMin)<<"]"<<endl;
00103 return cmpMin;
00104 }
00105
00106 double computeEnergyThreshold(FeatureServer & fs,double pSelect,unsigned long nbBins=100)
00107 {
00108 Histo histo(nbBins);
00109 Feature f;
00110 fs.reset();
00111 for (unsigned long ind=0;fs.readFeature(f); ind++)
00112 histo.accumulateValue(f[0]);
00113 histo.computeHisto();
00114 long i=nbBins-1;
00115 real_t count=0;
00116 while((i>=0) && (count<=pSelect)){
00117 count+=histo.count(i)*(histo.higherBound(i)-histo.lowerBound(i));
00118 i--;
00119 }
00120 double threshold;
00121 if (i>=0) threshold=histo.higherBound(i);
00122 else threshold=histo.lowerBound(0);
00123 if (verbose) cout << "Percentage wanted["<<(int) (pSelect*100.0) <<"]Energy threshold["<<threshold<<"]"<<endl;
00124 return threshold;
00125 }
00126
00127
00128 unsigned long selectFrames(FeatureServer &fs,SegServer & segServer,double threshold,SegCluster &selectedSeg,SegCluster &outputSeg,String labelOutput,String fileName)
00129 {
00130 unsigned long countFrames=0;
00131 fs.reset();
00132 unsigned long ind=0;
00133 unsigned long begin=0;
00134 bool in=false;
00135 Seg *seg;
00136 selectedSeg.rewind();
00137 while((seg=selectedSeg.getSeg())!=NULL){
00138 for (unsigned long idx=seg->begin();idx<seg->begin()+seg->length();idx++){
00139 Feature f;
00140 fs.seekFeature(idx);
00141 fs.readFeature(f);
00142 if (f[0]>threshold){
00143 countFrames++;
00144 if (in==false){
00145 in=true;
00146 begin=ind;
00147 }
00148 }
00149 else if (in){
00150 in=false;
00151 Seg & segFake=segServer.createSeg(begin,ind-begin,0,
00152 labelOutput,fileName);
00153 outputSeg.add(segFake);
00154 }
00155 ind++;
00156 }
00157 if (in){
00158 in=false;
00159 Seg & segFake=segServer.createSeg(begin,ind-begin+1,0,
00160 labelOutput,fileName);
00161 outputSeg.add(segFake);
00162 }
00163 }
00164
00165 return countFrames;
00166 }
00167
00168
00169
00170
00171
00172
00173 MixtureGD &energyMixtureInit(MixtureServer &ms, StatServer &ss, FeatureServer &fs,MixtureGD
00174 &world,SegCluster &selectedSegments,const DoubleVector &globalCov, Config& config)
00175 {
00176 unsigned long vectSize = world.getVectSize();
00177 unsigned long distribCount = world.getDistribCount();
00178
00179 double mean=-2.0;
00180 double meanIncrement;
00181 if (distribCount>1) meanIncrement=4.0/(double)(distribCount-1);
00182 else meanIncrement=1;
00183 for (unsigned long indg=0;indg<distribCount;indg++) {
00184 DistribGD& d = world.getDistrib(indg);
00185 for (unsigned long c=0;c<vectSize;c++,mean+=meanIncrement){
00186 d.setCov(1.0, c);
00187 d.setMean(mean, c);
00188 }
00189 d.computeAll();
00190 }
00191 world.equalizeWeights();
00192 return world;
00193 }
00194
00195
00196
00197
00198
00199
00200 SegCluster& energyDetector(Config& config,SegServer &segServer,String &featureFileName)
00201 {
00202 int nbTrainIt = config.getParam("nbTrainIt").toLong();
00203 String thresholdMode;
00204 if (config.existsParam("thresholdMode"))
00205 thresholdMode= config.getParam("thresholdMode");
00206 else thresholdMode="meanStd";
00207 double alpha = config.getParam("alpha").toDouble();
00208 double flooring = config.getParam("varianceFlooring").toDouble();
00209 double ceiling = config.getParam("varianceCeiling").toDouble();
00210 String labelSelectedFrames = config.getParam("labelSelectedFrames");
00211 String labelOutput = config.getParam("labelOutputFrames");
00212
00213 if (verbose) cout << "Proceeding Energy based silence detection for ["<<featureFileName<<"]"<<endl;
00214 FeatureServer fs(config,featureFileName);
00215 LabelServer labelServer;
00216 initializeClusters(featureFileName,segServer,labelServer,config);
00217 unsigned long codeSelectedFrame=labelServer.getLabelIndexByString(labelSelectedFrames);
00218 SegCluster& selectedSegments=segServer.getCluster(codeSelectedFrame);
00219
00220
00221 unsigned long codeOutput=segServer.getClusterCount();
00222 segServer.createCluster(codeOutput);
00223 SegCluster& outputSeg=segServer.getCluster(codeOutput);
00224 MixtureServer ms(config);
00225 StatServer ss(config,ms);
00226
00227 FrameAccGD globalFrameAcc;
00228 globalMeanCov (fs,selectedSegments,globalFrameAcc,config);
00229
00230 DoubleVector globalMean=globalFrameAcc.getMeanVect();
00231 DoubleVector globalCov=globalFrameAcc.getCovVect();
00232 if (verboseLevel>1){
00233 cout <<"global mean and cov"<<endl;
00234 for (unsigned i=0; i < fs.getVectSize(); i++)cout << "mean[" << i << "=" << globalMean[i] << "]\tcov[" << globalCov[i] << "]" << endl;
00235 }
00236 MixtureGD & energyModel=ms.createMixtureGD();
00237
00238 energyMixtureInit(ms, ss, fs,energyModel,selectedSegments,globalCov,config);
00239 if (verboseLevel>1)plotEnergyDistrib(energyModel);
00240 MixtureStat &emAcc=ss.createAndStoreMixtureStat(energyModel);
00241 for (int trainIt=0; trainIt<nbTrainIt; trainIt++){
00242 emAcc.resetEM();
00243 double llkPreviousIt=accumulateStatEM(ss,fs,emAcc,selectedSegments,config);
00244 energyModel = emAcc.getEM();
00245 varianceControl(energyModel,flooring,ceiling,globalCov);
00246 if (verbose) cout << "Partial Train it["<<trainIt-1 <<"] (-1 means initial partial it) LLK="<<llkPreviousIt<<" Nb Frames="
00247 <<emAcc.getEMFeatureCount()<<endl;
00248 if (verboseLevel>1)plotEnergyDistrib(energyModel);
00249 }
00250 unsigned long nbInitialFrames= (unsigned long) emAcc.getEMFeatureCount();
00251 double threshold=0;
00252 unsigned long higher=findMaxEnergyDistrib(energyModel);
00253 if (thresholdMode=="weight"){
00254 double selectedWeight=energyModel.weight(higher);
00255 if (energyModel.getDistribCount()== 3){
00256 unsigned long lower=findMinEnergyDistrib(energyModel);
00257 unsigned long middle=3-(higher+lower);
00258 double lossH=likelihoodLoss(energyModel.getDistrib(middle),energyModel.weight(middle),
00259 energyModel.getDistrib(higher),energyModel.weight(higher));
00260 double lossL=likelihoodLoss(energyModel.getDistrib(middle),energyModel.weight(middle),
00261 energyModel.getDistrib(lower),energyModel.weight(lower));
00262 if (verbose) cout << "lossL["<<lossL<<"] lossH["<<lossH<<"]"<<endl;
00263 if (lossH<lossL)
00264 selectedWeight+=alpha*energyModel.weight(middle);
00265 }
00266 threshold=computeEnergyThreshold(fs,selectedWeight);
00267 }
00268 else if (thresholdMode=="meanStd"){
00269 threshold=energyModel.getDistrib(higher).getMean(0) - (alpha*sqrt(energyModel.getDistrib(higher).getCov(0)));
00270 }
00271 else cout << thresholdMode<< "unknown"<<endl;
00272 unsigned long nbCurrentFrames=selectFrames(fs,segServer,threshold,selectedSegments,outputSeg,labelOutput,featureFileName);
00273 if (verbose){
00274 double selected=(float) nbCurrentFrames/ (float)nbInitialFrames;
00275 cout <<"File ["<<featureFileName<<"] Number of initial frames ["<<nbInitialFrames<<"] Number of selected frames ["
00276 <<nbCurrentFrames << "] percentage selected [" << (int) (selected*100) << "]" << endl;
00277 }
00278 return outputSeg;
00279 }
00280
00281
00282 #endif //!defined(ALIZE_EnergyDetector_cpp)