文 / Google 合作伙伴创新计划创意技术专家 Shan Huang
Pose Animator
https://pose-animator-demo.firebaseapp.com/camera.html
PoseNet
https://github.com/tensorflow/tfjs-models/tree/master/posenet
Facemesh
https://github.com/tensorflow/tfjs-models/tree/master/facemesh
Mediapipe
https://mediapipe.dev/
背景
TensorFlow.js 中的 PoseNet 和 Facemesh(来自 Mediapipe)模型通过简单的网络摄像头在浏览器中实现了实时的人类感知。作为一名想要掌握角色动画中复杂技巧的动画发烧友,我看到了希望,同时也感到非常兴奋,迫不及待地想要尝试将这些模型应用于可由身体控制的交互式动画中。
最终我制作了 Pose Animator,一种开源网络动画工具,可通过网络摄像头捕捉的身体检测结果,让 SVG 角色呈现出栩栩如生的效果。本文将介绍 Pose Animator 的技术设计,以及设计师如何基于自身需求创建角色并以动画方式呈现角色的步骤。
开源
https://github.com/yemount/pose-animator
以动画方式呈现全身角色
Pose Animator 的总体思路是采用 2D 矢量图并根据 PoseNet 和 FaceMesh 的识别结果实时更新其矢量曲线。为此,Pose Animator 借鉴了计算机图形技术中骨骼动画的思路,并将其应用于矢量角色。
用于对表皮进行动画处理的一组互连骨骼层级结构。
在 Pose Animator 中,表皮由输入 SVG 文件中的 2D 矢量路径定义。对于骨骼结构,Pose Animator 基于 PoseNet 和 FaceMesh 的关键点提供了预定义的(骨骼层级)绑定表示 (Rig Representation)。在输入 SVG 文件中以及字符插图中指定了此骨骼结构的初始姿态,同时通过机器学习模型的识别结果来实时更新骨骼位置。
来自 PoseNet(蓝色)和 FaceMesh(红色)的关键监测点
查看这些步骤,尝试使用 Pose Animator 创建自己的 SVG 角色。
这些步骤
https://github.com/yemount/pose-animator#animate-your-own-design
由 PoseNet 和 FaceMesh 输出控制的动画方式的贝塞尔曲线
绑定流程概览
完整的绑定(骨架绑定)流程需要以下步骤:
解析输入的 SVG 文件以获取矢量图和预定义的骨架,两者均为 T 姿态(初始姿态)。
遍历矢量路径中的每个分段,使用线性混合蒙皮(Linear Blend Skinning,本文中稍后会作出解释)计算每根骨骼的权重影响和变换矩阵 (Transformation)。
在每个输入帧上实时运行 FaceMesh 和 PoseNet,并使用结果关键点更新骨骼位置。
根据更新后骨骼的位置、骨骼的权重和变换矩阵,计算矢量分段的新位置。
还有其他工具也可提供类似的木偶操作功能,但是,大多数工具仅改变人物图像的位置,而不会通过识别关键点改变角色的实际几何形状。此外,很少有工具能提供全身识别和动画呈现。Pose Animator 能让单条曲线变形,因此十分擅长捕捉面部和全身运动的细微之处,并有望带来更具表现力的动画效果。
绑定定义
绑定结构依照 PoseNet 和 FaceMesh 的输出关键点设计。PoseNet 将返回 17 个全身关键点,非常简单,可以直接包含在绑定中。但是,FaceMesh 将提供 486 个关键点,所以我需要谨慎选择将包括哪些关键点。最后,我从 FaceMesh 输出中选择了 73 个关键点,这样我们就拥有了一个由 90 个关键点和 78 根骨骼组成的全身绑定,如下所示:
90 个关键点,78 根骨骼的全身绑定
每个输入 SVG 文件都应该在默认位置包含这个骨架。更具体地说,Pose Animator 将寻找一个名为“骨骼”的组,其中包含以它们所代表的各个关节命名的锚点元素。可在此处查看绑定 SVG 示例。设计师可以在设计文件中自由地移动关节,让骨骼最理想地嵌入到角色中。Pose Animator 将根据 SVG 文件中的默认位置来计算蒙皮,但有时绑定算法可能无法很好地支持一些极端情况(例如,腿/手臂骨骼非常短),并有可能让呈现的效果不自然。
此处
https://firebasestorage.googleapis.com/v0/b/pose-animator-demo.appspot.com/o/skeleton.svg?alt=media
在设计软件 (Adobe Illustrator) 中嵌入绑定的插图
用于矢量路径的线性混合蒙皮
Pose Animator 通过一种最常用的绑定算法,使用骨骼结构让表皮变形,这种算法称为线性混合蒙皮 (Linear Blend Skinning,LBS),该算法通过将每根骨骼单独控制的变换相混合,再由每根骨骼的影响因子加权,来变换表皮的顶点。在我们的例子中,顶点是指矢量路径上的锚点,骨骼由上述绑定中的两个相连关键点定义(例如,“leftWrist”和“leftElbow”关键点定义了骨骼“leftWrist-leftElbow”)。
要代入数学公式,那么顶点 vi’ 的实际空间位置计算为:
Tj 描述了让骨骼 j 的初始姿态与其当前姿态相一致的空间变换。
骨骼的影响因子可自动生成,也可以通过权重绘制来手动分配。Pose Animator 当前仅支持自动权重分配。顶点 i 上骨骼 j 的原始影响因子计算方式如下:
其中 d 是从 vi 到骨骼 j 上最近点的距离。最后,我们将一个顶点上所有骨骼的权重标准化,使其总和为 1。
现在,要将 LBS 应用于由直线和贝塞尔曲线组成的 2D 矢量路径,我们需要通过进出图柄对贝塞尔曲线分段进行一些特殊处理。我们需要分别计算曲线点、进控制点和出控制点的权重。由于这样可以更精准地捕获控制点的骨骼影响因子,因此会产生更好的外观效果。
这是一个特殊的例子。当进控制点、曲线点和出控制点共线时,我们对这三个点同时使用曲线点权重,以确保在以动画方式呈现时它们仍保持共线。这有助于保持曲线的平滑。
共线曲线手柄共享相同的权重以保持共线
动作稳定性
LBS 已经为我们提供了动画帧,但是 FaceMesh 和 PoseNet 原始输出引入了明显的抖动。为减少抖动,获得更流畅的动画,我们可以使用预测结果中的信任值分数对每个输入帧进行不均匀加权,让信任值较低的帧所带来的影响也较小。
遵循这一思路,Pose Animator 会按如下算式计算关节 i 在第 t 帧的平滑位置
其中
第 i 帧的平滑可信度计算方式如下
考虑极端情况。当两个连续帧的可信度均为 1 时,位置将以 50% 的速度靠近最新位置,这看起来很灵敏且相当平滑。(要进一步提高响应速度,可以通过更改最新帧的权重来调整靠近速度。)当最新帧的置信度为 0 时,其影响将被完全忽略,因此可防止低信任值结果造成的突然抖动。
基于可信度的剪裁
除了使用可信度对关节位置进行插值外,我们还引入了最小阈值来确定是否应该绘制路径。
路径的可信度是其分段点的平均可信度得分,而反过来它又是影响骨骼分数的加权平均值。当特定帧的分数低于特定阈值时,整个路径将被隐藏。
这对于隐藏低信任值区域的路径十分有用,这些区域中往往是镜头范围之外的身体部位。想象一下有一张上半身照:尽管腿部和臀部的关键点预测的可信度很低,但 PoseNet 始终会返回这些关键点预测。通过这种限制机制,我们可以确保下半身被恰当隐藏,而不显示为异常扭曲的路径。
展望未来
是否要网格化
目前的绑定算法主要围绕 2D 曲线。这是因为由 PoseNet 和 FaceMesh 构造的 2D 绑定运动范围较大,且骨骼长度可变,不像游戏中的动画一样,骨骼长度相对固定。目前,让贝塞尔曲线变形所得出的结果比让输入路径中的三角网格变形得出的结果更加平滑,因为贝塞尔曲线可以更好地保持输入线条的曲率/直度。
我很想改进网格的绑定算法。此外,我想探索一种比线性混合蒙皮更先进的绑定算法,因为线性混合蒙皮存在一定限制,如弯曲区域周围的体积减小。
新的编辑功能
在输入 SVG 文件中支持光栅图像,因此艺术家可以在设计中使用照片/绘画作品。图像边框可以轻松地表示为矢量路径,因此可以使用当前的绑定算法直接计算其变形。
自己试一试!
尝试实时演示,您可以在其中处理现有角色,也可以添加自己的 SVG 角色,看它们如何变得栩栩如生。
实时演示
https://pose-animator-demo.firebaseapp.com/
我最盼望看到的是创意社区将创作出哪种类型的交互式动画。尽管演示的是人类角色,但 Pose Animator 可用于任何 2D 矢量设计,因此您可以大胆尝试任何抽象/前卫的设计。
要创建自己的动画插图,请查看本指南!不要忘了在社交媒体上通过 #PoseAnimator# 与我们分享您的创作。如有任何问题,请通过 Github 与我联系。如果想直接查看源代码,可前往 Github 复制。尝试一下吧!
查看本指南
https://github.com/yemount/pose-animator#animate-your-own-design
Github
https://github.com/yemount/pose-animator