基于深度学习的人体姿态识别(本科毕业设计),一点头绪都没有怎么办,有无大神指点一下? 您所在的位置:网站首页 永不失联的爱和弦伴奏谱子 基于深度学习的人体姿态识别(本科毕业设计),一点头绪都没有怎么办,有无大神指点一下?

基于深度学习的人体姿态识别(本科毕业设计),一点头绪都没有怎么办,有无大神指点一下?

2023-03-13 19:53| 来源: 网络整理| 查看: 265

第一步:下定义对于”基于深度学习的人体姿态识别“这个课题,首先需要给课题下一个定义,明白我们要做什么。

人体姿态识别是指在一张包含人体的图像中,通过计算人体的关键点(通常是骨骼关节)的空间坐标,来表示人体的姿态状态。这项任务通常用于动作识别、人机交互、智能监控等领域。

人体姿态识别任务的目标是从输入的图像中提取出人体骨骼关键点的位置,即骨骼姿态。对于每个人体关键点,通常需要计算其在图像中的像素坐标或相对位置。

在实际应用中,人体骨骼姿态识别需要解决一些挑战,如多人姿态识别、姿态变化、遮挡、视角变化等。因此,人体骨骼姿态识别通常使用深度学习模型,这些模型可以从大量的训练数据中学习到骨骼关键点的位置,并且对不同的人体姿态具有很好的泛化能力。

基于以上介绍,人体姿态识别本质上是骨骼关键点检测,要做的是这样一件事:输入一张人体图片,由模型识别出其中的人体骨骼关键点。第二步:梳理任务技术路线对于人体姿态识别任务,先做一个基础调研:有哪些现有方法可以完成这个任务吗?

经过调研,你会发现已有不少封装好的库来供你实现这个任务,你只需要调用库里提供的api即可轻松实现一个简单的人体姿态识别功能,下面举例几种人体骨骼姿态识别任务中常用的模型:

1. OpenPoseOpenPose 是一种端到端的深度学习模型,能够实现多人姿态估计和关键点检测,能够检测多个人的骨骼姿态,并将姿态中的每个关节标记为一个热图,可以通过对这些热图进行分析,获得人体的关键点位置和连接信息。

使用方式:

import cv2 import numpy as np import openpose as op # 加载 OpenPose 模型 params = dict() params["model_folder"] = "/path/to/openpose/models/" opWrapper = op.WrapperPython() opWrapper.configure(params) opWrapper.start() # 加载输入图像 image_path = "/path/to/image.jpg" image = cv2.imread(image_path) # 运行 OpenPose 模型进行人体骨骼姿态估计 datum = op.Datum() datum.cvInputData = image opWrapper.emplaceAndPop([datum]) # 获取姿态信息 pose_keypoints = datum.poseKeypoints2. HourglassHourglass 是一种基于编码器-解码器结构的深度学习模型,该模型将输入图像沿着多个不同尺度的路径进行卷积和下采样,并在解码器阶段进行上采样和卷积操作,最终输出人体的骨骼姿态信息。

使用方式:

import torch import torchvision from torchvision.models import hg # 加载 Hourglass 模型 model = hg(num_stacks=2, num_blocks=2, num_classes=17) # 加载输入图像 image_path = "/path/to/image.jpg" image = torchvision.io.read_image(image_path) # 预处理图像数据 image = image.float() / 255.0 image = image.unsqueeze(0) # 运行 Hourglass 模型进行人体骨骼姿态估计 outputs = model(image) # 获取姿态信息 pose_keypoints = outputs[-1]3. Stacked HourglassStacked Hourglass 是 Hourglass 的一种改进版本,该模型增加了多个 Hourglass 模块,以提高骨骼姿态估计的准确性和鲁棒性。该模型可以同时预测多个人的骨骼姿态,并具有高效和准确的特点。

使用方式:

