Android | 通过机器学习实现精准字母手势识别

看过上一篇「一个很糙的字母手势识别方案」文章并尝试了的同学,就一定知道,「糙手势」的识别是有多糙,糙的只能识别字母「C」。

今天这篇就用 Android 自带的 gesture API 来实现更为精准的识别。

看到这里,有的同学可能就会说了,「标题党,哪有机器学习!」。别急,认真看,认真学。先上效果图,注意底部识别分数变化,至于为什么粉红色,这是「社会人」小猪佩奇的颜色好吧~

编不下去了,这个画板源码部分借鉴了 github 下面链接的控件,TA用的就是粉色,我没改~

https://github.com/imaiya/PainterView

PS:右上角按钮默认 load 的 26 字母数据集是我手动录入然后保存为文件的,每个字母大概画了 15-20个。此数据集文件大小为 287KB。可后台回复「精手势」获取。

故事的开端

即使在「糙手势」方案中学习到了手势识别的大概套路:「先存储后识别」,但心痛于其感人的识别率,在还没写上一篇文章之前,就开始搜寻更为精准的方案。

可能是从未接触过此类功能, 苦苦搜寻之下才找到了一个网友的帖子,其中的关键字「GestureLibrary」引起了我的注意。

我在 AndroidXref 中查询了一下,还真有这个类,大概了解并确定怎么用后,将「更精准的方案」之类的字眼写入前一篇文章的末尾,给大家留有悬念,并开始研究了起来。

送上一张 gesture API 的全家福:

一开始我直接投入研究如何使用这些API了,所以并未注意到其中的 「Instance.java」和「Learner.java」两个类。这两个类的命名是有玄机的。

如何使用?

我们知道,一个手势,是个平面,多数情况下是个字符,字则由笔画组成。笔画是一条线。笔画又是由点组成。

GesturePoint.java

-> 是「点」,它除了x,y属性还有时间戳属性。

GestureStroke.java

-> 是「线」,它由GesturePoint组成。

Gesture.java

-> 是「面」,它由一个或多个GestureStroke组成。

以上三个类是基本,构成了整个手势数据结构体系。如果你也想写个佩奇色的画板,那你就需要知道这三个类的关系。直接使用下面这个类就不需要关注。

GestureOverlayView.java

-> 为了方便画图,你可以在 xml 中直接使用 GestureOverlayView。使用这个 View 的好处是:不需要接触到 point 和 stroke 的概念,注册的回调会直接返回 Gesture。可以参考下面这个链接。

http://www.runoob.com/w3cnote/android-tutorial-gestures.html

无论哪种,手势数据采集好后都需要存储下来。

GestureStore.java

-> 提供存储手势的接口,以及识别接口。一个手势名,可对应多个手势数据。从addGesture()方法可以看出,一个手势名,对应着一个手势ArrayList。

GestureLibrary.java

-> 抽象类,持有GestureStore对象,封装了其大部分public方法。我认为目的是为了分离GestureStore中的复杂实现。每一个library对象都对应一个数据集文件。

GestureLibraries.java

-> 进一步封装了GestureLibrary,内部提供两个GestureLibrary私有实现类,以四个public static 方法暴露出来,方便数据的存储和加载,如下截图。

Prediction.java

-> 简单的类,代表预测结果值。name -> 手势名,score -> 得分。得分越高,越相似

更为详细的使用,后台回复「精手势」获取源码。

gesture API 中的机器学习

没错,gesture api 内部是通过机器学习来进行手势识别的,说是手势预测更贴切些。

一开始我是不知道的。由于好奇它的实现方式,以及对比方式,我阅读了它的源码,才得以发现。

机器学习中有三种学习技巧,分别是:

监督式学习(Supervised learning)

半监督式学习(Semi-supervised learning)

非监督式学习(Unsupervised learning)

其中难度从上到下依次递增。

gesture API 则为「监督式学习」。为什么?

为了更好的理解,先来了解下机器学习的基本术语。

机器学习术语:

监督式机器学习:机器学习系统通过学习如何组合输入信息来对从未见过的数据做出有用的预测。

标签:我们要预测的事物。在本篇文章中,假如我们要 A 字母进行识别预测,那 A 就是标签。更通俗点,每一个「手势名」就是一个「标签」。

