SMPL源码解读

article/2025/9/28 5:15:55

这是源码的整体结构,先简单说一下各个文件里面是什么。

一、models文件

包含3个模型的.pkl文件,.pkl文件是python提供的可以以字符串的形式记录对象、变量的文件格式。这个模型里面包括了:

1.'J_regressor_prior':关节回归矩阵的先验,保存形式为CSC(用array保存的稀疏矩阵)

2.'f':面信息(三个顶点为一组表示面片的组成)

(不是全部,有省略)

3.'J_regressor':关节回归矩阵,保存形式CSC

4. 'kintree_table':关节树表

5.'J':关节位置

6.'weights_prior':蒙皮权重先验

7.'weights':蒙皮权重

8.'vert_sym_idxs' :顶点索引

9.'posedirs':姿势矫正

10.:姿势矫正蒙皮方式

11.'v_template':T pose 顶点信息

12.'':形状矫正

 13.形状矫正蒙皮方式:

以上内容都有省略,但其实只需要知道有什么就行了,具体数字不重要(人眼也看不出意义),感兴趣可以用自己用下面代码写个脚本查看

注释掉的是用来显示全部内容,并写到.txt里面,用的时候记得改文件路径

 

二、smpl_webuser

可以看到里面还有个文件夹hello_world,里面两个脚本hello_smpl.py和render_smpl.py,这是作者提供的示例代码,可用其生成自己设定shape、pose参数的模型,区别是hello_smpl.py是直接生成.obj文件,render_smpl.py是直接渲染在屏幕上;个人觉得用meshlab或者Blender查看.obj比较舒服,所以只介绍hello_smpl.py。

hello_smpl.py

 可以看到很简单,先用写好的load_model方法,读出.pkl文件的内容,然后将里面的m.r(定点信息)和m.f(面信息)写进.obj,meshlab既可以根据这两个信息渲染出最终的模型。

所以重点放在其他几个脚本上,lbs.py, posemapper.py, serialization.py, verts.py,一共四个脚本

我根据正须(整体调用顺序)推一遍各个脚本和里面函数的作用。

1.serialization.py

脚本名可翻译为串行化,前面也提到这个名词,串行化,就是python用来将对象、变量转换成字符进行存储,所以里面是关于模型存储、读取的方法。

(1)存储模型

 (attribute  n.属性)

可以看到,就是检查model里面的内容,再写进新的文件里。

 

(2)命名规范检查

 对模型的参数可能存在的不同的命名进行检查,并规范化,算是提高复用性

(3)模型初始化(更添加顶点信息 &更新 形状修正后的关节点信息)

 在 if want_shapemodel:这一行之前,都是在加载,判断,添加修改 传入的数据,都是直接调用库里的函数。

之后,通过将数据里的'shapedirs'(形状纠正)和'beta'(形状参数)点乘,加上'v_template'(T pose定点信息),得到形状修正后的定点信息'v_shaped'。

再用'J_regressor'和'v_shaped'计算出形状矫正后的新的关节位置'J'。

 'v_posed'的计算中调用了其他脚本的方法'posemap',等下再看

最终这个方法的作用是根据数据里的'posedirs'&'shapedirs'计算出'v_posed' & 'J',并更新\添加到原来的数据文件中。

(4)模型加载