import torch import torchvision from torchvision.models import hg # 加载 Stacked Hourglass 模型 model = hg(num_stacks=4, num_blocks=1, num_classes=17) # 加载输入图像 image_path = "/path/to/image.jpg" image = torchvision.io.read_image(image_path) # 预处理图像数据 image = image.float() / 255.0 image = image.unsqueeze(0) # 运行 Stacked Hourglass 模型进行人体骨骼姿态估计 outputs = model(image) # 获取姿态信息 pose_keypoints = outputs[-1]4. DeepPoseDeepPose 是一种使用深度卷积神经网络进行人体骨骼姿态估计的模型。该模型使用了一个多阶段的卷积神经网络结构,通过在多个阶段对不同的尺度和特征进行卷积操作,以获得高分辨率和高质量的人体骨骼姿态估计结果。

使用方式:

import torch import torchvision from torchvision.models import resnet # 加载 DeepPose 模型 model = resnet18(pretrained=True) model.fc = torch.nn.Linear(512, 14) # 加载输入图像 image_path = "/path/to/image.jpg" image = torchvision.io.read_image(image_path) # 预处理图像数据 image = image.float() / 255.0 image = image.unsqueeze(0) # 运行 DeepPose 模型进行人体骨骼姿态估计 outputs = model(image) # 获取姿态信息 pose_keypoints = outputs

以上方法中的 `pose_keypoints` 是输出的关键点坐标信息,直接输出这些数值信息对人类来说并不直观,因此,你可以对其进行可视化。

常用的人体骨骼姿态可视化方法是在原始图像上绘制关键点,这可以使用 OpenCV 等图像处理库来实现。以下是一个简单的 Python 代码示例,可以将关键点绘制在原始图像上:

import cv2 # 加载原始图像和姿态信息 image_path = "/path/to/image.jpg" image = cv2.imread(image_path) pose_keypoints = [...] # 假设这里包含了一些姿态信息 # 绘制关键点 for i in range(pose_keypoints.shape[0]): x, y = pose_keypoints[i][:2] cv2.circle(image, (int(x), int(y)), 3, (0, 255, 0), -1) # 显示结果图像 cv2.imshow("Pose estimation result", image) cv2.waitKey(0)5. mediapipeMediaPipe 是一款由 Google Research 开发并开源的多媒体机器学习模型应用框架。MediaPipe封装了很多功能,可以做物体检测、自拍分割、头发分割、人脸检测、手部检测、运动追踪,等等。基于此可以实现更高级的功能。MediaPipe 库可以用于人体姿态估计任务,并且已经实现了一些预训练模型和应用程序。使用 MediaPipe 库可以简化模型开发和部署的过程,特别是对于那些想要快速部署模型的应用程序。

下面是一个使用 MediaPipe 进行人体姿态估计的简单示例代码:

import cv2 import mediapipe as mp # 加载预训练的模型 mp_drawing = mp.solutions.drawing_utils mp_pose = mp.solutions.pose # 初始化摄像头 cap = cv2.VideoCapture(0) with mp_pose.Pose( min_detection_confidence=0.5, min_tracking_confidence=0.5) as pose: while cap.isOpened(): # 读取视频帧 success, image = cap.read() if not success: print("Ignoring empty camera frame.") continue # 处理视频帧 image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) image.flags.writeable = False # 运行模型,获取姿态估计结果 results = pose.process(image) # 绘制关键点 image.flags.writeable = True image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) mp_drawing.draw_landmarks( image, results.pose_landmarks, mp_pose.POSE_CONNECTIONS) # 显示结果 cv2.imshow('MediaPipe Pose', image) if cv2.waitKey(5) & 0xFF == 27: break # 释放资源 cap.release() cv2.destroyAllWindows()6. 自定义模型

直接调用库中的函数可以快速搭建一个人体姿态识别应用,十分方便,但它的弊端在于:限制了后续的优化可能性。

如果我们能够训练一个自己的人体姿态识别模型,我们就可以尝试从训练数据集、模型架构、损失函数和优化器的选择等多个方面去优化它,也可以让你的毕设更加言之有物(通过调库实现的毕设多少有些工作量不足了)。

当我们决定要自定义人体姿态识别模型时,首先需要制定一个大体的训练方案:

(1)数据收集和准备:收集足够数量和多样性的人体骨骼姿态数据集,并进行数据清洗和标注。数据集的质量对模型的性能至关重要,因此建议使用多种不同的姿势、不同年龄、性别、体型、种族的数据,并进行多次标注来确保标注质量。