特征:特征是输入的变量。这篇中,我们录入的每一个「手势数据」就是一个「特征」。

样本:样本表示数据的特定实例。样本分为两类:有标签样本无标签样本

有标签样本:同时包含「标签」和「特征」。在本篇中,一个有标签样本就是「手势名」+「你画的手势数据」。通常有标签样本用来进行模型的训练。

无标签样本:不包含「标签」,只包含「特征」的样本。在本篇中,无标签样本就是我后面要识别的手势,仅有「手势数据」。根据训练出来的模型推断出此样本的「标签」,也就是「手势名」。

模型:模型定义了特征与标签之间的关系。主要分为两个阶段:训练推断

训练:表示创建或学习模型。也就是说,向模型展示有标签样本,让模型逐渐学习特征与标签之间的关系。

推断:表示将训练后的模型应用于无标签样本,做出有用的预测。

对于不同的问题,模式种类也不同:对于连续性问题,使用回归模型;对于离散问题,使用分类模型。

gesture API 是一个分类模型,其中的分类器根据不同配置(超参数),采用取不同的相似性算法:欧氏距离(Euclidean Distance) 和 夹角余弦(Cosine)

涉及的类主要是:

有兴趣的同学可以继续研究。我没有太过于深入,因为已经到最深层的具体实现细节了。

最后

大家可以后台回复「精手势」获取 apk 和 26 字母数据集下载链接,尝试下。当然,不仅是 26 字母,任何手势录入训练数据后都可以识别。

要我说,机器学习其实是一种编程方式,无关语言。

我之前无形中形成了「机器学习用 Python」这样的观点,限制了思路,这次也算是无意破除了思想的禁锢。

我们平时写代码,都是想好了如何解决问题,通过一行行的逻辑形成针对问题的方案。这时你还是个程序猿。

而机器学习,是你写了一个傻子,你拿数据训练这个傻子,最后让他聪明了起来。这时候你不是程序猿,是个教书育人的老师。

原文发布于微信公众号 - 猿湿Xoong(skypeng-funny)

原文发表时间:2018-06-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大数据文摘

手把手 | 如何训练一个简单的音频识别网络

3073
来自专栏iOSDevLog

quickdraw_datasetQuick Draw!数据集

https://console.cloud.google.com/storage/browser/quickdraw_dataset

2412
来自专栏人工智能LeadAI

从学习 Paddle 开始学习深度学习

优点 灵活性:PaddlePaddle支持广泛的神经网络结构和优化算法,很容易配置复杂的模型,如基于注意力(Attention)机制或复杂的内存(Memory)...

3453
来自专栏顶级程序员

Caffe源码直播

0.预告 开源项目名称:Caffe—— deep learning framework 语言:C++ 时间:10月22日(周六)早11:00-12:00 参与方...

4429
来自专栏AI研习社

可应用的目标检测代码来了,一秒锁定你

计算机视觉是人工智能的一个重要领域。计算机视觉是一门关于计算机和软件系统的科学,可以让计算机对图像及场景进行识别和理解。计算机视觉还包括图像识别、目标检测、图像...

811
来自专栏瓜大三哥

基于FPGA的Canny算子设计(二)

滞后阈值分割电路设计 滞后阈值需要两个阈值:一种方法是可以根据所要提取的图片,提前定好这两个阈值;另一种方式是采用自动阈值法(如大律法)。这里采用第一种方法。 ...

2486
来自专栏AI研习社

使用 SKIL 和 YOLO 构建产品级目标检测系统

在本文中,我们采用最新的神经网络实现目标检测,使用SKIL平台构建产品级目标检测系统。

1041
来自专栏SDNLAB

使用机器学习算法对流量分类的尝试——基于样本分类

导言 机器学习方法目前可以分为5个流派,分别是符号主义,联结主义,进化主义,贝叶斯和Analogzier。具体到实例有联结主义的神经网络,进化主义的遗传算法,贝...

63512
来自专栏iOSDevLog

seaborn的介绍

Seaborn是一个用Python制作统计图形的库。它建立在matplotlib之上,并与pandas数据结构紧密集成。

2281
来自专栏AI研习社

Github 项目推荐 | 用 PyTorch 实现全局/局部一致图像补全

本库用 PyTorch 实现了全局/局部一致图像补全(Globally and Locally Consistent Image Completion )。

1512

扫码关注云+社区