当前位置:网站首页>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 为对齐矩阵
这些代码在项目中不存在,只是为了更好的解释公式。
三、肢体驱动流程图
边栏推荐
- Illustrated network: the principle behind TCP three-time handshake, why can't two-time handshake?
- Questions about database: (5) query the barcode, location and reader number of each book in the inventory table
- Recursive method to realize the insertion operation in binary search tree
- 毕设-基于SSM高校学生社团管理系统
- Novice entry depth learning | 3-6: optimizer optimizers
- Lone brave man
- How to make your own robot
- STM32 key chattering elimination - entry state machine thinking
- MCU realizes OTA online upgrade process through UART
- Construction plan of Zhuhai food physical and chemical testing laboratory
猜你喜欢
毕设-基于SSM高校学生社团管理系统
KDD 2022 | 脑电AI助力癫痫疾病诊断
cf:H. Maximal AND【位运算练习 + k次操作 + 最大And】
What is the most suitable book for programmers to engage in open source?
esxi的安装和使用
cf:C. The Third Problem【关于排列这件事】
Cf:h. maximum and [bit operation practice + K operations + maximum and]
Some features of ECMAScript
MIT博士论文 | 使用神经符号学习的鲁棒可靠智能系统
Spark AQE
随机推荐
Novice entry depth learning | 3-6: optimizer optimizers
The population logic of the request to read product data on the sap Spartacus home page
282. Stone consolidation (interval DP)
SSH login is stuck and disconnected
SAP Spartacus home 页面读取 product 数据的请求的 population 逻辑
JMeter BeanShell的基本用法 一下语法只能在beanshell中使用
The value of applet containers
Meta AI西雅图研究负责人Luke Zettlemoyer | 万亿参数后,大模型会持续增长吗?
cf:D. Insert a Progression【关于数组中的插入 + 绝对值的性质 + 贪心一头一尾最值】
A preliminary study of geojson
直播系统代码,自定义软键盘样式:字母、数字、标点三种切换
WordPress collection plug-in automatically collects fake original free plug-ins
JVM_ 15_ Concepts related to garbage collection
朝招金安全吗 会不会亏损本金
For a deadline, the IT fellow graduated from Tsinghua suddenly died on the toilet
The basic usage of JMeter BeanShell. The following syntax can only be used in BeanShell
[pat (basic level) practice] - [simple mathematics] 1062 simplest fraction
How spark gets columns in dataframe --column, $, column, apply
Exciting, 2022 open atom global open source summit registration is hot
Opinions on softmax function