深度学习落地实战:手势识别

 前言

大家好,我是机长

本专栏将持续收集整理市场上深度学习的相关项目,旨在为准备从事深度学习工作或相关科研活动的伙伴,储备、提升更多的实际开发经验,每个项目实例都可作为实际开发项目写入简历,且都附带完整的代码与数据集。可通过百度云盘进行获取,实现开箱即用

正在跟新中~

项目背景

(基于CNN实现手势识别)

在5G时代,随着网络速度的大幅提升和低延迟特性的普及,手势识别技术迎来了前所未有的发展机遇,特别是在视频直播、智能家居和智能驾驶等领域。这些应用场景都极大地依赖于用户与设备之间的高效、直观交互,而手势识别正是实现这一目标的关键技术之一。

项目环境

  • 平台:windows 10
  • 语言环境:python 3.8
  • 编辑器:PyCharm
  • PyThorch版本:1.8

1.创建并跳转到虚拟环境

python -m venv myenvmyenv\Scripts\activate.bat

2. 虚拟环境pip命令安装其他工具包

pip install torch torchvision torchaudio

注:此处只示范安装pytorch,其他工具包安装类似,可通过运行代码查看所确实包提示进行安装

3.pycharm 运行环境配置

进入pytcharm =》点击file =》点击settings=》点击Project:...=》点击 Python Interpreter,进入如下界面

点击add =》点击Existing environment  =》 点击 ... =》选择第一步1创建虚拟环境目录myenv\Scripts\下的python.exe文件点击ok完成环境配置

数据集介绍

       

                                                     训练数据样式                       

数据集是一个包含手势识别信息的综合数据集,具体特点如下:

参与者数量:数据集由14个不同的个体(或“受试者”)组成,每个人都在数据集中贡献了他们的手势数据。

手势种类:每个参与者执行了10种不同的手势,这些手势可能代表了特定的命令、符号或动作,具体取决于数据集的设计目的。

数据重复性:为了增加数据集的多样性和鲁棒性,每种手势都被每个参与者重复了10次。这意味着对于每个手势,数据集都包含了来自每个参与者的10个样本。

总数据量:综合以上信息,数据集总共包含了14(人)x 10(手势种类)x 10(重复次数)= 1400个手势样本。

数据来源:

Kinect数据:这些数据通过Microsoft Kinect传感器获取,可能包括深度图像、彩色图像、骨骼跟踪数据等。Kinect的校准参数也被提供,这对于确保数据的准确性和一致性至关重要。

Leap Motion数据:Leap Motion是一种小型的手部追踪设备,能够提供高精度的手部姿势和手指运动数据。Leap SDK(软件开发工具包)提供的所有相关参数都被包含在内,这些参数可能包括手掌位置、手指关节角度、指尖位置等。

训练数据获取:

私信博主获取

LeNet网络介绍

        LeNet网络,由Yann LeCun及其团队在1990年代初期设计并优化,是卷积神经网络(CNN)领域的先驱之作。其最为人熟知的版本是LeNet-5,该网络在1998年被正式提出,主要用于手写数字识别,尤其是MINIST数据集上的表现尤为出色。

LeNet-5的结构相对简洁而高效,包括两个卷积层(C1、C3)、两个池化层(S2、S4)、两个全连接层(F6、OUTPUT)以及输入层和输出层。卷积层通过卷积核自动提取图像中的特征,池化层则通过下采样减少数据的空间尺寸,同时保留重要信息。全连接层则将提取的特征映射到最终的分类结果上。

LeNet网络的核心优势在于其自动提取特征的能力,这大大减少了传统图像识别方法中对手动设计特征的依赖。此外,其结构简单、计算量相对较小,使得在当时的硬件条件下也能实现较快的训练和推理速度。

然而,受限于当时的硬件条件和计算资源,LeNet网络的规模相对较小,难以处理更大规模或更复杂的图像识别任务。随着计算机硬件和深度学习技术的飞速发展,更加深层、更加复杂的卷积神经网络被设计出来,如AlexNet、VGG、ResNet等,它们在图像识别、分类、检测等领域取得了更加卓越的性能。

尽管如此,LeNet网络作为卷积神经网络的开山之作,其设计思想和基本结构仍然对后来的研究产生了深远的影响。它证明了卷积神经网络在图像识别领域的巨大潜力,并为后续的研究提供了宝贵的经验和启示。在今天,LeNet网络仍然被广泛应用于教学和科研领域,作为学习深度学习和卷积神经网络的基础模型之一。

定义CNN网络

  • 卷积层:用于图像的高级特征
  • 输出层:将卷积提取出的特征进行分类
