| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Python知识库 -> SMPL源码解读 -> 正文阅读 |
|
[Python知识库]SMPL源码解读 |
这是源码的整体结构,先简单说一下各个文件里面是什么。 一、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)关节在蒙皮中对顶点的影响 ? |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/16 5:53:39- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |