本帖最后由 zealsoft 于 2023-8-14 10:28 编辑
今天介绍一下如何利用米尔MYD-YG2LX开发板进行基于手势识别的控制系统的开发。
1、 手势识别的原理 人的手是非常灵活而且能够表达丰富含义的器官,当两个人语音不通的时候,我们经常可以借助手势来表达意思。感知手的形状和运动的能力是改善用户体验的重要组成部分,但是手势识别绝对是一项具有挑战性的计算机视觉任务。 一般的手势识别可以分成2个步骤:首先从图像或者视频中进行手势骨架与关键点提取,然后根据关键点之间的关系识别手势的含义。 (1) 利用MediaPipe Hands 进行关键点提取 MediaPipe是谷歌提供的用于构建机器学习管道的开源框架,用于处理视频、音频等时间序列数据。这个跨平台框架适用于桌面/服务器、Android、iOS和嵌入式设备。MediaPipe Hands 是其中一个一种高保真手和手指跟踪解决方案。它采用机器学习 (ML) 从单个帧中推断出手的 21 个 3D 地标(landmark)。当前最先进的方法往往依赖于强大的桌面环境进行推理,而MediaPipe Hands 在手机或嵌入式设备上实现了实时性能,甚至可以扩展到多只手。在米尔 MYD-YG2LX开发板上,MediaPipe Hands也是表现不错的。有关MediaPipe的详细介绍可以参考: https://developers.google.com/mediapipe。 MediaPipe提供了2个手势识别相关的解决方案:Hand Landmarker 和Gesture Recognizer。前者完成手势骨架与关键点提取,后者在前者的基础上完成手势含义的识别。我们的项目主要使用的是Hand Landmarker 。 MediaPipe可以识别手部的21个关键点,其含义如下图所示。 每个点都是3维的,其坐标为(x,y, z),每个坐标都是0~1之间的归一化结果。我们只使用(x, y)坐标。Z坐标表示手距离摄像头的远近,本文未使用。 MediaPipe中的hands.process是用于从图像中提取关键点的函数,它返回21个关键点的集合。 (2) 手势的定义 前面说了,手势的定义可以借助GestureRecognizer完成。不过为了实现更灵活的定义,我们采用直接判断关键点坐标的方法来实现手势定义。
比如,如果我们想判断有几个手指竖起来了,就可以用判断关键点之间的y坐标的方法。 - # 检测每个手指,如果手指竖起来,计数值加一
- # 拇指: TIP x 坐标必须逼IP x 坐标小
- if handLabel == "Left" and handLandmarks[4][0] > handLandmarks[3][0]:
- fingerCount = fingerCount+1
- elif handLabel == "Right" and handLandmarks[4][0] < handLandmarks[3][0]:
- fingerCount = fingerCount+1
- # 其他手指: TIP y 坐标必须 PIP y 坐标小
- # 所有坐标都是以图片左上角为基础
- if handLandmarks[8][1] < handLandmarks[6][1]: # 食指
- fingerCount = fingerCount + 1
- if handLandmarks[12][1] < handLandmarks[10][1]: # 中指
- fingerCount = fingerCount + 1
- if handLandmarks[16][1] < handLandmarks[14][1]: # 无名指
- fingerCount = fingerCount + 1
- if handLandmarks[20][1] < handLandmarks[18][1]: # 小拇指
- fingerCount = fingerCount + 1
复制代码下图就是手指计数为3的结果。 2、 基于手势识别的控制系统的实现 1) 系统架构
系统组成图如下图所示。采用USB摄像头作为视频采集设备,用于实时捕捉用户的手势操作。开发板处理采集的图像并进行手势识别的处理,根据用户输入手势所代表的数字控制gst-play-1.0播放不同的音乐。音乐的播放所使用的音箱连接到开发板的Audio接口上。 程序的处理流程如下图所示。 2) 开发环境的建立 l opencv-python l opencv-contrib-python l mediapipe l opencv-python-headless
需要注意的事,MediaPipe和protobuf 新版本不兼容,如果在运行MediaPipe程序时遇到如下错误信息: If this call came from a _pb2.py file, your generated code is out of date and must be regenerated with protoc >= 3.19.0.
If you cannot immediately regenerate your protos, some other possible workarounds are:
1. Downgrade the protobuf package to 3.20.x or lower.
2. Set PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python (but this will use pure-Python parsing and will be much slower).
请使用下面的语句进行模块降级:
- pip3 install protobuf==3.20.*
复制代码3) 几个细节问题 l 视频采集的参数 虽然MediaPipe对视频的尺寸只要120×120以上就行,不过从实际测试看,视频尺寸太小容易产生错误,所以视频的大小最好还是在640×480为宜。考虑到一般手势动作的速度不会太快,如果担心处理速度慢,可以降低帧率,这也是大多数嵌入式系统经常采用的方法。 l 避免误判的处理 虽然MediaPipe的识别正确率很高,但是也难免误判,特别是人脸的颜色和手的颜色很接近,所以当人脸和手同时出现在视频中,还是很容易出现误判的。为了避免错误,我们增加了条件限制,即只有连续三次判断为同一个数字才认为手势有效,从而避免频繁的切换歌曲。 4) 测试结果
实物连接图如下图所示。
代码见附件。 |