class LeNet5(nn.Module):def __init__(self,num_class=10):super(LeNet5,self).__init__()self.conv1 = nn.Conv2d(3, 8, 5)self.pool1 = nn.AvgPool2d((2, 2))self.conv2 = nn.Conv2d(8, 16, 5)self.pool2 = nn.AvgPool2d((2, 2))self.conv3 = nn.Conv2d(16, 32, 5)self.relu = nn.ReLU()self.fc1 = nn.Linear(28800, 1024)self.fc2 = nn.Linear(1024, num_class)def forward(self, x):# x: torch.Size([32, 3, 150, 150])x = self.conv1(x) # torch.Size([32, 8, 146, 146])x = self.relu(x)x = self.pool1(x) # torch.Size([32, 8, 73, 73])x = self.conv2(x) # torch.Size([32, 16, 69, 69])x = self.relu(x)x = self.pool2(x) # torch.Size([32, 16, 34, 34])x = self.conv3(x) # torch.Size([32, 32, 30, 30])x = self.relu(x)x = x.flatten(start_dim=1) # torch.Size([32, 28800])x = self.fc1(x) # torch.Size([32, 2024])x = self.relu(x)x = self.fc2(x) # torch.Size([32, 4])return x

加载数据集

# 1.数据转换
data_transform = {# 训练中的数据增强和归一化'train': transforms.Compose([transforms.RandomResizedCrop(150), # 随机裁剪transforms.ToTensor(), # 均值方差归一化transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])
}# 2.形成训练集
train_dataset = datasets.ImageFolder(root=os.path.join(image_path),transform=data_transform['train'])# 3.形成迭代器
train_loader = torch.utils.data.DataLoader(train_dataset,batch_size,True)print('using {} images for training.'.format(len(train_dataset)))

测试代码

# 加载索引与标签映射字典
with open('class_dict.pk', 'rb') as f:class_dict = pickle.load(f)# 数据变换
data_transform = transforms.Compose([transforms.CenterCrop(150),transforms.ToTensor(),transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])# 图片路径
img_path = r'./data/000-one/gesture-one-2021-03-07_23-07-48-1_37388.jpg'# 打开图像
img = Image.open(img_path)
print(np.array(img).shape)# 对图像进行变换
img = data_transform(img)plt.imshow(img.permute(1,2,0))
plt.show()# 将图像升维,增加batch_size维度
img = torch.unsqueeze(img, dim=0)# 获取预测结果
pred = class_dict[model(img).argmax(axis=1).item()]
print('【预测结果分类】:%s' % pred)

完整运行代码

