从姿态估计到3D动画

news2024/10/7 16:25:09

在本文中,我们将尝试通过跟踪 2D 视频中的动作来渲染人物的 3D 动画。

在 3D 图形中制作人物动画需要大量的运动跟踪器来跟踪人物的动作,并且还需要时间手动制作每个肢体的动画。 我们的目标是提供一种节省时间的方法来完成同样的任务。

我们对这个问题的解决方案包括以下步骤:

  • 2D 姿态估计:人体至少需要 17 个标志点才能完整描述其姿态。
  • DeepSORT+FaceReID:跟踪姿势的运动。
  • 将 2D 提升到 3D:我们从上一步获得的坐标是 2D 的。 为了以 3D 方式制作它们的动画,我们需要将这些 2 维坐标映射到 3 维空间。
  • 渲染为 3D:上一步中检测到的这 17 个标志点的坐标现在将是需要动画处理的 3D 角色的四肢关节的位置。

让我们在本文的其余部分详细讨论这些步骤。

1、2D 姿态估计

如上所述,只需指定 17 个关键点(在深度学习社区中称为landmark points)即可完整描述人体姿势。 你可能已经猜到,我们正在使用深度学习来估计人类的姿势(即跨视频帧跟踪人类的姿势)。 有很多最先进的框架(例如 PoseFlow 和 AlphaPose)可以在github上找到,它们已经实现了相当准确的姿势估计。

第一个框架是由 Yuliang Xiu 等人开发的 PoseFlow。 PoseFlow 算法的基本概述是,该框架首先通过最大化视频所有帧的整体置信度来构建姿势。 下一步是使用称为非极大值抑制(通常缩写为 NMS)的技术删除检测到的冗余姿势。

可以在下面附加的 GIF 中看到,使用 PoseFlow(左侧)估计的姿势在某些帧中存在轻微故障。 这给我们带来了下一个框架:AlphaPose。 AlphaPose由Hao-Shu Fang等人开发。 该框架在帧中检测到的人周围绘制边界框,并估计他们在每个帧中的姿势。 即使一个人被另一个人部分遮挡,它也可以检测姿势。

左:PoseFlow 右:AlphaPose

AlphaPose 框架的代码可以在这里找到。

2、DeepSORT + FaceReID

我们使用 Alpha Pose 来检测视频中人类的姿势。 下一步是跟踪他们的动作,以便能够构建平滑的移动动画。 DeepSORT 框架的研究论文可以在这里找到。

使用 DeepSORT 和 FaceReid 边界框的输出,我们通过以下方式分离不同人的姿势。

在每一帧中绘制人体周围的边界框

检查姿势关键点是否在边界框内的函数

分离不同人的姿势的循环

3、令人振奋的 2D 到 3D

如上所述,我们在姿态估计步骤中获得的坐标是二维的(即它们位于二维空间中)。 但为了实现 3D 动画的主要项目目标,这些坐标必须映射到 3 维空间。 这也是使用......你猜对了!......深度学习! Github 上有一个存储库以及 ICCV ’17 接受的一篇研究论文。 可以在此处找到存储库的链接。

3d-pose-baseline 存储库在 Human3.6M 数据集上训练了他们的模型。 该数据集包含约 360 万人在 17 种不同场景下的 3D 姿势及其相应图像。 简而言之,模型的输入是 360 万人类的图像,所需的输出是数据集中存在的 3D 姿势。 现在,可以构建和调整深度学习模型,直到达到相当的准确度:

4、3D 动画

一旦我们从姿势估计框架中获得了关键点的坐标,就可以将这些坐标提供给 3D 角色身体的每个肢体。 在这里,我们使用Unity作为3D动画环境来完成任务。

每帧的 17 个关键点的坐标存储在一个文本文件中,该文本文件是在 Unity 中使用 C# 读取的。 从文件中读取的坐标现在重新定位到 3D 人形模型中。 这17个关键点与Unity内置的人形头像的身体关键点进行映射。

现在,动画是使用 Unity 的逆运动学(inverse kinematics)、骨骼旋转和四元数完成的。首先看 charanim.cs 的渲染更新函数 update()

void Update()
{
	if (pos == null) {
		return;
	}
	play_time += Time.deltaTime;

	int frame = s_frame + (int)(play_time * 24.057f);  
	if (frame > e_frame) {
		play_time = 0;  
		frame = s_frame;
	}

	if (debug_cube) {
		UpdateCube(frame); 
	}

	Vector3[] now_pos = pos[frame];

	Vector3 pos_forward = TriangleNormal(now_pos[7], now_pos[4], now_pos[1]);
	bone_t[0].position = now_pos[0] * scale_ratio + new Vector3(init_position.x, heal_position, init_position.z);
	bone_t[0].rotation = Quaternion.LookRotation(pos_forward) * init_inv[0] * init_rot[0];

	for (int i = 0; i < bones.Length; i++) {
		int b = bones[i];
		int cb = child_bones[i];
		bone_t[b].rotation = Quaternion.LookRotation(now_pos[b] - now_pos[cb], pos_forward) * init_inv[b] * init_rot[b];
	}

	bone_t[8].rotation = Quaternion.AngleAxis(head_angle, bone_t[11].position - bone_t[14].position) * bone_t[8].rotation;
}

