摘要:本文详细介绍基于深度学习的手势识别系统,在介绍手势识别算法原理的同时,给出了
P
y
t
h
o
n
的实现代码以及
P
y
Q
t
的UI界面。手势识别采用了基于MediaPipe的改进SSD算法,进行手掌检测后对手部关节坐标进行关键点定位;在系统界面中可以选择手势图片、视频进行检测识别,也可通过电脑连接的摄像头设备进行实时识别手势;可对图像中存在的多个手势进行姿势识别,可选择任意一个手势显示结果并标注,实时检测速度快、识别精度较高。博文提供了完整的Python代码和使用教程,适合新入门的朋友参考,完整代码资源文件请转至文末的下载链接。本博文目录如下:
➷点击跳转至文末所有涉及的
完整代码文件
下载页☇
随着计算机性能的发展,人机交互越来越频繁。在工程应用方面,计算机通过对手势的分析理解,可以进一步开发出相应的远程操控系统,在疫情当下,可以更好的实现零接触操作。同时通过手势也可以进一步了解人的表情与情感,例如在警匪影片中,通过手势的微小变化,对罪犯的阐述进行分析判断,但这只是更深层次的系统设想。
手势识别是个计划已久的项目,通过手势可以传达很多信息,从而实现很多好玩的事情,比如石头剪刀布、切水果等游戏。网上也有一些相关手势识别的博客或代码,不过很少有人对其进行详细介绍,为了便于演示和交付用户使用,我们将其开发成一个可以展示的完整软件,方便选择文件和实时检测。对此这里给出博主设计的界面,关注过的朋友可能清楚我的简约风,功能上也满足了图片、视频和摄像头的识别检测,希望大家可以喜欢,初始界面如下图:
检测手势时的界面截图(点击图片可放大)如下图,可识别画面中存在的多个手势,也可开启摄像头或视频检测:
详细的功能演示效果参见博主的B站视频或下一节的动图演示,觉得不错的朋友敬请点赞、关注加收藏!系统UI界面的设计工作量较大,界面美化更需仔细雕琢,大家有任何建议或意见和可在下方评论交流。
手势识别系统借助深度学习算法,开发有选择图片识别、视频识别以及摄像画面识别,结果的可视化显示功能,这里给出几张动图供大家参考。
(一)选择手势图片识别
可点击手势识别系统中的图片选择按钮,即可弹出图片文件选择窗口,选中文件后自动显示识别结果;对于多个手势,可通过下拉框选择单独显示结果。本功能的界面展示如下图所示:
(二)手势视频识别效果展示
对于视频文件同样可以通过对应的视频选择按钮,选中可用的视频后自动利用算法对视频帧进行逐个识别,此时对算法和设备的实时性要求较高,但系统同样能够保持高的检测速度。效果如下图所示:
(三)摄像头检测效果展示
在真实场景中,我们往往利用设备摄像头获取实时画面,同时需要对画面中的手势进行识别,因此本文考虑到此项功能。如下图所示,点击摄像头按钮后系统进入准备状态,系统显示实时画面并开始检测画面中的手势,识别结果展示如下图:
目前现阶段手势识别的研究方向主要分为:基于穿戴设备的手势识别和基于视觉方法的手势识别。基于穿戴设备的手势识别主要是通过在手上佩戴含有大量传感器的手套获取大量的传感器数据,并对其数据进行分析。该种方法相对来虽然精度比较高,但是由于传感器成本较高很难在日常生活中得到实际应用,同时传感器手套会造成使用者的不便,影响进一步的情感分析,所以此方法更多的还是应用在一些特有的相对专业的仪器中。而本博客更多的还是将关注点放在基于视觉方法的手势研究中,在此特地以Mediapipe的框架为例,方便读者更好的复现和了解相关领域。
基于视觉方法的手势识别主要分为静态手势识别和动态手势识别两种。从文字了解上来说,动态手势识别肯定会难于静态手势识别,但静态手势是动态手势的一种特殊状态,我们可以通过对一帧一帧的静态手势识别来检测连续的动态视频,进一步分析前后帧的关系来完善手势系统。在本博客中向大家推荐一篇比较基础的中文期刊帮助大家简单了解:
由解迎刚老师发表在计算机工程与应用上的《基于视觉的动态手势识别研究综述》,论文从传感开始介绍,然后在介绍了相关检测算法,将手势识别分为了手势检测与分割、手势追踪、特征提取、手势分类与识别四个方面来介绍
1
。还有许多手势识别的英文综述可供大家参考,感兴趣的可以了解一下。
Mediapipe深度学习框架的官网是
https://google.github.io/mediapipe/
,大家可以直接通过本博客访问其网站。MediaPipe 是一款由 Google Research 开发并开源的多媒体机器学习模型应用框架。首先在官网首页我们就可以直接看到MediaPipe能干的有:
从左到右分别是人脸检测,人脸关键点检测,瞳孔检测、手势识别、身体姿态识别、全身的动作识别,更难的像发丝检测、简单的目标检测、追踪和实时物体控制,3D物体检测和标志标牌检测。然后MediaPipe支持的语言有如下:
在官方的网址上可以知道,MediaPipe的手势识别算法主要分为两个部分,第一个部分是手掌识别模型,第二个是手部关键点标记模型。
MediaPipe在训练手掌模型中,使用的是单阶段目标检测算法SSD。同时利用三个操作对其进行了优化:1.NMS;2.encoder-decoder feature extractor;3.focal loss。NMS主要是用于抑制算法识别到了单个对象的多个重复框,得到置信度最高的检测框;encoder-decoder feature extractor主要用于更大的场景上下文感知,甚至是小对象(类似于retanet方法);focal loss是有RetinaNet上提取的,主要解决的是正负样本不平衡的问题,这对于开放环境下的目标检测是一个可以涨点的技巧。利用上述技术,MediaPie在手掌检测中达到了95.7%的平均精度。在没有使用2和3的情况下,得到的基线仅为86.22%。增长了9.48个点,说明模型是可以准确识别出手掌的。而至于为啥做手掌检测器而不是手部,主要是作者认为训练手部检测器比较复杂,可学习到的特征不明显,所以做的是手掌检测器。
MediaPipe通过对整个图像进行手掌检测后,使用手部关键点模型通过回归对被检测手部区域内的21个三维手部关节坐标进行精确的关键点定位,即直接进行坐标预测。标记点如图所示:
在此我们就简单的介绍了MediaPipe,接下来我们将通过代码来使用python调用MediaPipe实现手势识别。主要从三个方面来写这个脚本:第一个如果识别静态照片的手势;第二个如何识别视频流中的手势;第三个如果实时识别摄像头图像。
实现代码前首先进行依赖安装,这里需要安装python-opencv和MediaPipe,可使用以下命令:
pip install opencv-python
pip install mediapipe
首先是引入库文件,这里主要用到的是一个mediapipe的sdk包和opencv的包。其他的numpy、time、math都是python和深度学习的基础包,不多介绍。
import mediapipe as mp
import cv2
import numpy as np
import time
import math
接下来我们将通过mediapipe的sdk来引入我们需要的手势识别的API,其代码如下:
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_hands = mp.solutions.hands
然后我们将预设一张手势识别的图片,可以填入相对路径和绝对路径。并预设一组数字,用于后期的手势分析。
IMAGE_List = ['jpgDet.jpg']
gesture = [0,1,2,3,4,5]
以下就是手势识别的主程序,也就是主要核心内容。通过mediapipe的api我们可以分析出检测到的是左手还是右手,并获取相应手的21个关键点坐标。
with mp_hands.Hands(
static_image_mode = True,
max_num_hands = 2,
model_complexity = 0,
min_detection_confidence = 0.5,
) as hands:
for idx ,file in enumerate(IMAGE_List):
image = cv2.flip(cv2.imread(file),1)
image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
t0 = time.time()
results =hands.process(image)
results.multi_handedness
包括label和score,label是字符串"Left"或"Right",score是置信度
results.multi_hand_landmarks
results.multi_hand_landmrks:被检测/跟踪的手的集合
其中每只手被表示为21个手部地标的列表,每个地标由x、y和z组成。
x和y分别由图像的宽度和高度归一化为[0.0,1.0]。Z表示地标深度
以手腕深度为原点,值越小,地标离相机越近。
z的大小与x的大小大致相同。
t1 = time.time()
fps = 1 / (t1 - t0)
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
dict_handnumber = {}
if results.multi_handedness:
if len(results.multi_handedness) == 2:
for i in range(len(results.multi_handedness)):
label = results.multi_handedness[i].classification[0].label
index = results.multi_handedness[i].classification[0].index
hand_landmarks = results.multi_hand_landmarks[index]
mp_drawing.draw_landmarks(
image,
hand_landmarks,
mp_hands.HAND_CONNECTIONS,
mp_drawing_styles.get_default_hand_landmarks_style(),
mp_drawing_styles.get_default_hand_connections_style())
gesresult = ges(hand_landmarks)
dict_handnumber[label] = gesresult
else:
label = results.multi_handedness[0].classification[0].label
hand_landmarks = results.multi_hand_landmarks[0]
mp_drawing.draw_landmarks(
image,
hand_landmarks,
mp_hands.HAND_CONNECTIONS,
mp_drawing_styles.get_default_hand_landmarks_style(),
mp_drawing_styles.get_default_hand_connections_style())
gesresult = ges(hand_landmarks)
dict_handnumber[label] = gesresult
if len(dict_handnumber) == 2:
leftnumber = dict_handnumber['Right']
rightnumber = dict_handnumber['Left']
显示实时帧率,右手值,左手值,相加值
s = 'FPS:{0}\nRighthand Value:{1}\nLefthand Value:{2}\nAdd is:{3}'.format(int(fps),rightnumber,leftnumber,str(leftnumber+rightnumber))
elif len(dict_handnumber) == 1 :
labelvalue = list(dict_handnumber.keys())[0]
if labelvalue == 'Right':
number = list(dict_handnumber.values())[0]
s = 'FPS:{0}\nRighthand Value:{1}\nLefthand Value:0\nAdd is:{2}'.format(int(fps),number,number)
else:
number = list(dict_handnumber.values())[0]
s = 'FPS:{0}\nLefthand Value:{1}\nRighthand Value:0\nAdd is:{2}'.format(int(fps),number,number)
else:
s = 'FPS:{0}\n'.format(int(fps))
y0,dy = 50,25
for i ,txt in enumerate(s.split('\n')):
y = y0 + i*dy
cv2.putText(image,txt,(50,y),cv2.FONT_HERSHEY_SIMPLEX,1,(255,0,0),3)
cv2.imshow('MediaPipe Gesture Recognition',image)
cv2.imwrite('save/{0}.jpg'.format(idx),image)
if cv2.waitKey(5) & 0xFF == 27:
break
运行以上代码,通过读取一张手势图片,调用算法对画面中的手势进行识别,其中手指数目、画面帧率、手势结果等信息标记在图像中,如下图所示:

