做数字人或者动画工具的同学,大概率都听过“人体参数化模型”这个词,但真正能把它讲透的文章其实不多。我最近整理了一套比较完整的学习笔记,准备用一系列文章把它彻底拆开——从为什么需要参数化、到SMPL系列的具体计算链路、再到怎么选型、怎么部署,全部过一遍。系列1先解决最基础也最关键的问题:人体参数化模型到底是什么,SMPL这个家族从哪来的,它内部的参数到底怎么驱动一个三维人体网格,以及你在真实项目里应该怎么上手、怎么避坑。这篇文章适合正在做虚拟人、动作捕捉、游戏角色、虚拟试衣,或者刚刚开始接触三维人体建模和数字人渲染的开发者,就算你对图形学不熟,只要按照文章里的思路走一遍,也能把整套逻辑捋顺。
1. 为什么人体模型非要“参数化”:传统建模模式的三个死穴
1.1 传统手工建模为什么撑不起数字人需求
我们先把问题退回到最原始的场景。想象一下,你需要为某跨平台系统做一个数字人角色。传统做法是什么?建模师在三维软件里拉一个基础人形,再手工雕刻细节,然后做骨骼绑定、刷蒙皮权重,导出一个固定模型。这套流程做一个角色没问题,但一旦需求变成“同一个角色,要高一点、胖一点、腿长一点”,或者“同一套动作,要套到一百个不同体型的用户身上”,传统流程立刻就卡住了——每换一个体型,基本等于重新来一遍建模和绑定。
我在做模拟项目X的时候也踩过这个坑。当时需要给一套试衣系统生成不同BMI区间的虚拟试穿者,如果用传统手工建模,意味着每个体型都要单独准备一套网格,而且顶点数量和拓扑结构都不一样,后续做布料仿真、姿态驱动、测量分析,全部要对齐一遍,工程量成倍增加。这时候“参数化”就成了唯一的出路。
1.2 参数化到底在“参数”什么
人体参数化模型的核心思想,说穿了就是:把一个人体网格,用一个低维向量表示。这个向量通常包含两类东西,一类是体型参数,控制高矮胖瘦;一类是姿态参数,控制关节怎么弯曲旋转。给每个用户量好身高、腰围、臂长之类的数值,通过一套确定的函数关系,就能生成一个符合这些数值的三维人体网格。
生活化类比很好理解,大家在捏人游戏里调整的滑块,本质上就是一个参数化模型的简化版:你拖动“身高”滑块,游戏里的角色顶点位置跟着变化;你拖动“手臂弯曲”滑块,手臂的顶点位置也跟着变化。人体参数化模型就是这种“滑块机制”的专业版本,只不过这些滑块背后的运算不是美术手调的,而是从大量真实人体扫描数据里统计出来的规律。
1.3 参数化模型的关键收益
用参数化模型,你只需要维护一组参数,而不是维护一整套网格。同一套蒙皮逻辑、同一套顶点拓扑,可以在不同体型的人之间复用。这样你做的表情系统、布料系统、动捕重定向系统,全都变成了“参数输入-网格输出”的流水线,而不是“每个角色定制一套”。
这一点的价值怎么强调都不过分:它把“做一个人体”的成本,从以周为单位的手工创作,压缩到了以毫秒为单位的数值计算。
2. 人体参数化模型的“前世”:从手工雕刻到统计形状建模
2.1 把人体当成一组可统计的数据
你可能好奇,SMPL 那一堆参数是从哪来的?它不是一个拍脑袋设计出来的公式,而是从大量真实人体数据里统计出来的。这就要说到早期统计形状模型的思路。
早年做二维人脸识别和人体检测的研究者,已经把“统计形状模型”用得很熟了。思路是这样的:采集一堆同类的形状,把它们对齐到同一个坐标系、同一套顶点编号,然后对顶点坐标做统计分析,找出形状变化的主要方向。每个方向对应一个“主成分”,比如第一个主成分可能主要是高矮,第二个主要是胖瘦,第三个可能是腿长比例的差异等等。把这些人体的共性统计出来之后,任何一个新的人体形状,都可以用“平均形状 + 若干主成分的线性组合”来逼近。
2.2 三维扫描时代的建模思路升级
二维时代受限于图像信息,做起来比较吃力。真正让这件事发生质变的,是高精度三维扫描设备的普及。有了三维扫描仪之后,研究者可以拿到大量真实人体的完整三维网格,而不是从照片里猜深度。
这里的关键步骤是“对齐”。每个被扫描的人,姿态不同、体型不同,扫描出来的网格拓扑也完全不一样。为了在同一套顶点编号下做统计,就必须有一个模板网格,把它通过非刚性变形的方式“贴合”到每一个扫描数据上。这个步骤在学术上叫非刚性配准。经过这一步之后,一千个不同的人体,就变成了一千个“顶点编号完全相同、顶点坐标不同”的网格。只有在这种对齐之后的数据上做PCA,得到的参数空间才有意义。
2.3 为什么需要姿态和体型拆开建模
早期模型往往把姿态和体型混在一起处理,这样会产生一个很尴尬的问题:一个站直的人和一个弯腰的人,即使体型完全一样,统计出来的“形状主成分”也会被姿态干扰,导致你很难单独控制“高矮”和“弯曲”。
后来研究团队意识到,必须把姿态变化也从形状统计里分离出去。换句话说,先估计出人体当前姿态,把所有扫描数据都“摆正”到统一姿态,再做体型统计;然后再单独从姿态数据里学习“姿态变化会导致网格表面哪些局部鼓起或塌陷”的规律。这个思路直接影响了后续经典模型的设计框架,也是为什么今天的主流模型都把参数分为体型和姿态两大类。
2.4 “模型”也不止一个,只是SMPL生态最完整
这个领域其实有多个模型演进分支,有些偏人体形状重建,有些偏蒙皮驱动,有的带手部,有的带面部。只是从工程生态、开源资料、社区使用量等角度来看,SMPL 这一支的积累最厚,配套的代码、模型文件、下游应用也最多,所以它成了事实上的“通用语言”。做这个领域研究或开发,绕不开它。
3. SMPL家族逐项拆解:基础版、手部扩展版、全身高精度版
3.1 三个成员到底差在哪
SMPL 全称是“Skinned Multi-Person Linear Model”,它的核心是“线性”:网格顶点的位置变化,主要由体型和姿态的线性叠加决定,加上最后的线性蒙皮变换。它发布于2015年前后,到今天仍然是学术和工业用得最广的人体表示之一。后来为了精细化和扩展,团队又做了带手部关节的版本,以及覆盖全身和面部表情的版本。为了方便对比,我把它们的差异列成了一张表。
| 模型 | 顶点规模(约) | 三角面片数(约) | 核心参数 | 能做什么 |
|---|---|---|---|---|
| SMPL 基础版 | 6890 | 13776 | 体型β(常用10维)+ 姿态θ(24个关节旋转) | 全身大体型与姿态驱动 |
| SMPL+H | 约7753 | 约15400 | 在SMPL基础上增加双手关节建模 | 需要精细手部动作的场景 |
| SMPL-X | 10475 | 20908 | 体型β + 姿态θ + 表情ψ + 手部关节 | 数字人全身+面部表情的完整表达 |
注意,上表的顶点数和面数是模型本身的网格规模,不直接代表精度高低。SMPL-X 之所以顶点多、面数多,是因为它额外包含了面部、眼球、牙齿、手指等精细结构,这些结构在基础版里是没有的。
3.2 基础版SMPL:姿态与体型的解耦
SMPL 基础版是最容易上手的一个。它把人体抽象成 24 个关节节点,每个关节用 3 个旋转数值表示,姿态参数总维度是 72。体型参数则默认用 10 个数值表示,这 10 个数值就对应PCA主成分的系数,控制身高、体重、比例等变化维度。如果需要更精细的体型差异,官方扩展版本还提供高达300维的体型参数。
对大多数项目来说,10维体型参数已经足够产生肉眼能看出明显差异的各种体型。我一开始做测试的时候会故意把体型参数调到±3,结果能生成非常极端的身材。实际业务里一般只需要在±1范围内微调,就已经能满足“同一个人形,不同BMI”的试衣或游戏需求。
3.3 手部扩展与SMPL-X的工程价值
之所以要有 SMPL+H,是因为基础版的手部只有两个顶点很少的关节球形状。拿这种手去做手势识别、抓取仿真、手语生成,效果肉眼可见地不准。SMPL+H 在每只手上增加了几十个额外关节点和精细网格,手部动作的表达能力瞬间提升一个档次。
SMPL-X 则是在 SMPL+H 的基础上继续叠加了面部表情参数。它把人脸表情建模成一组低维系数,可以和语音驱动、面部捕捉系统对接。对于要做高真实感虚拟主播、数字代言人、线上互动角色的团队来说,SMPL-X 是比基础版更合适的起点。当然,模型越精细,计算量也越大,后续无论做渲染还是做姿态回归,都要有一定算力支撑,这是选型时必须权衡的。
4. 核心链路拆解:β、θ、蒙皮权重如何共同决定一个人体网格
4.1 从参数到网格的总公式
很多人听说过 SMPL,但不知道它内部是怎么算的。其实它的核心计算链路可以用一个公式概括:
M(β, θ) = W( T_p(β, θ), J(β), θ, W )拆开看就是:模型接收体型参数 β 和姿态参数 θ,先计算出一个“处于标准姿态、但已经带上个人体型特征”的模板网格 T_p;再根据 β 计算出关节位置 J;然后通过蒙皮权重 W,把标准姿态下的网格按照 θ 的旋转变换到最终姿态。W 在这里既是蒙皮权重,也是线性蒙皮函数的名字。
4.2 先叠加体型:T_p = T̄ + B_s(β)
初始模板 T̄ 是一个平均人体网格,代表“标准人”的默认形状。体型参数 β 的作用,就是在平均网格的每个顶点上叠加一个偏移量。这个偏移量是由一组预计算好的“体型混合形状”决定的:
B_s(β) = Σ β_i * S_i其中 S_i 就是PCA分析得到的主成分,比如第1个主成分可能是“整体胖瘦”,第2个可能是“肩宽变化”,第3个可能是“腿长比例”。每个主成分都是一组顶点偏移向量。当你把10个主成分按各自系数叠加起来,得到的偏移量加到平均网格上,就是这个人的体型。
这一过程是线性的,所以计算起来很快。也正因为是线性叠加,体型参数稍微调大一点,就会出现很夸张的效果,这是正常的,不代表模型坏了。
4.3 再叠加姿态混合形状:B_p(θ)
接下来是姿态参数 θ。为什么不能直接对标准姿态网格做关节旋转?因为人体在运动时,不只是骨头在转,肌肉和皮肤还会因为挤压或拉伸产生局部隆起。比如你屈肘时,上臂前侧的肌肉会鼓起;弯腰时,腹部的皮肤会堆叠。如果只做关节旋转,这些真实的局部形变就全丢了。
SMPL 的处理办法是:预先从动捕数据里学习一组“姿态混合形状”。每种关节旋转组合,都会对应一组顶点偏移。当输入一个特殊姿态 θ 时,模型会计算当前的姿态变化量,然后从姿态混合形状里查表式地叠加一个偏移量:
B_p(θ) = Σ (θ_j - θ_j^0) * P_j这部分是非线性的,但因为形态上是“线性叠加姿态矩阵”,所以整体计算仍然可控。
4.4 蒙皮权重与线性蒙皮变换
模板网格准备好之后,需要把关节旋转真正作用到每个顶点上。SMPL 用的是线性蒙皮(Linear Blend Skinning)。每一个顶点都有一个权重向量,表示它分别受哪些关节影响、影响程度多大。比如手肘附近的顶点,一部分权重分配给上臂关节,一部分分配给前臂关节;手掌上的顶点,则基本全部分给前臂关节或手部关节。
对每个顶点来说,最终的坐标等于它受所有相关关节旋转影响后的加权平均。这个操作本身不复杂,却决定了模型在极端姿态下会不会出现“关节处塌陷”或者“皮肤拉伸得离谱”的问题。SMPL 之所以效果好,很大程度上就是蒙皮权重的初始化和优化做得比较到位。
4.5 关节位置也不是随便定的
还要注意,SMPL 的关节位置不是手工标注的,而是通过一个回归矩阵,从变形后的网格顶点里算出来的。这样才能保证:当你改变体型参数时,关节位置也跟着变化——胖子的膝盖和瘦子的膝盖位置肯定不一样。这一步如果做错了,就会出现“体型变了但关节还在老位置”的明显失真。
5. 参数不是拍脑袋设计出来的:模型是怎么“练”出来的
5.1 先要有大量对齐的人体数据
前面已经提到,训练一套人体参数化模型,数据是第一关。需要采集成百上千个不同年龄、不同性别、不同体质指数的志愿者的三维扫描数据,每人还要摆出多种标准姿态。采集时通常还会同步录制动捕数据,用来获取关节旋转信息。
这个环节很容易被低估。数据量不够、覆盖人群不全、姿态种类太少,都会导致统计出来的PCA主成分无法泛化到新样本上。一个只在欧美人群数据上训练的模型,应用到亚洲人群体检数据时,体型空间就很容易出现偏差。这一点做产品的时候要格外留意。
5.2 非刚性配准:把模板“贴”到每一具扫描上
有了扫描数据,下一步是让模板网格与每一具扫描高精度对齐。这个对齐不是简单做刚性变换,而是要允许模板网格的每个顶点局部移动,去贴合扫描表面细节。但在贴合的同时又要保持网格拓扑结构稳定,不能出现翻转面、过于拉伸的三角形。
这类非刚性配准算法在实现上有很多细节,比如正则化项怎么写、怎么防止顶点漂移、怎么处理衣物遮挡等。对SMPL这种模型来说,模板网格的对齐质量直接决定了后续PCA的可靠程度。这也是为什么不同团队做出来的模型即使原理相同,效果差异却很大的原因——数据清洗和配准的质量占据了大部分功劳。
5.3 姿态混合形状和蒙皮权重的联合优化
体型PCA做完之后,还要做姿态混合形状和蒙皮权重的联合优化。这个过程通常需要一批同时包含三维网格和动捕数据作为监督的样本。算法通过最小化“模型输出网格与真实扫描网格的顶点距离”,同时估计出姿态混合形状矩阵、蒙皮权重和关节回归矩阵。
训练结束后的最终产物,就是一套固定张量:平均模板、体型混合形状、姿态混合形状、蒙皮权重和关节回归矩阵。你在代码里加载模型文件时,加载的就是这些张量。明白了这一点,就不会再把SMPL模型当成某种黑盒“AI模型”,它本质上更像是一套经过统计优化和校准的数值表达系统。
5.4 模型文件与通用标准
工程中最常遇到的一个问题是:拿到手的是不同版本、不同性别、不同参数空间的模型文件,怎么对齐使用?这里有一个实践原则:尽量统一使用同一个模型版本和参数配置。比如你要跑虚拟试衣,就固定用SMPL中性模型和10维β;你要做表情数字人,就统一用SMPL-X。跨版本混用,顶点索引对不上,后面所有处理都会出错。
6. 高频应用场景与最简上手流程:从安装到跑出一帧数字人
6.1 六类高频场景
人体参数化模型的应用范围远比我最初以为的要广。按我实际观察和参与过的情况,可以粗略分成以下六类。
| 应用场景 | 典型需求 | 主要使用的参数 |
|---|---|---|
| 游戏与动画 | 角色快速换体型、换动作 | β + θ |
| 数字人与虚拟主播 | 全身动作+面部表情联动 | β + θ + ψ |
| 虚拟试衣 | 生成不同尺码的试穿者 | β 为主 |
| 动作捕捉重定向 | 从动捕数据驱动人体模型 | θ 为主 |
| 人体测量与工效学 | 测量围度、体表尺寸 | β 为主 |
| 自动驾驶与机器人仿真 | 生成多样化行人姿态 | β + θ |
注意,这些场景之间并不互斥。比如虚拟试衣系统也可能需要姿态参数把人摆出展示动作,只是核心变量不同。理解自己的“主参数”是哪一个,对选型会很有帮助。
6.2 最小上手流程:用Python库生成一个人体网格
现在用开源库跑通一个最小示例,大概只需要几步。首先安装依赖:
pip install smplx torchSMPL 官方模型文件需要申请下载,拿到之后放在本地目录。下面的代码会生成一个随机体型、随机姿态的人体网格:
import smplx import torch model = smplx.create( model_path="models", # 存放SMPL模型文件的目录 model_type="smpl", gender="neutral", num_betas=10, use_pca=False, batch_size=1, ) # 初始化体型参数,范围控制在0.1以内,避免极端体型 betas = torch.randn(1, model.num_betas) * 0.1 # 随机一个身体姿态,维度以模型实际输出为准 body_pose = torch.randn(1, model.body_pose.shape[1]) * 0.1 global_orient = torch.randn(1, 3) * 0.1 output = model( betas=betas, body_pose=body_pose, global_orient=global_orient, ) verts = output.vertices.detach().numpy()[0] # (6890, 3) joints = output.joints.detach().numpy()[0] # (24, 3)这里有两个容易踩的细节。第一,body_pose的维度在不同实现里可能有差异,有的实现是63,有的是69,这和内部关节定义有关。写代码时不要硬编码维度,直接从model.body_pose.shape读,最稳妥。第二,use_pca=True时姿态参数会被压缩成低维表示,适合动作捕捉输出;而use_pca=False时是原始轴角参数,更适合当你已经有关节角度、需要精确驱动模型时使用。
6.3 生成后怎么检查结果
拿到顶点数组之后,建议先用可视化工具把它渲染出来看一眼,不要直接进下游。常见的检查项包括:人体比例是否合理、有没有网格自穿插、姿态是否符合预期、关节是否落在合理位置。如果你发现下图中人变成了一团乱麻,多半是姿态参数范围太大,或者姿态树索引对不上。
从我的经验来看,第一次跑通后最容易犯的错是用随机参数生成姿态,结果歪七扭八,然后误以为是模型坏了。实际上模型没问题,是参数范围没有控制在合理区间。随机参数做烟雾测试可以,但正式的动画或者试衣流程里,姿态最好来自动捕、动作库或者手动设定的关键帧。
6.4 模型输出如何接到渲染引擎
获得网格顶点之后,还需要知道网格的三角面片索引,才能渲染出来。这个索引在SMPL模型文件里自带,一般叫faces。拿到verts和faces之后,可以直接导出成OBJ、FBX,或者用游戏引擎的网格接口直接构建一个网格对象。这里有个小提醒:不同引擎的坐标系和单位制不一样,比如有的引擎Z轴向上,有的Y轴向上;有的视图单位是米,有的是厘米。接入时先做一次坐标系和缩放的统一,能省掉后面大量对不齐的麻烦。
7. 选型建议与学习路线:从你的问题倒推该用哪个模型
7.1 先想清楚你要解决的“主问题”
不要一上来就问“该研究哪个模型”,要先问“我的核心问题是姿态驱动、体型变化、手部动作,还是面部表情”。这个问题答案基本决定了选型方向,我整理了下面这张决策表。
| 核心需求 | 推荐模型 | 理由 |
|---|---|---|
| 全身大体型变化、基础动作 | SMPL 基础版 | 轻量、生态最完整 |
| 手势识别、抓取、手语 | SMPL+H | 手部关节足够丰富 |
| 高真实感数字人、虚拟偶像 | SMPL-X | 全身+表情一体 |
| 快速原型验证、课程学习 | SMPL 基础版 | 最容易理解、资料最多 |
| 高精度工业级虚拟试衣 | SMPL-X 或其他扩展 | 可扩展鞋服、表情等语义 |
这里再多说一句:模型不是“越大越全越好”。SMPL-X 比基础版好,但它对动捕数据的对齐要求也更高,如果你手里只有全身姿态的动捕数据,没有面部捕捉数据,SMPL-X 的头面部表情参数反而变成空转的额外开销,白白增加计算量。
7.2 一条比较稳的学习路线
如果你完全是从零开始,我建议按下面这条路线走,别一上来就啃训练代码:
- 先把 OpenAI 开源库或类似封装库的最小示例跑通,生成几个不同β、不同θ的人体。这一步的目标是建立“参数->网格”的直觉。
- 把同一个模型的不同参数组合导出成OBJ,在三维软件里切开看看顶点数量、拓扑结构,理解“同一套拓扑”意味着什么。
- 阅读SMPL论文的方法部分,重点看懂公式里的每一部分,回到第4节的内容找一个顶点,尝试手工推导它的最终坐标。
- 跑一个简单的姿态回归任务,比如从2D关键点估计β和θ,把“网格输入-参数输出”的反方向也打通。
- 最后再考虑训练自己模型的进阶内容,比如自己采集数据、做非刚性配准、做PCA。
7.3 常见的学习误区
有一些误区我在实际带人做项目时反复遇到,在这里一起说清楚。
第一个误区,是试图完全绕开数学推导。其实你不需要把论文里所有优化细节都推一遍,但至少要能看懂“线性叠加偏移量”和“蒙皮权重加权平均”这两个基本逻辑。如果你连顶点是怎么算出来的都不清楚,后面做自定义蒙皮、自定义表情、模型拼接的时候会非常痛苦。
第二个误区,是把参数化模型当成最终成品直接上线。真实项目里,光有一层人体网格是不够的,还需要材质贴图、头发、衣服、配饰、动画系统。人体参数化模型通常只是整个管线里的“地基”,而不是全部。
第三个误区,是忽略不同模型之间的顶点序和命名差异。同一个SMPL文件,在不同库之间重建时,顶点顺序可能被打乱;不同性别模型文件之间也存在差异。有些算法结构上没问题,实际跑起来却对不上,原因就是顶点顺序没有统一。建议一开始就把模型文件、顶点索引、面片索引固定下来,通过统一的预处理步骤进入下游。
7.4 系列规划预告
这一篇主要是理论基础和整体框架。后面我打算继续写几个方向:SMPL-X 的完整参数解析和表情驱动;从单目视频回归人体参数化模型的实战流程;参数化模型在布料仿真和虚拟试衣里的具体接入方式;以及多视角动捕数据如何重定向到SMPL。每个方向都会结合实际跑过的流程和踩过的坑来写,保证能直接照着做。
最后再分享一点个人体会。人体参数化模型这套东西,最让我觉得“通了”的时刻,不是看懂了论文公式,而是自己动手把一个随机的体型参数调小、调大,再叠加一个弯腰姿态,可视化之后眼睁睁看着网格顶点跟着变化。那种“参数在驱动形状”的感觉一旦建立起来,后面很多事情就好办了。如果你现在连一个SMPL模型都还没跑起来,这篇文章读完以后最应该做的事,就是去装一个库、加载一个人体模型、改两个参数、导出看一眼。看一次,比读十篇博客都管用。