(三)Qt 动态手势识别“握拳”

2023-10-18 23:10
文章标签 动态 qt 识别 手势 握拳

本文主要是介绍(三)Qt 动态手势识别“握拳”,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

系列文章目录

通过Qt实现手势识别控制软件操作相关系列技术方案

(一)Qt 将某控件、图案绘制在最前面的方法,通过QGraphicsScene模块实现
(二)Qt QGraphicsScene模块实现圆点绘制在所有窗体的最前方,实现圆点的“彩色拖尾”效果以及“选中方框”效果
(三)Qt 动态手势识别“握拳”
(四)Qt 动态手势识别“手掌随动”+“握拳选择”
(五)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。

  先看演示效果视频:

动态手势识别-握拳(视角1)

动态手势识别-握拳(视角2)

效果演示动态图

请添加图片描述
请添加图片描述

图1 “握拳”动态手势识别效果示意图

2、代码实现

2.1 思路

  要检测出“握拳”动作,可以将握拳的动态过程静态化,可以观察下图,为握拳动作的静态分解图。
在这里插入图片描述

图2 “握拳”动态手势的静态分解示意图

  “握拳”的动态手势其实能够分解为:先开始有一段“连续的手掌形状”,紧接着有一段“连续的握拳形状”,再紧接着一段“连续的手掌形状”,只要在动态手势序列中检测出有类似上述存储规则的动态手势,则可判定为“握拳”动作。

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模块实现圆点绘制在所有窗体的最前方,实现圆点的“彩色拖尾”效果以及“选中方框”效果
(三)Qt 动态手势识别“握拳”
(四)Qt 动态手势识别“手掌随动”+“握拳选择”
(五)Qt 动态手势识别“左右滑动”以及实现翻页效果

  本项目所有代码的获取,请私信与本人联系。

这篇关于(三)Qt 动态手势识别“握拳”的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/235703

相关文章

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

C#如何动态创建Label,及动态label事件

《C#如何动态创建Label,及动态label事件》:本文主要介绍C#如何动态创建Label,及动态label事件,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#如何动态创建Label,及动态label事件第一点:switch中的生成我们的label事件接着,

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

使用PyTorch实现手写数字识别功能

《使用PyTorch实现手写数字识别功能》在人工智能的世界里,计算机视觉是最具魅力的领域之一,通过PyTorch这一强大的深度学习框架,我们将在经典的MNIST数据集上,见证一个神经网络从零开始学会识... 目录当计算机学会“看”数字搭建开发环境MNIST数据集解析1. 认识手写数字数据库2. 数据预处理的

Pytorch微调BERT实现命名实体识别

《Pytorch微调BERT实现命名实体识别》命名实体识别(NER)是自然语言处理(NLP)中的一项关键任务,它涉及识别和分类文本中的关键实体,BERT是一种强大的语言表示模型,在各种NLP任务中显著... 目录环境准备加载预训练BERT模型准备数据集标记与对齐微调 BERT最后总结环境准备在继续之前,确

Qt 中 isHidden 和 isVisible 的区别与使用小结

《Qt中isHidden和isVisible的区别与使用小结》Qt中的isHidden()和isVisible()方法都用于查询组件显示或隐藏状态,然而,它们有很大的区别,了解它们对于正确操... 目录1. 基础概念2. 区别清见3. 实际案例4. 注意事项5. 总结1. 基础概念Qt 中的 isHidd

mybatis-plus 实现查询表名动态修改的示例代码

《mybatis-plus实现查询表名动态修改的示例代码》通过MyBatis-Plus实现表名的动态替换,根据配置或入参选择不同的表,本文主要介绍了mybatis-plus实现查询表名动态修改的示... 目录实现数据库初始化依赖包配置读取类设置 myBATis-plus 插件测试通过 mybatis-plu

QT移植到RK3568开发板的方法步骤

《QT移植到RK3568开发板的方法步骤》本文主要介绍了QT移植到RK3568开发板的方法步骤,文中通过图文示例介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录前言一、获取SDK1. 安装依赖2. 获取SDK资源包3. SDK工程目录介绍4. 获取补丁包二

Qt把文件夹从A移动到B的实现示例

《Qt把文件夹从A移动到B的实现示例》本文主要介绍了Qt把文件夹从A移动到B的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录如何移动一个文件? 如何移动文件夹(包含里面的全部内容):如何删除文件夹:QT 文件复制,移动(