实现思路:通过加速度传感器获得水平方向和垂直方向的加速度,然后通过加速度计算在水平方向和垂直方向上的x,y坐标,然后通过github开源项目https://github.com/MarsToken/recognizer 的识别库识别手势。加速度通过没间隔一段时间就获取传感器的加速度值,这个时间间隔设置得好的话可能识别准确度就高,还有就是计算水平方向和垂直方向的x和y值的算法,算法好的话识别准确率就高,还有就是本文没有使用到陀螺仪的数据,希望大家按照这个思路自己设计更好的算法,那样子手势识别率更高。由于之前的文章(Android-NDK传感器示例)有说到安卓加速度传感器的导入,所以本项目以该项目为基础进行修改。


下面开始阅读sensor-graph项目源码。首先我们要获取各个方向上的加速度,我们先查看项目的native方法,可以看到有surface相关方法可以直接忽略掉,同时由于我们需要各个方向的加速度,所以添加三个方法分别获取三个方向上的加速度。

光标移动到init方法上然后按下Ctrl+B查看init方法对应的(C/C+)函数,可以看到还有一个还有一个对象(gSensorGraph)调用了一个init方法,我们在gSensorGraph对象下按下Ctrl+B查看该对象。

可以看到gSensorGraphsensorgraph类对象的一个实例,将光标移动到sensorgraph上面然后按下Ctrl+B查看sensorgraph类。

可以看到类sensorgraph里面有一个结构体Accelerometer有三个成员变量xyz,事实上这就是存放加速度值的结构体。

我们再看一下native方法,其中有一个叫drawFrame的方法,由于本项目是将加速度的变化通过SurfaceView显示在屏幕上,可以知道drawFrame方法应该会用到xyz方向的加速度,所以我们可以查看方法的实现,从而知道获取各个方向上的加速度的值的方法。

光标移动到该方法上按下Ctrl+B查看方法实现,可以看到该函数调用了两个函数,一个update而另一个是render

光标移动到update函数上然后Ctrl+B查看update函数实现,可以通过event获取加速度传感器的xyz方向的加速度值,当然还有用到函数ASensorEventQueue_getEvents

根据update函数我们仿写get_xget_yget_z函数分别获得xyz方向上的加速度值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    float gravity[3];
float linear_acceleration[3];
float alpha = 0.8f;

//修改的函数:获取x方向加速度
float get_x() {
ASensorEvent event;
while (ASensorEventQueue_getEvents(accelerometerEventQueue, &event, 1) > 0) {
gravity[0] = alpha gravity[0] + (1.0f - alpha) event.acceleration.x;
gravity[1] = alpha gravity[1] + (1.0f - alpha) event.acceleration.y;
gravity[2] = alpha gravity[2] + (1.0f - alpha) event.acceleration.z;
linear_acceleration[0] = event.acceleration.x - gravity[0];
linear_acceleration[1] = event.acceleration.y - gravity[1];
linear_acceleration[2] = event.acceleration.z - gravity[2];
}
return linear_acceleration[0];
}


//修改的函数:获取y方向加速度
float get_y() {
ASensorEvent event;
while (ASensorEventQueue_getEvents(accelerometerEventQueue, &event, 1) > 0) {
gravity[0] = alpha gravity[0] + (1.0f - alpha) event.acceleration.x;
gravity[1] = alpha gravity[1] + (1.0f - alpha) event.acceleration.y;
gravity[2] = alpha gravity[2] + (1.0f - alpha) event.acceleration.z;
linear_acceleration[0] = event.acceleration.x - gravity[0];
linear_acceleration[1] = event.acceleration.y - gravity[1];
linear_acceleration[2] = event.acceleration.z - gravity[2];
}
return linear_acceleration[1];
}

//修改的函数:获取x方向加速度
float get_z() {
ASensorEvent event;
while (ASensorEventQueue_getEvents(accelerometerEventQueue, &event, 1) > 0) {
gravity[0] = alpha gravity[0] + (1.0f - alpha) event.acceleration.x;
gravity[1] = alpha gravity[1] + (1.0f - alpha) event.acceleration.y;
gravity[2] = alpha gravity[2] + (1.0f - alpha) event.acceleration.z;
linear_acceleration[0] = event.acceleration.x - gravity[0];
linear_acceleration[1] = event.acceleration.y - gravity[1];
linear_acceleration[2] = event.acceleration.z - gravity[2];
}
return linear_acceleration[2];
}

增加一个MainActivity.java文件,并将该Activity设置为启动Activity,在生命方法中调用相应的native方法,onCreate方法中设置按钮监听,点击该按钮启动手势识别的线程。

手势识别的线程代码如下图所示,只是通过简单的计算得到xy的值传给Recognizer,然后通过Recognizer识别手势。

Recognizer代码如下,每个方法的作用都有说明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package com.android.accelerometergraph;

/*
手写识别库
Created by wangmaobo on 2016/5/18.
/
public class Recognizer {

// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("recognizer-lib");
}

/
初始化
/
public static native boolean recognizer_init();

/

每次识别完clear一下
/
public static native boolean recognizer_clear();

/
添加x,y坐标
/
public static native boolean recognizer_add(int x, int y);

/

识别,返回识别结果
/
public static native int recognizer_classify();

/
打印Log检测用 :得到对应下标的x坐标
/
public static native int recognizer_getx(int i);

/

打印Log检测用 :得到对应下标的y坐标
/
public static native int recognizer_gety(int i);

/
识别结束,将库逆向初始化
/
public static native boolean recognizer_deInit();

/
打印Log检测用:获取最终识别方向
/
public static native String recognizer_getDirectionStr();

/

@return 返回显著的点的数目
/
public static native int recognizer_getResultCnt();
}

完整源代码请关注小海电脑公众号回复Sensor-Graph获取,项目导入成功后可以直接编译运行哦。

温馨提示:导入项目时注意要更改一下项目配置信息哦,如果忘记的话可以查看Android Studio导入项目前要注意的事项

最后修改日期:2020年5月14日

留言

撰写回覆或留言