首先调用方法(3)读取.pkl文件中的'v_posed' & 'J'以及其他信息,然后将.pkl中的参数按照名称建立成字典。verts_core是一个重载函数,主要作用是在蒙皮过程中模型空间和世界空间进行转换,返回值是顶点息和Jtr,具体之后分析。setattr将未进行坐标转换的定点信息作为属性k,添加到result。所以最后返回的加载模型得到的result包含了顶点的模型空间和世界空间内的坐标(疑问:其他信息呢?hello_smpl.py里明明还对。

2.posemapper.py

接下来先看在初始化模型中调用的posemap函数,已知这个是用来计算pose参数的

 

 

 有三个方法,但主要都是为第二个方法lortmin()服务,lortmin是一个很复杂的计算(没看懂),用到了罗德里斯公式,输出的是一个一维向量,这个向量与pose参数相乘后和posedirs矩阵点乘,这个脚本是用来将pose参数(旋转轴角,而且非线性)转换为线性可插值的旋转矩阵。

从纬度的计算看,

的结果是Nx3,从公式里可之'posedirs'也就是P的纬度是3Nx9K,''pose'向量在模型初始化的方法里初始化的3K,可以推导出'lortmin'的纬度是3x9x1,也符合旋转矩阵的表达形式(将3维的周角转换成3x3的旋转矩阵)。

3.verts.py

前面load_model中用到的重载函数verts_core(**args)也在该脚本调用。先看这个。

这个方法我这里只截图了命名,内容上也是根据已知的posedirs和shapedirs算出v_posed和J,其中的J的回归矩阵对是否为系数矩阵进行了判断,可能是为了防止有的模型定义变量名的不同。其他跟模型初始化的内容一样。作者给的注释是

其他地方也没有调用这个方法,应该是个模型定义的备选项

 这里是被调用的重载函数的定义,假定了蒙皮形式为线性蒙皮和参数状态。

整个脚本就是先假定一下smpl的T pose 和 J 和 蒙皮形式。
 

4.lbs.py

(1)将模型从模型空间转变到世界空间

 通过对kintree_table的按列读取,确定每个关节的parent

 从kintree_table按列看,即可得知关节之间的父子关系

 

 lambda 是方法的简写,冒号前为变量,后面为函数体,.vstack()是按列方向排列,result[0]是通过罗德里斯公式,得到0关节在世界坐标系的位置。因为0关节没有parent,其世界坐标和模型坐标是一样的。所以没有运算,只是通过行列排列即可得到。

for循环对每个关节,通过点承消去parent对自身坐标的改变,得到关节在世界坐标中的位置。

排列后得到所有关节世界位置组成的矩阵result_global。

 再将世界坐标逐个点乘parent的坐标得到关节在模型坐标中的位置。返回最终结果

(2)关节在蒙皮中对顶点的影响

 


http://chatgpt.dhexx.cn/article/cVMqN2IM.shtml

相关文章

SMPL 人体模型简要

smpl是指2015 马普的一篇文章“SMPL: a skinned multi-person linear model”中构建的人体参数化三维模型,人体可以理解为是一个基础模型和在该模型基础上进行形变的总和,在形变基础上进行PCA,得到刻画形状的低维参数——形状参数&#xff08…

SMPL-论文解读

文章目录 创新点算法shape blend shape:pose blend shapeJoint locationSMPL model 训练过程Pose Parameter Trainingjoint regressorShape Parameter TrainingOptimization summary DMPL实验结论 论文: 《SMPL: A skinned multi-person linear model》…

SMPL模型进阶

SMPL模型是一种参数化人体模型,是马普所提出的一种人体建模方法,该方法可以进行任意的人体建模和动画驱动。这种方法与传统的LBS的最大的不同在于其提出的人体姿态影像体表形貌的方法,这种方法可以模拟人的肌肉在肢体运动过程中的凸起和凹陷。…

SMPL源代码实现和模型解读

对于SLAM的工作已经告一段落了,传统的人体动态三维重建也要告一段落了,由于课题研究的方向是基于图像\视频的人体三维重建,三维shape、pose的恢复:所以今天和大家交流的是SMPL模型,对于SMPL模型的理论部分欢迎大家交流…

SMPL简析

SMPL模型是一种参数化人体模型,是马普所提出的一种人体建模方法。这种方法可以模拟人的肌肉在肢体运动过程中的凸起和凹陷。因此可以避免人体在运动过程中的表面失真,可以精准的刻画人的肌肉拉伸以及收缩运动的形貌。 该模型可以通过身体形状参数和姿势参…

SMPL学习笔记

文章目录 前言一、SMPL概述1.形状参数( β \beta β)2.姿态参数( θ \theta θ) 二、体姿转换过程原理1.基于形状的混合成形(Shape Blend Shapes)2.基于姿态的混合成形 (Pose Blend Shapes)3.蒙皮 (Skinning) 三、具体过程分析1.基于形状的混合成形2.基于姿态的混合成形3.骨骼点…

Java的生产者消费者模型

前言 学完了线程后,我又去找了一些线程相关的练习题来练手,其中印象最深的就是生产者消费者模型这一块,为什么呢,因为它每一篇练习题里都有,开始没看懂,后面就去仔细研究了一下,哦,…

多线程之生产者消费者模型

生产者消费者模型 1.为什么要使用生产者和消费者模式2.案例 1.为什么要使用生产者和消费者模式 在线程开发中,生产者就是生产线程的线程,消费者就是消费线程的线程。在多线程开发中,如果生产者如理数据很快,消费者处理数据很慢&am…

生产者消费者模型(多线程工作)

目录 1.模型前提 2.阻塞队列(消费场所) 3. 实验 4.有关效率 1.模型前提 以单生产者对单消费者为例子: 前提一:有一个缓冲区作为消费场所。 前提二:有两种功能不同的线程分别具有消费与生产的能力。 前提三&…

生产者消费者模型的实现(线程通信)

✅作者简介:我是18shou,一名即将秋招的java实习生 🔥系列专栏:牛客刷题专栏 📃推荐一款模拟面试、刷题神器👉 [在线刷题面经模拟面试](在线面试刷题) 目录 实现一: 实现二: 实现一…

生产者消费者模型【新版】

目录 啥是生产者消费者模型? 生产者消费者模型存在问题??如何进行解决呢?? 生产者消费者模型导致的问题 什么是阻塞队列 生产者消费者模型优点 生产者消费者模型实现 Message MessageQueue 获取消息get方法 生产消息take方法 测试生产者消费者模型 啥是生产者消…

【Linux】生产者消费者模型

文章目录 一. 什么是生产者消费者模型1. 基本概念2. 三种关系3. 再次理解生产者消费者模型 二. 生产者消费者模型的优点三. 基于BlockingQueue的生产者消费者模型1. 准备工作2. 阻塞队列实现3. 测试阻塞队列4. 阻塞队列完整代码5. 关于改进阻塞队列的几点补充5.1 多生产者多消费…

生产者与消费者模型

1、【什么是生产者与消费者模型呢?】 一种重要的模型,基于等待/通知机制。生产者/消费者模型描述的是有一块缓冲区作为仓库,生产者可将产品放入仓库,消费者可以从仓库中取出产品,生产者/消费者模型关注的是以下几个点&…

生产者消费者模型——C语言代码详解

概念 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据…

【Java总结】生产者消费者模型

生产者消费者模型主要结构如下,是一个典型的线程同步的案例。下面就来使用java做几种线程同步的方式来实现以下该模型 确保一个生产者消费者模型的稳定运行的前提有以下几个 生成者应该具备持续生成的能力消费者应该具备持续消费的能力生产者的生成和消费消费有一定…

【设计模式】生产者消费者模型

带你轻松理解生产者消费者模型!生产者消费者模型可以说是同步与互斥最典型的应用场景了!文末附有模型简单实现的代码,若有疑问可私信一起讨论。 文章目录 一:为什么要使用生产者消费者模型?二:生产者消费者…

模拟生产者消费者模型

生产者消费者是多线程很经典的一个模型 牵涉三个对象:仓库、生产者、消费者 仓库代表共享变量 生产者表示在仓库生产货物 消费者表示从仓库拿出货物 实现思路:利用synchronizedwait()notify() 对生产者消费者对应的操作用synchronized关键字保证线程安全…

生产者消费者模型java实现

做题的时候遇到了生产者消费者问题,这个问题可以说是线程学习的经典题目了,就忍不住研究了一波。它描述是有一块缓冲区(队列实现)作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品。在Java…

生产者消费者模型详解以及实现

生产者消费者模式 我们先来看看什么是生产者消费者模式,生产者消费者模式是程序设计中非常常见的一种设计模式,被广泛运用在解耦、消息队列等场景。在现实世界中,我们把生产商品的一方称为生产者,把消费商品的一方称为消费者&…

Java生产者消费者模型的五种实现方式

转自:https://juejin.im/entry/596343686fb9a06bbd6f888c 前言 生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一个存储空间,生产者往存储空间中添加产品,消费者从存储空间中取走产品&#xff0c…