人体姿态估计是计算机视觉领域很多研究工作的基础,也是研究的热点问题,在行为识别、人机交互、姿态跟踪等领域有着广泛的应用前景。
按照人体姿态维度的差异,可以将人体姿态估计任务分为二维人体姿态估计和三维人体姿态估计。2D人体姿态估计的目标是定位并识别出人体关键点,将这些关键点按照关节顺序相连形成在图像二维平面的投影,从而得到人体骨架。3D人体姿态估计的主要任务是预测出人体关节点的三维坐标位置和角度等信息。
在实际应用中,由于3D姿态估计在2D姿态估计的基础上加入了深度信息,其对于人体姿态的表述比2D更为精准,因此其应用范围和研究价值都要高于2D人体姿态估计,但是3D姿态估计的难度也更高,存在着遮挡,单视角2D到3D的映射中固有的深度模糊性、不适定性,缺少大型的室外数据集等挑战。
本项目通过使用3DPose模型实现对人体的三维实时姿态识别。其最终实现的效果如下图可见:
1、基本介绍
在深度学习方法得到广泛应用之前,3D人体姿态标注数据集和具有高运算能力的GPU还没有普及,研究人员主要通过一些应用在传统计算机视觉或机器学习领域的方法来进行3D人体姿态的估计。传统三维人体姿态估计和基于深度学习的姿态估计之间最明显的特征在于是否使用了多层神经网络的学习方法,因为建模方式不同,在估计精确性、计算复杂度等方面也有着较大的差别。其中建模是三维人体姿态估计一个很重要的方面,目的是表示从输入数据中提取的关键点和特征。在解决实际问题时由于实验个体所处环境的复杂性,很大程度上增加了模型的建立难度,因此选取适当且有效的图像特征来简化模型建立过程十分重要。
1.1 环境要求:
本次环境使用的是python3.6.5+windows平台。
主要用的库有:ONNX Runtime库、opencv-python模块、Numpy模块。
ONNX Runtime库
ONNX Runtime库是一个用于ONNX(Open Neural Network Exchange)模型推理的引擎。微软联合Facebook等在2017年搞了个深度学习以及机器学习模型的格式标准--ONNX,顺路提供了一个专门用于ONNX模型推理的引擎。
opencv-python模块
opencv-python是一个Python绑定库,旨在解决计算机视觉问题。其使用Numpy,这是一个高度优化的数据库操作库,具有MATLAB风格的语法。所有Opencv数组结构都转换为Numpy数组。这也使得与使用Numpy的其他库(如Scipy和Matplotlib)集成更容易。
Numpy模块
Numpy是应用Python进行科学计算时的基础模块。它是一个提供多维数组对象的Python库,除此之外,还包含了多种衍生的对象(比如掩码式数组(masked arrays)或矩阵)以及一系列的为快速计算数组而生的例程,包括数学运算,逻辑运算,形状操作,排序,选择,I/O,离散傅里叶变换,基本线性代数,基本统计运算,随机模拟等。
1.2 方法总结:传统方法很多是采用基于人体模型的方法来描述和推断人体姿态,通过算法提取图像姿态特征,因此对特征表示和关键点的空间位置关系这两个维度有比较高的要求,除去边界、颜色这类低层次特征,典型的有尺度不变特征变换、梯度直方图等表达能力更强、可有效压缩特征空间维度的高层次特征,它们虽然在时间效率方面具有优势,但依然存在着较大的不足。
而深度学习模型操作过程相对简单且对特征的表示能力强大,对输入信息自动进行特征提取而无需人为手动提取特征。
基于深度学习的人体姿态估计可以通过建立网络模型在图像数据上进行训练和学习,直接得到最有效的表征方法,其核心是深度神经网络,主要是利用卷积神经网络从图像中提取出比人工特征语义信息更丰富、准确性更高和更具鲁棒性的卷积特征,并且网络模型的表达能力会因网络堆叠数量的增加而呈指数增长,因此相较于传统方法可以进一步提升复杂环境下的人体姿态的精度和鲁棒性。深度学习在人体姿态估计任务中的应用已经取得了显著的进展,然而像遮挡、训练数据不足和深度模糊等挑战仍然是难以克服的。
2.三维人体可视化
传统方法与深度学习方法
其中3DPose算法提供的模型架构如下图可见:
2.1 图片预处理:
其中图片处理代码如下,分别为读取图片,显示图片,BGR转RGB以及尺寸变换等:
img=cv2.imread("1.jpg")
cv2.imshow("test", img)
cv2.waitKey(1)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, (448, 448))
img = img.astype(np.float32) / 255.0
img = img.transpose(2, 1, 0)
img = img[np.newaxis, ...]
2.2 模型训练:
首先通过使用onnxruntime,
然后读取Resnet34_inputs_448x448_20200609.0nnx模型文件,实时需要识别的图片数据,获取每一张图片的offset图和heatmap图。通过找到第j个关节的28个特征图,并找到最大值的索引来获取个点坐标。并把坐标按照一定比例缩放。使得图像变形较为符合人体规律。
for j in range(0, 24):
# 找到第j个关节的28个特征图,并找到最大值的索引
joint_heat = heatMap3D[j * 28:(j + 1) * 28, ...]
if np.max(joint_heat)>0.1:
print(np.max(joint_heat))
[x, y, z] = np.where(joint_heat == np.max(joint_heat))
x = int(x[-1])
y = int(y[-1])
z = int(z[-1])
# 通过heatmap的索引找到对应的offset图,并计算3D坐标的xyz值
pos_x = offset3D[j * 28 + x, y, z] + x
pos_y = offset3D[24 * 28 + j * 28 + x, y, z] + y
pos_z = offset3D[24 * 28 * 2 + j * 28 + x, y, z] + z
kps[j, 0] = pos_x
kps[j, 1] = pos_y
kps[j, 2] = pos_z
else:
try:
kps[j, 0] = kps[j-1, 0]
kps[j, 0] = kps[j-1, 0]
kps[j, 2] = kps[j-1, 2]
except:
pass
parent = np.array([15, 1, 2, 3, 3, 15, 6, 7, 8, 8, 12, 15, 14, 15, 24, 24, 16, 17, 18, 24, 20, 21, 22, 0]) - 1;
for i in range(len(kps)):
if (parent[i] != -1):
ax.plot3D(kps[[i, parent[i]], 0], -kps[[i, parent[i]], 1], -kps[[i, parent[i]], 2], 'gray')
完整代码:
链接:https://pan.baidu.com/s/1pb0uG9Uy36sOBuWNTsZUpA
提取码:0ahr
作者简介:李秋键,CSDN博客专家,CSDN达人课作者。硕士在读于中国矿业大学,开发有taptap竞赛获奖等。
来源: AI科技大本营