プログラムを書いて方向を検出できるようになりました^^。

以前に写真上の星の位置を検出するアプリを書いているのでちょっと応用ができました。

 

各方向で微分を取って、まず負の傾きを示し0の傾きに最初に戻ったもの、を検出方向とするものです。←2階ガウシアンなど取ればもっと確実なんでしょうけどPICなので^^;

 

センサ上を左から右に指を横切らせた場合

元データのグラフ。

 

左が元データ。右が元データから各方向毎に微分を取ったデータ。

 

センサ上を右から左の場合(255が続く最初のデータはカットしてあります)

元データのグラフ。

 

左が元データ。右が微分データ。

 

最初のグラフで見て分かるように、データ終端で各データがUPは69、DOWNは5、LEFTは21、RIGHTは42、という差異が発生しています。これはどんなジェスチャーをしたときも大体この程度で安定しています。

 

設定でこれらのオフセットを調整することは可能です。が、今回検出に使った方法では、この調整は特に必要ではありません。

 

最初に大きな負の傾きを示した2候補を選択し、そのあとはその2候補だけ追加検査していき、最初に傾きが0近辺(閾値を設定)に戻った方を採用します。

 

計算量が少なく(候補絞り込みや検出でループ打ち切り)、確実な判定だとは思いますが、センサーはゆっくりすぎると全データが255で飽和速すぎると16セット(UDLR)データが取得できず破棄になるのでジェスチャー自体にコツが必要です。

 

判定プログラムはこんな具合です↓

--------------------------

/*
 * それぞれの方向の微分を取り、最初に閾値を下回った2方向を候補にし(over=1)
 * 次に2方向のうち先に閾値を上回った方を移動方向と決定する。同時の場合は大きく上回った
 * 方を選択する。
 */
unsigned char Direction(unsigned char lvl) {
    int d[4], tmp;
    unsigned char i, j, k, over = 0, c[4] = {0, 1, 2, 3}, tpc;
#define THRSH -2
    for (i = 0; i < lvl - 1; i++) {
        if (over == 0) {
            // differential value of each direction
            for (k = 0; k < 4; k++)
                d[k] = gv[i + 1][k] - gv[i][k];
            if (d[0] <= THRSH || d[1] <= THRSH || d[2] <= THRSH || d[3] <= THRSH) {
                // Bubble sort
                for (k = 3; k > 0; k--) {
                    for (j = 0; j < k; j++) {
                        if (d[j] > d[j + 1]) {
                            // swap d[j] d[j + 1]
                            tmp = d[j]; d[j] = d[j + 1]; d[j + 1] = tmp;
                            tpc = c[j]; c[j] = c[j + 1]; c[j + 1] = tpc;
                        }
                    }
                }
                if (d[1] >= 0)
                    return c[0];
                over = 1;
            }
        } else {
            d[0] = gv[i + 1][c[0]] - gv[i][c[0]];
            d[1] = gv[i + 1][c[1]] - gv[i][c[1]];
            if (d[0] >= THRSH || d[1] >= THRSH) {
                if (d[0] >= d[1]) {
                    return c[0];
                } else {
                    return c[1];
                }
            }
        }
    }
    return 4;
}
--------------------------

 

 

 

動画でも誤検出や不検出が発生しているのがわかります^^;