본문 바로가기

Robotics/Software Tech.

HMM(Hidden Markov Model)을 이용한 Wiimote 제스쳐 인식


http://wiki.jienew.twbbs.org/project:wiimote-gesture-recognition 참조.


Wiimote Gesture Recognition

Architecture

architecture.png

Wiimote Acceleration Sensor

Raw Data from Sensor

Ranged from 0 to 255.

  • About 130 when no acceleration.
  • About 155 when a==g.
  • About 105 when a==-g.

(a: acceleration, g: gravity)

Calibration

x_g, y_g, z_g are raw data when a == g on x, y, z axes. About 154~156.

x_0, y_0, z_0 are raw data when a == 0 on x, y, z axes. About 128~130.

(1)
\begin{align} x &= \frac{x_{raw} - x_0}{x_g - x_0}\ y &= \frac{y_{raw} - y_0}{y_g - y_0}\ z &= \frac{z_{raw} - z_0}{z_g - z_0}

Then calibrated x, y, z = 1.0 when a == g on x, y, z axes.

x_0, y_0, z_0 and x_g, y_g, z_g are constants built in wiimote. So wiimote dirvers can get calibrated data x, y, z by above computation.

Gesture Analysis

Quantization

Pseudo code

size_t Quantize(const Acceleration& acc) const{
    double rho = sqrt(acc.x*acc.x+acc.y*acc.y+acc.z*acc.z);
    return (rho>3.0? 3<<3 : rho>2.0? 2<<3 : rho>1.0? 1<<3 :0)
        | (acc.x>acc.y? 1<<2 : 0)
        | (acc.y>acc.z? 1<<1 : 0)
        | (acc.z>acc.x? 1 : 0);
}

Training

Hidden Markov Models

5 state L-to-R or circular both works.

Training with Multiple Sequence

Method modified from Rabiner & Juang[1]:

(2)
\begin{align} \bar{a}_{ij}&=\dfrac {\displaystyle\sum_{k=1}^K \left\{\dfrac{1}{P_k}\sum_{t=1}^{T_k-1} \left[ \alpha_t^{(k)}(i) a_{ij} b_j(o_{t+1}^{(k)}) \beta_{t+1}^{(k)}(j) \right] \right\} } {\displaystyle\sum_{k=1}^K \left\{\dfrac{1}{P_k}\sum_{t=1}^{T_k-1} \left[ \alpha_t^{(k)}(i) \beta_t^{(k)}(i) \right] \right\}}\ \ \bar{b}_j(l)&=\dfrac {\displaystyle\sum_{k=1}^K \left\{\dfrac{1}{P_k} \sum_{\substack{t=1\\s.t.\phantom{.}o_t^{(k)}=l}}^{T_k} \left[ \alpha_t^{(k)}(i) \beta_t^{(k)}(i) \right] \right\} } {\displaystyle\sum_{k=1}^K \left\{\dfrac{1}{P_k} \sum_{t=1}^{T_k} \left[ \alpha_t^{(k)}(i) \beta_t^{(k)}(i) \right] \right\}} \end{align}

Pseudo Code

// reestimate transition matrix and prob of symbols to states
for(i = 0; i < hmm.N; i++) {
    denominatorA = 0.0;
    denominatorB = 0.0;
    for(curSeq = seqs.begin(); curSeq < seqs.end(); curSeq++){
        double& logProb = curSeq->logProb[&hmm];
        vector< vector<double> >& gamma = curSeq->gamma;
        T = curSeq->o.size();
        denominatorA_partial = 0.0;
        for(t = 0; t < T - 1; t++)
            denominatorA_partial += gamma[t][i];
        denominatorB_partial = denominatorA_partial + gamma[T-1][i];
        denominatorA += denominatorA_partial/exp(logProb);
        denominatorB += denominatorB_partial/exp(logProb);
    }
 
    for(j = 0; j < hmm.N; j++) {
        numeratorA = 0.0;
        for(curSeq = seqs.begin(); curSeq < seqs.end(); curSeq++){
            vector< vector< vector<double> > >& xi = curSeq->xi;
            T = curSeq->o.size();
            numeratorA_partial = 0.0;
            for(t = 0; t < T - 1; t++)
                numeratorA_partial += xi[t][i][j];
            numeratorA += numeratorA_partial/exp(curSeq->logProb[&hmm]);
        }
        hmm.TranProb(i,j) = 0.0001 + 0.9999*numeratorA/denominatorA;
    }
 
    for(k = 0; k < hmm.M; k++) {
        numeratorB = 0.0;
        for(curSeq = seqs.begin(); curSeq < seqs.end(); curSeq++){
            vector< vector<double> >& gamma = curSeq->gamma;
            vector<size_t>& o = curSeq->o;
            T = o.size();
            numeratorB_partial = 0.0;
            for(t = 0; t < T; t++) {
                if(o[t] == k)
                    numeratorB_partial += gamma[t][i];
            }
            numeratorB += numeratorB_partial/exp(curSeq->logProb[&hmm]);
        }
        hmm.ObsProb(i,k) = 0.0001 + 0.9999*numeratorB/denominatorB;
    }
}

Real Time Recognition

Forward Algorithm

Pseudo code

/*
Only do iteration necessary for newly added
symbols of input sequence.
*/
for(t = t_begin; t < T; t++) {
    /*
    Do initialization if forward algorithm haven't been applied to
    the input sequence before.
    */
    if(t == 0){
        logProb = 0.0;
        scale[0] = 0.0;
        alpha[0].resize(hmm.N);
        for(i = 0; i < hmm.N; i++) {
            alpha[0][i] = hmm.pi[i] * hmm.ObsProb(i,o[0]);
            scale[0] += alpha[0][i];
        }
        for(i = 0; i < hmm.N; i++)
            alpha[0][i] /= scale[0];
    }else{
        scale[t] = 0.0;
        alpha[t].resize(hmm.N);
        for(j = 0; j < hmm.N; j++) {
            sum = 0.0;
            for(i = 0; i < hmm.N; i++)
                sum += alpha[t-1][i] * hmm.TranProb(i,j);
 
            alpha[t][j] = sum * hmm.ObsProb(j,o[t]);
            scale[t] += alpha[t][j];
        }
        for(j = 0; j < hmm.N; j++)
            alpha[t][j] /= scale[t];
    }
}
 
/*
Compute sequence probability
*/
for(t = t_begin; t < T; t++){
    logProb += log(scale[t]);
}

Demo & Source Code

WiimoteGR.zip

Wiimote Driver

WiiYourself!

See Building WiiYourself! Library

Reference

Wiimote

WiiBrew

HMM library

UMDHMM
UMDHMM (C library)
C++ HMM Library
A C++ Implementation of Hidden Markov Model

Bibliography

1. Fundamentals of Speech Recognition - by Lawrence Rabiner , Biing-Hwang Juang
2. Pattern Recognition and Machine Learning - by Christopher M. Bishop
3. Hidden Markov Models: Applications in Computer Vision - by Horst Bunke (Author), Terry Caelli (Editor)

'Robotics > Software Tech.' 카테고리의 다른 글

Sound Localization  (0) 2009.06.14
Visual studio 2008에서 응용프로그램 배포할 때 필요한 dll  (2) 2009.06.10
[STL] string tokenizer  (0) 2009.03.11
[boost] string tokenizer  (0) 2009.03.08
[MFC]SDI기반 OpenGL 사용  (6) 2009.02.26