前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android | 通过机器学习实现精准字母手势识别

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

作者头像
菜天哥哥
发布2018-07-03 12:40:15
3.5K4
发布2018-07-03 12:40:15
举报
文章被收录于专栏:猿湿Xoong

看过上一篇「一个很糙的字母手势识别方案」文章并尝试了的同学,就一定知道,「糙手势」的识别是有多糙,糙的只能识别字母「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」这样的观点,限制了思路,这次也算是无意破除了思想的禁锢。

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-06-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 菜天 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档