unity项⽬源码_基于python和unity交互的卡通⾓⾊肢体和表情
驱动(深度学习)
前⾔
最近看到了好多卡通⾓⾊的肢体驱动的东东,感觉是时候发挥⼀下读研时候学的东西了,⽽且虽然现在不炼丹了,但是还是得保持吃丹的技能。这个项⽬了很多很多代码进⾏测试,最终集成了⼀个 3D 姿态估计和⼈脸关键点提取的代码。然后应⽤到unity中实现卡通⾓⾊的肢体和表情驱动。
国际惯例,参考博客:
2D 姿态估计 HRNet[1]
3D 姿态估计 SemGCN[2]
⼈脸检测 mtcnn[3]
68 ⼈脸关键点提取[4]
⼈头⽅向估算[5]
沫燃个人资料
Unity 官⽅⽂档 BS 的获取和控制[6]
再加和本博⽂所实现功能类似的 demo ⽹址:
效果超级好:上传视频输出同样动作的 FBX 模型[7]
开源:基于单⽬摄像头的 3D ⼈体和⼿部姿态估计附带卡通⾓⾊驱动[8]
开源:之前解析过的卡通⾓⾊驱动算法,内嵌到 unity 中了[9]
开源:BS 表情驱动案例[10]
简介少女时代解散
先放两张结果图表明最终实现功能,分别是卡通⾓⾊肢体驱动、表情驱动。以下视频为了上传,采⽤了抽帧处理。
完整视频DEMO可以点击如下链接:
实现⽅案
本⽂算法主要涉及两⼤模块:
朱镇模妻子肢体驱动部分:深度学习做 3D 姿态估计、unity 做⾻骼驱动(注意动⼒学相关内容)
博客上传视频
表情驱动部分:深度学习做⼈脸关键点检测和⼈头⽅向估算以及表情系数,unity做BlendShape表情驱动
了⼀些⽅法将深度学习算法嵌⼊到unity中,发现有点复杂,很多库⽽且不宜扩展;即想到采⽤python+flask部署的⽅法将深度学习作为后台接受unity发过来的请求;⽽unity则是前端,发送各种请求,⽐如请求将视频中⼈的3D姿态或者⼈脸表情计算出来,返回结果到unity中。
服务端
主要是深度学习模块,所采⽤的模型全部在参考博客,但是本⼈做了⼀下合成,分别设计了四个接⼝:
接收视频:因为算法实时性不太好,所以采⽤服务端上传视频,然后使⽤算法处理对应功能的⽅法
3D 关键点提取:结合 2D 姿态估计和 3D 姿态估计算法,直接端到端,输⼊视频输出 3D 关节坐标,⽬前结合的算法在 2060 上能达到 5-10FPS,⼤部分时间耗费在⼈体检测上,⽤的 faster-rcnn
2D ⼈脸关键点提取:最开始使⽤ 2D ⼈脸关键点检测,发现效果不是特别好,所以加⼊了mtcnn进⾏⼈脸框检测,然后再输⼊到关键点检测模型中去,最后根据关键点计算头部的表情和⽅向,⼤约 10FPS,主要耗费在⼈脸框检测上
2D ⼈脸关键点实时检测:当时为了测试⼈脸关键点与 unity 交互的实时性,留了⼀个接⼝,unity 端不需要上传视频,直接将每帧图⽚发送到服务端预测,发现这样⾮常卡,可能交互也花费时间了,或者其他原因
客户端
主要是unity展⽰端和驱动端,分为三个模块:
开始界⾯:输⼊请求地址、选择上传视频功能、选择肢体/表情驱动功能,选择对应功能后将会在服务端处理数据,最后返回到客户端肢体驱动界⾯:根据客户端接收到的关节 3D 数据,结合 unity 的lookat函数和简单的动⼒学修正进⾏肢体驱动
汲布表情驱动界⾯:有离线和在线的,离线版和肢体驱动⼀样从服务端拿到对应的表情数据后对⼈头进⾏驱动,利⽤颈部关节旋转量和BlendShape表情系数控制
难点技术
整个⼯程的设计花费了接近⼀个⽉的时间才搭起来,毕竟 996 嘛,你们懂得,每天还得熬会夜。
如何向喜欢的女生表白其中还是有⼀些技术难点的,分为深度学习部分和驱动部分。
深度学习算法部分
本来是奔着实时驱动去的,结果发现很难到实时性较⾼且效果稳定的算法,最后实在没办法,抛弃了实时功能(但是保留了接⼝,便于⼤佬们测试),采⽤上传视频,处理视频,返回整个视频结果的模式进⾏交互。
难点有两块:
2D 姿态估计和 3D 姿态估计算法的集成:算法的时候发现很多 3D 姿态估计的算法是在假设 2D 关键点坐标提供的情况下估算 3D 坐标的,所以必须去尝试寻 2D 姿态估计算法,有的算法直接通过视频估算⼈体坐标如 openpose,⽽有的是检测到⼈体框再去估算⼈体⽅向如最近的 HRNet;但是我觉得还是先检测到⼈体框再去估算会靠谱点,但是速度应该没有直接端到端快。最终采⽤了HRNet+SemGCN 的⽅法从视频中提取 3D 关节坐标
⼈脸表情:因为表情动画通常使⽤ BS 来驱动,每个 BS 通常代表动画的某个表情,多个 BS 加上不同的系数能组合出不同的表情,但是直接做表情识别的泛化性太差了,不如直接⽤关键点计算,所以使采⽤ mtcnn+HRNet 进⾏视频中⼈脸关键点的提取;然后⽹上⼜有很多基于关键点去计算⼈头朝向的算法,随便了⼀个;还有就是表情,仅仅做了简单的睁眼闭眼、张嘴程度的计算,具体⽅法可以看源码。
驱动部分
分为肢体驱动和表情驱动,所以也是两个难点:
肢体驱动:最开始打算⽤unity⾃带的IK来做,但是它只能⽤来控制关节末端如双⼿双脚,⽆法控制肘部等中间关节,然后想到先把中间关节位置调整好,再去⽤ IK 控制末端,结果发现调整中间关节会影响到 Ik 的计算;实在没辙,直接全部⼿动控制,采⽤lookat函数,让每根⾻骼的⽅向与真⼈的对应⾻骼⽅向保持⼀致,但是⼈体运动不仅仅是⾻骼⽅向⼀致,还要符合⼈体动⼒学,所以对每个关节的⾃转⼜进⾏了控制,下图就是未矫正和矫正后的肘关节案例;可能模型看的不太清楚,⼤概意思就是肘部不能直接朝上弯曲,必须让⼤臂
转动⼀点以后再去弯曲才⽐较⾃然。
表情驱动:这个相对来说⽐较简单,需要注意的是利⽤solvePnP、Rodrigues、decomposeProjectionMatrix计算得到的欧拉⾓和 unity 中可能有点区别,注意尝试变换⼀下就⾏了,可能是定义的标准 3D 模型和⼈脸刚好相反的原因,导致正常情况下的⼈头扭转⾓度接近180 度。表情部分因为没太多的 BS 可控制,不然还能根据关键点细分⼀下各种其他的表情进⾏驱动。
待优化点
点好⽤的深度学习模型
利⽤ FABRIK 动⼒学算法替代lookat
尝试实时驱动
导出 BVH 动作⽂件
后记
整个项⽬的内容看似少,但是细节很多,各种深度学习算法的集成、测试;unity 中lookat在关节上的应⽤;动⼒学矫正;unity+flask 通信等。
所有功能可以按照博客介绍的流程和算法完整复现,所以本⼯程代码打算便宜付费开源,到的算法LICENSE均允许商⽤,后续打算攒够钱买个Kinect玩玩驱动,还有⼿指部分也想⽤买个设备试试;⼤家别怪我,毕竟我之前所有的博客都是免费开源的;等钱够了设备到了,再来开源其它更好玩的算法。
当然,开发过程中涉及到的知识点我会不断在博客中更新尽请关注,⽬前打算把的基础知识部分补充完毕再来折腾这篇博客涉及到的知识。
源码获取请关注,发送“卡通⾓⾊驱动”
参考资料
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10]