原文来源:Lemberg Solutions Ltd

作者:Zahra Mahoor、Jack Felag、 Josh Bongard

「雷克世界」编译:嗯~阿童木呀、KABUDA

现如今,与智能手机进行交互的方式有很多种:触摸屏、硬件按钮、指纹传感器、视频摄像头(如人脸识别)、方向键(D-PAD)、手持设备控制等等。但是我们该如何使用动作识别功能呢?

我们可以举一个例子来说明这个问题,比如当你持手机将其快速移动到左侧或右侧时,可以非常精确地显示出想要切换到播放列表中下一首或上一首歌曲的意图;或者,你可以将手机快速向上向下翻转,从而刷新应用程序内容。引入这样的交互看起来是非常有发展前景的,并且为用户体验增添了一个新的层面。接下来,本文将介绍该如何使用机器学习和Android上的Tensorflow库实现这一目标。

对于我们的目标,我们可以将其描述为希望手机能够识别左右的快速动作。

我们希望能够在一个单独的Android库中完成这一实现,以便它能够容易地集成到任何其他应用程序中。

这些动作可以通过手机上的几个传感器进行捕获:加速度计、陀螺仪、磁力计等等。随后,这些批量动作可以用于机器学习算法,以便进行训练和后续识别。

为了捕捉数据,我们将开发一个Android应用程序。预处理和训练过程将在Jupyter Notebook环境的PC上使用Python和TensorFlow库执行。手势识别将在一个Android应用程序演示中执行,并生成训练数据。最后,我们将开发一个即时可用的Android库,用于手势识别,而且可以很容易地集成到其他应用程序中。

下面是有关该实现过程的高级计划:

1.在手机上收集数据

2.设计和训练神经网络

3.将神经网络导出到手机中

4.开发一个测试Android应用程序

5.开发Android库

实现

•准备数据

首先,我们来明确一下什么样的传感器和什么样的数据可以用于描述我们的动作手势。为了准确地描述这些手势,我们应该使用加速度计和陀螺仪。

加速度计传感器明显是用于测量加速度,然后测量运动:

加速度计有一个有趣的细微差别;它不仅测量设备本身的加速度,而且测量地球重力的加速度,大约为9.8m/s2。这意味着放在桌子上的手机加速度向量的大小将等于9.8。这些值不能直接使用,而应从地球重力值中提取。这并不是一件容易的任务,因为它需要磁力计和加速度计传感器值的融合。不过幸运的是,Android已经有了特定的线性加速度传感器以执行这样的计算并返回正确的值。

另一方面,陀螺仪将用于测量旋转:

我们试着找出将与我们的手势相关联的值。显然,在加速度计(即线性加速度计)中,X和Y值将高度描述手势,而加速度计的Z值不太可能受到我们手势的影响。

至于陀螺仪传感器,似乎只有Z轴会受到手势的轻微影响。不过,为了简化实施,我们可以不将该值考虑在内。在这种情况下,我们的手势检测器不仅能够识别手机在手中的移动,而且还能识别出其沿着水平线的移动——例如在桌子上。这大概不是一个太大的问题。

所以,我们需要开发一个能够记录加速度计数据的Android应用程序。

我开发了一款这样的应用程序,下面是记录的“向右移动”手势的屏幕截图:

正如你所看到的那样,X轴和Y轴对手势的反应非常强烈。 Z轴也有反应,但正如我们所说的那样,我们没有将其考虑在内。

这是“左移”手势:

请注意,X值与前一手势的值几乎相反。

还有一点需要提及的是数据采样率。这反映了数据采样的频率,并且直接影响每个时间间隔的数据量。

另一个要考虑的是手势持续时间。这个值,就像这里许多其他值一样,应该根据经验对其进行选择。我所建立的那个手势持续时间不超过1秒,但为了让事情进行得更为顺利,我把它四舍五入到了1.28秒。

