当前位置:网站首页>ThreeDPoseTracker项目解析
ThreeDPoseTracker项目解析
2022-07-06 01:08:00 【烫青菜】
目录
一、源码
Digital Standard Co., LTD. (github.com)
参考文章:
二、肢体驱动
1.算法模型
(1)数据说明
项目中算法模型预测数据的代码主要为VNectBarracudaRunner.cs。函数PredictPose()中更新的节点数据为JointPoint中的三个变量(也就是驱动时要用到的算法数据):
public class JointPoint
{
public Vector3 Pos3D = new Vector3();
public float score3D;
public bool Visibled;
}JointPoint类中还有几个变量是预测过程中用于数据优化(防抖动等)的:
public class JointPoint
{
public Vector3 Now3D = new Vector3();
public Vector3[] PrevPos3D = new Vector3[6];
public Vector3 P = new Vector3();
public Vector3 X = new Vector3();
public Vector3 K = new Vector3();
}JointPoint类中其他的数据需要在肢体驱动时自己推算:
public class JointPoint
{
public Transform Transform = null;
public Quaternion InitRotation;
public Quaternion Inverse;
public Quaternion InverseRotation;
public JointPoint Child = null;
public JointPoint Parent = null;
}(2)算法理论解析
解决抖动:卡尔曼滤波+低通滤波: 关键点平滑方案
算法模型解析:模型解析 、 heatmap&offset
- 有三个input,其实都是一样,都要输入(448,448,3)的图片:
private void UpdateVNectAsync()
{
input = new Tensor(videoCapture.MainTexture, 3);
if (inputs[inputName_1] == null)
{
inputs[inputName_1] = input;
inputs[inputName_2] = new Tensor(videoCapture.MainTexture, 3);
inputs[inputName_3] = new Tensor(videoCapture.MainTexture, 3);
}
else
{
inputs[inputName_3].Dispose();
inputs[inputName_3] = inputs[inputName_2];
inputs[inputName_2] = inputs[inputName_1];
inputs[inputName_1] = input;
}
if (!Lock && videoCapture.IsPlay())
{
StartCoroutine(ExecuteModelAsync());
}
}
- 四个output,但我们只用后两个:
for (var i = 2; i < _model.outputs.Count; i++)
{
b_outputs[i] = _worker.PeekOutput(_model.outputs[i]);
}
offset3D = b_outputs[2].data.Download(b_outputs[2].shape);
heatMap3D = b_outputs[3].data.Download(b_outputs[3].shape);
用heatmap粗略定位关节位置,然后使用offset在heatmap结果上精确调整关节位置。
heatmap的 ( 672 , 28 , 28 ) 代表 24个关节的28个大小为(28,28)的特征图。而offset比heatmap的特征图多三倍,很明显就是刚才说的精确定位,只不过需要在offset中定位到x,y,z三个坐标,所以就是三倍关系了。
- heatmap的顺序是第1个关节的第1个特征图、第1个关节的第2个特征图、…、第2个关节的第1个特征图、第二个关节的第2个特征图、…、第24个关节的第28个特征图
- offsetmap的顺序是第1个关节的第1个特征图对应的x坐标偏移、第1个关节的第2个特征图对应的x坐标偏移、第1个关节的第3个特征图对应的x坐标偏移、…、第1个关节的第28个特征图对应的x坐标偏移、…、第2个关节的第1个特征图对应的x坐标偏移、…、第24个关节的第28个特征图对应的x坐标偏移、第1个关节的第1个特征图对应的y坐标偏移、第1个关节的第2个特征图对应的y坐标偏移、…、第24个关节的第28个特征图对应的y坐标偏移、第1个关节的第1个特征图对应的z坐标偏移、第1个关节的第2个特征图对应的z坐标偏移、…、第24个关节的第28个特征图对应的z坐标偏移。
2.Unity肢体驱动
项目中肢体驱动的代码主要为VNectModel.cs。
(1)相关知识
- 四元素的逆,⽐如⼀个四元数为(1,1,1,1)它的逆是(-1,-1,-1,1)。
Quaternion Inverse(Quaternion rotation);返回⼀个相反的旋转。
- 注视旋转
public static Quaternion LookRotation(Vector3 forward, [DefaultValue("Vector3.up")] Vector3 upwards);创建一个指定的forward 和upward方向的旋转,返回一个计算的四元数。如果用来确定一个transform:如果向量是正交的, z轴将和forward对齐,y轴将和upward对齐。如果forward方向是0将会报错。
(2)项目中的使用
由当前关节的lookrotation=初始旋转InitRotation×对齐矩阵 及
可得出:
a. Quaternion.Inverse(对齐矩阵)=当前旋转Rotation*Quaternion.Inverse(当前关节的lookrotation)
hip.Inverse = Quaternion.Inverse(Quaternion.LookRotation(forward));
hip.InverseRotation = hip.Inverse * hip.InitRotation;函数Init()中有大量类似的代码,目的是求中间矩阵,根据中间矩阵,我们可以通过算法数据得出当前object的旋转。VNectModel.cs中的hip.InverseRotation就是Quaternion.Inverse(对齐矩阵)。
b. 当前旋转Rotation=当前关节的lookrotation×Quaternion.Inverse(对齐矩阵)
//基于根关节和左右胯关节坐标计算出人体朝向,然后以此作为所有关节LookRotation的y方向
var forward = TriangleNormal(jointPoints[PositionIndex.hip.Int()].Pos3D, jointPoints[PositionIndex.lThighBend.Int()].Pos3D, jointPoints[PositionIndex.rThighBend.Int()].Pos3D);
jointPoints[***].Transform.rotation = Quaternion.LookRotation(Vector3.up, forward) * jointPoint[***].InverseRotation;
函数PoseUpdate()用于肢体驱动,上面这行代码就是用来计算关节的当前旋转的。
c. 对齐矩阵=当前关节的lookrotation*Quaternion.Inverse(当前旋转Rotation);
root = animator.GetBoneTransform(HumanBodyBones.Hips);
midRoot = Quaternion.Inverse(root.rotation) * Quaternion.LookRotation(forward);//midRoot 为对齐矩阵这些代码在项目中不存在,只是为了更好的解释公式。
三、肢体驱动流程图