其中的 updateCube() 定义如下:

void UpdateCube(int frame)
	{
		if (cube_t == null) {
			
			cube_t = new Transform[bone_num];

			for (int i = 0; i < bone_num; i++) {
				Transform t = GameObject.CreatePrimitive(PrimitiveType.Cube).transform;
				t.transform.parent = this.transform;
				t.localPosition = pos[frame][i] * scale_ratio;
				t.name = i.ToString();
				t.localScale = new Vector3(0.05f, 0.05f, 0.05f);
				cube_t[i] = t;

				Destroy(t.GetComponent<BoxCollider>());
			}
		}
		else {
			
			Vector3 offset = new Vector3(1.2f, 0, 0);

			
			for (int i = 0; i < bone_num; i++) {
				cube_t[i].localPosition = pos[frame][i] * scale_ratio + new Vector3(0, heal_position, 0) + offset;
			}
		}
	}

最终我们得到的结果如下,视频点击这里:

还不错!

5、结束语

总而言之,我们能够实现视频中多个人的姿势估计,并使用 Unity 等 3D 环境制作运动动画,同时还保持视频中两个不同人之间的相对位置。我们项目的 Github 存储库链接可以在这里找到。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1548822.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Canvas与艺术】简约式胡萝卜配色汽车速度表

【效果图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>胡萝卜色汽车速度仪表盘简化版</title><style type"…

如何在电脑桌面上创建可视化工作计划日程表?

对于职场人士来说&#xff0c;高效的时间管理和工作计划是提升工作效率、确保任务按时完成的关键。一款优秀的电脑工作计划软件&#xff0c;不仅能够帮助我们清晰地规划每一项任务&#xff0c;还能提醒我们按时完成&#xff0c;从而避免遗漏或延误。 那么&#xff0c;电脑工作…

06_Request

文章目录 前置知识点URL和URIHTTP请求报文和HTTP响应报文 Request请求行请求头请求体特殊信息获取客户机和服务器主机信息 请求参数直接封装引用类型 POST请求请求参数乱码文件上传案例&#xff08;与前面的getServletContext结合&#xff09; Request做请求的转发 前置知识点 …

PTA-练习9

目录 实验10-4 递归实现顺序输出整数 实验10-10 十进制转换二进制 实验10-6 递归求简单交错幂级数的部分和 实验11-1-2 输出月份英文名 实验11-1-6 指定位置输出字符串 实验11-1-8 查找子串 递归的基本思路&#xff1a; 推出递归的条件或者进入递归的条件每层递归需要执行…

JavaScript 打印教程(第二部分)设置编码

JavaScript 打印教程&#xff08;第二部分&#xff09;设置编码 在进行文本打印时&#xff0c;尤其是涉及到中文或其他特殊字符时&#xff0c;正确的编码设置是非常重要的。不同的打印机支持不同的指令集&#xff0c;因此了解并使用适合您打印机的指令集是关键。本篇教程继续使…

07、JS实现:用回溯法实现数组全排列的算法(一步一步剖析,很详细)

回溯法实现数组全排列的算法 Ⅰ、回溯法实现数组全排列&#xff1a;1、题目描述&#xff1a;2、解题思路&#xff1a;3、实现代码&#xff1a; Ⅱ、小结&#xff1a; Ⅰ、回溯法实现数组全排列&#xff1a; 1、题目描述&#xff1a; 给定⼀个 没有重复 数字的序列&#xff0c;…

DBeaver修改sql语句保存位置

1、dbeaver通过工作空间方式来管理Script的sql脚本以及数据库连接。 工作空间&#xff0c;其实也就是一个文件夹 默认保存路径查看&#xff1a; 文件--> 切换工作空间 --> 其他 sql脚本的保存位置默认在工作空间下的 \General\Scripts 文件夹中。 2、 3、点击浏览&#…

海外业务运营 别让资金支出管控成为开疆拓土的“绊脚石”

据《中国企业出海信心报告》显示,超六成企业有海外业务拓展计划。成熟出海企业将把目光放至新市场,新锐出海企业更聚焦新业务线的开辟。其中,当属高端制造业的出海步伐“迈得早”、“迈得大”。 高端制造业主要包含医药制造业,通用设备制造业,专用设备制造业,汽车制造业,通信设…