import math
import pickle
import osimport numpy as np
import pandas as pd
import torch
import torch.nn as nn
from keras.preprocessing.sequence import pad_sequences
from sklearn.model_selection import train_test_split
from torch.utils.data import TensorDataset
from torchvision import transforms, datasets
from torch import optim
from torchnet import meter
from tqdm import tqdm
from PIL import Imageimport matplotlib.pyplot as plt# 模型输入参数,需要自己根据需要调整
num_class = 14 # 分类数
epochs = 20 # 迭代次数
batch_size = 64 # 每个批次样本大小
lr = 0.003 # 学习率
image_path = './data' # 图像数据路径
save_path = './best_model.pkl' # 模型保存路径
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') # 设备# 1.数据转换
data_transform = {# 训练中的数据增强和归一化'train': transforms.Compose([transforms.RandomResizedCrop(150), # 随机裁剪transforms.ToTensor(), # 均值方差归一化transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])
}# 2.形成训练集
train_dataset = datasets.ImageFolder(root=os.path.join(image_path),transform=data_transform['train'])# 3.形成迭代器
train_loader = torch.utils.data.DataLoader(train_dataset,batch_size,True)print('using {} images for training.'.format(len(train_dataset)))# 4.建立分类标签与索引的关系
cloth_list = train_dataset.class_to_idx
class_dict = {}
for key, val in cloth_list.items():class_dict[val] = key
with open('class_dict.pk', 'wb') as f:pickle.dump(class_dict, f)class LeNet5(nn.Module):def __init__(self,num_class=10):super(LeNet5,self).__init__()self.conv1 = nn.Conv2d(3, 8, 5)self.pool1 = nn.AvgPool2d((2, 2))self.conv2 = nn.Conv2d(8, 16, 5)self.pool2 = nn.AvgPool2d((2, 2))self.conv3 = nn.Conv2d(16, 32, 5)self.relu = nn.ReLU()self.fc1 = nn.Linear(28800, 1024)self.fc2 = nn.Linear(1024, num_class)def forward(self, x):# x: torch.Size([32, 3, 150, 150])x = self.conv1(x) # torch.Size([32, 8, 146, 146])x = self.relu(x)x = self.pool1(x) # torch.Size([32, 8, 73, 73])x = self.conv2(x) # torch.Size([32, 16, 69, 69])x = self.relu(x)x = self.pool2(x) # torch.Size([32, 16, 34, 34])x = self.conv3(x) # torch.Size([32, 32, 30, 30])x = self.relu(x)x = x.flatten(start_dim=1) # torch.Size([32, 28800])x = self.fc1(x) # torch.Size([32, 2024])x = self.relu(x)x = self.fc2(x) # torch.Size([32, 4])return x# 6.模型训练
model = LeNet5(num_class)
model = model.to('cpu')
criterion = nn.CrossEntropyLoss() # 损失函数
optimizer = torch.optim.Adam(model.parameters(), lr=lr) # 优化器best_acc = 0 # 最优精确率
best_model = None # 最优模型参数for epoch in range(epochs):model.train()running_loss = 0 # 损失epoch_acc = 0  # 每个epoch的准确率epoch_acc_count = 0  # 每个epoch训练的样本数train_count = 0  # 用于计算总的样本数,方便求准确率train_bar = tqdm(train_loader)for data in train_bar:images, labels = dataoptimizer.zero_grad()output = model(images.to(device))loss = criterion(output, labels.to(device))loss.backward()optimizer.step()running_loss += loss.item()train_bar.desc = "train epoch[{}/{}] loss:{:.3f}".format(epoch + 1,epochs,loss)# 计算每个epoch正确的个数epoch_acc_count += (output.argmax(axis=1) == labels.view(-1)).sum()train_count += len(images)# 每个epoch对应的准确率epoch_acc = epoch_acc_count / train_count# 打印信息print("【EPOCH: 】%s" % str(epoch + 1))print("训练损失为%s" % str(running_loss))print("训练精度为%s" % (str(epoch_acc.item() * 100)[:5]) + '%')if epoch_acc > best_acc:best_acc = epoch_accbest_model = model.state_dict()# 在训练结束保存最优的模型参数if epoch == epochs - 1:# 保存模型torch.save(best_model, save_path)print('Finished Training')# 加载索引与标签映射字典
with open('class_dict.pk', 'rb') as f:class_dict = pickle.load(f)# 数据变换
data_transform = transforms.Compose([transforms.CenterCrop(150),transforms.ToTensor(),transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])# 图片路径
img_path = r'./data/000-one/gesture-one-2021-03-07_23-07-48-1_37388.jpg'# 打开图像
img = Image.open(img_path)
print(np.array(img).shape)# 对图像进行变换
img = data_transform(img)plt.imshow(img.permute(1,2,0))
plt.show()# 将图像升维,增加batch_size维度
img = torch.unsqueeze(img, dim=0)# 获取预测结果
pred = class_dict[model(img).argmax(axis=1).item()]
print('【预测结果分类】:%s' % pred)

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

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

相关文章

Android 11 HAL层集成FFMPEG

1.集成目录: android/vendor/noch/common/external/NoboMediaCodec 2.文件夹目录 3. Android.mk实现 # Copyright #LOCAL_PATH : $(call my-dir)SF_COMMON_MK : $(LOCAL_PATH)/common.mkinclude $(call first-makefiles-under,$(LOCAL_PATH))4.common.mk实现 # #…

【EI检索】第二届机器视觉、图像处理与影像技术国际会议(MVIPIT 2024)

一、会议信息 大会官网:www.mvipit.org 官方邮箱:mvipit163.com 会议出版:IEEE CPS 出版 会议检索:EI & Scopus 检索 会议地点:河北张家口 会议时间:2024 年 9 月 13 日-9 月 15 日 二、征稿主题…

Mysql解忧杂货铺

欢迎来到一夜看尽长安花 博客,您的点赞和收藏是我持续发文的动力 对于文章中出现的任何错误请大家批评指出,一定及时修改。有任何想要讨论的问题可联系我:3329759426qq.com 。发布文章的风格因专栏而异,均自成体系,不足…

【python虚拟环境管理】【mac m3】 使用pipx安装poetry

文章目录 一. 安装 pipx二. 安装Poetry1. 安装2. advanced 操作 官网文档:https://python-poetry.org/docs/ pipx介绍文档:https://blog.51cto.com/u_15064632/2570626 一. 安装 pipx pipx 用于全局安装 Python 命令行应用程序,同时在虚拟环…

注册安全分析报告:OneApm

前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 暴力破解密码,造成用户信息泄露短信盗刷的安全问题,影响业务及导致用户投诉带来经济损失,尤其是后付费客户,风险巨大,造成亏损无底洞 …

【大型实战】企业网络实验(华为核心交换、ESXI7.0vmware虚拟机、DHCP中继、服务端网络及用户端网络配置)

需求 实验 vmware网络配置(企业内部一般为ESXI) 这样服务器虚拟机使用192.168.200.X网段才能与用户侧互通 vmware虚拟机配置(DHCP服务器网络配置) 打开网络管理页面 nmtui重置一下网络连接(重启网卡) …