边栏推荐
- The inconsistency between the versions of dynamic library and static library will lead to bugs
- 朝招金安全吗 会不会亏损本金
- 从 1.5 开始搭建一个微服务框架——调用链追踪 traceId
- Vulhub vulnerability recurrence 74_ Wordpress
- 【第30天】给定一个整数 n ,求它的因数之和
- Meta AI西雅图研究负责人Luke Zettlemoyer | 万亿参数后,大模型会持续增长吗?
- Mysql--- query the top 5 students
- 毕设-基于SSM高校学生社团管理系统
- Intensive learning weekly, issue 52: depth cuprl, distspectrl & double deep q-network
- Arduino hexapod robot
猜你喜欢

Free chat robot API

Illustrated network: the principle behind TCP three-time handshake, why can't two-time handshake?

Vulhub vulnerability recurrence 75_ XStream

Five challenges of ads-npu chip architecture design
![[groovy] JSON serialization (jsonbuilder builder | generates JSON string with root node name | generates JSON string without root node name)](/img/dd/bffe27b04d830d70f30df95a82b3d2.jpg)
[groovy] JSON serialization (jsonbuilder builder | generates JSON string with root node name | generates JSON string without root node name)

The growth path of test / development programmers, the problem of thinking about the overall situation

Finding the nearest common ancestor of binary tree by recursion

Dede collection plug-in free collection release push plug-in

VMware Tools安装报错:无法自动安装VSock驱动程序

VSphere implements virtual machine migration
随机推荐
KDD 2022 | EEG AI helps diagnose epilepsy
95后CV工程师晒出工资单,狠补了这个,真香...
MCU realizes OTA online upgrade process through UART
SAP Spartacus home 页面读取 product 数据的请求的 population 逻辑
Five challenges of ads-npu chip architecture design
servlet(1)
[groovy] XML serialization (use markupbuilder to generate XML data | set XML tag content | set XML tag attributes)
ADS-NPU芯片架构设计的五大挑战
JVM_ 15_ Concepts related to garbage collection
几百行代码实现一个 JSON 解析器
synchronized 和 ReentrantLock
vSphere实现虚拟机迁移
有谁知道 达梦数据库表的列的数据类型 精度怎么修改呀
MIT博士论文 | 使用神经符号学习的鲁棒可靠智能系统
Building core knowledge points
Getting started with devkit
MYSQL---查询成绩为前5名的学生
Is chaozhaojin safe? Will it lose its principal
Study diary: February 13, 2022
毕设-基于SSM高校学生社团管理系统