本文参考以下文章:
http://www.cmsoft.com.br/index.php?option=com_content&view=article&id=292:kinect-sdk-17-hand-events&catid=1:latest-news&Itemid=110
http://blog.csdn.net/creategen/article/details/8698821
微软的Kinect SDK在1.7版本中新增了手的抓握事件, 给程序开发增添了新的可能。 微软在Developer Toolkit中提供的例子使用了标准的Kinect控制控件(Kinect.toolkits.controls), 其中滑动列表控件就利用了抓握手势。 但是如果我的程序只需要获取手的状态, 不需要将其应用在界面程序中呢?这就需要我们去研究Kinect控件中的代码了~但是其中的代码非常复杂, 这里给出一个监听手抓握事件的最小C#程序
首先新建工程, 然后向工程中添加引用, 添加如下引用:
Microsoft.Kinect
Microsoft.Kinect.Toolkit
Microsoft.Kinect.Toolkit.Interaction
然后在Form1.cs中的窗口加载事件中加入初始化代码:
// Look through all sensors and start the first connected one. // This requires that a Kinect is connected at the time of app startup. // To make your app robust against plug/unplug, // it is recommended to use KinectSensorChooser provided in Microsoft.Kinect.Toolkit (See components in Toolkit Browser). foreach (var potentialSensor in KinectSensor.KinectSensors) { if (potentialSensor.Status == KinectStatus.Connected) { this.sensor = potentialSensor; break; } } if (null != this.sensor) { // Turn on the skeleton stream to receive skeleton frames // grip release的识别需要这两种frame, 在后边需要 this.sensor.SkeletonStream.Enable(); this.sensor.DepthStream.Enable(); // Add an event handler to be called whenever there is new color frame data this.sensor.AllFramesReady += this.SensorAllFramesReady; // bind gesture related recalls // 这里绑定一个Microsoft.Kinect.Toolkit.Interaction.IInteractionClient接口的实现类 // 下面有详细说明 interactionClientImp = new InteractionClientImp(); interactionStream = new InteractionStream(this.sensor, interactionClientImp); interactionStream.InteractionFrameReady += new System.EventHandler<InteractionFrameReadyEventArgs>(SensorInteractionFrameReady); // Start the sensor! try { this.sensor.Start(); } catch (IOException) { this.sensor = null; } } if (null == this.sensor) { Console.WriteLine("Kinect启动失败!code:"+Properties.Resources.NoKinectReady); } |
刚才在实例化InteractionStream的时候我们传入了IInteractionClient接口的实现类
这个类是供kinect控件(Kinect.Toolkits.Controls)使用的, 我们不需要使用, 只要实现它, 在他的接口方法中返回固定的值即可, 实现方法参见附件中代码
接下来是响应kinect中“所有帧都准备好了”这个事件
private void SensorAllFramesReady(object sender, AllFramesReadyEventArgs e) { Skeleton[] skeletons = new Skeleton[0]; DepthImageFrame depthFrame = e.OpenDepthImageFrame(); SkeletonFrame skeletonFrame = e.OpenSkeletonFrame(); if (skeletonFrame != null && depthFrame != null) { skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength]; skeletonFrame.CopySkeletonDataTo(skeletons); // 这里就是关键了 Microsoft.Kinect.Vector4 accelerometerReading = this.sensor.AccelerometerGetCurrentReading(); interactionStream.ProcessSkeleton(skeletons, accelerometerReading, skeletonFrame.Timestamp);//Grip Release interactionStream.ProcessDepth(depthFrame.GetRawPixelData(), depthFrame.Timestamp); } // 这里要显式销毁, 不然会有警告 if (depthFrame != null) { depthFrame.Dispose(); } if (skeletonFrame != null) { skeletonFrame.Dispose(); } } |
InteractionStream 对深度图和骨架图处理后一旦发现手势变化(注意, 只有变化的时候)就会呼叫回调方法
如下实现回调方法:
private void SensorInteractionFrameReady(object sender, InteractionFrameReadyEventArgs e) { InteractionFrame interactionFrame = e.OpenInteractionFrame(); if (interactionFrame == null) { return; } UserInfo[] userInfos = new UserInfo[InteractionFrame.UserInfoArrayLength]; interactionFrame.CopyInteractionDataTo(userInfos); if (userInfos == null) { return; } for (int userIndex = 0; userIndex < userInfos.Length; userIndex++) { int playerIndex = userIndex; UserInfo userInfo = userInfos[userIndex]; int skeletonTrackingId = userInfo.SkeletonTrackingId; foreach (InteractionHandPointer interactionHandPointer in userInfo.HandPointers) { if (interactionHandPointer.HandType == InteractionHandType.None && interactionHandPointer.IsPrimaryForUser == false && interactionHandPointer.IsActive == false && interactionHandPointer.IsInteractive == false && interactionHandPointer.IsTracked == false) { continue; } if (interactionHandPointer.HandType == InteractionHandType.Left)//左手 { if (interactionHandPointer.HandEventType == InteractionHandEventType.None) { continue; } if (interactionHandPointer.HandEventType == InteractionHandEventType.Grip) { Console.WriteLine("左手握住"); } if (interactionHandPointer.HandEventType == InteractionHandEventType.GripRelease) { Console.WriteLine("左手张开"); } } if (interactionHandPointer.HandType == InteractionHandType.Right)//右手 { if (interactionHandPointer.HandEventType == InteractionHandEventType.None) { continue; } if (interactionHandPointer.HandEventType == InteractionHandEventType.Grip) { Console.WriteLine("右手握住"); } if (interactionHandPointer.HandEventType == InteractionHandEventType.GripRelease) { Console.WriteLine("右手张开"); } } } } } |
最后在程序退出时关闭kinect
private void Form1_FormClosing(object sender, FormClosingEventArgs e) { if (null != this.sensor) { this.sensor.Stop(); } Application.Exit(); } |
运行的时候要注意
需要将C:\Program Files\Microsoft SDKs\Kinect\Developer Toolkit v1.7.0\Redist\x86\KinectInteraction170_32.dll(根据实际情况修改)拷贝到工程的bin\Debug(根据实际情况修改)目录下
附项目打包:
由于KinectInteraction170_32.dll文件较大, 所以没有放在打包中, 请自行拷贝
GripReleaseDemo