视频人体姿态怎么做三维可视化?2D关键点、深度局限与技术选型

动作分析页面里,一张人像提取出肩、肘、腕、膝、踝关键点后,很容易画出一个"正面看起来对齐"的人偶。继续让人偶转 90°,问题才出现:手臂可能穿过躯干,左右脚的朝向不一致;转到背面,原视频根本没有拍到的部位却被画得十分确定。正面投影正确与三维形体正确,不是同一件事。

本文用一组完全合成的 200×400 画面关键点做实验:左腕位于 (87,25),分别给它 z=0、z=+0.2、z=-0.2 三种深度假设。三个模型在正面都落回 x=87,转到 90° 后却分别落在 x=100、120、80。先把这种不可辨识性讲清楚,再讨论坐标、左右语义、手鞋细节和验收,才不会把一个解释性预览误当成"还原了真人"。

示例采用 Python 3.11+ 标准库做几何计算,浏览器预览可用 Three.js 正交相机实现。文中的输入均为合成坐标,不涉及真人画面;可运行的实验和预期结果见下文。

目录

  1. 问题不在旋转动画,而在输入信息不足
  2. 二维关键点怎样进入三维坐标系
  3. 为什么正面正确不代表侧面正确
  4. 左右手、遮挡和手鞋细节如何处理
  5. 技术路线怎么选,哪些结果不能承诺
  6. 用合成姿态做回归和上线验收
  7. 小结与参考资料

一、问题不在旋转动画,而在输入信息不足

常见的 2D 姿态模型输出的是图像平面上的关键点位置,可选附带关键点置信度。以 17 点人体骨架为例,左肩、右肩、左腕、右腕、左右脚踝各有明确索引;输出中的第三个数如存在,通常是可见性或置信度,不能直接拿来当物理深度 。Ultralytics 的姿态文档也将 xy 定义为像素坐标,将 data 的可选第三分量说明为可见性/置信度。Ultralytics 姿态估计文档

对于单张照片里的左腕 (87,25),相机前方或后方的不同三维位置,都可能投影到同一个像素。旋转展示相当于主动询问"它究竟在身体前面还是后面",而原始输入没有给答案。程序可以分配一个深度,使画面能转起来;分配值是建模先验,不是测量结果。

画面症状 更可能的原因 第一项排查
正面人物左右颠倒 视频镜像、坐标或左右索引混用 在输入帧标出有语义的左/右腕,再回投影
侧面手臂穿过躯干 深度次序由固定常数猜测 同角度分别渲染 z=0/±0.2
鞋尖反向或鞋底漂浮 踝点被当成整只鞋 单独核对鞋尖线索、地面和鞋模型朝向
背面出现"准确"衣着 看不见的区域被外观模板补全 标注为示意,不以此进行身体测量

图1:同一套二维关键点能约束正面投影,但侧面和背面的深度、表面与遮挡需要额外证据。

二、二维关键点怎样进入三维坐标系

先约定坐标,否则"左手反了"甚至无法定位是模型问题还是显示问题。示例帧宽 200、高 400,图像原点在左上角,x 向右、y 向下。用于显示的坐标把原点移到画面中心,让 x 向右、y 向上,规定 100 像素对应 1 个展示单位:

text 复制代码
X = (x - 100) / 100
Y = (200 - y) / 100
Z = 单独提供的深度假设

所以左腕 (87,25) 变成 (-0.13, 1.75, Z)。把这个点放进正交相机,在 0° 回投影,应该仍得到 x=87。选择正交相机是为了使本例的展示比例不随点到相机距离变化,便于隔离深度歧义;若用透视相机,景深和相机内参也要一并校准。Three.js 正交相机文档

下面是完整的最小计算。真实项目还要根据画面裁切、人物包围框和预览目标区域设定统一缩放;切忌每帧重新按人体高度归一化,否则人物会在连续播放时忽大忽小。

python 复制代码
import math

def lift(x, y, depth, confidence):
    if confidence < 0.5:
        raise ValueError("low-confidence joint")
    return ((x - 100) / 100, (200 - y) / 100, depth)

def turn_y(point, degrees):
    x, y, z = point
    a = math.radians(degrees)
    return (x * math.cos(a) + z * math.sin(a), y,
            -x * math.sin(a) + z * math.cos(a))

def screen_x(point):
    return round(100 + point[0] * 100, 2)