(2)定义模型架构:根据任务需求选择适合的模型,例如卷积神经网络(CNN)、循环神经网络(RNN)或 Transformer 等深度学习模型。我们可以站在巨人的肩膀上,从以上介绍过的成熟库中选择一种模型,将它的模型架构作为我们的基础模型架构,后续再根据需要对此结构进行优化。

(3)训练模型:将数据集划分为训练集、验证集和测试集,并使用训练集进行模型的训练。在训练过程中,可以使用数据增强和正则化等技术来避免过拟合,同时选择合适的损失函数和优化器来优化模型。

(4)模型评估和调整:使用验证集对模型进行评估和调整,比较不同模型的性能和效率,并选择最佳模型。可以使用各种指标可以使用各种指标来评估模型,例如准确率、召回率、F1 分数等。

(5)模型测试:使用测试集来测试模型的性能,并对模型测试结果进行结果分析。

(6)模型部署:将训练好的模型部署到实际应用中,并集成到现有系统中。

第三步:数据收集和准备

以下是一些开源的人体骨骼姿态数据集,它们可以用于训练人体姿势识别模型,这些数据集可以通过各自的官方网站或者相关研究论文中的链接来下载。

数据集名称数据集描述COCO (Common Objects in Context)包含超过 25 万个图像。MPII (Max Planck Institute for Informatics)包含超过 25,000 张图像,以及关键点标注和骨骼姿态标注。Human3.6M一个大规模的人体姿势估计数据集,其中包含超过 3.6 万个动作的视频。该数据集包括 15 个人的运动,每个人都有 4 个摄像头捕捉的视频。PoseTrack一个数据集和竞赛项目,旨在提高人体姿势跟踪的准确性。该数据集包含超过 5000 个视频,其中包含各种类型的人体运动。Penn Action包括动作视频和骨骼姿态标注。该数据集包含大约 2,300 个视频,覆盖 15 种不同的动作类别。第四步:定义模型架构

这里以Stacked Hourglass 模型为基础模型架构,以下是一个简化版本的代码示例,包含了一个基本的 Hourglass 模块,以及堆叠多个 Hourglass 模块组成的 Stacked Hourglass 模型:

import torch import torch.nn as nn class Hourglass(nn.Module): def __init__(self, n, f): super(Hourglass, self).__init__() self.n = n self.f = f self.conv1 = nn.Conv2d(f, f, kernel_size=3, stride=1, padding=1) self.bn1 = nn.BatchNorm2d(f) self.conv2 = nn.Conv2d(f, f, kernel_size=3, stride=1, padding=1) self.bn2 = nn.BatchNorm2d(f) self.skip = nn.Sequential( nn.Conv2d(f, f, kernel_size=1, stride=1, padding=0), nn.BatchNorm2d(f) ) self.downsample = nn.MaxPool2d(kernel_size=2, stride=2) self.up1 = nn.Upsample(scale_factor=2, mode="nearest") self.up2 = nn.Upsample(scale_factor=2, mode="nearest") if n > 1: self.hg = Hourglass(n - 1, f) else: self.hg = None def forward(self, x): out1 = self.conv1(x) out1 = self.bn1(out1) out1 = torch.relu(out1) out2 = self.conv2(out1) out2 = self.bn2(out2) out2 = torch.relu(out2) skip = self.skip(out1) if self.n > 1: downsample = self.downsample(out2) hg = self.hg(downsample) up1 = self.up1(hg) else: up1 = self.up1(out2) out = up1 + skip up2 = self.up2(out) return up2 class StackedHourglass(nn.Module): def __init__(self, n, f, num_classes): super(StackedHourglass, self).__init__() self.n = n self.f = f self.num_classes = num_classes self.conv1 = nn.Conv2d(3, f, kernel_size=7, stride=2, padding=3) self.bn1 = nn.BatchNorm2d(f) self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2) self.res1 = self.make_residual(2 * f, 2 * f) self.res2 = self.make_residual(2 * f, 4 * f) self.hg = self.make_hourglass(n, 4 * f) self.conv2 = nn.Conv2d(4 * f, 4 * f, kernel_size=1, stride=1, padding=0) self.bn2 = nn.BatchNorm2d(4 * f) self.conv3 = nn.Conv2d(4 * f, num_classes, kernel_size=1, stride=1, padding=0) def make_residual(self, in_f, out_f): return nn.Sequential( nn.Conv2d(in_f, out_f, kernel_size=3, stride=1, padding=1), nn.BatchNorm2d(out_f), nn.ReLU(), nn.Conv2d(out_f, out_f, kernel_size=3, stride=1, padding=1), nn.BatchNorm2d(out_f) ) def make_hourglass(self, n, f): hg = Hourglass(n, f) if n > 1: return nn.Sequential( hg, self.make_residual(f, f), self.make_hourglass(n - 1, f), self.make_residual(f, f), nn.Upsample(scale_factor=2, mode="nearest") ) else: return nn.Sequential( hg, self.make_residual(f, f), nn.Upsample(scale_factor=2, mode="nearest") ) def forward(self, x): out1 = self.conv1(x) out1 = self.bn1(out1) out1 = torch.relu(out1) out1 = self.pool1(out1) out1 = self.res1(out1) out1 = self.res2(out1) out1 = self.hg(out1) out1 = self.conv2(out1) out1 = self.bn2(out1) out1 = torch.relu(out1) out1 = self.conv3(out1) return out1 第五步:模型训练

