YOLOv5手势物体识别(附代码)

之前是做的yolov3手势物体识别,最近几天我将该项目进行了重新的整理和升级,实现了yolov5手势物体识别,同时为了方便更多的人直接拿来应用,我生成了支持windows系统的应用小程序,即便你电脑上没有安装pytorch,没有安装cuda、python,都可以使用~!


相关资料:

yolov3手势物体识别


应用程序效果如下:

yolov5手势物体识别


技术说明

本项目使用了三个算法模型进行的功能实现。yolov5做手部目标检测,ReXNet(支持Resnet系列)做手部21关键点回归检测,Resnet50做物体分类识别。(其实就是三个算法做的级联)

yolov5手部目标检测

使用yolov5s进行训练,数据集共有3W+,因本地训练环境受限,我只训练到mAP 64%左右,因此准确率并不是很高,大家有需要的可以自行再去训练~

数据集说明

数据集链接:

(ps:这里的数据集采用的公共数据集,没有做过数据清洗)

链接:https://pan.baidu.com/s/1jnXH3yBuGJ8_DRXu-gKtNg 
提取码:yypn 

数据集格式:

images:存放所有的数据集

labels:已经归一化后的label信息

train.txt:训练集划分,25934张

val.txt:验证集划分,3241张

test.txt:测试集划分,3242张图

训练实验记录

采用马赛克数据增强,如下图:

 评价指标:

(我这里只训练了大该十多个epoch,没服务器训练太慢了~(T^T)~,所以准确率比较低,有需要的可以自己训练一下)

PRmAP 0.5mAP 0.5:0.95
0.753960.590750.646710.27652

手部21关键点检测

手部关键点识别采用的网络为ReXNet(支持Resnet系列),这里需要说明的是关键点预测并没有采用openpose网络!而是采用的坐标回归方法,这个问题需要强调一下,不然总有小伙伴问我,而且还很质疑~ 在本任务中,由于有yolo作为前置滤波器算法将手部和背景进行分离,分离后的图像前景和背景相对平衡,而且前景(手部)占主要部分,因此任务其实相对简单,可以采用坐标回归方法。

网络的定义在yolov5_hand_pose/components/hand_keypoints/models/。

21个关键点,那就是有42个坐标(x,y坐标)。因此代码中num_classes=42,代码:

