This commit is contained in:
205
java/src/org/wiigee/logic/GestureModel.java
Normal file
205
java/src/org/wiigee/logic/GestureModel.java
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* wiigee - accelerometerbased gesture recognition
|
||||
* Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
|
||||
*
|
||||
* Developed at University of Oldenburg
|
||||
* Contact: wiigee@benjaminpoppinga.de
|
||||
*
|
||||
* This file is part of wiigee.
|
||||
*
|
||||
* wiigee is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
package org.wiigee.logic;
|
||||
|
||||
import java.util.Vector;
|
||||
import org.wiigee.event.AccelerationEvent;
|
||||
import org.wiigee.util.Log;
|
||||
|
||||
/**
|
||||
* This Class units a Quantizer-Component and an Model-Component.
|
||||
* In this implementation a k-mean-algorithm for quantization and
|
||||
* a hidden markov model as instance for the model has been used.
|
||||
*
|
||||
* @author Benjamin 'BePo' Poppinga
|
||||
*/
|
||||
public class GestureModel {
|
||||
|
||||
/** The number of states the hidden markov model consists of */
|
||||
private int numStates;
|
||||
|
||||
/** The number of observations for the hmm and k-mean */
|
||||
private int numObservations;
|
||||
|
||||
/** The quantization component */
|
||||
private Quantizer quantizer;
|
||||
|
||||
/** The statistical model, hidden markov model */
|
||||
private HMM markovmodell;
|
||||
|
||||
/** The default probability of this gesturemodel,
|
||||
* needed for the bayes classifier */
|
||||
private double defaultprobability;
|
||||
|
||||
|
||||
/** Creates a Unit (Quantizer&Model).
|
||||
*
|
||||
* @param id
|
||||
* int representation of a gesture "name"/class.
|
||||
*/
|
||||
public GestureModel() {
|
||||
this.numStates=8; // n=8 states empirical value
|
||||
this.numObservations=14; // k=14 observations empirical value
|
||||
this.markovmodell = new HMM(numStates, numObservations); // init model
|
||||
this.quantizer = new Quantizer(numStates); // init quantizer
|
||||
}
|
||||
|
||||
/**
|
||||
* Trains the model to a set of motion-sequences, representing
|
||||
* different evaluations of a gesture
|
||||
*
|
||||
* @param trainsequence a vector of gestures
|
||||
*/
|
||||
public void train(Vector<Gesture> trainsequence) {
|
||||
// summarize all vectors from the different gestures in one
|
||||
// gesture called sum.
|
||||
double maxacc=0;
|
||||
double minacc=0;
|
||||
Gesture sum = new Gesture();
|
||||
|
||||
for(int i=0; i<trainsequence.size(); i++) {
|
||||
Vector<AccelerationEvent> t = trainsequence.elementAt(i).getData();
|
||||
|
||||
// add the max and min acceleration, we later get the average
|
||||
maxacc+=trainsequence.elementAt(i).getMaxAcceleration();
|
||||
minacc+=trainsequence.elementAt(i).getMinAcceleration();
|
||||
|
||||
// transfer every single accelerationevent of each gesture to
|
||||
// the new gesture sum
|
||||
for(int j=0; j<trainsequence.elementAt(i).getData().size(); j++) {
|
||||
sum.add(t.elementAt(j));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// get the average and set it to the sum gesture
|
||||
sum.setMaxAndMinAcceleration(maxacc/trainsequence.size(), minacc/trainsequence.size());
|
||||
|
||||
// train the centeroids of the quantizer with this master gesture sum.
|
||||
this.quantizer.trainCenteroids(sum);
|
||||
|
||||
// convert gesture vector to a sequence of discrete values
|
||||
Vector<int[]> seqs = new Vector<int[]>();
|
||||
for(int i=0; i<trainsequence.size(); i++) {
|
||||
seqs.add(this.quantizer.getObservationSequence(trainsequence.elementAt(i)));
|
||||
}
|
||||
|
||||
// train the markov model with this derived discrete sequences
|
||||
this.markovmodell.train(seqs);
|
||||
|
||||
// set the default probability for use with the bayes classifier
|
||||
this.setDefaultProbability(trainsequence);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the probability that a gesture matches to this
|
||||
* gesture model.
|
||||
*
|
||||
* @param gesture a gesture to test.
|
||||
* @return probability that the gesture belongs to this gesture
|
||||
* model.
|
||||
*/
|
||||
public double matches(Gesture gesture) {
|
||||
int[] sequence = quantizer.getObservationSequence(gesture);
|
||||
return this.markovmodell.getProbability(sequence);
|
||||
}
|
||||
|
||||
/**
|
||||
* For debug purposes or very technical interested people. :)
|
||||
*/
|
||||
public void printMap() {
|
||||
Log.write("Gesture Quantizer-Map:");
|
||||
this.quantizer.printMap();
|
||||
}
|
||||
|
||||
/***
|
||||
* For debug purposes or very technical interested people. :)
|
||||
* @return
|
||||
*/
|
||||
public void print() {
|
||||
Log.write(Log.DEBUG, "HMM-Print:", this);
|
||||
this.markovmodell.print();
|
||||
Log.write(Log.DEBUG, "Quantizer-Print:", this);
|
||||
this.quantizer.printMap();
|
||||
}
|
||||
|
||||
public int getNumStates() {
|
||||
return this.numStates;
|
||||
}
|
||||
|
||||
public int getNumObservations() {
|
||||
return this.numObservations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the model probability for bayes.
|
||||
*
|
||||
* @return
|
||||
* the model probability
|
||||
*/
|
||||
public double getDefaultProbability() {
|
||||
return this.defaultprobability;
|
||||
}
|
||||
|
||||
/**
|
||||
* Since the bayes classifier needs a model probability for
|
||||
* each model this has to be set once after training. As model
|
||||
* probability the average probability value has been choosen.
|
||||
*
|
||||
* TODO: try lowest or highest model probability as alternative
|
||||
*
|
||||
* @param defsequence the vector of training sequences.
|
||||
*/
|
||||
private void setDefaultProbability(Vector<Gesture> defsequence) {
|
||||
double prob=0;
|
||||
for(int i=0; i<defsequence.size(); i++) {
|
||||
prob+=this.matches(defsequence.elementAt(i));
|
||||
}
|
||||
|
||||
this.defaultprobability=(prob)/defsequence.size();
|
||||
}
|
||||
|
||||
public void setDefaultProbability(double prob) {
|
||||
this.defaultprobability = prob;
|
||||
Log.write("def-prob. set to = "+this.defaultprobability);
|
||||
}
|
||||
|
||||
public Quantizer getQuantizer() {
|
||||
return this.quantizer;
|
||||
}
|
||||
|
||||
public void setQuantizer(Quantizer q) {
|
||||
this.quantizer = q;
|
||||
}
|
||||
|
||||
public HMM getHMM() {
|
||||
return this.markovmodell;
|
||||
}
|
||||
|
||||
public void setHMM(HMM hmm) {
|
||||
this.markovmodell = hmm;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user