Kinect
作者:追风剑情 发布于:2019-9-19 13:11 分类:Unity3d
官方文档
Xbox NUI Camera Drivers Download
Microsoft WDF KinectSensor Interface Driver
Kinect-v2 Examples with MS-SDK(译文二)
Kinect-v2 Examples with MS-SDK Doc(Chinese documents)
Kinect驱动安装目录
C:\Program Files\Microsoft Kinect Drivers\Drivers
一、安装开发环境
1、官方下载 Kinect for Windows SDK 2.0,并安装。
2、测试Kinect设备是否正常工作。
绿勾代表正常工作
有时Kinect connected显示叉,尝试让kinect断开电源10秒以上,再插上。
Kinect V2必须插USB 3.0才能正常工作。USB 2.0、USB 3.1都不行。
设备管理器查看USB接口版本
确保麦克风阵列处于启用状态,否则 Kinect 可能出现工作不稳定。
3、下载示例并导入到Unity2017或更高版本中
百度网盘下载 (Kinect v2 Examples with_2.13.unitypackage) 提取码: 5yjs
百度网盘下载 (Kinect v2 Examples with MS-SDK 2.20.unitypackage) 提取码: aj05
注意: Kinect v2 Examples with MS-SDK 2.20.unitypackage 需要Unity2019.1.0或更高版本、Direct3D11。
=====================================================================================
»KinectManager接口功能
1.检查Kinect是否完成了初始化
if ( KinectManager.IsKinectInitialized() ) { }
2.获取摄像头画面(一般作为背景)
Texture2D background = manager.GetUsersClrTex();
3.判断指定用户的某关节是否正处于跟踪中
long userId = manager.GetUserIdByIndex(0);//0代表第1个用户
int joint = (int)KinectInterop.JointType.HandRight;//判断右手
if (manager.IsJointTracked (userId, joint)) {}
4.获取关节坐标及旋转角
//关节坐标 long userId = manager.GetUserIdByIndex(0); int joint = (int)KinectInterop.JointType.HandRight;//右手 Rect backgroundRect = foregroundCamera.pixelRect; Vector3 posJoint = manager.GetJointPosColorOverlay(userId, joint, foregroundCamera, backgroundRect); //关节旋转角度 Vector3 vForward = foregroundCamera ? foregroundCamera.transform.forward : Vector3.forward; bool objFlipped = (Vector3.Dot(overlayObject.forward, vForward) < 0);//夹角为锐角 Quaternion rotJoint = manager.GetJointOrientation(userId, joint, !objFlipped);
5.获取父关节
KinectInterop.JointType jointParent = manager.GetParentJoint(KinectInterop.JointType.HandRight);
6.是否至少有1个用户被跟踪
if (!manager.IsUserDetected()) {
//没用户时,可以暂停或停止游戏
}
7.判断指定用户ID是否在跟踪用户列表中
if (manager.IsUserTracked(userId)) {}
8.清除所有被跟踪的用户
manager.ClearKinectUsers();//通常在游戏结束时调用
9.骨骼枚举
Kinect中的定义:KinectInterop.JointType
Unity中的定义: HumanBodyBones
PS: 注意定义中的对应关系
例如:KinectInterop.JointType.ShoulderLeft对应的是HumanBodyBones.LeftUpperArm
10.获取骨骼
//获取KinectInterop.JointType.ShoulderLeft
animatorComponent.GetBoneTransform(HumanBodyBones.LeftUpperArm)
11.改变人类化身姿态
//确保对象不为null,且为人类
if (animatorComponent && animatorComponent.avatar && animatorComponent.avatar.isHuman)
{
HumanPoseHandler humanPoseHandler = new HumanPoseHandler(animatorComponent.avatar, rootTransform);
HumanPose humanPose = new HumanPose();
humanPoseHandler.GetHumanPose(ref humanPose);
humanPose.bodyPosition = 新值;
humanPose.bodyRotation = 新值;
humanPose.muscles = 新值;//当前姿势的肌肉值的数组
humanPoseHandler.SetHumanPose(ref humanPose);
}
12.刷新姿态监听器列表(通常进入场景后调用一次)
找出场景中实现了KinectGestures.GestureListenerInterface的脚本,并加入到监听列表,同时找出场景中
KinectGestures脚本。
manager.refreshGestureListeners();
13.刷新化身控制器列表(通常进入场景后调用一次)
找出场景中的AvatarController脚本并加入avatarControllers列表
manager.refreshAvatarControllers()
14.获取主用户ID
获取主用户(第一个或最近的用户)的userid,如果没有检测到用户,则获取0
manager.GetPrimaryUserID();
15.获取前景图像(通常指用户)
backManager = BackgroundRemovalManager.Instance;
if (backManager && backManager.IsBackgroundRemovalInitialized()) {
foregroundTex = (RenderTexture)backManager.GetForegroundTex ();
}
前景图像使用的渲染shader为Color2DepthShader.shader,修改此shader可以调整渲染效果。
在 BackgroundRemovalManager 类的 Start() 中替换 sensorData.color2DepthMaterial 可自定义前景渲染材质。
Compute User Map: 必须设置为Body Texture
Compute Color Map: 必须勾选
16.获取坐标点深度值
//获取头部关节坐标
Vector3 posHeadRaw = kinectManager.GetJointKinectPosition(userId, (int)KinectInterop.JointType.Head);
if(posHeadRaw != Vector3.zero)
{
//转到深度坐标系
Vector2 posDepthHead = kinectManager.MapSpacePointToDepthCoords(posHeadRaw);
//得到深度值
ushort depthHead = kinectManager.GetDepthForPixel((int)posDepthHead.x, (int)posDepthHead.y);
}
17.获取面部矩形区域
if (faceManager.IsFaceTrackingInitialized() && faceManager.IsTrackingFace(userId))
{
Rect faceJointRect = faceManager.GetFaceColorRect(userId);
}
18.调整前景裁剪边缘
Erode Iterations: 缩小裁剪边缘
Dilate Iterations: 扩大裁剪边缘
19.获取面部模型数据
KinectInterop.SensorData sensorData = kinectManager.GetSensorData();
//获取面部模型顶点数
int iNumVertices = sensorData.sensorInterface.GetFaceModelVerticesCount(0);
if (iNumVertices <= 0)
return;
Vector3[] avModelVertices = new Vector3[iNumVertices];
//获取面部模型顶点
bool bGotModelVertices = sensorData.sensorInterface.GetFaceModelVertices(0, ref avModelVertices);
//获取三角形数量
int iNumTriangles = sensorData.sensorInterface.GetFaceModelTrianglesCount();
if(iNumTriangles <= 0)
return;
//获取三角形顶点索引
int[] avModelTriangles = new int[iNumTriangles];
bool bGotModelTriangles = sensorData.sensorInterface.GetFaceModelTriangles(mirroredModelMesh, ref avModelTriangles);
//获取头在kinect中的坐标
Vector3 headPos = Vector3.zero;
bGotHeadPos = sensorData.sensorInterface.GetHeadPosition(primaryUserID, ref headPos);
//从kinect坐标系转到Unity世界坐标系
Matrix4x4 kinectToWorld = kinectManager ? kinectManager.GetKinectToWorldMatrix() : Matrix4x4.identity;
Vector3 headPosWorld = kinectToWorld.MultiplyPoint3x4(headPos);
//将顶点坐标从kinect坐标系转到Unity世界坐标
Vector3[] vMeshVertices = new Vector3[avModelVertices.Length];
for(int i = 0; i < avModelVertices.Length; i++)
{
//世界坐标转面部模型的本地坐标
vMeshVertices[i] = kinectToWorld.MultiplyPoint3x4(avModelVertices[i]) - headPosWorld;
}
//创建Mesh
if (faceModelMesh)
{
Mesh mesh = new Mesh();
mesh.name = "FaceMesh";
faceModelMesh.GetComponent().mesh = mesh;
mesh.vertices = vMeshVertices;
mesh.triangles = avModelTriangles;
mesh.RecalculateNormals();
}
//为面部Mesh设置贴图
Texture texColorMap = kinectManager ? kinectManager.GetUsersClrTex() : null;
RenderTexture faceMeshTexture = new RenderTexture(texColorMap.width, texColorMap.height, 0);
faceModelMesh.GetComponent().material.mainTexture = faceMeshTexture;
if (faceMeshTexture && texColorMap)
{
// update the color texture
Graphics.Blit(texColorMap, faceMeshTexture);
}
20.获取采集图像尺寸
//摄像头采集的图像尺寸 kinectManager.GetColorImageWidth(); kinectManager.GetColorImageHeight(); //红外摄像头采集的深度图像尺寸 kinectManager.GetDepthImageWidth(); kinectManager.GetDepthImageHeight();
21.获取面部模型特征点在Unity中的世界坐标
FacetrackingManager faceManager = FacetrackingManager.Instance;
int iVertCount = faceManager.GetUserFaceVertexCount(userId);
Vector3[] faceVertices = new Vector3[iVertCount];
//这里的顶点坐标系是Kinect设备
if (faceManager.GetUserFaceVertices(userId, ref faceVertices))
{
//Kinect坐标到Unity世界坐标系的转换矩阵
Matrix4x4 kinectToWorld = kinectManager.GetKinectToWorldMatrix();
//面部关键点枚举数组
HighDetailFacePoints[] facePoints = (HighDetailFacePoints[])System.Enum.GetValues(typeof(HighDetailFacePoints));
Dictionary dictFacePoints = new Dictionary();
for (int i = 0; i < facePoints.Length; i++)
{
HighDetailFacePoints point = facePoints[i];
//转换到Unity世界坐标系
dictFacePoints[point] = kinectToWorld.MultiplyPoint3x4(faceVertices[(int)point]);
}
//让面具模型坐标跟随鼻尖(即,实现面具跟随面部)
//NoseTip: 鼻尖
HighDetailFacePoints facePoint = HighDetailFacePoints.NoseTip;
Vector3 facePointPos = faceVertices[(int)facePoint];
facePointTransform.position = facePointPos;
}
22.调整背景画面显示大小及位置
//显示摄像头画面
KinectManager manager = KinectManager.Instance;
mGUITexture.texture = manager.GetUsersClrTex();

