之前写了一篇录制学习动作的blog,有兴趣的可以看一下。传动门
但是录制学习虽方便,问题有有很多,检测可能不灵敏。
有一定能力的强烈建议自己写动作判断。
话不多说,步入正题:
1.打开KinectGestures源码,这里会看到官方给定义好的N多动作枚举及判断。
2.下面增加自己的动作,增加枚举:
3.找到检测动作的方法CheckForGesture,写自己的动作判断。我这边写了两个动作判断,代码奉上:
//挥手
case Gestures.HuiShou:
switch (gestureData.state)
{
case 0: // gesture detection
if (jointsTracked[rightHandIndex] && jointsTracked[leftHandIndex] && jointsTracked[rightShoulderIndex] &&//要判断的骨骼点 举右手
Mathf.Abs(jointsPos[rightHandIndex].y - jointsPos[rightShoulderIndex].y) < 0.15f &&//左手高度和左肩高度差值小于15cm
(jointsPos[leftHandIndex].y - jointsPos[rightShoulderIndex].y) < 0f)//左手高度低于右肩高度
{
SetGestureJoint(ref gestureData, timestamp, rightHandIndex, jointsPos[rightHandIndex]);
gestureData.progress = 0.5f;//进度完成50%
}
else if (jointsTracked[rightHandIndex] && jointsTracked[leftHandIndex] && jointsTracked[leftShoulderIndex] &&//或者判断,因为也有可能举左手
Mathf.Abs(jointsPos[leftHandIndex].y - jointsPos[leftShoulderIndex].y) < 0.15f &&
(jointsPos[rightHandIndex].y - jointsPos[leftShoulderIndex].y) < 0f)
{
SetGestureJoint(ref gestureData, timestamp, leftHandIndex, jointsPos[leftHandIndex]);
gestureData.progress = 0.5f;
}
break;
case 1: // gesture complete
if ((timestamp - gestureData.timestamp) < 1.5f)//如果上面的做作时间差为1.5s,则继续执行,否则为动作取消。即举手动作需1.5s内完成
{
bool isInPose = (gestureData.joint == rightHandIndex)//三元(运算符)表达式,左右手判断
? jointsTracked[rightHandIndex] && jointsTracked[leftHandIndex] && jointsTracked[rightShoulderIndex] &&
(jointsPos[rightHandIndex].y - jointsPos[rightShoulderIndex].y) >= 0.3f &&//右手高度大于右肩30cm
(jointsPos[leftHandIndex].y - jointsPos[rightShoulderIndex].y) < 0f
: jointsTracked[rightHandIndex] && jointsTracked[leftHandIndex] && jointsTracked[leftShoulderIndex] &&
Mathf.Abs(jointsPos[leftHandIndex].y - jointsPos[leftShoulderIndex].y) >= 0.3f &&
(jointsPos[rightHandIndex].y - jointsPos[leftShoulderIndex].y) < 0f;
if (isInPose)
{
Vector3 jointPos = jointsPos[gestureData.joint];
CheckPoseComplete(ref gestureData, timestamp, jointPos, isInPose, 0);//动作完成
}
}
else
{
// cancel the gesture
SetGestureCancelled(ref gestureData);
}
break;
}
break;
//鼓掌
case Gestures.HandClip:
switch (gestureData.state)
{
case 0:
if (jointsTracked[leftHandIndex] && jointsTracked[rightHandIndex] && jointsTracked[shoulderCenterIndex]&&
(jointsPos[leftHandIndex].y < jointsPos[shoulderCenterIndex].y) &&
(jointsPos[rightHandIndex].y < jointsPos[shoulderCenterIndex].y) &&
(Mathf.Abs(jointsPos[leftHandIndex].x - jointsPos[rightHandIndex].x) < 0.5f)&&
(Mathf.Abs(jointsPos[leftHandIndex].x - jointsPos[rightHandIndex].x) > 0.1f))
{
SetGestureJoint(ref gestureData, timestamp, rightHandIndex, jointsPos[rightHandIndex]);
gestureData.progress = 0.5f;
}
break;
case 1:
if ((timestamp - gestureData.timestamp) < 1.5f)
{
bool isInPose = jointsTracked[leftHandIndex] && jointsTracked[rightHandIndex] && jointsTracked[shoulderCenterIndex] &&
(jointsPos[leftHandIndex].y < jointsPos[shoulderCenterIndex].y) &&
(jointsPos[rightHandIndex].y < jointsPos[shoulderCenterIndex].y) &&
(Mathf.Abs(jointsPos[leftHandIndex].x - jointsPos[rightHandIndex].x) < 0.1f) &&
(Mathf.Abs(jointsPos[leftHandIndex].y - jointsPos[rightHandIndex].y) < 0.1f);
if (isInPose)
{
Vector3 jointPos = jointsPos[gestureData.joint];
CheckPoseComplete(ref gestureData, timestamp, jointPos, isInPose, 0);
}
}
else
{
// cancel the gesture
SetGestureCancelled(ref gestureData);
}
break;
}
break;
4.绑定动作:
写脚本,调用KinectGestures.GestureListenerInterface接口。
实现:
5.解绑动作:
6.判断动作:
Over
说一下持续动作(Progress)和离散动作的用途区别:
用举手动作来说明:
离散动作:手举起来后,检测到举手动作完成后(一定时间,2s内)才能执行,如果一直举就会间隔(2s)执行。【具体时间可能不是2s,忘记了】
持续动作:手举起来的瞬间就会执行,无等待。且只会执行一次。如果需要再次执行,必须再次举手。
具体使用因个人项目而定。