基于华为AR Engine与Unity3D的动作捕捉实现——骨骼点位置提取
简介
使用HUAWEI AR Engine(其实底层还是ARCore),在Mate 20 X设备上进行人体骨骼追踪
环境搭建
HUAWEI AR Engine可在华为开发者网站上下载到,具体步骤里面文档写的很清楚就不多说了
项目准备
项目基于华为官方提供的BodyARSample进行修改
代码
修改文件BodyARController
namespace BodyARSample
{
using UnityEngine;
using System.Collections.Generic;
using HuaweiARUnitySDK;
using Common;
using HuaweiARInternal;
public class BodyARController : MonoBehaviour
{
[Tooltip("body prefabs")]
public GameObject mesh;
private List<ARBody> newBodys = new List<ARBody>();
private List<ARBody> Bodys = new List<ARBody>();
private Dictionary<ARBody.SkeletonPointName, ARBody.SkeletonPointEntry> skeletons = new Dictionary<ARBody.SkeletonPointName, ARBody.SkeletonPointEntry>();
private List<GameObject> objs3D = new List<GameObject>();
private List<GameObject> objs2D = new List<GameObject>();
private Material m_skeletonMaterial;
GUIStyle bb = new GUIStyle();
private void Start()
{
//用于设置Debug字体的大小颜色等
bb.normal.background = null;
bb.normal.textColor = new Color(1, 0, 0);
bb.fontSize = 40;
DeviceChanged.OnDeviceChange += ARSession.SetDisplayGeometry;
//创建骨骼的材质
m_skeletonMaterial = new Material(Shader.Find("Diffuse"));
//生成用于描述3D空间骨骼的白色小球
for (int i = 0; i < 15; i++)
{
GameObject g = GameObject.CreatePrimitive(PrimitiveType.Sphere);
g.transform.localScale = new Vector3(0.08f, 0.08f, 0.08f);
g.SetActive(false);
objs3D.Add(g);
}
//生成用于描述2D空间骨骼的白色小球
for (int i = 0; i < 15; i++)
{
GameObject g = GameObject.CreatePrimitive(PrimitiveType.Sphere);
g.transform.localScale = new Vector3(0.08f, 0.08f, 0.08f);
g.SetActive(false);
objs2D.Add(g);
}
}
public void Update()
{
int i = 0;
newBodys.Clear();
//查找是否有新的对象
ARFrame.GetTrackables<ARBody>(newBodys, ARTrackableQueryFilter.NEW);
//如果存在新的对象则加入到Bodys中
foreach (var t in newBodys)
Bodys.Add(t);
if (Bodys.Count > 0)
{
//清空骨骼
skeletons.Clear();
//获取对象的骨骼
Bodys[0].GetSkeletons(skeletons);
//遍历骨骼的每一个骨骼点
foreach (var pair in skeletons)
{
if (!pair.Value.Is3DValid)
{
continue;
}
if (!pair.Value.Is2DValid)
{
continue;
}
//获取骨骼点的3D空间位置
Vector3 gl3DCoord = pair.Value.Coordinate3D;
//获取骨骼点的2D空间位置
Vector3 gl2DCoord = pair.Value.Coordinate2D;
//将2D位置转化为3D位置(伪3D)
Vector3 worldCoord = new Vector3((gl2DCoord.x + 1) / 2,
(gl2DCoord.y + 1) / 2, 3);
Vector3 wloc = Camera.main.ViewportToWorldPoint(worldCoord);
//赋予对象名称
objs2D[i].name = pair.Key.ToString() + "2D";
objs3D[i].name = pair.Key.ToString() + "3D";
//赋予对象材质
objs2D[i].GetComponent<MeshRenderer>().material = m_skeletonMaterial;
objs3D[i].GetComponent<MeshRenderer>().material = m_skeletonMaterial;
//更新对象世界位置
objs2D[i].transform.position = wloc;
objs3D[i].transform.position = new Vector3(gl3DCoord.x * -0.2f, gl3DCoord.y * -0.2f, gl3DCoord.z * -0.2f);
//**对象
objs2D[i].SetActive(true);
objs3D[i].SetActive(true);
i++;
}
}
}
//在屏幕右上角显示Debug信息
void OnGUI()
{
int j = 0;
foreach(var i in objs3D)
{
GUI.Label(new Rect(0, j++ * 40, 200, 200), "Location:" + i.transform.position.ToString(), bb);
}
if(Bodys.Count > 0)
GUI.Label(new Rect(400, 0, 200, 200), Bodys[0].GetCoordinateSystemType().ToString(), bb);
}
}
}
效果
小一点的白球是2D出来的
大的白球是3D出来的
3D的看起来不是很准,不知道是不是环境问题