如何用Flask中的Blueprints构建大型Web应用

本文分享自华为云社区《构建大型Web应用Flask中的Blueprints指南》&#xff0c;作者&#xff1a; 柠檬味拥抱。 什么是Blueprints&#xff1f; 什么是Blueprints&#xff1f; Blueprints是Flask中的一种模式&#xff0c;用于将应用程序分解为可重用的模块。每个蓝图实际上是…

23届嵌入式被裁,有什么好的就业建议?

最近看到了一个提问&#xff0c;原话如下&#xff1a; 本人23届毕业生&#xff0c;就业方向嵌入式软件&#xff0c;坐标深圳&#xff0c;工作3月公司裁员&#xff0c;目前接近12月开始找工作。 boss上投递简历&#xff0c;校招岗&#xff0c;比较有规模的好公司基本已读不回&am…

浅析扩散模型与图像生成【应用篇】(十二)——DiffI2I

12. DiffI2I: Efficient Diffusion Model for Image-to-Image Translation 该文提出一种基于扩散模型的图像到图像的转换算法&#xff08;DiffI2I&#xff09;,可用于图像修复、超分辨率提升、图像去模糊、语义分割等任务。作者指出一般的扩散模型&#xff0c;虽然在图像生成任…

C++STL学习之unordered_map与unordered_set(底层Hash)

前言&#xff1a;我们前面已经学习论map和set&#xff0c;现在又冒出来一个unordered_map和unordered_set&#xff0c;这两个有啥差别吗&#xff1f;前面我们已经说过&#xff0c;map和set的底层是红黑树&#xff0c;那unordered_map和unordered_set的底层是什么呢&#xff1f;…

基于nodejs+vue“共享书角”图书借还管理系统python-flask-django-php

同时还能为借阅者提供一个方便实用的“共享书角”图书借还管理系统&#xff0c;使得借阅者能够及时地找到合适自己的图书借还信息。管理员在使用本系统时&#xff0c;可以通过后台管理员界面管理借阅者的信息&#xff0c;也可以发布系统公告&#xff0c;让借阅者及时了解图书借…

免杀对抗-C2远控篇CC++SC转换格式UUID标识MAC物理IPV4地址减少熵值

参考文章&#xff1a; https://github.com/INotGreen/Bypass-AMSI https://mp.weixin.qq.com/s/oJ8eHdX8HGuk6dZv0kmFxg https://kyxiaxiang.github.io/2022/12/14/AMSIandEtw https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell 文章参考&#xff1a; https://www.…

Go——结构体

Go语言中没有类的概念&#xff0c;也不支持类的继承等面向对象的概念。Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性。 一. 类型别名和自定义类型 1.1 自定义类型 在Go语言中有一些基本的数据类型&#xff0c;如string&#xff0c;整型&#xff0c;…

YOLOv9改进策略:block优化 | SEAM提升小目标遮挡物性能

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文改进内容&#xff1a;SEAM提升小目标遮挡物性能&#xff0c;在多个数据集得到很好的验证 改进结构图如下&#xff1a; YOLOv9魔术师专栏 ☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️ ☁️☁️☁️…

docker学习笔记 四-----docker基本使用方法

基础命令奉上&#xff1a; 1、docker命令查询方法 docker --help 获取docker命令帮助 docker search --help 查询docker 子命令search的帮助 2、查询镜像 查询镜像 docker search 192.168.206.100:5000/mysql 查询指定服务器指定镜像 docker search mysql …

Qt Design Studio各个组件怎么用?【长期更新】

写在前面&#xff1a;本文长期更新&#xff0c;建议点赞/收藏/关注~ 在Qt Design Studio中&#xff0c;组件类别有&#xff1a; 每一种&#xff0c;都有其特定的用途和适用场景&#xff1a; 1.My Components 使用时机&#xff1a;当你需要重用自定义的设计元素或者特殊功能…

【wallabag】数字化阅读时代的救星——wallabag来了!

为什么需要 ✨在海量信息涌动的时代&#xff0c;一篇好文章却总是在最不恰当的时候出现。想要留住精彩内容&#xff0c;却苦于当下分身乏术&#xff1f;墙裂推荐你试试wallabag&#xff0c;这款智能稍后阅读神器&#xff0c;让你随时随地畅享深度阅读的乐趣&#xff01; Walla…

2024第六届环境科学与可再生能源国际会议能源 (ESRE 2024) 即将召开!

2024第六届环境科学与可再生能源国际会议 能源 &#xff08;ESRE 2024&#xff09; 即将举行 2024 年 6 月 28 日至 30 日在德国法兰克福举行。ESRE 2024 年 旨在为研究人员、从业人员和专业人士提供一个论坛 从工业界、学术界和政府到研究和 发展&#xff0c;环境科学领域的专…