{
public void features(FeatFile featFile, boolean clearOriginalFeatures)
{
int totalChunks = featFile.chunks.size();
FeatChunk testChunk = (FeatChunk)featFile.chunks.elementAt(0);
double[] testChunkFeatures = testChunk.getFeatures();
int numFeatures = testChunkFeatures.length;
// Pass 1 - gather feature statistics
double sumx[] = new double[numFeatures];
double sumx2[] = new double[numFeatures];
double meanx[] = new double[numFeatures];
double stdx[] = new double[numFeatures];
double mahaldist[] = new double[totalChunks];
Arrays.fill(sumx, 0);
Arrays.fill(sumx2, 0);
Arrays.fill(meanx, 0);
Arrays.fill(stdx, 0);
Arrays.fill(mahaldist, 0);
double N = 0.0;
for(int chunk=0; chunk<totalChunks; chunk++)
{
FeatChunk curChunk = (FeatChunk)featFile.chunks.elementAt(chunk);
double[] features = curChunk.getFeatures();
for(int feature = 0; feature < numFeatures; feature++)
{
sumx[feature] += features[feature];
sumx2[feature] += features[feature] * features[feature];
}
N = N + 1.0;
}
// figure mean and variance
for(int feature = 0; feature < numFeatures; feature++)
{
meanx[feature] = sumx[feature] / N;
stdx[feature] = Math.sqrt(sumx2[feature]/N - meanx[feature]*meanx[feature]);
}
// Pass 2 - figure Mahalanobis distance (= unlikeliness score)
// under diagonal covariance Gaussian for each frame
// (i.e. Euclidean distance to mean in a variance-normalized space)
for(int chunk=0; chunk<totalChunks; chunk++)
{
FeatChunk curChunk = (FeatChunk)featFile.chunks.elementAt(chunk);
double[] features = curChunk.getFeatures();
mahaldist[chunk] = 0;
for(int feature = 0; feature < numFeatures; feature++)
{
double dist = (features[feature] - meanx[feature])/stdx[feature];
mahaldist[chunk] += dist*dist;
}
mahaldist[chunk] = Math.sqrt(mahaldist[chunk]/numFeatures);
double value = mahaldist[chunk];
double[] feats = new double[1];
feats[0] = value;
if(clearOriginalFeatures)
curChunk.clearFeatures();
curChunk.addFeature(feats);
}
}