Kinect传感器编程指南

Kinect传感器是一款由微软开发的深度感应摄像头,它能够捕捉用户的体感动作,广泛应用于游戏、教育、医疗等领域。本文将介绍如何使用Kinect传感器进行编程,包括初始化、数据获取、录制与回放等功能的实现。

在本文中,假设读者已经具备了使用Kinect传感器和Kinect SDK(非OpenNI版本)的基础知识,并且熟悉C#编程语言。本文的应用程序是基于Kinect Beta 2 SDK开发的。如果对Kinect传感器不太熟悉,可以查看一系列优秀的教程

准备工作

在开始编程之前,需要准备以下工具和资源:

使用KinectRecorderInterface

KinectRecorderInterface类的使用非常简单。首先,来看一下这个类的公共成员、方法和事件。

声明并创建这个类的实例,就像大多数类的声明一样。

KinectRecorderInterface recorder = new KinectRecorderInterface();

初始化时,通过recorder打开Kinect传感器,并选择适当的图像分辨率(深度图像可以高达640x480)。

注意:一次只能有一个应用程序使用Kinect!

使用以下代码仅打开深度流:

recorder.InitializeSensor(ImageResolution.Resolution320x240);

使用以下代码同时打开深度流和视频流:

recorder.InitializeSensor(ImageResolution.Resolution320x240, ImageResolution.Resolution640x480);

完整的初始化代码如下:

private KinectRecorderInterface recorder; public void InitializeKinectRecorder() { recorder = new KinectRecorderInterface(); recorder.InitializeSensor(ImageResolution.Resolution640x480, ImageResolution.Resolution640x480); recorder.PlaybackSkeletonDataReady += new KinectRecorderInterface.PlaybackFrameHandler(recorder_PlaybackSkeletonDataReady); recorder.SkeletonFrameReady += new KinectRecorderInterface.SkeletonFrameHandler(recorder_SkeletonFrameReady); recorder.ImageFrameReady += new KinectRecorderInterface.ImageFrameHandler(recorder_ImageFrameReady); recorder.DepthFrameReady += new KinectRecorderInterface.DepthFrameHandler(recorder_DepthFrameReady); }

现在,可以创建适当的事件处理程序来从Kinect获取数据。

注意:事件处理程序和EventArgs与使用Kinect SDK时相同,除了回放!

recorder.SkeletonFrameReady += new KinectRecorderInterface.SkeletonFrameHandler(recorder_SkeletonFrameReady); recorder.ImageFrameReady += new KinectRecorderInterface.ImageFrameHandler(recorder_ImageFrameReady); recorder.DepthFrameReady += new KinectRecorderInterface.DepthFrameHandler(recorder_DepthFrameReady);

回放事件处理程序与实时数据获取非常相似,但它区分其EventArgs(稍后会详细介绍)。

recorder.PlaybackSkeletonDataReady += new KinectRecorderInterface.PlaybackFrameHandler(recorder_PlaybackSkeletonDataReady);

现在,可以像通常一样从SkeletonTracking、DepthStream和VideoStream获取Kinect的数据,但目前还没有录制或回放。

开始/停止录制

可以随时使用StartRecording()方法开始捕获可用的(Tracked)SkeletonData。

使用StopRecording()方法停止捕获并保存任何存储的SkeletonData。默认情况下,数据存储在"Recordings"文件夹中,除非从RecordDirectory更改它。

注意:如果没有SkeletonData,保存将被中止。

recorder.RecordDirectory = "./StoreData"; recorder.StartRecording(); // 等待想要的时间 recorder.StopRecording();

现在,默认情况下,已经创建了一个新的"Recordings"文件夹,以及一个名为"recording_00x.dat"的文件。

开始/停止回放

录制了一些动作后,可以随时回放它们。使用StartPlayback()开始回放最后一个可用的录制。

另外,可以使用StartPlayback(recording_xxx.dat)来回放选择的录制。

注意:每次应用程序开始/录制/保存时,都会更新一个录音目录(List),可以通过ExistingRecords属性选择任何录音。

// 播放最后一个可用的录音 recorder.StartPlayback(); // 播放选择的录音 List records = recorder.ExistingRecords; recorder.StartPlayback(records[0]);

SkeletonData与SerializableSkeletonData

当到达需要存储数据的阶段时,意识到不能序列化SkeletonData,因为它没有标记为Serializable。因此,实现了Json.Net,效果非常好!但是,不幸的是,当尝试反序列化并转换(见下文)存储的数据时,它又失败了,因为SkeletonData没有任何public构造函数(它的构造函数设置为internal)!欢迎提供更好的解决方案!

// 这段代码因为SkeletonData没有public构造函数而出错 var json = System.IO.File.ReadAllText(filepath); var skeletonData = Newtonsoft.Json.JsonConvert.DeserializeObject>(json);

最后,没有想出任何其他解决方案,只能创建一个与SkeletonData几乎相同的新类,如下所示:

将在获取SkeletonDataArgs时获取SerializableSkeletonData。SkeletonDataArgs包含SerializableSkeletonData。

使用SerializableSkeletonData:它几乎与使用SkeletonData的过程相同!

例如,假设有以下代码用于SkeletonData:

private void recorder_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs skeletonFrameArgs) { SkeletonData skeleton = skeletonFrameArgs.SkeletonFrame.Skeletons[0]; if (skeleton != null) { // 用数据做一些事情 setEclipsePos(HeadEclipse, skeleton.Joints[JointID.Head]); setEclipsePos(LeftHandEclipse, skeleton.Joints[JointID.HandLeft]); setEclipsePos(RightHandEclipse, skeleton.Joints[JointID.HandRight]); } }

使用回放的SerializableSkeletonData的相同功能:

private void recorder_PlaybackSkeletonDataReady(object sender, SkeletonDataArgs skeletonDataArgs) { SerializableSkeletonData skeleton = skeletonDataArgs.serializableSkeletonData; if (skeleton != null) { // 用数据做一些事情 setEclipsePos(HeadEclipse, skeleton.Joints[(int)JointID.Head]); setEclipsePos(LeftHandEclipse, skeleton.Joints[(int)JointID.HandLeft]); setEclipsePos(RightHandEclipse, skeleton.Joints[(int)JointID.HandRight]); } }

额外属性

KinectRecorderInterface有一个PlayPause方法,当在录制或回放模式时可以使用。

使用PlayPauseRecording()或PlayPausePlayback(),每次想要暂停录制或回放时。再次使用相同的方法继续。

// 暂停或恢复录制 recorder.PlayPauseRecording(); // 暂停或恢复回放 recorder.PlayPausePlayback();

使用Status来检查或查看录制接口的当前状态!

public enum KinectRecorderStatus { Idle = 0, Initializing = 1, Recording = 2, Playing = 3, Saving = 4, Loading = 5, NotConnected = 6, PlayingPaused = 7, RecordingPaused = 8 } // 打印当前状态 statusLabel.Text = recorder.Status.ToString(); // 检查'Status' if (recorder.Status == KinectRecorderStatus.Playing) { // 做一些事情 }

应用程序已经在后台运行了HotKey识别!可以设置多达4个HotKeys来处理:

  • 开始/停止录制:RecordHotKey
  • 开始/停止回放:PlaybackHotKey
  • 暂停/恢复录制:PauseRecordingHotKey
  • 暂停/恢复回放:PausePlaybackHotKey
// 将'F9'设置为录制的HotKey recorder.RecordHotKey = System.Windows.Forms.Keys.F9;
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485