for depth in (0, 0.2, -0.2):
    wrist = lift(87, 25, depth, 0.95)
    print(depth, screen_x(wrist), screen_x(turn_y(wrist, 90)))

预期输出:

text 复制代码
0    87.0 100.0
0.2  87.0 120.0
-0.2 87.0 80.0

这里的 0.95 只负责判断该关键点能否使用,并没有参与深度计算;0.2 才是人为设定的深度。生产实现中应分别保存这两类字段,避免一个含义不明的 z 被下游当成测量值。

图2:左腕从图像坐标 (87,25) 映射为展示坐标 (-0.13,1.75,z),其中 z 必须标明来源。

三、为什么正面正确不代表侧面正确

正交投影下,正面可见的横坐标主要由 X 决定,Z 没有提供可区分的图像证据。人偶绕竖直轴转 90° 时,新横坐标变成原来的 Z,三种深度假设立刻分开。转到 180° 后,又都投影到 x=113;这只表示几何旋转的计算一致,并不说明背面形体是真的。完整计算报告在合成实验结果。

左腕深度假设 正面 0° 侧面 90° 背面 180° 可以得出的结论
z=0 87 100 113 平面骨架在侧面收拢
z=+0.2 87 120 113 假设手臂位于一侧
z=-0.2 87 80 113 假设手臂位于另一侧

实际工程里,给左臂固定负深度、给右臂固定正深度,可以让正面造型有厚度,却可能在转身、交叉手臂、镜像视频时产生错误遮挡。较稳妥的策略是:先记录"视频可见的二维证据",再单独维护"为了预览所设的三维先验"。当遮挡或低置信度导致证据不足时,可以保留上一个可信姿态、显示中性形体,或者标记该角度仅供示意;不要把猜测结果静默混进动作评分。

若要提升侧背面可信度,需要改变输入或模型条件:增加第二视角、利用连续帧的时序约束,或者使用明确输出三维姿态的模型。即使模型输出三维关键点,也还需弄清其坐标原点、尺度、相机设定和训练域,并通过实测验证。它不是简单给 2D 点补一个 z 就完成重建。

图3:三种深度在正面均为 x=87;转到侧面分别落到 100/120/80,差异来自假设而非新增观测。

四、左右手、遮挡和手鞋细节如何处理

左右手先看语义,不看屏幕位置。 姿态模型中的"左腕"指被检测者的左腕;前置摄像头镜像、视频翻转、人物转身后,它未必在图像左半边。数据结构应保留关节索引和原始帧是否镜像的信息。检查可以分两层:原图上分别标记左右腕;转换后在 0° 回投影,应落回同一语义点。如果图像已经镜像,先统一输入坐标,再做 3D 映射,不要在某个输出环节临时交换数组索引。

遮挡顺序由深度决定,但二维点只能部分提示。 肩、肘、腕的连接段可以构成简化手臂;只凭几个关节点,不知道手臂在胸前还是背后。运动连续帧中的可见性变化、局部边缘和物体交互有时能提供线索,但需要与单帧静态姿态区分。无法判断时应采用明确的默认规则,并在侧面测试中暴露这个规则的局限。

手和鞋不是一个点。 腕点不等于掌心朝向,踝点不等于鞋尖。画一只手或一双鞋,可以采用独立的简化几何体;若要贴近原视频,应额外观察手掌、脚部轮廓或地面接触方向。利用局部颜色、轮廓去估计鞋尖时,要保存"检测得到"还是"缺失回退"这一来源。黑色鞋、深色地面、遮挡和出框都会让基于颜色的方案失效;回退鞋尖只能维持画面完整,不能成为动作角度的测量依据。

图4:腕点和踝点可定位关节,却不直接给出掌面、鞋尖和鞋底方向;缺少图像证据时只展示中性形状。

五、技术路线怎么选,哪些结果不能承诺

做展示和做测量的路线不同。需求若只是说明"这个瞬间肘部抬高了",2D 骨架叠加往往已经足够,风险也最低。需要换视角帮助观众理解动作,可以做 2D 关键点驱动的 3D 示意人偶,但必须标出深度来源。要比较真实空间中的关节轨迹,就需要三维估计、相机校准和误差评估;要生成可用于游戏或成片的自然人物,还要处理网格、蒙皮、时序稳定和遮挡,问题已远超关键点绘制。