视频识别在代码结构上与图片识别是一致的,主要的原理就是通过cv2.VideoCapture()函数将视频读取成每一帧,并对每一帧图像进行检测,返回结果。以下我直接贴出源码,相关注释与图片识别相同。定义好cv2.VideoCapture函数,传入视频路径,并预设好手势列表。
cap = cv2.VideoCapture('GesDet.mp4')
gesture = [0,1,2,3,4,5]
使用while循环去遍历每一帧图像,并使用imshow来展示检测结果。注意这里的static_image_mode参数要设置为False。
with mp_hands.Hands(
static_image_mode = False,
max_num_hands = 2,
model_complexity = 0,
min_detection_confidence = 0.5,
min_tracking_confidence = 0.5
) as hands:
while True:
success ,image = cap.read()
if image is None:
break
image.flags.writeable = False
image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
t0 = time.time()
results =hands.process(image)
results.multi_handedness
包括label和score,label是字符串"Left"或"Right",score是置信度
results.multi_hand_landmarks
results.multi_hand_landmrks:被检测/跟踪的手的集合
其中每只手被表示为21个手部地标的列表,每个地标由x、y和z组成。
x和y分别由图像的宽度和高度归一化为[0.0,1.0]。Z表示地标深度
以手腕深度为原点,值越小,地标离相机越近。
z的大小与x的大小大致相同。
t1 = time.time()
fps = 1 / (t1 - t0)
image.flags.writeable = True
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
dict_handnumber = {}
if results.multi_handedness:
if len(results.multi_handedness) == 2:
for i in range(len(results.multi_handedness)):
label = results.multi_handedness[i].classification[0].label
index = results.multi_handedness[i].classification[0].index
hand_landmarks = results.multi_hand_landmarks[index]
mp_drawing.draw_landmarks(
image,
hand_landmarks,
mp_hands.HAND_CONNECTIONS,
mp_drawing_styles.get_default_hand_landmarks_style(),
mp_drawing_styles.get_default_hand_connections_style())
gesresult = ges(hand_landmarks)
dict_handnumber[label] = gesresult
else:
label = results.multi_handedness[0].classification[0].label
hand_landmarks = results.multi_hand_landmarks[0]
mp_drawing.draw_landmarks(
image,
hand_landmarks,
mp_hands.HAND_CONNECTIONS,
mp_drawing_styles.get_default_hand_landmarks_style(),
mp_drawing_styles.get_default_hand_connections_style())
gesresult = ges(hand_landmarks)
dict_handnumber[label] = gesresult
if len(dict_handnumber) == 2:
leftnumber = dict_handnumber['Right']
rightnumber = dict_handnumber['Left']
显示实时帧率,右手值,左手值,相加值
s = 'FPS:{0}\nRighthand Value:{1}\nLefthand Value:{2}\nAdd is:{3}'.format(int(fps),rightnumber,leftnumber,str(leftnumber+rightnumber))
elif len(dict_handnumber) == 1 :
labelvalue = list(dict_handnumber.keys())[0]
if labelvalue == 'Left':
number = list(dict_handnumber.values())[0]
s = 'FPS:{0}\nRighthand Value:{1}\nLefthand Value:0\nAdd is:{2}'.format(int(fps),number,number)
else:
number = list(dict_handnumber.values())[0]
s = 'FPS:{0}\nLefthand Value:{1}\nRighthand Value:0\nAdd is:{2}'.format(int(fps),number,number)
else:
s = 'FPS:{0}\n'.format(int(fps))
y0,dy = 50,25
image = cv2.flip(image,1)
for i ,txt in enumerate(s.split('\n')):
y = y0 + i*dy
cv2.putText(image,txt,(50,y),cv2.FONT_HERSHEY_SIMPLEX,1,(255,0,0),3)
cv2.imshow('MediaPipe Gesture Recognition',image)
if cv2.waitKey(5) & 0xFF == 27:
break
cap.release()
相机实时检测相比于前面两种,主要是cv2.VideoCapture()中,我们传入的不在是文件路径,而是一个一个的数字,以电脑自带摄像头为例,我们传入参数0。如果有多个相机也可传入相应的相机代号。
cap = cv2.VideoCapture(0)
读取视频或摄像头画面进行识别的过程,与前面读取图片文件相似,通过循环读取画面帧逐个识别手势,并标记在画面中,运行结果如下图所示:
在使用了MediaPipe的手势识别后,我发现难得不是对于手势关键点的检测,MediaPipe的手势识别,在CPU上基本可以达到实时的标准,更难的应该是对手势的判断,对关键点的理解,这里我也观摩了很多其他博主的文章,对于不同方法得到的准确度也不一样,这值得我们更多的去思考。对于手势更准的判断,我们可以将其应用在很多的工程实例中。
打开QtDesigner软件,拖动以下控件至主窗口中,调整界面样式和控件放置,性别识别系统的界面设计如下图所示:
控件界面部分设计好,接下来利用PyUIC工具将.ui文件转化为.py代码文件,通过调用界面部分的代码同时加入对应的逻辑处理代码。博主对其中的UI功能进行了详细测试,最终开发出一版流畅得到清新界面,就是博文演示部分的展示,完整的UI界面、测试图片视频、代码文件,以及Python离线依赖包(方便安装运行,也可自行配置环境),均已打包上传,感兴趣的朋友可以通过下载链接获取。
若您想获得博文中涉及的实现完整全部程序文件(包括测试图片、视频,py, UI文件等,如下图),这里已打包上传至博主的面包多平台和CSDN下载资源,具体可见参考文章和参考视频,已将所有涉及的文件同时打包到里面,点击即可运行,完整文件截图如下:
在文件夹下的资源显示如下,其中包含了Python的离线依赖包,读者可在正确安装Anaconda和Pycharm软件后,点击bat文件进行安装,详细演示也可见参考视频或参考文章。
注意:本资源已经过调试通过,下载后可通过Pycharm运行;运行界面的主程序为runMain.py,测试图片可运行JPGDet.py,测试视频文件可运行VideoDet.py,测试摄像头识别可运行Cameradet.py,为确保程序顺利运行,请配置Python依赖包的版本如下:➷➷➷
Python版本:3.8,请勿使用其他版本,详见requirements.txt文件;
absl-py==1.0.0
attrs==21.4.0
certifi==2021.10.8
cvzone==1.5.6
cycler==0.11.0
fonttools==4.29.1
kiwisolver==1.3.2
matplotlib==3.5.1
mediapipe==0.8.9.1
numpy==1.22.3
opencv-contrib-python==4.5.5.62
opencv-python==4.5.5.64
packaging==21.3
Pillow==9.0.1
protobuf==3.19.4
pyparsing==3.0.7
PyQt5==5.15.6
PyQt5-Qt5==5.15.2
PyQt5-sip==12.9.1
python-dateutil==2.8.2
six==1.16.0
wincertstore==0.2
参考博客文章:https://www.cnblogs.com/sixuwuxian/p/16160843.html
参考视频演示:https://www.bilibili.com/video/BV12a411v7vr/
由于博主能力有限,博文中提及的方法即使经过试验,也难免会有疏漏之处。希望您能热心指出其中的错误,以便下次修改时能以一个更完美更严谨的样子,呈现在大家面前。同时如果有更好的实现方法也请您不吝赐教。
参考资料:
- https://blog.csdn.net/weixin_45930948/article/details/115444916
- https://cloud.tencent.com/developer/article/1492209
- 王如斌,窦全礼,张淇,周诚.基于MediaPipe的手势识别用于挖掘机遥操作控制[J/OL].土木建筑工程信息技术:1-8[2022-03-31].
摘要:本文详细介绍基于深度学习的手势识别系统,在介绍手势识别算法原理的同时,给出了Python的实现代码以及PyQt的UI界面。手势识别采用了改进的SSD算法,进行手掌检测后对手部关节坐标进行关键点定位;在系统界面中可以选择手势图片、视频进行检测识别,也可通过电脑连接的摄像头设备进行实时识别手势;可对图像中存在的多个手势进行姿势识别,可选择任意一个手势显示结果并标注,实时检测速度快、识别精度较高。博文提供了完整的Python代码和使用教程,适合新入门的朋友参考,完整代码资源文件请转至文末的下载链接。
Python:手势识别器 —— 实现手部动作的识别(源代码附带)手势识别是现代计算机视觉领域研究的一个重点,而手势识别器是其中非常重要的一种应用。本文将介绍如何使用Python实现手势识别器,以此来实现手部动作的识别,同时我们将附带完整的源代码供读者参考。在开始之前,我们需要准备好以下环境和库:接下来我们开始编写代码。首先,导入所需的库:import cv2
import numpy as np
import pyautoguicap = cv2.VideoCapture(0)cv2.namedWindow
Python开发OpenCV2机器学习人脸识别系统源码,是基于OpenCV2跨平台计算机视觉和机器学习软件库的人脸检测及人脸识别系统,采用Web应用作为用户和管理的交互页面。系统人脸识别模块的图像处理采用PIL(Python Image Library)。 BPL是python的第三方图像处理库,但是由于其强大的功能与众多的使用人数,几乎已经被认为是python官方图像处理库了。Python开发OpenCV2机器学习人脸识别系统源码,是基于OpenCV2跨平台计算机视觉和机器学习软件库的人脸检测及人脸识别系统,采用Web应用作为用户和管理的交互页面。系统人脸识别模块的图像处理采用PIL(Python Image Library)。 BPL是python的第三方图像处理库,但是由于其强大的功能与众多的使用人数,几乎已经被认为是python官方图像处理库了。Python开发OpenCV2机器学习人脸识别系统源码,是基于OpenCV2跨平台计算机视觉和机器学习软件库的人脸检测及人脸识别系统,采用Web应用作为用户和管理的交互页面。系统人脸识别模块的图像处理采用PIL。。。。。
人脸识别不同于人脸检测。在人脸检测中,我们只检测了人脸的位置,在人脸识别任务中,我们识别了人的身份。
本文重点介绍使用库 face_recognition 实现人脸识别,该库基于深度学习技术,并承诺使用单个训练图像的准确率超过 96%。
识别系统用例
寻找失踪者
识别社交媒体上的帐户
识别汽车中的驾驶员
考勤系统
了解人脸识别的工作原理
我们将人的照片和他们的名字传递给模型。
该模型拍摄每张照片,将它们转换为某种数字编码,并将它们存储在一个列表中,并将所有标签(人名)存储在另一个列表中。
让学生了解数字图像处理在人工智能方面的应用。通过一个人脸识别系统的开发,提高学生综合运用面向对象程序设计思想、数字图像处理等专业知识和技术的能力;通过了解人脸识别系统开发方法与步骤,为以后从事图像分析与图像理解等人工智能方面的相关工作奠定基础。
一、项目介绍
1. 技术介绍
cv2: 在本项目中主要用于:
a. 图像的读取
b. 图像大小的改变
c. 人脸的检测(非识别,检测的目的在
此代码资源包为本人在 CSDN 上分享的博文:基于深度学习的中文车牌识别与管理系统(含UI界面,Python代码),网址:https://blog.csdn.net/qq_32892383/article/details/123088309中分享的完整代码和资源整合。
功能:在界面中既可以选择需要识别的车牌视频、图片文件、批量图片进行检测识别,也可以通过电脑自带的摄像头进行实时检测、识别、管理车牌,通过车牌记录查看历史识别的车牌。给出Python的实现代码以及PyQt的UI界面,系统界面清新美观,文中包含完整的代码文件及测试图片、视频,开箱即用,适合新手朋友学习参考。
资源包含文件:lunwen文档+任务书+开题报告+文献综述+外文翻译+软件使用说明书+源码及数据集
流程分为两个部分,一是文本检测,二是文本识别。
文字检测的主要功能为:从图像中找到文字区域,并将文字区域从原始图像中分离出来。
文字识别的主要功能为:从分离出来的图像上,进行文字识别。
文字识别流程:
1)预处理:去噪(滤波算法)、图像增强、缩放,其目的是去除背景或者噪点,突出文字部分,并缩放图片为适于处理的大小
2)特征抽取:常用特征:边缘特征、笔画特征、结构特征、纹理特征。
3)识别:分类器,随机森林 、SVM、NN、CNN等神经网络。
本次设计的环境如下
操作系统 ubantu 16.04
Tensorflow tensorflow1.3.0-gpu
Python python2.7
CPU Intel(R) Xeon(R) CPU E5-2650 v4 @ 2.20GHz
GPU TITAN X (Pascal)
详细介绍参考:https://biyezuopin.blog.csdn.net/article/details/125342848
基于深度学习opencv的python车牌识别系统是一种先进的计算机视觉技术,可以实现车牌的自动识别和识别结果的输出。整个系统主要分为图像预处理、车牌检测、字符分割、字符识别和结果输出等五个部分。
系统的第一个部分是图像预处理,该部分的主要任务是对输入的待识别车牌图像进行预处理,通过图像增强的方式使图像在后续的处理中更加容易被区分出来。
接下来的车牌检测部分,就是通过深度学习模型对预处理后的图像进行分析,检测出车牌区域并进行标记。
然后就是字符分割,该部分通过对车牌图像进行切割,从中识别出车牌上的每一个字符。
最后是字符识别部分,该部分主要通过深度学习模型对切割出来的字符进行识别。
最终,车牌识别系统将输出识别结果,并将结果进行存储或展示给用户。
总之,基于深度学习opencv的python车牌识别系统是在开发自动化车牌识别系统方面,极具实用性和广泛应用前景的计算机视觉技术。