下面是一个基于 PyTorch 的训练函数,可以用于训练一个 Stacked Hourglass 模型:

import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader def train_model(model, train_loader, val_loader, criterion, optimizer, num_epochs=10): device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") model.to(device) train_losses = [] val_losses = [] for epoch in range(num_epochs): # Training phase model.train() running_loss = 0.0 for inputs, targets in train_loader: inputs = inputs.to(device) targets = targets.to(device) optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, targets) loss.backward() optimizer.step() running_loss += loss.item() * inputs.size(0) train_loss = running_loss / len(train_loader.dataset) train_losses.append(train_loss) # Validation phase model.eval() running_loss = 0.0 with torch.no_grad(): for inputs, targets in val_loader: inputs = inputs.to(device) targets = targets.to(device) outputs = model(inputs) loss = criterion(outputs, targets) running_loss += loss.item() * inputs.size(0) val_loss = running_loss / len(val_loader.dataset) val_losses.append(val_loss) print(f"Epoch {epoch+1}/{num_epochs}: train loss = {train_loss:.4f}, val loss = {val_loss:.4f}") return train_losses, val_losses

其中,model 是一个 Stacked Hourglass 模型,train_loader 和 val_loader 是 PyTorch 的 DataLoader 对象,用于加载训练集和验证集。criterion 是损失函数,optimizer 是优化器,num_epochs 是迭代次数。

这个函数使用了 PyTorch 的 GPU 加速,如果你的电脑没有 GPU,可以将 device 改为 device = torch.device("cpu")。在训练过程中,每个 epoch 分别对训练集和验证集进行迭代,并计算平均损失。最后返回训练集和验证集的损失列表,用于绘制学习曲线。

数据集加载器(DataLoader)是 PyTorch 提供的一种数据批量加载器,可以在训练过程中将数据分成小批量进行训练,这样可以节省内存,同时也可以加速训练。在使用 PyTorch 训练深度学习模型时,我们通常会先将数据转换为 Tensor,然后使用 DataLoader 加载数据。

在人体骨骼姿态识别任务中,可以先将输入图像和对应的骨骼姿态标注转换为 Tensor,并组合成一个 PyTorch 数据集(Dataset),然后使用 DataLoader 加载这个数据集。下面是一个示例:

from torch.utils.data import Dataset class BodyPoseDataset(Dataset): def __init__(self, image_paths, pose_data, transform=None): self.image_paths = image_paths self.pose_data = pose_data self.transform = transform def __len__(self): return len(self.image_paths) def __getitem__(self, index): image_path = self.image_paths[index] pose = self.pose_data[index] image = Image.open(image_path).convert('RGB') if self.transform is not None: image = self.transform(image) return image, pose