路线 所需输入 合适的用途 不宜承诺
2D 骨架叠加 单视角视频及关键点 标注画面中的关节位置、辅助选帧 真实深度和背面形体
2D 驱动 3D 示意 上述输入 + 人工/规则深度先验 教学预览、解释动作结构 精确 3D 运动学测量
单目 3D 姿态估计 适配场景的三维模型、相机假设 估计相对三维姿态 未校准的绝对距离和跨场景精度
多视角/专用采集 同步摄像机、标定或深度设备 较严肃的空间分析 不经标定就直接合并坐标

选择依据不是"哪项技术更高级",而是输出要被拿来做什么决定。用户只看一个旋转示意,允许外观是模板化的;要据此评估人体动作、康复或安全风险,就不能让模板深度冒充观测深度。

六、用合成姿态做回归和上线验收

合成输入的好处是能把一个"看起来怪"的问题变成可断言的数值。本文的 200×400 帧含左右肩 (82,112)/(118,112)、左右腕 (87,25)/(113,25)、左右踝 (77,360)/(123,360),置信度均为 0.95。完整教学脚本和测试分别在实验脚本与自动测试。运行后应得到:前述三种深度在 0° 都回到 87;90° 分别为 100/120/80;180° 都为 113;360° 回到 87;低于阈值的关键点被拒绝。若结果不同,先查角度单位、旋转方向和 y 轴翻转,再查渲染器。

自动化还应增加展示层检查:在正面、侧面、背面以及一整圈末尾分别渲染;断言画布不为空、人物不越界、360° 与 0° 的朝向一致,并在手机和桌面画布上各跑一遍。一组浏览器回归使用合成关键点,在 240×853 与 640×720 两种画布检查七个角度,测试可通过;它证明的是渲染可见且不裁切,不是人偶已经像真人。上线前仍要抽检授权素材中的手臂前后关系、鞋尖、镜像输入和被遮挡肢体。

验收层 可自动判断 仍需人工或额外真值
数值 关键点回投影、低置信度拒绝、360° 归位 相机与人物尺度是否代表真实空间
画面 非空、无越界、不同分辨率可显示 遮挡是否自然、手鞋是否朝向正确
声明 深度来源、回退情况是否记录 "真实重建"等对外措辞是否成立

图5:数值回归能抓坐标和越界问题;侧背面的真实性还需要多视角证据或人工抽检。

七、小结与参考资料

2D 姿态驱动 3D 人偶有实用价值:它能把一个动作瞬间变成可旋转的解释性图形。但只要输入仍是单视角二维关键点,深度、遮挡、掌面和鞋底就不可能凭"转一圈"自动获得真值。工程上先统一坐标和左右语义,再把观测与假设分开保存;用合成姿态保证计算可重复,用真实多视角证据决定能否做更强的结论。

参考资料:

  1. Ultralytics:Pose Estimation,关键点结构与 17 点索引
  2. Three.js:OrthographicCamera,正交投影的尺寸特性
  3. Three.js:Euler,旋转角以弧度表示
相关推荐
古希腊掌管代码的神THU1 小时前
为什么DPO中chosen/rejected概率同时下降?
人工智能·深度学习·机器学习·自然语言处理·面试
北京青蓝智慧马老师1 小时前
比外部黑客更难防的,是那个有权限的自己人(3 个脱敏复盘)
大数据·数据库·人工智能
库拉镜像AI牛牛1 小时前
零基础做漫剧怎么统一全片画风 知漫剧内置成熟风格模板
人工智能
?abc!2 小时前
(数组)581. 最短无序连续子数组
数据结构·算法·leetcode
长欢喜一场2 小时前
豆包:字节跳动AI助手的全方位透视
人工智能·搜索引擎·1024程序员节
4SAPI2 小时前
搭建 AI 数据分析工具大模型 API 选型指南
数据库·人工智能·架构·php·1024程序员节
vibecoding772 小时前
Kimi Code 如何接入 Kimi K3.1 Pro:三条路径全流程
人工智能·agent
俊哥V2 小时前
每日 AI 研究简报 · 2026-10-24
人工智能·ai·1024程序员节
镜子AI2 小时前
镜子AI工程教程:用Python实现关键词布局检查器与语义改写查重(附完整代码)
人工智能·python·microsoft