动作捕捉(MoCap)
说到 动作捕捉 (Motion capture)技术,很多人都会立刻联想到好莱坞的特效大片和XBox的体感游戏。
影视方面对动作捕捉技术的应用已经炉火纯青。
在游戏方面尤其是一些体育类游戏在这方面的应用也很非常的广泛和接地气。在家庭娱乐方面相信很多人都接触到了体感游戏。微软的Kinect也为开发人员提供了完善的开发环境。可以很方便的进行体感游戏内容开发。
好了,言归正传,本文分享的动作捕捉是在Unity中结合OpenPose的数据来开发的。
OpenPose是一个能识别图像中人体动作骨骼的开源人工智能框架。其对大量的人体图像进行训练学习,对人体是识别准确度很高。
官网地址: http://openpose.org/
github: https://github.com/CMU-Perceptual-Computing-Lab/openpose
本文就是通过其3D重建部分 输出的数据导入到Unity中进行模型的动作驱动。
OpenPose输出的骨骼点原始数据:
此处不考虑头部数据,故忽略掉 14、15、16、17这4个点。
另外由8、9两个点产生一个新的节点作为动画模型的Hip骨骼节点,并将其定义为0,其他点依次顺延1。
这样Unity中HumanBodyBones枚举对的OpenPose点索引关系如下所示:
{ HumanBodyBones.Hips, 0},
{ HumanBodyBones.Head, 1},
{ HumanBodyBones.Chest, 2},
{ HumanBodyBones.RightUpperArm, 3},
{ HumanBodyBones.RightLowerArm, 4},
{ HumanBodyBones.RightHand, 5},
{ HumanBodyBones.LeftUpperArm, 6},
{ HumanBodyBones.LeftLowerArm, 7},
{ HumanBodyBones.LeftHand, 8},
{ HumanBodyBones.RightUpperLeg, 9},
{ HumanBodyBones.RightLowerLeg, 10},
{ HumanBodyBones.RightFoot, 11},
{ HumanBodyBones.LeftUpperLeg, 12},
{ HumanBodyBones.LeftLowerLeg, 13},
{ HumanBodyBones.LeftFoot, 14},
void Deformation(PoseFrame frame, float t) { // update position Vector3 offset = GetHipPosition(frame) - initialFramePosition; transform.position += offset * Time.deltaTime; // update rotatoin Quaternion orientation = AvatarComputeOrientation(frame); transform.rotation = Quaternion.Lerp(transform.rotation, orientation, t); // update pose for (int i = 0; i < frame.positions.Count; i++) { HumanBodyBones hbb = index2MecanimMap[i]; HumanBodyBones hbbp = mapBoneParent[hbb]; Vector3 pos = (Vector3)frame.positions[i]; Vector3 posParent = (Vector3)frame.positions[mecanim2IndexMap[hbbp]]; Vector3 dir = pos - posParent; if (dir == Vector3.zero) { dir = Vector3.up; } Transform boneParent = null; Quaternion vFixRotation = Quaternion.identity; if (HumanBodyBones.Chest == hbb) { Transform bone = animatorComponent.GetBoneTransform(hbb); boneParent = animatorComponent.GetBoneTransform(HumanBodyBones.Hips); Vector3 dirOrig = (bone.position - boneParent.position); vFixRotation = Quaternion.FromToRotation(dirOrig, dir); } else { if (mapBoneValid[hbbp]) { Transform bone = animatorComponent.GetBoneTransform(hbb); boneParent = bone.transform.parent; Vector3 dirOrig = (bone.position - bone.transform.parent.position); vFixRotation = Quaternion.FromToRotation(dirOrig, dir); } } if (boneParent) { Quaternion aimrot = vFixRotation * boneParent.rotation; Quaternion rotation = Quaternion.Lerp(boneParent.rotation, aimrot, t); boneParent.rotation = rotation; } } }
好了,看看实际效果:
初始状态:
目标状态:
过程动图:
好了,本文到处结束。欢迎关注公众号(ArtStealer)进行技术探讨。