这个代码定义了一个 BodyPoseDataset 类,继承自 PyTorch 的 Dataset 类。在构造函数中,传入了图像路径列表 image_paths 和骨骼姿态数据列表 pose_data,还可以传入一个可选的图像变换函数 transform。在 __len__ 方法中,返回数据集的长度。在 __getitem__ 方法中,根据索引 index 返回一个图像和对应的骨骼姿态标注。

在构造了数据集之后,可以使用 DataLoader 对数据集进行批量加载,下面是一个示例:

train_dataset = BodyPoseDataset(train_image_paths, train_pose_data, transform=train_transform) val_dataset = BodyPoseDataset(val_image_paths, val_pose_data, transform=val_transform) train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True, num_workers=4) val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False, num_workers=4)

这个代码使用 BodyPoseDataset 类构造了训练集和验证集,然后使用 DataLoader 分别加载了训练集和验证集。其中,batch_size 表示每个批次的大小,shuffle 表示是否随机打乱数据顺序,num_workers 表示使用的线程数。

同时,训练函数中还传入了参数损失函数 criterion 和优化器 `optimizer` 。

在 PyTorch 中,常用的损失函数包括:

CrossEntropyLoss:交叉熵损失函数,常用于分类问题;BCELoss:二分类交叉熵损失函数,用于二分类问题;MSELoss:均方误差损失函数,常用于回归问题;L1Loss:绝对值损失函数,也常用于回归问题。

下面是使用 PyTorch 内置的 MSELoss的示例代码:

import torch.nn as nn # 使用 MSELoss criterion = nn.MSELoss()

在 PyTorch 中,常用的优化算法包括:

SGD:随机梯度下降算法;Adam:自适应矩估计算法,可以看作是基于动量法的改进版。

下面是使用 PyTorch 内置的 SGD 和 Adam 优化算法的代码示例:

import torch.optim as optim # 使用 SGD optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9) # 使用 Adam optimizer = optim.Adam(model.parameters(), lr=0.001)

在人体骨骼姿态识别任务中,常用的损失函数是均方误差(Mean Squared Error,MSE)。MSE 表示预测值与真实值之间的差异,是回归任务中常用的损失函数。对于人体骨骼姿态识别任务,我们的目标是预测每个关键点的坐标,因此可以使用 MSE 作为损失函数,优化网络的参数,使预测值与真实值之间的差异最小化。

对于优化算法,我们可以选择常用的随机梯度下降法(Stochastic Gradient Descent,SGD)、Adam 等优化算法。这些算法在优化神经网络模型中表现良好,并且已经被广泛应用于各种任务中。

选择优化算法时,我们需要考虑训练时间、模型性能、调节难度等因素。SGD 是一种常用的优化算法,易于实现和调节,因此是许多模型的首选优化算法。Adam 算法则相对于 SGD 来说收敛更快,并且对超参数的选择相对较少敏感,但也可能存在一些缺点,如收敛到次优解等。

在实际应用中,我们可以根据任务的具体情况来选择损失函数和优化算法。对于人体骨骼姿态识别任务,一般来说,MSE 和 SGD 是不错的选择。当然,如果需要更好的性能,我们也可以尝试其他损失函数和优化算法。

第六步:模型评估和调整

在训练好人体骨骼姿态识别模型之后,可以使用验证集来评估模型的性能。以下是一些常用的评测指标:

(1)PCK (Percentage of Correct Keypoints):

表示正确检测出的关键点占总体检测出的关键点的比例。通常情况下,PCK的阈值设为一定的像素距离,如[email protected]表示当检测点与真实点的距离小于0.1倍图像的对角线时,就认为是正确的。这个指标的计算需要依赖于数据集中的真实关键点坐标和模型预测的关键点坐标。

下面是一个使用PCK指标评估模型的代码示例:

def evaluate_pck(model, test_loader, threshold=0.2): model.eval() correct = 0 total = 0 with torch.no_grad(): for images, targets in test_loader: images = images.to(device) targets = targets.to(device) outputs = model(images) for i in range(outputs[-1].shape[0]): pred = outputs[-1][i] gt = targets[i] dist = torch.norm(pred - gt, dim=1) num_correct = torch.sum(dist


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有