系列文章目录
通过Qt实现手势识别控制软件操作相关系列技术方案
(一)Qt 将某控件、图案绘制在最前面的方法,通过QGraphicsScene模块实现
(二)Qt QGraphicsScene模块实现圆点绘制在所有窗体的最前方,实现圆点的“彩色拖尾”效果以及“选中方框”效果
(三)Qt 动态手势识别“握拳”
文章目录
- 系列文章目录
- 1、前言
- 1.1 目标
- 1.2 静态手势识别
- 1.2.1 定义
- 1.2.2 难点
- 1.2.3 现有算法、框架
- 1.3 动态手势识别
- 1.3.1 定义
- 1.3.2 难点
- 2、效果
- 2、代码实现
- 2.1 思路
- 2.2 核心代码
- 总结
1、前言
1.1 目标
本篇博客主要记录了在Qt平台实现动态手势“握拳”的识别过程。
首先要明确所谓动态手势识别的含义,动态手势识别是区别于静态手势识别而言的。
1.2 静态手势识别
1.2.1 定义
“静态手势识别”,就是算法的输入只有“一帧图像”,输出则是关于此图像中的手的各种状态、信息等,即检测、识别出单帧图像上的人手,此状态可能包含了如下信息内容:
(1)手部形状的最小外接矩形框,该框四顶点在图像中的像素坐标值;
(2)手部形状的分割区域,该区域按像素点划分后的像素点坐标集合;
(3)手部按关节划分后,各个关节点的图像像素点坐标值;
根据上述输出的信息内容,根据某些经验定义,从而确定某个手势的具体含义如:
(1)根据手部各关节点的相对位置坐标、关节角度等,可以确定一些常用的手势,比如说,食指伸出,指向上方,其余手指握拳,这种手势可以判定为“数字1”,再比如说,五根手指全部伸出两两手指保持一定夹角,这种手势可以判定为“数字5”等等;
(2)根据手部所在输入图像上的具体像素点位置,确定此时手所位于的区域,从而确定其表示的含义,比如,在交通指挥时,交警的手位于左边还是右边决定了正向行驶过来的车辆是能够向左转还是向右转(此处只是打比方)。
1.2.2 难点
(1)样本数据量,现有的静态手势识别几乎均通过神经网络算法,需要大量手部样本,要经过清理、标注等环节,对样本外的手的图像适应性不一定很准确;
(2)环境因素,诸如光照、背景、遮挡等因素,造成图像质量差,从而识别效果不好;
1.2.3 现有算法、框架
现有的手势识别框架主要有OpenPose、Mediapipe、DeepLabCut、Detraction等(这里只列举了本人比较熟悉的几种),有些用python调用可能比较快,有的可能C++接口都没有开放。
可以考虑使用上述框架的python脚本先获取手部数据,然后通过网络通信的方式与Qt端软件进行通信。
1.3 动态手势识别
1.3.1 定义
“动态手势识别”,本质与“静态手势识别”有一定的区别,“静态手势识别”仅考虑“一帧图像”,“动态手势识别需要考虑,在某一连续的时间段内的多帧静态手势,动态手势识别的算法输入为“一段事件内的连续多帧图像”。动态手势识别分类、判定时应具体考虑以下因素:
(1)各帧图像“静态手势”的单独识别结果;
(2)按时间前后顺序,各帧图像“静态手势”识别结果之间的关联;
(3)在时间、空间双重维度下,手势的具体信息,如“速度”
、“加速度”等;
1.3.2 难点
在实际应用中,往往是通过传感器(如摄像头,TOF,雷达等),实时拍摄手部的画面,这就牵扯到如何判断一个手势的开始与结束了。其实这种问题,在语音识别中也会遇到,即“如何判断一段语音需要去做语音识别”,而不是每时每刻都在让计算机不停地做识别不同的语句,仅仅在有需要时做识别,现在常用的方法就是在语音的开始处加“唤醒语句”,即在设备待机状态时,仅需要侦测特定的语句即可,当侦测到特定语句后,进入整正的语音识别算法中去。
现在大部分的语音识别大厂,如苹果的“Siri”、小米的“小爱同学”、百度的“小度”、比亚迪汽车等均是这样做的,先设定一个“唤醒语句”,当触发了该唤醒语句后再进行相应的操作。
在手势识别时,也可以通过类似上述操作的方式进行“唤醒”,可以设置某一特定的静态手势作为唤醒手势,在检测到该手势后,进入“动态手势监测程序”,从而避免在平常状态(未进行手势识别)时误触发动态手势识别程序,造成误识别等。
同样,判断手势的结束,类比于语音识别的结束,当检测不到说话人的语音输入一段时间后,则被程序可认为结束。手势识别的是否结束,可通过前后帧图像差来进行判断,当前后帧图像差别小于一定阈值累计达到一定帧数后,可判断动态手势的结束。
上面所说这种类似语音的“唤醒”功能的方式判断手势的启动方式,在某些具体环境下可能不行,即不能指定“唤醒”启动方式时,当某场景需要你直接动作,不能有“唤醒”阶段时,又不能这样干。具体实现可通过判断这段动态手势中,各静态手势出现的相对时间、相对帧数,以及每帧之间的位置、顺序关系。
2、效果
为了便于观察手势识别结果以及原始手势图像,我分别打开两个Widget窗口,左边的窗口用于显示识别结果,每当检测到一次“握拳”动作,左边Widget窗口的底色将会改变一次,同时其正中的数字(代表已经识别出“握拳”的次数)增加1。
先看演示效果视频:
动态手势识别-握拳(视角2)
效果演示动态图
2、代码实现
2.1 思路
要检测出“握拳”动作,可以将握拳的动态过程静态化,可以观察下图,为握拳动作的静态分解图。
“握拳”的动态手势其实能够分解为:先开始有一段“连续的手掌形状”,紧接着有一段“连续的握拳形状”,再紧接着一段“连续的手掌形状”,只要在动态手势序列中检测出有类似上述存储规则的动态手势,则可判定为“握拳”动作。
2.2 核心代码
QString HandPostureDetect::dynamic_gesture_recognize(const QQueue<QString>& gestureQueue)
{
int state = 0;
int countFive1 = 0;
int countFist = 0;
int countFive2 = 0;
for (const QString& gesture : gestureQueue)
{
if (state == 0)
{
if (gesture == "five")
{
countFive1++;
if (countFive1 >= 5)
{
state = 1;
countFive1 = 0;
}
}
else
{
countFive1 = 0;
}
}
else if (state == 1)
{
if (gesture == "fist")
{
countFist++;
if (countFist >= 5)
{
state = 2;
countFist = 0;
}
}
else
{
countFist = 0;
}
}
else if (state == 2)
{
if (gesture == "five")
{
countFive2++;
if (countFive2 >= 5)
{
if(pre_condition == 0)
{
qDebug()<<"select_"<<count;
count++;
pre_condition = 1;
emit send_result(pre_condition);
return "select";
}
if(pre_condition == 1)
{
return "";
}
}
}
else
{
countFive2 = 0;
}
}
}
if(pre_condition == 1)
{
pre_condition = 0;
}
emit send_result(pre_condition);
return "";
}
本项目所有代码的获取,请私信与本人联系。
总结
本系列文章,通过动、静态手势识别技术方式操控Qt界面软件实现相关操作功能:
(一)Qt 将某控件、图案绘制在最前面的方法,通过QGraphicsScene模块实现
(二)Qt QGraphicsScene模块实现圆点绘制在所有窗体的最前方,实现圆点的“彩色拖尾”效果以及“选中方框”效果
本项目所有代码的获取,请私信与本人联系。