当前位置:网站首页>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 为对齐矩阵
这些代码在项目中不存在,只是为了更好的解释公式。
三、肢体驱动流程图
边栏推荐
- MCU realizes OTA online upgrade process through UART
- Xunrui CMS plug-in automatically collects fake original free plug-ins
- Meta AI西雅图研究负责人Luke Zettlemoyer | 万亿参数后,大模型会持续增长吗?
- Arduino hexapod robot
- GNSS terminology
- 毕设-基于SSM高校学生社团管理系统
- 详细页返回列表保留原来滚动条所在位置
- Finding the nearest common ancestor of binary search tree by recursion
- [groovy] XML serialization (use markupbuilder to generate XML data | set XML tag content | set XML tag attributes)
- Promise
猜你喜欢
毕设-基于SSM高校学生社团管理系统
View class diagram in idea
Questions about database: (5) query the barcode, location and reader number of each book in the inventory table
After Luke zettlemoyer, head of meta AI Seattle research | trillion parameters, will the large model continue to grow?
Study diary: February 13, 2022
Some features of ECMAScript
Illustrated network: the principle behind TCP three-time handshake, why can't two-time handshake?
[groovy] compile time meta programming (AST syntax tree conversion with annotations | define annotations and use groovyasttransformationclass to indicate ast conversion interface | ast conversion inte
ADS-NPU芯片架构设计的五大挑战
如何制作自己的機器人
随机推荐
2020.2.13
Some features of ECMAScript
WordPress collection plug-in automatically collects fake original free plug-ins
MYSQL GROUP_ The concat function realizes the content merging of the same ID
关于softmax函数的见解
logstash清除sincedb_path上传记录,重传日志数据
Cloud guide DNS, knowledge popularization and classroom notes
Cf:h. maximum and [bit operation practice + K operations + maximum and]
Arduino hexapod robot
Recursive method to realize the insertion operation in binary search tree
Ubantu check cudnn and CUDA versions
[groovy] JSON string deserialization (use jsonslurper to deserialize JSON strings | construct related classes according to the map set)
[groovy] compile time meta programming (AST syntax tree conversion with annotations | define annotations and use groovyasttransformationclass to indicate ast conversion interface | ast conversion inte
Dedecms plug-in free SEO plug-in summary
SSH login is stuck and disconnected
Modify the ssh server access port number
从 1.5 开始搭建一个微服务框架——调用链追踪 traceId
MCU realizes OTA online upgrade process through UART
Differences between standard library functions and operators
看抖音直播Beyond演唱会有感