23.设置前景像机(渲染3D物体)与Kinect摄像头的视场角相等
KinectManager manager = KinectManager.Instance;
KinectInterop.SensorData sensorData = manager.GetSensorData();
foregroundCamera.fieldOfView = sensorData.colorCameraFOV;
24.获取关节在Camera坐标系中的坐标
Rect backgroundRect = foregroundCamera.pixelRect;
ortraitBackground portraitBack = PortraitBackground.Instance;
if(portraitBack && portraitBack.enabled)
{
backgroundRect = portraitBack.GetBackgroundRect();
}
//返回关节在Unity中的世界坐标
Vector3 posColorOverlay = kinectManager.GetJointPosColorOverlay(
primaryUserID, (int)KinectInterop.JointType.Head, foregroundCamera, backgroundRect);
//让目标3D对象跟随关节
faceModelMesh.transform.position = posColorOverlay;
25.计算面部模型顶点对应的UV贴图坐标
//获取模型顶点坐标
KinectInterop.SensorData sensorData = kinectManager.GetSensorData();
int iNumVertices = sensorData.sensorInterface.GetFaceModelVerticesCount(primaryUserID);
Vector3[] avModelVertices = new Vector3[iNumVertices];
sensorData.sensorInterface.GetFaceModelVertices(primaryUserID, ref avModelVertices);
//Kinect摄像头采集的画面宽高
float colorWidth = (float)kinectManager.GetColorImageWidth();
float colorHeight = (float)kinectManager.GetColorImageHeight();
//计算模型顶点对应的UV坐标
for(int i = 0; i < avModelVertices.Length; i++)
{
//顶点对应的深度图坐标
Vector2 posDepth = kinectManager.MapSpacePointToDepthCoords(avModelVertices[i]);
if(posDepth != Vector2.zero)
{
//得到深度值
ushort depth = kinectManager.GetDepthForPixel((int)posDepth.x, (int)posDepth.y);
//得到顶点在Color图像中的坐标
Vector2 posColor = kinectManager.MapDepthPointToColorCoords(posDepth, depth);
if(posColor != Vector2.zero && !float.IsInfinity(posColor.x) && !float.IsInfinity(posColor.y))
{
//转成[0,1]区间的UV坐标
avModelUV[i] = new Vector2(posColor.x / colorWidth, posColor.y / colorHeight);
}
}
}
//设置uv
mesh.uv = avModelUV;
//如果顶点有变化,别忘了重新计算下
mesh.RecalculateNormals();
mesh.RecalculateBounds();
26.获取面部细节点坐标
int NoseTip = (int)Microsoft.Kinect.Face.HighDetailFacePoints.NoseTip; Vector3 NoseTipPos = avModelVertices[NoseTip];//鼻尖坐标
27.表情动画
//获取动画单元(AU)权重值,Shape各动画表情权重值 //AU是中性形状的增量,您可以使用它来对动画化身模型上的目标进行变形, //以使化身像被跟踪的用户一样起作用。例如,AU定义是否张口,抬起眉毛以及其他面部表情细节。 DictionarydictAU = new Dictionary (); sensorData.sensorInterface.GetAnimUnits(userId, ref dictAU); //获取形状单位(SU)权重 //SU估计用户头部的特定形状:眉毛,鼻子,脸颊,嘴巴或下巴等特征的形状。 Dictionary dictSU = new Dictionary (); ensorData.sensorInterface.GetShapeUnits(userId, ref dictSU);
»需要开发人员自己实现的接口:
public class MyGestureListener : KinectGestures.GestureListenerInterface
{
//用户进入
void UserDetected(long userId, int userIndex)
{
KinectManager manager = KinectManager.Instance;
// 添加希望追踪的用户手势
manager.DetectGesture(userId, KinectGestures.Gestures.SwipeLeft);
manager.DetectGesture(userId, KinectGestures.Gestures.SwipeRight);
}
//用户离开
void UserLost(long userId, int userIndex)
{
}
//返回手势进度
void GestureInProgress(long userId, int userIndex, Gestures gesture, float progress,
KinectInterop.JointType joint, Vector3 screenPos)
{
}
//手势完成
//return true(手势必须重新开始)
bool GestureCompleted(long userId, int userIndex, Gestures gesture,
KinectInterop.JointType joint, Vector3 screenPos)
{
// 判断手势类型并做出相应处理
switch (gesture)
{
case KinectGestures.Gestures.SwipeLeft:
break;
case KinectGestures.Gestures.SwipeRight:
break;
}
//返回true,KinectManager会调用ResetPlayerGestures();意味着手势将重新开始
return true;
}
//手势取消
bool GestureCancelled(long userId, int userIndex, Gestures gesture,
KinectInterop.JointType joint)
{
//返回true,KinectManager会调用ResetGesture();意味着手势将重新开始
return true;
}
}
public class MyInteractionListener : InteractionListenerInterface
{
//手握住
void HandGripDetected(long userId, int userIndex, bool isRightHand,
bool isHandInteracting, Vector3 handScreenPos)
{
}
//手释放
void HandReleaseDetected(long userId, int userIndex, bool isRightHand,
bool isHandInteracting, Vector3 handScreenPos)
{
}
//左手或右手在适当的位置停留至少2.5秒
//return true(手势必须重新开始)
bool HandClickDetected(long userId, int userIndex, bool isRightHand, Vector3 handScreenPos)
{
}
}
»手势识别
Kinect手势类型定义在KinectGestures.cs中
KinectGestures.Gestures
public enum Gestures
{
None = 0,
RaiseRightHand,//右手举起过肩并保持至少一秒
RaiseLeftHand,//左手举起过肩并保持至少一秒
Psi,//双手举起过肩并保持至少一秒
Tpose,//触摸
Stop,//双手下垂
Wave,//左手或右手举起来回摆动
Click,//左手或右手在适当的位置停留至少2.5秒
SwipeLeft,//右手向左挥
SwipeRight,//左手向右挥
SwipeUp,//左手或者右手向上挥
SwipeDown,//左手或者右手向下挥
RightHandCursor,//假手势,用来使光标随着手移动
LeftHandCursor,//假手势,用来使光标随着手移动
ZoomIn,//手肘向下,两手掌相聚至少0.7米,然后慢慢合在一起
ZoomOut,//手肘向下,左右手掌合在一起(求佛的手势),然后慢慢分开
Wheel,//想象一下你双手握着方向盘,然后左右转动
Jump,//在1.5秒内髋关节中心至少上升10厘米 (跳)
Squat,//在1.5秒内髋关节中心至少下降10厘米 (下蹲)
Push,//在1.5秒内将左手或右手向外推
Pull,//在1.5秒内将左手或右手向里拉
ShoulderLeftFront,//左肩前倾
ShoulderRightFront,//右肩前倾
LeanLeft, //身体向左倾斜
LeanRight, //身体向右倾斜
LeanForward,//身体向前倾斜
LeanBack,//身体向后倾斜
KickLeft,//踢左脚
KickRight,//踢右脚
Run,//跑
RaisedRightHorizontalLeftHand,//左手平举
RaisedLeftHorizontalRightHand,//右手平举
//自定义手势
UserGesture1 = 101,
UserGesture2 = 102,
UserGesture3 = 103,
UserGesture4 = 104,
UserGesture5 = 105,
UserGesture6 = 106,
UserGesture7 = 107,
UserGesture8 = 108,
UserGesture9 = 109,
UserGesture10 = 110,
}
每种手势的识别处理在KinectGestures.CheckForGesture()方法中,可以在这个方法中扩展自定义手势识别。
Gestures.Push
右手向前推的姿态定义:
1、右手.y - 左肘.y > -0.1米
2、Mathf.Abs(右手.x - 右肩.x) < 0.2米
3、右手.z - 左肘.z < -0.2米
»关节
每个姿态由手、肘、肩、脊柱、臀部、膝、踝关节共同组成,参见KinectGestures.GetNeededJointIndexes()方法:
/// <summary>
/// 获取组成姿态的关节索引列表
/// </summary>
public virtual int[] GetNeededJointIndexes(KinectManager manager)
{
//手
leftHandIndex = manager.GetJointIndex(KinectInterop.JointType.HandLeft);
rightHandIndex = manager.GetJointIndex(KinectInterop.JointType.HandRight);
//肘
leftElbowIndex = manager.GetJointIndex(KinectInterop.JointType.ElbowLeft);
rightElbowIndex = manager.GetJointIndex(KinectInterop.JointType.ElbowRight);
//肩
leftShoulderIndex = manager.GetJointIndex(KinectInterop.JointType.ShoulderLeft);
rightShoulderIndex = manager.GetJointIndex(KinectInterop.JointType.ShoulderRight);
//脊柱
hipCenterIndex = manager.GetJointIndex(KinectInterop.JointType.SpineBase);
shoulderCenterIndex = manager.GetJointIndex(KinectInterop.JointType.SpineShoulder);
//臀部
leftHipIndex = manager.GetJointIndex(KinectInterop.JointType.HipLeft);
rightHipIndex = manager.GetJointIndex(KinectInterop.JointType.HipRight);
//膝
leftKneeIndex = manager.GetJointIndex(KinectInterop.JointType.KneeLeft);
rightKneeIndex = manager.GetJointIndex(KinectInterop.JointType.KneeRight);
//踝
leftAnkleIndex = manager.GetJointIndex(KinectInterop.JointType.AnkleLeft);
rightAnkleIndex = manager.GetJointIndex(KinectInterop.JointType.AnkleRight);
int[] neededJointIndexes = {
leftHandIndex, rightHandIndex, leftElbowIndex, rightElbowIndex, leftShoulderIndex,
rightShoulderIndex, hipCenterIndex, shoulderCenterIndex, leftHipIndex, rightHipIndex,
leftKneeIndex, rightKneeIndex, leftAnkleIndex, rightAnkleIndex
};
return neededJointIndexes;
}
»只跟踪指定关节
创建XXXAvatarController继承自AvatarController,并重写基类的MapBones()方法。
protected virtual void MapBones()
AvatarController中声明了Kinect关节与Mecanim关节之间的映射关系
//kinect-joints to mecanim-bones mapping
//Kinect关节到Mecanim动画系统中的关节映射
protected static readonly Dictionary<int, HumanBodyBones> boneIndex2MecanimMap = new Dictionary<int, HumanBodyBones>
{
{0, HumanBodyBones.Hips},
{1, HumanBodyBones.Spine},
//{2, HumanBodyBones.Chest},
{3, HumanBodyBones.Neck},
//{4, HumanBodyBones.Head},
{5, HumanBodyBones.LeftUpperArm},
{6, HumanBodyBones.LeftLowerArm},
{7, HumanBodyBones.LeftHand},
//{8, HumanBodyBones.LeftIndexProximal},
//{9, HumanBodyBones.LeftIndexIntermediate},
//{10, HumanBodyBones.LeftThumbProximal},
{11, HumanBodyBones.RightUpperArm},
{12, HumanBodyBones.RightLowerArm},
{13, HumanBodyBones.RightHand},
//{14, HumanBodyBones.RightIndexProximal},
//{15, HumanBodyBones.RightIndexIntermediate},
//{16, HumanBodyBones.RightThumbProximal},
{17, HumanBodyBones.LeftUpperLeg},
{18, HumanBodyBones.LeftLowerLeg},
{19, HumanBodyBones.LeftFoot},
//{20, HumanBodyBones.LeftToes},
{21, HumanBodyBones.RightUpperLeg},
{22, HumanBodyBones.RightLowerLeg},
{23, HumanBodyBones.RightFoot},
//{24, HumanBodyBones.RightToes},
{25, HumanBodyBones.LeftShoulder},
{26, HumanBodyBones.RightShoulder},
{27, HumanBodyBones.LeftIndexProximal},
{28, HumanBodyBones.RightIndexProximal},
{29, HumanBodyBones.LeftThumbProximal},
{30, HumanBodyBones.RightThumbProximal},
};
//kinect手指关节到Mecanim动画系统中的关节映射
protected static readonly Dictionary<int, HumanBodyBones> fingerIndex2MecanimMap = new Dictionary<int, HumanBodyBones>
{
{0, HumanBodyBones.LeftThumbProximal},
{1, HumanBodyBones.LeftThumbIntermediate},
{2, HumanBodyBones.LeftThumbDistal},
{3, HumanBodyBones.LeftIndexProximal},
{4, HumanBodyBones.LeftIndexIntermediate},
{5, HumanBodyBones.LeftIndexDistal},
{6, HumanBodyBones.LeftMiddleProximal},
{7, HumanBodyBones.LeftMiddleIntermediate},
{8, HumanBodyBones.LeftMiddleDistal},
{9, HumanBodyBones.LeftRingProximal},
{10, HumanBodyBones.LeftRingIntermediate},
{11, HumanBodyBones.LeftRingDistal},
{12, HumanBodyBones.LeftLittleProximal},
{13, HumanBodyBones.LeftLittleIntermediate},
{14, HumanBodyBones.LeftLittleDistal},
{15, HumanBodyBones.RightThumbProximal},
{16, HumanBodyBones.RightThumbIntermediate},
{17, HumanBodyBones.RightThumbDistal},
{18, HumanBodyBones.RightIndexProximal},
{19, HumanBodyBones.RightIndexIntermediate},
{20, HumanBodyBones.RightIndexDistal},
{21, HumanBodyBones.RightMiddleProximal},
{22, HumanBodyBones.RightMiddleIntermediate},
{23, HumanBodyBones.RightMiddleDistal},
{24, HumanBodyBones.RightRingProximal},
{25, HumanBodyBones.RightRingIntermediate},
{26, HumanBodyBones.RightRingDistal},
{27, HumanBodyBones.RightLittleProximal},
{28, HumanBodyBones.RightLittleIntermediate},
{29, HumanBodyBones.RightLittleDistal}
};
// get bone transforms from the animator component
//Animator animatorComponent = GetComponent<Animator>();
Transform bone = animatorComponent.GetBoneTransform(boneIndex2MecanimMap[boneIndex]);
Transform fingerBone = animatorComponent.GetBoneTransform(fingerIndex2MecanimMap[boneIndex]);
示例:只跟踪上半身关节
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 只绑定上半身骨骼
/// </summary>
public class UpperAvatarController : AvatarController
{
// Public variables that will get matched to bones. If empty, the Kinect will simply not track it.
public Transform HipCenter;
public Transform Spine;
public Transform ShoulderCenter;
public Transform Neck;
//public Transform Head;
public Transform ClavicleLeft;
public Transform ShoulderLeft;
public Transform ElbowLeft;
public Transform HandLeft;
public Transform FingersLeft;
//private Transform FingerTipsLeft = null;
public Transform ThumbLeft;
public Transform ClavicleRight;
public Transform ShoulderRight;
public Transform ElbowRight;
public Transform HandRight;
public Transform FingersRight;
//private Transform FingerTipsRight = null;
public Transform ThumbRight;
public Transform HipLeft;
public Transform KneeLeft;
public Transform FootLeft;
//private Transform ToesLeft = null;
public Transform HipRight;
public Transform KneeRight;
public Transform FootRight;
//private Transform ToesRight = null;
[Tooltip("The body root node (optional).")]
public Transform BodyRoot;
// Offset node this transform is relative to, if any (optional)
//public GameObject OffsetNode;
// If the bones to be mapped have been declared, map that bone to the model.
protected override void MapBones()
{
bones[0] = HipCenter;
bones[1] = Spine;
bones[2] = ShoulderCenter;
bones[3] = Neck;
//bones[4] = Head;
bones[5] = ShoulderLeft;
bones[6] = ElbowLeft;
bones[7] = HandLeft;
//bones[8] = FingersLeft;
//bones[9] = FingerTipsLeft;
//bones[10] = ThumbLeft;
bones[11] = ShoulderRight;
bones[12] = ElbowRight;
bones[13] = HandRight;
//bones[14] = FingersRight;
//bones[15] = FingerTipsRight;
//bones[16] = ThumbRight;
bones[17] = HipLeft;
bones[18] = KneeLeft;
bones[19] = FootLeft;
//bones[20] = ToesLeft;
bones[21] = HipRight;
bones[22] = KneeRight;
bones[23] = FootRight;
//bones[24] = ToesRight;
// special bones
bones[25] = ClavicleLeft;
bones[26] = ClavicleRight;
bones[27] = FingersLeft;
bones[28] = FingersRight;
bones[29] = ThumbLeft;
bones[30] = ThumbRight;
// body root and offset
bodyRoot = BodyRoot;
}
}
»动态加载kinect配置参数
kinect.xml
<?xml version="1.0" encoding="UTF-8"?>
<root>
<!-- 以下参数名与Kinect Manager(Script)属性面板中的参数对应 -->
<SensorHeight>1</SensorHeight>
<SensorAngle>0</SensorAngle>
<!-- DontUse, ShowInfoOnly, AutoUpdate, AutoUpdateAndShowInfo -->
<AutoHeightAngle>DontUse</AutoHeightAngle>
<!-- None, RawUserDepth, BodyTexture, UserTexture, CutOutTexture -->
<ComputeUserMap>RawUserDepth</ComputeUserMap>
<ComputeColorMap>true</ComputeColorMap>
<ComputeInfraredMap>false</ComputeInfraredMap>
<DisplayUserMap>false</DisplayUserMap>
<DisplayColorMap>false</DisplayColorMap>
<DisplaySkeletonLines>false</DisplaySkeletonLines>
<DisplayMapsWidthPercent>20</DisplayMapsWidthPercent>
<UseMultiSourceReader>true</UseMultiSourceReader>
<MinUserDistance>0.5</MinUserDistance>
<MaxUserDistance>0</MaxUserDistance>
<MaxLeftRightDistance>0</MaxLeftRightDistance>
<MaxTrackedUsers>6</MaxTrackedUsers>
<ShowTrackedUsersOnly>true</ShowTrackedUsersOnly>
<!-- Appearance, Distance, LeftToRight -->
<UserDetectionOrder>Appearance</UserDetectionOrder>
<IgnoreInferredJoints>false</IgnoreInferredJoints>
<IgnoreZCoordinates>false</IgnoreZCoordinates>
<LateUpdateAvatars>false</LateUpdateAvatars>
<SkipRemoteAvatars>false</SkipRemoteAvatars>
<!-- None, Default, Light, Medium, Aggressive -->
<Smoothing>Default</Smoothing>
<UseBoneOrientationConstraints>false</UseBoneOrientationConstraints>
<EstimateJointVelocities>false</EstimateJointVelocities>
<!-- None, Default, Light, Medium, Aggressive -->
<VelocitySmoothing>Light</VelocitySmoothing>
<AllowTurnArounds>false</AllowTurnArounds>
<!-- None, Default, All -->
<AllowedHandRotations>Default</AllowedHandRotations>
<WaitTimeBeforeRemove>1</WaitTimeBeforeRemove>
<!-- None = 0,RaiseRightHand, RaiseLeftHand, Psi, Tpose,
Stop, Wave, Click, SwipeLeft, SwipeRight, SwipeUp,
SwipeDown, RightHandCursor, LeftHandCursor, ZoomIn, Wheel,
Jump, Squat, Push, Pull, ShoulderLeftFront, ShoulderRightFront,
LeanLeft, LeanRight, LeanForward, LeanBack, KickLeft, KickRight, Run,
RaisedRightHorizontalLeftHand, // by Andrzej W
RaisedLeftHorizontalRightHand,
UserGesture1 = 101,
UserGesture2 = 102,
UserGesture3 = 103,
UserGesture4 = 104,
UserGesture5 = 105,
UserGesture6 = 106,
UserGesture7 = 107,
UserGesture8 = 108,
UserGesture9 = 109,
UserGesture10 = 110,
-->
<PlayerCalibrationPose>None</PlayerCalibrationPose>
<MinTimeBetweenGestures>0.7</MinTimeBetweenGestures>
</root>
KinectConfig.cs
// 与kinect.xml对应
public static class KinectConfig
{
public static float SensorHeight { get; private set; }
public static float SensorAngle { get; private set; }
public static bool ComputeColorMap { get; private set; }
public static bool ComputeInfraredMap { get; private set; }
public static bool DisplayUserMap { get; private set; }
public static bool DisplayColorMap { get; private set; }
public static bool DisplaySkeletonLines { get; private set; }
public static float DisplayMapsWidthPercent { get; private set; }
public static bool UseMultiSourceReader { get; private set; }
public static float MinUserDistance { get; private set; }
public static float MaxUserDistance { get; private set; }
public static float MaxLeftRightDistance { get; private set; }
public static int MaxTrackedUsers { get; private set; }
public static bool ShowTrackedUsersOnly { get; private set; }
public static bool IgnoreInferredJoints { get; private set; }
public static bool IgnoreZCoordinates { get; private set; }
public static bool LateUpdateAvatars { get; private set; }
public static bool SkipRemoteAvatars { get; private set; }
public static bool UseBoneOrientationConstraints { get; private set; }
public static bool EstimateJointVelocities { get; private set; }
public static bool AllowTurnArounds { get; private set; }
public static float WaitTimeBeforeRemove { get; private set; }
public static float MinTimeBetweenGestures { get; private set; }
public static KinectManager.AutoHeightAngle AutoHeightAngle = KinectManager.AutoHeightAngle.DontUse;
public static KinectManager.UserMapType ComputeUserMap = KinectManager.UserMapType.RawUserDepth;
public static KinectManager.UserDetectionOrder UserDetectionOrder = KinectManager.UserDetectionOrder.Appearance;
public static KinectManager.Smoothing Smoothing = KinectManager.Smoothing.Default;
public static KinectManager.Smoothing VelocitySmoothing = KinectManager.Smoothing.Light;
public static KinectManager.AllowedRotations AllowedHandRotations = KinectManager.AllowedRotations.Default;
public static KinectGestures.Gestures PlayerCalibrationPose;
public static bool Done { get; private set; }
// 加载配置
public static void Load(string path)
{
if (!File.Exists(path))
{
Debug.LogErrorFormat("Not found: {0}", path);
return;
}
XmlDocument xml = new XmlDocument();
xml.Load(path);
Parse(xml);
}
// 读入配置到kinect
public static void Read(KinectManager kinect)
{
if (kinect == null)
{
Debug.Log("[KinectConfig] Read(null)");
return;
}
if (!Done)
{
Debug.Log("[KinectConfig] Unparse completion");
return;
}
kinect.sensorHeight = SensorHeight;
kinect.sensorAngle = SensorAngle;
kinect.computeColorMap = ComputeColorMap;
kinect.computeInfraredMap = ComputeInfraredMap;
kinect.displayUserMap = DisplayUserMap;
kinect.displayColorMap = DisplayColorMap;
kinect.displaySkeletonLines = DisplaySkeletonLines;
kinect.DisplayMapsWidthPercent = DisplayMapsWidthPercent;
kinect.useMultiSourceReader = UseMultiSourceReader;
kinect.minUserDistance = MinUserDistance;
kinect.maxUserDistance = MaxUserDistance;
kinect.maxLeftRightDistance = MaxLeftRightDistance;
kinect.maxTrackedUsers = MaxTrackedUsers;
kinect.showTrackedUsersOnly = ShowTrackedUsersOnly;
kinect.ignoreInferredJoints = IgnoreInferredJoints;
kinect.ignoreZCoordinates = IgnoreZCoordinates;
kinect.lateUpdateAvatars = LateUpdateAvatars;
kinect.skipRemoteAvatars = SkipRemoteAvatars;
kinect.useBoneOrientationConstraints = UseBoneOrientationConstraints;
kinect.estimateJointVelocities = EstimateJointVelocities;
kinect.allowTurnArounds = AllowTurnArounds;
kinect.waitTimeBeforeRemove = WaitTimeBeforeRemove;
kinect.minTimeBetweenGestures = MinTimeBetweenGestures;
kinect.autoHeightAngle = AutoHeightAngle;
kinect.computeUserMap = ComputeUserMap;
kinect.userDetectionOrder = UserDetectionOrder;
kinect.smoothing = Smoothing;
kinect.velocitySmoothing = VelocitySmoothing;
kinect.allowedHandRotations = AllowedHandRotations;
kinect.playerCalibrationPose = PlayerCalibrationPose;
}
// 解析配置
private static void Parse(XmlDocument xml)
{
Type type = Type.GetType("KinectConfig");
XmlNode root = xml.SelectSingleNode("/root");
XmlNodeList childList = root.ChildNodes;
for (int i = 0; i < childList.Count; i++)
{
XmlNode node = childList.Item(i);
if (node.NodeType == XmlNodeType.Comment) //跳过XML中的注释
continue;
string text = node.InnerText;
PropertyInfo property = type.GetProperty(node.Name);
FieldInfo field = type.GetField(node.Name);
if (property == null && field == null)
{
Debug.LogErrorFormat("[KinectConfig] Parse Error, node.Name={0}, MemberType={1}", node.Name, type.MemberType);
continue;
}
if (property != null)
{
bool IsInt = property.PropertyType == typeof(int);
bool IsFloat = property.PropertyType == typeof(float);
bool IsBool = property.PropertyType == typeof(bool);
if (IsInt)
property.SetValue(null, int.Parse(text));
else if (IsFloat)
property.SetValue(null, float.Parse(text));
else if (IsBool)
property.SetValue(null, bool.Parse(text));
}
if (field != null)
{
if (field.FieldType.IsEnum)
{
System.Object obj = Enum.Parse(field.FieldType, text);
field.SetValue(null, obj);
}
}
}
Done = true;
Debug.Log(ToString());
}
public static string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("Kinect配置信息\n\n<color=blue>");
Type type = Type.GetType("KinectConfig");
PropertyInfo[] propertyInfos = type.GetProperties();
for (int i=0; i< propertyInfos.Length; i++)
{
PropertyInfo p = propertyInfos[i];
sb.AppendFormat("{0}={1}\n", p.Name, p.GetValue(null));
}
FieldInfo[] fieldInfos = type.GetFields();
for (int i = 0; i < fieldInfos.Length; i++)
{
FieldInfo p = fieldInfos[i];
sb.AppendFormat("{0}={1}\n", p.Name, p.GetValue(null));
}
sb.Append("</color>");
return sb.ToString();
}
}
»打包发布
注意:需要手动将kinect相关的dll从工程目录拷到发布目录下。
标签: Unity3d
日历
最新文章
随机文章
热门文章
分类
存档
- 2025年11月(1)
- 2025年9月(3)
- 2025年7月(4)
- 2025年6月(5)
- 2025年5月(1)
- 2025年4月(5)
- 2025年3月(4)
- 2025年2月(3)
- 2025年1月(1)
- 2024年12月(5)
- 2024年11月(5)
- 2024年10月(5)
- 2024年9月(3)
- 2024年8月(3)
- 2024年7月(11)
- 2024年6月(3)
- 2024年5月(9)
- 2024年4月(10)
- 2024年3月(11)
- 2024年2月(24)
- 2024年1月(12)
- 2023年12月(3)
- 2023年11月(9)
- 2023年10月(7)
- 2023年9月(2)
- 2023年8月(7)
- 2023年7月(9)
- 2023年6月(6)
- 2023年5月(7)
- 2023年4月(11)
- 2023年3月(6)
- 2023年2月(11)
- 2023年1月(8)
- 2022年12月(2)
- 2022年11月(4)
- 2022年10月(10)
- 2022年9月(2)
- 2022年8月(13)
- 2022年7月(7)
- 2022年6月(11)
- 2022年5月(18)
- 2022年4月(29)
- 2022年3月(5)
- 2022年2月(6)
- 2022年1月(8)
- 2021年12月(5)
- 2021年11月(3)
- 2021年10月(4)
- 2021年9月(9)
- 2021年8月(14)
- 2021年7月(8)
- 2021年6月(5)
- 2021年5月(2)
- 2021年4月(3)
- 2021年3月(7)
- 2021年2月(2)
- 2021年1月(8)
- 2020年12月(7)
- 2020年11月(2)
- 2020年10月(6)
- 2020年9月(9)
- 2020年8月(10)
- 2020年7月(9)
- 2020年6月(18)
- 2020年5月(4)
- 2020年4月(25)
- 2020年3月(38)
- 2020年1月(21)
- 2019年12月(13)
- 2019年11月(29)
- 2019年10月(44)
- 2019年9月(17)
- 2019年8月(18)
- 2019年7月(25)
- 2019年6月(25)
- 2019年5月(17)
- 2019年4月(10)
- 2019年3月(36)
- 2019年2月(35)
- 2019年1月(28)
- 2018年12月(30)
- 2018年11月(22)
- 2018年10月(4)
- 2018年9月(7)
- 2018年8月(13)
- 2018年7月(13)
- 2018年6月(6)
- 2018年5月(5)
- 2018年4月(13)
- 2018年3月(5)
- 2018年2月(3)
- 2018年1月(8)
- 2017年12月(35)
- 2017年11月(17)
- 2017年10月(16)
- 2017年9月(17)
- 2017年8月(20)
- 2017年7月(34)
- 2017年6月(17)
- 2017年5月(15)
- 2017年4月(32)
- 2017年3月(8)
- 2017年2月(2)
- 2017年1月(5)
- 2016年12月(14)
- 2016年11月(26)
- 2016年10月(12)
- 2016年9月(25)
- 2016年8月(32)
- 2016年7月(14)
- 2016年6月(21)
- 2016年5月(17)
- 2016年4月(13)
- 2016年3月(8)
- 2016年2月(8)
- 2016年1月(18)
- 2015年12月(13)
- 2015年11月(15)
- 2015年10月(12)
- 2015年9月(18)
- 2015年8月(21)
- 2015年7月(35)
- 2015年6月(13)
- 2015年5月(9)
- 2015年4月(4)
- 2015年3月(5)
- 2015年2月(4)
- 2015年1月(13)
- 2014年12月(7)
- 2014年11月(5)
- 2014年10月(4)
- 2014年9月(8)
- 2014年8月(16)
- 2014年7月(26)
- 2014年6月(22)
- 2014年5月(28)
- 2014年4月(15)
友情链接
- Unity官网
- Unity圣典
- Unity在线手册
- Unity中文手册(圣典)
- Unity官方中文论坛
- Unity游戏蛮牛用户文档
- Unity下载存档
- Unity引擎源码下载
- Unity服务
- Unity Ads
- wiki.unity3d
- Visual Studio Code官网
- SenseAR开发文档
- MSDN
- C# 参考
- C# 编程指南
- .NET Framework类库
- .NET 文档
- .NET 开发
- WPF官方文档
- uLua
- xLua
- SharpZipLib
- Protobuf-net
- Protobuf.js
- OpenSSL
- OPEN CASCADE
- JSON
- MessagePack
- C在线工具
- 游戏蛮牛
- GreenVPN
- 聚合数据
- 热云
- 融云
- 腾讯云
- 腾讯开放平台
- 腾讯游戏服务
- 腾讯游戏开发者平台
- 腾讯课堂
- 微信开放平台
- 腾讯实时音视频
- 腾讯即时通信IM
- 微信公众平台技术文档
- 白鹭引擎官网
- 白鹭引擎开放平台
- 白鹭引擎开发文档
- FairyGUI编辑器
- PureMVC-TypeScript
- 讯飞开放平台
- 亲加通讯云
- Cygwin
- Mono开发者联盟
- Scut游戏服务器引擎
- KBEngine游戏服务器引擎
- Photon游戏服务器引擎
- 码云
- SharpSvn
- 腾讯bugly
- 4399原创平台
- 开源中国
- Firebase
- Firebase-Admob-Unity
- google-services-unity
- Firebase SDK for Unity
- Google-Firebase-SDK
- AppsFlyer SDK
- android-repository
- CQASO
- Facebook开发者平台
- gradle下载
- GradleBuildTool下载
- Android Developers
- Google中国开发者
- AndroidDevTools
- Android社区
- Android开发工具
- Google Play Games Services
- Google商店
- Google APIs for Android
- 金钱豹VPN
- TouchSense SDK
- MakeHuman
- Online RSA Key Converter
- Windows UWP应用
- Visual Studio For Unity
- Open CASCADE Technology
- 慕课网
- 阿里云服务器ECS
- 在线免费文字转语音系统
- AI Studio
- 网云穿
- 百度网盘开放平台
- 迅捷画图
- 菜鸟工具
- [CSDN] 程序员研修院
- 华为人脸识别
- 百度AR导航导览SDK
- 海康威视官网
- 海康开放平台
- 海康SDK下载
- git download
- Open CASCADE
- CascadeStudio
交流QQ群
-
Flash游戏设计: 86184192
Unity游戏设计: 171855449
游戏设计订阅号
















