手语也能机器翻译了!机器学习手势识别功能了解一下
华为机器学习(ML Kit)提供手部关键点识别服务,可用于手语识别。手部关键点识别服务能识别手部21个关键点,通过每个手指的方向和手语规则作比较去找手语字母表。
应用场景
手语通常被听力和口语有障碍的人来使用,是收集手势包含日常互动中所使用的动作和手势。使用ML Kit 可以建立一个智能手语字母表识别器,它可以像一个辅助器一样将手势翻译成单词或者句子,也可以将单词或者句子翻译成手势。这里尝试的是手势当中的美国手语字母表,是基于关节,手指和手腕的位置进行分类。接下来小编将会尝试从手势中收集单词“HELLO”。
开发步骤
1. 开发准备
详细的准备步骤可以参考华为开发者联盟,这里列举关键的开发步骤。
1.1 启动ML Kit
在华为开发者AppGallery Connect, 选择Develop > Manage APIs。确保ML Kit 激活。
1.2 项目级gradle里配置Maven仓地址
buildscript {repositories {...maven {url 'https://developer.huawei.com/repo/'}}}dependencies {...classpath 'com.huawei.agconnect:agcp:1.3.1.301'}allprojects {repositories {...maven {url 'https://developer.huawei.com/repo/'}}}
1.3 集成SDK后,在文件头添加配置
apply plugin: 'com.android.application' apply plugin: 'com.huawei.agconnect' dependencies{// Import the base SDK.implementation 'com.huawei.hms:ml-computer-vision-handkeypoint:2.0.2.300'// Import the hand keypoint detection model package.implementation 'com.huawei.hms:ml-computer-vision-handkeypoint-model:2.0.2.300'}
1.4 将以下语句添加到AndroidManifest.xml文件中
<meta-data android:name="com.huawei.hms.ml.DEPENDENCY" android:value= "handkeypoint"/>
1.5 申请摄像头权限和本地文件读取权限
<!--Camera permission--><uses-permission android:name="android.permission.CAMERA" /><!--Read permission--><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
2. 代码开发
2.1 创建用于相机预览的Surface View,创建用于结果的Surface View。
目前我们只在UI中显示结果,您也可以使用TTS识别扩展和读取结果。
mSurfaceHolderCamera.addCallback(surfaceHolderCallback) private val surfaceHolderCallback = object : SurfaceHolder.Callback { override fun surfaceCreated(holder: SurfaceHolder) { createAnalyzer() } override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { prepareLensEngine(width, height) mLensEngine.run(holder) } override fun surfaceDestroyed(holder: SurfaceHolder) { mLensEngine.release() } }
2.2 创建手部关键点分析器
//Creates MLKeyPointAnalyzer with MLHandKeypointAnalyzerSetting.
val settings = MLHandKeypointAnalyzerSetting.Factory().setSceneType(MLHandKeypointAnalyzerSetting.TYPE_ALL).setMaxHandResults(2).create()
// Set the maximum number of hand regions that can be detected within an image. A maximum of 10 hand regions can be detected by defaultmAnalyzer = MLHandKeypointAnalyzerFactory.getInstance().getHandKeypointAnalyzer(settings)
mAnalyzer.setTransactor(mHandKeyPointTransactor)
2.3 开发者创建识别结果处理类“HandKeypointTransactor”
该类MLAnalyzer.MLTransactor接口,使用此类中的“transactResult”方法获取检测结果并实现具体业务。
class HandKeyPointTransactor(surfaceHolder: SurfaceHolder? = null): MLAnalyzer.MLTransactor<MLHandKeypoints> {override fun transactResult(result: MLAnalyzer.Result<MLHandKeypoints>?) {var foundCharacter = findTheCharacterResult(result)if (foundCharacter.isNotEmpty() && !foundCharacter.equals(lastCharacter)) {lastCharacter = foundCharacterdisplayText.append(lastCharacter)}canvas.drawText(displayText.toString(), paddingleft, paddingRight, Paint().also {it.style = Paint.Style.FILLit.color = Color.YELLOW})}
2.4 创建LensEngine
LensEngine lensEngine = new LensEngine.Creator(getApplicationContext(), analyzer)
setLensType(LensEngine.BACK_LENS)
applyDisplayDimension(width, height) // adjust width and height depending on the orientation
applyFps(5f)
enableAutomaticFocus(true)
create();
2.5 运行LensEngine
private val surfaceHolderCallback = object : SurfaceHolder.Callback { // run the LensEngine in surfaceChanged()
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {createLensEngine(width, height)mLensEngine.run(holder)
}}
2.6 停止分析器,释放检测资源
fun stopAnalyzer() { mAnalyzer.stop() }
2.7 处理 transactResult() 以检测字符
您可以使用HandKeypointTransactor类中的transtresult方法来获取检测结果并实现特定的服务。检测结果除了手部各关键点的坐标信息外,还包括手掌和每个关键点的置信值。手掌和手部关键点识别错误可以根据置信值过滤掉。在实际应用中,可以根据误认容忍度灵活设置阈值。
2.7.1 找到手指的方向
让我们先假设可能手指的矢量斜率分别在X轴和Y轴上。
private const val X_COORDINATE = 0
private const val Y_COORDINATE = 1
假设我们有手指分别在5个矢量上,任意手指的方向在任意时间可以被分类为上,下,下-上,上-下,不动。
enum class FingerDirection {VECTOR_UP, VECTOR_DOWN, VECTOR_UP_DOWN, VECTOR_DOWN_UP, VECTOR_UNDEFINED
}enum class Finger {THUMB, FIRST_FINGER, MIDDLE_FINGER, RING_FINGER, LITTLE_FINGER
}
首先将对应的关键点从结果中分离到不同手指的关键点数组,像这样:
var firstFinger = arrayListOf<MLHandKeypoint>()
var middleFinger = arrayListOf<MLHandKeypoint>()
var ringFinger = arrayListOf<MLHandKeypoint>()
var littleFinger = arrayListOf<MLHandKeypoint>()
var thumb = arrayListOf<MLHandKeypoint>()
手指上的每个关键点都对应手指的关节,通过计算关节与手指的平均位置值之间的距离就可以计算出斜率。根据附近关键点的坐标,查询该关键点的坐标。
拿字母H的两个简单关键点来说:
int[] datapointSampleH1 = {623, 497, 377, 312, 348, 234, 162, 90, 377, 204, 126, 54, 383, 306, 413, 491, 455, 348, 419, 521 };
int [] datapointSampleH2 = {595, 463, 374, 343, 368, 223, 147, 78, 381, 217, 110, 40, 412, 311, 444, 526, 450, 406, 488, 532};
用手指坐标的平均值来计算矢量
//For ForeFinger - 623, 497, 377, 312double avgFingerPosition = (datapoints[0].getX()+datapoints[1].getX()+datapoints[2].getX()+datapoints[3].getX())/4;
// find the average and subract it from the value of x
double diff = datapointSampleH1 [position] .getX() - avgFingerPosition ;
//vector either positive or negative representing the direction
int vector = (int)((diff *100)/avgFingerPosition ) ;
矢量的结果将会是正值或者负值,如果它是正值它会出现X轴的正四方向,如果相反它就是负值。用这个方式对所有字母进行矢量映射,一旦你掌握了所有的矢量我们就可以用它们来进行编程。
用上述矢量方向,我们可以分类矢量,定义第一个为手指方向枚举
private fun getSlope(keyPoints: MutableList<MLHandKeypoint>, coordinate: Int): FingerDirection {when (coordinate) {X_COORDINATE -> {if (keyPoints[0].pointX > keyPoints[3].pointX && keyPoints[0].pointX > keyPoints[2].pointX)return FingerDirection.VECTOR_DOWNif (keyPoints[0].pointX > keyPoints[1].pointX && keyPoints[3].pointX > keyPoints[2].pointX)return FingerDirection.VECTOR_DOWN_UPif (keyPoints[0].pointX < keyPoints[1].pointX && keyPoints[3].pointX < keyPoints[2].pointX)return FingerDirection.VECTOR_UP_DOWNif (keyPoints[0].pointX < keyPoints[3].pointX && keyPoints[0].pointX < keyPoints[2].pointX)return FingerDirection.VECTOR_UP}Y_COORDINATE -> {if (keyPoints[0].pointY > keyPoints[1].pointY && keyPoints[2].pointY > keyPoints[1].pointY && keyPoints[3].pointY > keyPoints[2].pointY)return FingerDirection.VECTOR_UP_DOWNif (keyPoints[0].pointY > keyPoints[3].pointY && keyPoints[0].pointY > keyPoints[2].pointY)return FingerDirection.VECTOR_UPif (keyPoints[0].pointY < keyPoints[1].pointY && keyPoints[3].pointY < keyPoints[2].pointY)return FingerDirection.VECTOR_DOWN_UPif (keyPoints[0].pointY < keyPoints[3].pointY && keyPoints[0].pointY < keyPoints[2].pointY)return FingerDirection.VECTOR_DOWN}}
return FingerDirection.VECTOR_UNDEFINED
获取每个手指的方向并且储存在一个数组里。
xDirections[Finger.FIRST_FINGER] = getSlope(firstFinger, X_COORDINATE)
yDirections[Finger.FIRST_FINGER] = getSlope(firstFinger, Y_COORDINATE )
2.7.2 从手指方向找到字符:
现在我们把它当作唯一的单词“HELLO”,它需要字母H,E,L,O。它们对应的X轴和Y轴的矢量如图所示。
假设:手的方向总是竖向的。让手掌和手腕与手机平行,也就是与X轴成90度。姿势至少保持3秒用来记录字符。
开始用字符映射矢量来查找字符串
// Alphabet H
if (xDirections[Finger.LITTLE_FINGER] == FingerDirection.VECTOR_DOWN_UP&& xDirections [Finger.RING_FINGER] == FingerDirection.VECTOR_DOWN_UP&& xDirections [Finger.MIDDLE_FINGER] == FingerDirection.VECTOR_DOWN&& xDirections [Finger.FIRST_FINGER] == FingerDirection.VECTOR_DOWN&& xDirections [Finger.THUMB] == FingerDirection.VECTOR_DOWN)return "H"//Alphabet E
if (yDirections[Finger.LITTLE_FINGER] == FingerDirection.VECTOR_UP_DOWN&& yDirections [Finger.RING_FINGER] == FingerDirection.VECTOR_UP_DOWN&& yDirections [Finger.MIDDLE_FINGER] == FingerDirection.VECTOR_UP_DOWN&& yDirections [Finger.FIRST_FINGER] == FingerDirection.VECTOR_UP_DOWN&& xDirections [Finger.THUMB] == FingerDirection.VECTOR_DOWN)return "E"if (yDirections[Finger.LITTLE_FINGER] == FingerDirection.VECTOR_UP_DOWN&& yDirections [Finger.RING_FINGER] == FingerDirection.VECTOR_UP_DOWN&& yDirections [Finger.MIDDLE_FINGER] == FingerDirection.VECTOR_UP_DOWN&& yDirections [Finger.FIRST_FINGER] == FingerDirection.VECTOR_UP&& yDirections [Finger.THUMB] == FingerDirection.VECTOR_UP)return "L"if (xDirections[Finger.LITTLE_FINGER] == FingerDirection.VECTOR_UP&& xDirections [Finger.RING_FINGER] == FingerDirection.VECTOR_UP&& yDirections [Finger.THUMB] == FingerDirection.VECTOR_UP)
return "O"
3. 画面和结果
4.更多技巧和诀窍
1. 当扩展到26个字母时,误差很更多。为了更精准的扫描需要2-3秒,从2-3秒的时间寻找和计算最有可能的字符,这可以减少字母表的误差。
2. 为了能支持所有方向,在X-Y轴上增加8个或者更多的方向。首先,需要求出手指的度数和对应的手指矢量。
总结
这个尝试是强力坐标技术,它可以在生成矢量映射后扩展到所有26个字母,方向也可以扩展所有8个方向,所以它会有26*8*5个手指=1040个矢量。为了更好的解决这一问题,我们可以利用手指的一阶导数函数来代替矢量从而简化计算。
我们可以增强其它的去代替创建矢量,可以使用图像分类和训练模型,然后使用自定义模型。这个训练是为了检查华为ML Kit使用关键点处理特性的可行性。
了解更多相关内容>>
访问华为机器学习服务官网
获取华为机器学习服务开发指导文档
华为HMS Core官方论坛
华为机器学习开源仓地址:GitHub、Gitee
解决集成问题请到Stack Overflow
点击关注,第一时间了解HMS Core最新技术~
手语也能机器翻译了!机器学习手势识别功能了解一下相关推荐
- python基于opencv的手势识别_怎么在Python3.5 中利用OpenCV实现一个手势识别功能
怎么在Python3.5 中利用OpenCV实现一个手势识别功能 发布时间:2020-12-22 11:56:32 来源:亿速云 阅读:67 作者:Leah 怎么在Python3.5 中利用OpenC ...
- 手势识别功能(Gesture Recognizer)
1. 手势识别概念 a. iOS 3.2之后,苹果推出了手势识别功能(GestureRecognizer),在触摸事件处理方面,大大简化了开发者的开发难度. b. 为了完成手势识别,必须借助于手势识别 ...
- 体感游戏 | 手势识别玩飞机大战游戏(二) Python+OpenCV实现简易手势识别功能
后面将分四篇文章来介绍实现手势识别控制飞机大战游戏的功能,它们分别是: 使用Pygame实现简易飞机大战小游戏 使用Python+OpenCV实现简单手势识别 使用OpenCV实现手势识别玩飞机大战游 ...
- 基于Python+Open CV的手势识别算法设计
素材资料下载: 基于Python+OpenCV的手势识别算法设计源代码材料-机器学习文档类资源-CSDN下载采用Python的集成开发环境Pycharm进行本次课程设计,在Pycharm中进行需要库( ...
- 手势识别(1):基础理论
像点击(clicks)是GUI平台的核心,轻点(taps)是触摸平台的核心那样,手势(gestures)是Kinect应用程序的核心.和图形用户界面中的数字交互不同,手势是现实生活中存在的动作.如果没 ...
- 图表对比详解:亚马逊、微软和谷歌云的机器学习即服务哪家强
林鳞 编译自 KDnuggets 量子位 出品 | 公众号 QbitAI 对于大多数公司来说,机器学习是一项复杂而伤神的工作,花销大.对人才要求高.机器学习即服务针对这个痛点应运而生. 什么是&quo ...
- 机器学习入门1-译文-机器学习是什么以及它的重要性(machine learning--what it is and why it matters)
本文目录索引 1.前言 1.0侵删 1.0.1 20200920首发 1.0.2 良心翻译 1.1 此系列说明 1.2 聊点机器学习 1.2.1 机器学习的定义 1.2.2 知识发现.机器学习.人工智 ...
- 拯救非洲的粮食危机,机器学习做了这些!
2016年,在非洲首次发现了破坏农作物的毛毛虫,秋粘虫(FAW).此后,农作物病虫害感染了数百万玉米田,破坏了农业,从而威胁到该区域的粮食安全.依靠收成获得粮食的农民需要与有害生物作斗争,该有害生物现 ...
- Insights直播回顾——手语服务,助力沟通无障碍
HMS Core Insights第九期直播–手语服务,助力沟通无障碍,已于12月29日圆满结束,本期直播与小伙伴们一同了解了HMS Core手语服务的亮点特性.底层技术以及演进规划,下面我们一起来回 ...
最新文章
- [感动]看来的故事:小孩和鱼
- plor 回归的r方_简单线性回归模型
- 随便聊一些编程开发工具
- Angular Component的DOM级别的单元测试方法
- Spring Data JPA框架
- Redis系列教程(三):如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
- Android 之父裁员 30%:开发者如何避免“被离职”?
- 深入理解计算机的字长
- pandas忽略行列索引,纵向拼接多个dataframe
- 45W快充没了?三星Galaxy Note10 Pro可能还是25W快充
- 落魄前端,整理给自己的前端知识体系复习大纲(下篇)
- echarts java动态数据_[ASP.net教程]ECharts Java 动态加载数据,echartsjava
- cubic算法优化_CUBIC拥塞拥塞控制算法
- [IOS APP]毕淑敏经典有声小说
- LeetCode刷题日记:LCP 03.机器人大冒险
- html5 游戏 响应式,关于html5:响应式游戏网页有什么特点呢
- 如何自定义炫酷浏览器主页
- 修图教程:为照片增加云雾效果
- 单片机应用编程技巧100问
- C++获取网卡名称和IP地址