十分钟“手撕”七大排序

前言:可以通过目录来找你需要的排序的源代码。先是解释底层原理,后附带代码。 目录 稳定的概念 一、插入排序 二、希尔排序 三、选择排序 四、堆排序 五、冒泡排序 六、快速排序 七、归并排序 八、排序总结 额外:计数排序 稳定的…

论文翻译:Explainability for Large Language Models: A Survey

https://arxiv.org/pdf/2309.01029 目录 可解释性在大型语言模型中:一项调查摘要1 引言2 LLMs的训练范式2.1 传统微调范式2.2 提示范式 3 传统微调范式的解释3.1 局部解释3.1.1 基于特征归因的解释3.1.2 基于注意力的解释3.1.3 基于示例的解释 3.2 全局解释3.2.1 基…

大规模优化问题,Scipy?Ceres?PyTorch!

背景: 优化问题一般通过scipy.optimize或者Ceres Solver优化器求解。但在参数量较大的优化问题上,scipy提供的BFGS、L-BFGS-B、CG、SLSQP等梯度优化算法其复杂度和存储需求指数级上升,无法满足计算效率;而Ceres需要额外的语言来支…

VTK----3D picking的原理、类型及实现

目录 3D picking概述 3D射线投射原理 VTK picking框架 vtkPicker(选Actor) vtkPointPicker(选点) vtkCellPicker(选单元) vtkAreaPicker(框选) 3D picking概述 3D picking 是一种在三维场景中确定用户点击或指向的对象的技术。这在3D应用程序和游戏中非常常见,…

React Native 自定义 Hook 获取组件位置和大小

在 React Native 中自定义 Hook useLayout 获取 View、Pressable 等组件的位置和大小的信息 import {useState, useCallback} from react import {LayoutChangeEvent, LayoutRectangle} from react-nativeexport function useLayout() {const [layout, setLayout] useState&l…

JavaScript Math 函数举例

https://andi.cn/page/621577.html

Mongodb数组字段索引之多键索引

学习mongodb,体会mongodb的每一个使用细节,欢迎阅读威赞的文章。这是威赞发布的第92篇mongodb技术文章,欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题,欢迎在文章下面点个赞,或者关…

【中项第三版】系统集成项目管理工程师 | 第 5 章 软件工程② | 5.4 - 5.8

前言 第 5 章对应的内容选择题和案例分析都会进行考查,这一章节属于技术的内容,学习要以教材为准。 目录 5.4 软件实现 5.4.1 软件配置管理 5.4.2 软件编码 5.4.3 软件测试 5.5 部署交付 5.5.1 软件部署 5.5.2 软件交付 5.5.3 持续交付 5.5.4…

Java语言程序设计——篇五

数组 概述数组定义实例展示实战演练 二维数组定义数组元素的使用数组初始化器实战演练:矩阵计算 💫不规则二维数组实战演练:杨辉三角形 概述 ⚡️数组是相同数据类型的元素集合。各元素是有先后顺序的,它们在内存中按照这个先后顺…

论文分享|AAAI2024‘北航|软标签监督实现通用密集检索——图文检索中的跨模态和单模态软标签对齐

论文题目:Cross-Modal and Uni-Modal Soft-Label Alignment for Image-Text Retrieval 来源:AAAI2024/实验室师兄/北航 方向:跨模态检索 开源地址:https://github.com/lerogo/aaai24_itr_cusa 摘要 近年来,目前的…

保障低压设备安全!中国星坤连接器精密工艺解析!

在现代电子设备中,连接器扮演着至关重要的角色,它们是电子系统之间沟通的桥梁。随着技术的发展,对连接器的需求也在不断提升,特别是在低电压应用领域。中国星坤最新推出的低压连接器,以其精密性和安全性,为…

Kafka Producer发送消息流程之分区器和数据收集器

文章目录 1. Partitioner分区器2. 自定义分区器3. RecordAccumulator数据收集器 1. Partitioner分区器 clients/src/main/java/org/apache/kafka/clients/producer/KafkaProducer.java,中doSend方法,记录了生产者将消息发送的流程,其中有一步…

书生浦语-大模型平台学习-环境搭建01

任务:完成SSH连接与端口映射并运行hello_world.py 详细步骤详见:https://github.com/InternLM/Tutorial/blob/camp3/docs/L0/Linux/readme.md 1、InternStudio介绍 InternStudio 是大模型时代下的云端算力平台。基于 InternLM 组织下的诸多算法库支持…

CentOS快速安装Docker(腾讯镜像源)

这里是引用"> 1、卸载旧版本的 Docker yum list installed | grep docker yum -y remove docker-ce-cli.x86_64 yum -y remove docker-ce.x86_64 yum -y remove containerd.io2、安装相关依赖 yum install -y yum-utils device-mapper-persistent-data lvm23、添加 …