我选择的数据采样率是每个选定的持续时间内128点,这将产生10毫秒的延迟(1.28 / 128)。这个值应该被传递给registerListener(https://developer.android.com/reference/android/hardware/SensorManager.html#registerListener%28android.hardware.SensorEventListener,%20android.hardware.Sensor,%20int%29)方法。

因此,这个想法就是训练一个神经网络,用以在加速度传感器中的实时数据流中识别这些信号。

所以,接下来,我们需要记录一系列手势并将其导出到文件。当然,相同类型的手势(右侧或左侧)应该使用相同的标签进行标记。我们很难事先说出需要多少样本来训练这个网络,但这可以通过训练结果进行确定。

通过点击数据,样本持续时间将自动高亮显示:

现在,“保存”按钮启用,点击它将自动把已选项保存到工作目录中的文件。文件名将以“{label} _ {timestamp} .log”的形式生成。可以使用应用程序菜单来选择工作目录。

另外请注意,保存当前选择后,将自动选择下一个手势。下一个手势的选择是使用一个非常简单的算法实现的:找到其绝对值大于3的第一个X条目,然后返回20个样本。

这种自动化过程使我们能够快速保存一系列样本。对于每个手势我们记录了500个样本。保存的数据应该被复制到一台PC上以进行进一步处理。 (直接在手机上进行处理和训练看起来很有发展前景,但是Android的TensorFlow目前不支持训练)。

在前面提供的截图中,数据范围大约为±6。但是,如果你更有力地挥动手机,它可以达到±10。对数据进行正则化操作比较好,从而使得范围为±1,这更适合神经网络数据格式。我只是把所有的数据除以一个常数系数,我通常使用的是9。

开始训练之前可以执行的下一步是过滤数据以消除高频振荡。这种振动与我们的手势无关。

有很多方法可以过滤数据。一种是基于移动平均值(https://en.wikipedia.org/wiki/Moving_average)框进行过滤。

请注意,X数据的最大值现在是原来值的一半。由于我们将在识别过程中对实时数据执行相同的过滤,所以这应该不成问题。

改善训练的最后一步是数据增强(data augmentation)。该过程通过执行一些操作扩展了原始数据集。在我们的例子中,我简单地将数据左右移动了几个点:

•设计一个神经网络

设计一个神经网络并不是一个简单的任务,需要一些经验和直觉。另一方面,神经网络在某些任务中是众所周知的,而且你可以简单地对现有网络做些调整。我们的任务与图像分类任务非常相似,输入可以被视为高度为1像素的图像(这是真实的——第一个操作是将二维数据[128列x 2信道]的输入转换为三维数据[1行x 128列x 2信道])。

所以,神经网络输入是[128,2]。

神经网络输出是长度等于标签数量的向量。在我们的例子中是[2]。数据类型是双精度浮点数。

这里是神经网络的示意图:

这里是通过TensorBoard获得的详细原理图:

该示意图包含一些仅用于训练的辅助节点。之后,我将提供一个干净的、优化后的图片。

•训练


训练将在具有Jupyter Notebook环境的PC上使用Python和TensorFlow库进行。可以使用以下配置文件在Conda环境中启动Notebook。以下是一些训练超参数(hyperparameters):

Optimizer: Adam

Number of training epochs: 3

Learning rate: 0.0001

数据集按照7/3的比例被分为训练集和验证集。

训练质量可以通过训练和测试精确度值来控制。训练的精确度应该接近但不能达到1。如果值太低,则表示识别率低且不准确,并且过高的值将导致模型过度拟合,并且可能在识别期间引入一些伪像,如非手势数据的非零识别评估。良好的测试精度可以证明:一个训练有素的模型可以识别不可见的早期数据。

训练日志:

(‘Epoch: ‘, 0, ‘ Training Loss: ‘, 0.054878365, ‘ Training Accuracy: ‘, 0.99829739)

(‘Epoch: ‘, 1, ‘ Training Loss: ‘, 0.0045060506, ‘ Training Accuracy: ‘, 0.99971622)

(‘Epoch: ‘, 2, ‘ Training Loss: ‘, 0.00088313385, ‘ Training Accuracy: ‘, 0.99981081)

(‘Testing Accuracy:’, 0.99954832)

TensorFlow图和相关数据使用以下方法保存到文件中:

saver = tf.train.Saver()

with tf.Session() as session:

session.run(tf.global_variables_initializer())

# save the graph

tf.train.write_graph(session.graph_def, '.', 'session.pb', False)

for epoch in range(training_epochs):

# train

saver.save(session, './session.ckpt')

完整的notebook代码可以在这里查看:

https://github.com/ryanchyshyn/motion_gestures_detection/blob/master/Python/training.ipynb

•输出神经网络

上一部分展示了如何保存Tensor Flow数据。图形保存到“session.pb”文件中,训练数据(权重,偏差等)被保存到一批“session.ckpt”文件中。这些文件可以足够大:

session.ckpt.data-00000-of-00001                 3385232

session.ckpt.index                               895

session.ckpt.meta                                65920

session.pb                                       47732

表格和训练数据可以被冻结,并转化成适合在移动设备上运行的单个文件。

为了冻结它,需要将tensorflow / python / tools / freeze_graph.py文件复制到notebook目录中,然后运行以下命令:

python freeze_graph.py --input_graph=session.pb \

--input_binary=True \

--input_checkpoint=session.ckpt \

--output_graph=frozen.pb \

--output_node_names=labels_output

生成的文件比之前的文件要小,但就单个文件而言,仍然足够大:

frozen.pb                                           1130835

这是TensorBoard中的模型:

tensorflow / python / tools / import_pb_to_tensorboard.py文件复制到notebook目录并启动:

python import_pb_to_tensorboard.py --model_dir=frozen.pb --log_dir=tmp

其中frozen.pb是一个模型文件。

现在,启动TensorBoard:

tensorboard --logdir=tmp

有几种方法可以为移动环境优化模型。想要运行所描述的命令,需要从源代码编译TensorFlow:

1.删除未使用的节点和常规优化。执行:

bazel build tensorflow/tools/graph_transforms:transform_graph

bazel-bin/tensorflow/tools/graph_transforms/transform_graph --in_graph=mydata/frozen.pb --out_graph=mydata/frozen_optimized.pb --inputs='x_input' --outputs='labels_output' --transforms='strip_unused_nodes(type=float, shape="128,2") remove_nodes(op=Identity, op=CheckNumerics) round_weights(num_steps=256) fold_constants(ignore_errors=true) fold_batch_norms fold_old_batch_norms'

这是TensorBoard运行结果:

2.执行量化(转换浮点数据格式信息8位数据格式),执行:

bazel-bin/tensorflow/tools/graph_transforms/transform_graph --in_graph=mydata/frozen_optimized.pb --out_graph=mydata/frozen_optimized_quant.pb --inputs='x_input' --outputs='labels_output' --transforms='quantize_weights strip_unused_nodes'

因此,与3.5 Mb的原始文件相比,输出文件的大小为287129字节。这个文件可以在Android的TensorFlow中使用。

•演示 Android应用程序

想在Android应用程序中执行信号识别,你需要使用Android的Tensor Flow库。将库添加至gradle属性项:

dependencies {

implementation 'org.tensorflow:tensorflow-android:1.4.0'

}

现在,你可以通过TensorFlowInferenceInterface类访问TensorFlow API。首先,将“frozen_optimized_quant.pb”文件放入应用程序的“assets”目录中 (即 “app/src/main/assets” ),并将其加载到代码中(如:从Activity开始;但是,像往常一样,最好在后台线程中执行有关IO的相关操作)

inferenceInterface = new TensorFlowInferenceInterface(getAssets(), “file:///android_asset/frozen_optimized_quant.pb”);

注意如何选定模型文件

最后,看一下如何进行识别:

float[] data = new float[128 * 2];

String[] labels = new String[]{"Right", "Left"};

float[] outputScores = new float[labels.length];

// populate data array with accelerometer data

inferenceInterface.feed("x_input", data, new long[] {1, 128, 2});

inferenceInterface.run(new String[]{“labels_output”});

inferenceInterface.fetch("labels_output", outputScores);

数据是我们“黑盒”的一个输入,应该有一个加速度计X和Y测量的平面阵列,即数据格式是[x1, y1, x2, y2, x3, y3, …, x128, y128]。

在输出方面,我们有两个浮点值,它们根据“左”或“右”的手势变化,随不同输入值在0到1的范围内取值。需要注意的是,这些值的总和是1。因此,举一个例子,如果输入信号与左或右手势不匹配,那么输出将接近[0.5,0.5]。为了进一步简化,最好使用简单的数学方法将这些值转化为绝对值在0到1之间的数。

在运行之前,需要对数据进行过滤和正则化操作。

这里是演示应用程序的最终测试屏幕:

其中“红色”和“绿色”的线条是实时预处理信号,黄线和青线分别属于“固定”、“左”和“右”概率。“时间”是处理时间,非常短,这使得实时识别成为可能。(2毫秒意味着可以以500Hz的频率运行处理,同时我们请求加速度计以100Hz的频率进行更新)。

正如你所看到的,有一些令人惊奇的细微差别。首先,即便是“沉默”信号,也存在一些非零概率。其次,每个手势在中心都具有长时间的“真实”识别,其值接近于1,并且在边缘处具备较小的相反识别。

看起来,要执行准确的实际手势识别,需要进行一些附加的处理。

•Android库

我在一个单独的Android库中对输出信号进行附加处理,实现了TensorFlow识别。以下是库和演示应用程序。

如果在你自己的应用程序中使用它,请将库属性项添加至模块gradle文件中:

repositories { maven { url "https://dl.bintray.com/rii/maven/" } }

dependencies {

...

implementation 'uk.co.lemberg:motiondetectionlib:1.0.0'

}

创建一个动作检测器监听器(MotionDetector listener):

private final MotionDetector.Listener gestureListener = new MotionDetector.Listener() {

@Override

public void onGestureRecognized(MotionDetector.GestureType gestureType) {

Log.d(TAG, "Gesture detected: " + gestureType);

}

};

启用动作检测:

MotionDetector motionDetector = new MotionDetector(context, gestureListener);

motionDetector.start();

我们通过利用TensorFlow库,在Android应用程序上实现了对动作手势进行识别的所有步骤:采集和预处理训练数据、设计和训练神经网络、开发测试应用程序以及随时可用的Android库。所描述的方法可以用于其他任何识别/分类任务。生成的库可以集成到其他任何Android应用程序中,并通过动作手势进行升级。

欢迎个人分享,媒体转载请后台回复「转载」获得授权,微信搜索「BOBO_AI」关注公众号

中国人工智能产业创新联盟于2017年6月21日成立,超200家成员共推AI发展,相关动态:

中新网:中国人工智能产业创新联盟成立

ChinaDaily:China forms 1st AI alliance

证券时报:中国人工智能产业创新联盟成立 启动四大工程搭建产业生态“梁柱”

工信部网站:中国人工智能产业创新联盟与贵阳市政府、英特尔签署战略合作备忘录

点击下图加入联盟

下载中国人工智能产业创新联盟入盟申请表

关注“雷克世界”后不要忘记置顶

我们还在搜狐新闻、雷克世界官网、腾讯新闻、网易新闻、一点资讯、天天快报、今日头条、雪球财经……

↓↓↓点击阅读原文查看中国人工智能产业创新联盟手册

安卓手机如何玩转「动作手势检测」?有TensorFlow就够了 | 实用教程相关推荐

  1. 安卓手机上玩口袋妖怪gba全集的方法

    最近想起以前小时候玩口袋妖怪的回忆,想在自己的手机上玩一下口袋妖怪,发现手机市场的搜到的不是崩溃,就是广告多到爆.偶然在一个论坛发现一个口袋妖怪的合集,太高兴了哈哈. 废话少说,上截图 史上最全的口袋 ...

  2. 安卓虚拟机_安卓手机上面玩虚拟机?这才是真正的玩机神器

    一年前这个时候,我们安利过一款名为虚拟大师 VMOS 的安卓应用. 它的作用就是把安卓系统以 App 的形式运行在任意 Linux 或安卓系统上. 具体来讲就是在安卓手机上,运行一个Android 5 ...

  3. 苹果安卓手机试玩赚钱app

    推荐一个试玩赚零花App[多多红包] 第1步:点击链接下载多多红包 第2步:下载成功后试玩1个任务,就能赚钱提现了 http://gf.aaifbao.cn/?r=815152873&d=20 ...

  4. java模拟器游戏要钱吗_安卓java模拟器(安卓手机如何玩JAVA游戏以及JAVA软件的方法)...

    首先最简单的方法就是JAVA模拟器,但是由于JAVA模拟器的兼容性并不是太好而导致部分(挺大部分的)机型无法使用.所以就有了第二个方法,那就是PSP模拟器,因为PSP上是有JAVA模拟器的,所以就可以 ...

  5. c语言编的游戏怎么在安卓平台使用,谁知道怎么把c语言写的游戏安装到安卓手机上面玩??...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 #define UP 1 #define DN -1 #define RT 2 #define LT -2 #define DW 20 #define S ...

  6. 如何在安卓手机C语言,谁知道怎么把c语言写的游戏安装到安卓手机上面玩??...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 #define UP 1 #define DN -1 #define RT 2 #define LT -2 #define DW 20 #define S ...

  7. 「AI癌症检测 」手机拍照就能检测肿瘤,也太牛了吧!

    近日麻省理工学院发布了一种可以帮助检测黑色素瘤的人工智能,它利用深层卷积神经网络,快速分析患者皮肤的广域图像,可以更有效检测癌症. 它的工作原理是先使用智能手机摄像头拍摄一张病人的皮肤切片,人工智能检 ...

  8. YOLObile:面向移动设备的「实时目标检测」算法

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 分享一篇AAAI 2021录用论文:YOLObile: Real-Time Object Detect ...

  9. 微信小程序「发现流浪猫」宠物互助喂养社区系统部署教程-期末作业项目实例(附源码)

    文末附源码免费下载地址 一.项目介绍 这是一款拍照记录校园内猫猫的成长轨迹的小程序. 可以为不同的猫猫添加身份档案,猫猫相册,并通过精选瀑布流的方式展示给大家. 用户可以上传照片,发表留言,点赞照片或 ...

最新文章

  1. 如何获得Oracle系统性能统计? Oracle大型数据库系统在AIXUNIX上的实战详解 集中讨...
  2. jQuery 1.4 版本的十五个新特性-转载
  3. VSCode中屏蔽文件files.exclude和屏蔽文件搜索search.exclude
  4. 试题 F: 特别数的和 第十届蓝桥杯
  5. Git 基础 - 打标签 tag
  6. MP4文件格式带数据详解
  7. 3DSlicer22:Module-ExtensionWizard Build Install
  8. 有关UNLIMITED TABLESPACE权限
  9. 【转载】MyBatis报错Invalid bound statement (not found)
  10. PowerDesigner生成数据库时的列中文注释乱码问题[mysql]
  11. 单片机实验-定时中断
  12. js 调用c语言函数看,web前端:JS高级---函数中的this的指向,函数的不同调用方式...
  13. Struts1表单验证方式
  14. 基于Caffe的人脸关键点检测实现
  15. 线性代数让我想想:两步得到二阶矩阵的逆
  16. 优化mysql效率_巧用这19条MySQL优化,效率至少提高3倍
  17. 美国弗吉尼亚大学计算机科学,弗吉尼亚大学计算机科学专业怎么样?
  18. python 输出结果图文混排_Django图文混排
  19. 【知识图谱】知识图谱数据库提供一站式全域行业数据融合
  20. 【Go语言学习】——go 数据结构底层原理

热门文章

  1. html圆圈倒计时,基于HTML5 canvas圆形倒计时器jQuery插件
  2. Unexpected token ‘ in JSON
  3. Qt Designer中布局工具的使用
  4. Popup.js 弹出窗口简介
  5. 性能测试loadrunner之参数关联
  6. 六维空间 linux登录,ubuntu安装utorrent,以闪电的速度在六维空间下载东西!
  7. poi导出excel色阶设置工具类
  8. Linux下rsync设置+inotify设置文件同步
  9. 2021年全球壁挂式书柜行业调研及趋势分析报告
  10. Java实现简单井字棋小游戏代码实例