class handpose_x_model(object):def __init__(self,model_path = '',img_size= 256,num_classes = 42,# 手部关键点个数 * 2 : 21*2model_arch = "rexnetv1"):

再看下网络最终的输出:

这里输出的通道数为num_classes!所以和openpose是有一定区别的!这里必须要说明一下,不然老有人不信哈哈~

    features.append(nn.AdaptiveAvgPool2d(1))self.features = nn.Sequential(*features)self.output = nn.Sequential(nn.Dropout(dropout_factor),nn.Conv2d(pen_channels, num_classes, 1, bias=True))def forward(self, x):x = self.features(x)x = self.output(x).squeeze()return x

言归正传,21关键点识别效果如下,首先是通过yolov5提取手部box信息,再把手分离出来,将手部图像resize为256x256大小,用关键点网络进行关键点回归。

 

训练

训练代码在train.py中。

可采用提供的预权重进行fine tune训练。

输入以下命令开始训练:

python train.py --model resnet_50 --train_path [数据集路径] --fintune_model 【fine tune模型路径】--batch_size 16

 如果是fine tune训练,建议初始学习率(init_lr)设置为5e-4,否则建议设置为1e-3。

损失函数此次采用的是MSE,还可支持wing loss。

训练好的权重会保存在model_exp中,对应的tensorboard会存储在logs中


分类网络

这里的分类网络采用是resnet50网络,权重为ImageNet数据集上的(1000个类),可以根据自己任务需求去训练。

网络定义在yolov5_hand_pose/components/classify_imagenet/models。

那具体是如何分类的呢?

首先触发分类模型的手势是食指和大拇指捏合。主要是计算两个关键点的欧式距离,当距离小于阈值则为触发状态click_state=True

            # 计算食指大拇指的距离dst = np.sqrt(np.square(thumb_[0]-index_[0]) +np.square(thumb_[1]-index_[1]))# 计算大拇指和手指相对手掌根部的角度:angle_ = vector_2d_angle((thumb_[0]-hand_root_[0],thumb_[1]-hand_root_[1]),(index_[0]-hand_root_[0],index_[1]-hand_root_[1]))# 判断手的点击click状态,即大拇指和食指是否捏合click_state = Falseif dst<dst_thr and angle_<angle_thr: # 食指和大拇指的坐标欧氏距离,以及相对手掌根部的相对角度,两个约束关系判断是否点击click_state = True

那么又有个问题了,总不能我两个手指一捏合就触发,这带来了很大的误触,这里解决的方法是判断触发状态(可以理解为时间长短)。代码如下:

'''判断各手的click状态是否稳定(点击稳定充电环),即click是否持续一定阈值注意:charge_cycle_step 充电步长越大,触发时间越短
'''
def judge_click_stabel(img,handpose_list,charge_cycle_step = 32):flag_click_stable = Truefor i in range(len(handpose_list)):_,_,_,dict_ = handpose_list[i]id_ = dict_["id"]click_cnt_ = dict_["click_cnt"]pt_ = dict_["choose_pt"]if click_cnt_ > 0:# print("double_en_pts --->>> id : {}, click_cnt : <{}> , pt : {}".format(id_,click_cnt_,pt_))# 绘制稳定充电环# 充电环时间控制charge_cycle_step = charge_cycle_step # 充电步长越大,触发时间越短fill_cnt = int(click_cnt_*charge_cycle_step)if fill_cnt < 360:cv2.ellipse(img,pt_,(16,16),0,0,fill_cnt,(255,255,0),2)else:cv2.ellipse(img,pt_,(16,16),0,0,fill_cnt,(0,150,255),4)# 充电环未充满,置为 Falseif fill_cnt<360:flag_click_stable = Falseelse:flag_click_stable = Falsereturn flag_click_stable

当两个手都触发捏合动作,那么判断是有效动作,同时将左右手选定的区域截出来(和yolo的操作类似),送入分类网络进行分类识别。


语音播报

当手势动作触发成功后会触发语音播报函数,此时会自动语音播放"正在识别物体请等待",如果成功识别,并且也有该物体的语音包(需要自己录制),那么会说“您识别的物体为。。。”

语音播报函数:

'''启动识别语音进程  该项目中主要用到下面的自定义函数
'''
def audio_process_recognize_up_edge(info_dict):while (info_dict["handpose_procss_ready"] == False): # 等待 模型加载time.sleep(2)gesture_names = ["double_en_pts"] # 姿态列表,gesture_dict = {}for k_ in gesture_names:#k_= double_en_ptsgesture_dict[k_] = None #gesture_dict[double_en_pts]=Nonewhile True:time.sleep(0.01)# print(" --->>> audio_process")try:for g_ in gesture_names:  # 输出 double_en_pts ,因为gesture_name列表内容为str,所以g_也是str,输出的g_=double_en_ptsif gesture_dict[g_] is None:  # gesture_dict[double_en_pts] 为真gesture_dict[g_] = info_dict[g_]  #info_dict[g_]为Falseelse:if ("double_en_pts"==g_):if (info_dict[g_]^gesture_dict[g_]) and info_dict[g_]==True:# 判断Click手势信号为上升沿,Click动作开始playsound("./materials/audio/sentences/IdentifyingObjectsWait.mp3")playsound("./materials/audio/sentences/ObjectMayBeIdentified.mp3")if info_dict["reco_msg"] is not None:print("process - (audio_process_recognize_up_edge) reco_msg : {} ".format(info_dict["reco_msg"]))doc_name = info_dict["reco_msg"]["label_msg"]["doc_name"]reco_audio_file = "./materials/audio/imagenet_2012/{}.mp3".format(doc_name)if os.access(reco_audio_file,os.F_OK):# 判断语音文件是否存在playsound(reco_audio_file)info_dict["reco_msg"] = Nonegesture_dict[g_] = info_dict[g_]except Exception as inst:print(type(inst),inst)    # exception instanceif info_dict["break"] == True:break

整个项目,也就是三个算法、语音播报等是采用多进程显现的,四个功能之间的通信是利用的共享字典进行的数据共享。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/6329.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

4 Spring AOP

目录 AOP 简介 传统开发模式 先来看一个需求 解决方案 AOP 图示 Spring 启用 AspectJ 基于 xml 配置 创建 pom.xml 创建 UserService 借口和 UserServiceImpl实现类 创建 LogAdvice 日志通知 创建 log4j.properties 重点&#xff1a;创建 spring-context-xml.xml 配…

MYSQL从入门到精通(二)

1、MYSQL高级概述 【1】架构概述 【2】索引优化 【3】查询截取 【4】mysql锁机制 【5】主从复制 2、MYSQL概述 【1】mysql内核 【2】sql优化工程师 【3】mysql服务器的优化 【4】各种参数常量设定 【5】查询语句优化 【6】主从复制 【7】软硬件升级 【8】容灾百分 【9】sql编…

使用Neo4j和Langchain创建知识图谱

使用Neo4j和Langchain创建知识图谱 知识图谱是组织和整合信息的强大工具。通过使用实体作为节点和关系作为边缘&#xff0c;它们提供了一种系统的知识表示方法。这种有条理的表示有利于简化查询、分析和推理&#xff0c;使知识图在搜索引擎、推荐系统、自然语言处理和人工智能…

从0开始学习制作一个微信小程序 学习部分(6)组件与事件绑定

系列文章目录 学习篇第一篇我们讲了编译器下载&#xff0c;项目、环境建立、文件说明与简单操作&#xff1a;第一篇链接 第二、三篇分析了几个重要的配置json文件&#xff0c;是用于对小程序进行的切换页面、改变图标、控制是否能被搜索到等的操作第二篇链接、第三篇链接 第四…

Windows设置Redis为开机自启动

前言 Redis作为当前最常用的当前缓存技术&#xff0c;基本上Web应用中都有使用。所以&#xff0c;每次我们在本地启动项目前&#xff0c;都必须将Redis服务端启动&#xff0c;否则项目就会启动失败。但是&#xff0c;每次都要去启动Redis就很麻烦&#xff0c;有没有办法做到开…

Python爬虫--爬取糗事百科段子

爬取糗事百科段子&#xff1a; 段子在 <div class"content"> 里面的 <span> 标签里面 不过这里有个坑&#xff0c;div 标签跟 span 标签 之间有很多空行 普通 .*? 是匹配不了的&#xff0c;需要使用模式修饰符 S S 的意思 让 .(点) 匹配&#xff0c…

吴恩达2022机器学习专项课程(一)正则化(正则化成本函数正则化线性回归正则化逻辑回归)

目录 一.正则化1.1 正则化的好处1.2 正则化的实现方式 二.正则化改进线性回归的成本函数2.1 正则化后的成本函数的意义2.2 λ参数的作用2.3 不同λ对算法的影响2.4 为什么参数b没有正则化项 三.正则化线性回归的梯度下降3.1 为什么正则化可以在梯度下降迭代中减小w3.2 导数的计…

机器学习笔记-18

异常检测问题 异常检测虽然主要用于无监督学习问题上&#xff0c;但是和监督学习问题很相似。 异常检测(Anomaly Detection)&#xff1a;给定正确样本集{ x ( 1 ) , x ( 2 ) . . . x ( n ) x^{(1)},x^{(2)}...x^{(n)} x(1),x(2)...x(n)}&#xff0c;记新样本即要检测的样本为…

eNSP-抓包解析HTTP、FTP、DNS协议

一、环境搭建 1.http服务器搭建 2.FTP服务器搭建 3.DNS服务器搭建 二、抓包 三、http协议 1.HTTP协议&#xff0c;建立在FTP协议之上 2.http请求 3.http响应 请求响应报文参考&#xff1a;https://it-chengzi.blog.csdn.net/article/details/113809803 4.浏览器开发者工具抓包…

002-ChatGLM4接入Langchain

智谱AI GLM-4 新一代基座大模型GLM-4,整体性能相比GLM3全面提升60%,逼近GPT-4;支持更长上下文;更强的多模态;支持更快推理速度,更多并发,大大降低推理成本;同时GLM-4增强了智能体能力。 基础能力(英文):GLM-4 在 MMLU、GSM8K、MATH、BBH、HellaSwag、HumanEval等…

ubuntu搭建jupyter_notebook服务器

环境&#xff1a;ubuntu 22.04 目录 环境&#xff1a;ubuntu 22.04 一、创建一个anaconda用户 创建用户condaUser 为用户condaUser设置密码 开放opt文件夹的权限 登录condaUser用户 二、安装anaconda 下载anaconda 安装anaconda 三、添加环境变量 四、anaconda换源 …

【Unity Shader入门精要 第4章】数学基础(二)

1. Unity中的坐标空间 1.1 五个坐标空间 模型空间 模型自身的3D坐标系空间&#xff0c;左手坐标系是一个相对空间&#xff0c;坐标轴指向随模型旋转变化当物体有父节点时&#xff0c;Transform组件中各属性的值表示的即为该物体在其父物体的模型空间中的值当模型顶点传入顶点…

ARP防火墙能够为网络安全贡献什么样的力量

ARP防火墙&#xff08;Address Resolution Protocol Firewall&#xff09;作为网络安全的一环&#xff0c;起到保护网络免受ARP欺骗攻击的关键作用。今天德迅云安全给您介绍ARP防火墙的相关方面&#xff0c;帮助您深入了解和认识这一关键的安全措施。 网络安全对于现代社会的信…

「 网络安全常用术语解读 」SBOM主流格式CycloneDX详解

CycloneDX是软件供应链的现代标准。CycloneDX物料清单&#xff08;BOM&#xff09;可以表示软件、硬件、服务和其他类型资产的全栈库存。该规范由OWASP基金会发起并领导&#xff0c;由Ecma International标准化&#xff0c;并得到全球信息安全界的支持&#xff0c;如今CycloneD…

Java——认识异常

目录 一.异常的概念与体系结构 1.异常的概念 1.1算术异常 1.2数组越界异常 1.3空指针异常 2.异常的体系结构 3.异常的分类 3.1编译时异常 3.2运行时异常 二.异常的处理 1.防御式编程 1.1LBYL 1.2EAFP&#xff08;核心&#xff09; 2.异常的抛出 3.异常的捕获 3…

使用 ORPO 微调 Llama 3

原文地址&#xff1a;https://towardsdatascience.com/fine-tune-llama-3-with-orpo-56cfab2f9ada 更便宜、更快的统一微调技术 2024 年 4 月 19 日 ORPO 是一种新的令人兴奋的微调技术&#xff0c;它将传统的监督微调和偏好校准阶段合并为一个过程。这减少了训练所需的计算…

【深度学习】第二门课 改善深层神经网络 Week 2 3 优化算法、超参数调试和BN及其框架

&#x1f680;Write In Front&#x1f680; &#x1f4dd;个人主页&#xff1a;令夏二十三 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f4e3;系列专栏&#xff1a;深度学习 &#x1f4ac;总结&#xff1a;希望你看完之后&#xff0c;能对…

python实现验证码-图片类型

1 utils.py import randomdef get_random_code():code for i in range(5):# 随机生成大写字母upper_char chr(random.randint(65, 90))lower_char chr(random.randint(97, 122))num_char str(random.randint(0, 9))res random.choice([upper_char, lower_char, num_char]…

软件应用开发安全设计指南

1.1 应用系统架构安全设计要求 设计时要充分考虑到系统架构的稳固性、可维护性和可扩展性&#xff0c;以确保系统在面对各种安全威胁时能够稳定运行。 在设计系统架构时&#xff0c;要充分考虑各种安全威胁&#xff0c;如DDoS攻击、SQL注入、跨站脚本攻击&#xff08;XSS&…

如何使用 Node.js 开发一个文件上传功能?

在 Node.js 中实现文件上传功能可以通过多种方式完成&#xff0c;但其中最常用的方法之一是使用 Express 框架和 Multer 中间件。Express 是一个流行的 Node.js Web 框架&#xff0c;而 Multer 是一个用于处理文件上传的中间件。 步骤 1: 准备工作 首先&#xff0c;确保你已经…