Kinect 录制界面





5.00/5 (2投票s)
一个应用程序,可以录制 Kinect 的数据并在之后回放。
引言
自从我开始使用 Kinect 开发桌面应用程序以来,我不得不通过站在传感器前进行代码测试。起初这很有趣,但很快我就不得不一天进行几十次,这开始变得令人厌烦。因此,我决定创建一个可以录制和回放任何动作的应用程序!
背景
在本文中,我们假设您对使用 Kinect 传感器和 Kinect SDK(非 OpenNI)有基本了解,并且熟悉 C#。该应用程序是为 Kinect Beta 2 SDK 驱动程序版本 1.0.0.45 编写的。
如果您不熟悉 Kinect,请查看一系列很棒的 教程!
必备组件
- Kinect 传感器
- Kinect Beta 2 SDK
- .NET Framework 4.0
- Visual Studio
- Json.Net(包含在项目中)
使用 KinectRecorderInterface
使用 KinectRecorderInterface
类非常简单。首先,让我们看一下该类的 public
成员/方法/事件。
它的使用目的是尽可能简单!
像大多数类一样声明创建该类。
KinectRecorderInterface recorder = new KinectRecorderInterface();
通过录制器初始化打开 Kinect 传感器,并选择适当的 ImageResolution
(DepthImage
最高可达 640x480)。
注意:一次只有一个应用程序可以使用 Kinect!!
用于仅打开 DepthStream
recorder.InitializeSensor(ImageResolution.Resolution320x240);
用于打开 DepthStream
和 VideoStream
recorder.InitializeSensor(ImageResolution.Resolution320x240, ImageResolution.Resolution640x480);
整个初始化代码
private KinectRecorderInterface recorder;
public void InitializeKinectRecorder()
{
recorder = new KinectRecorderInterface();
//Initialize Sensor through recorder
recorder.InitializeSensor(ImageResolution.Resolution640x480, ImageResolution.Resolution640x480);
//Set all the event handlers
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 获取数据。注意:EventHandlers
和 EventArgs
与使用 Kinect SDK 相同,除了回放!!
recorder.SkeletonFrameReady +=
new KinectRecorderInterface.SkeletonFrameHandler(recorder_SkeletonFrameReady);
recorder.ImageFrameReady +=
new KinectRecorderInterface.ImageFrameHandler(recorder_ImageFrameReady);
recorder.DepthFrameReady +=
new KinectRecorderInterface.DepthFrameHandler(recorder_DepthFrameReady);
回放 EventHandler
基本相同,但它区分了它的 EventArgs
(稍后参见'SkeletonData VS SerializableSkeletonData
')。
recorder.PlaybackSkeletonDataReady +=
new KinectRecorderInterface.PlaybackFrameHandler(recorder_PlaybackSkeletonDataReady);
现在,您可以像往常一样(实时)从 SkeletonTracking
、DepthStream
和 VideoStream
中检索 Kinect 数据,但此时没有录制或回放。
开始/停止录制 随时可以调用 StartRecording()
方法,以开始捕获仅可用的(已跟踪的)SkeletonData。
使用 StopRecording()
方法以停止捕获并保存任何存储的 SkeletonData
。默认情况下,数据保存在 "Recordings" 文件夹中,除非您从 RecordDirectory
更改它。
注意:如果没有 SkeletonData
,保存将被中止。
recorder.RecordDirectory = "./StoreData";
recorder.StartRecording();
//Wait as much you want
recorder.StopRecording();
现在,默认情况下,一个名为 "Recordings" 的新文件夹已与项目的可执行文件一起创建;并且在该文件夹中创建了一个名为 "recording_00x.dat" 的文件。
# 开始 / 停止回放
录制了一些动作后,您可以随时回放它们。使用 StartPlayback()
来回放最后可用的录制。您也可以使用 StartPlayback
(recording_xxx.dat),来回放您选择的录制。
注意:每次应用程序启动/录制/保存时,可通过 ExistingRecords
属性获得一个更新的录制目录(List<string>
),以便您选择任何录制。
//Play the last available recording
recorder.StartPlayback();
//Play a record of your choice
List<string> records = recorder.ExistingRecords;
recorder.StartPlayback(records[0]);
SkeletonData VS SerializableSkeletonData
当我达到必须存储数据的那一点时,我意识到我无法序列化 SkeletonData
,因为它没有被标记为 Serializable
。因此,我实现了 Json.Net,它效果很好!但遗憾的是,当我尝试反序列化并(如下所示)转换存储的数据时,它再次失败,因为 SkeletonData
没有任何 public
构造函数(它的构造函数设置为 internal
)!!欢迎有更好的解决方案!!!
<代码不工作>
//This code gave me an error because there is no public constructor for SkeletonData
var json = System.IO.File.ReadAllText(filepath);
var skeletonData = Newtonsoft.Json.JsonConvert.DeserializeObject<List<SkeletonData>>(json);
</代码不工作>
最终,我没有想出其他解决方案,而是创建了一个与 SkeletonData
几乎相同的类,如下所示。
您将获得 SerializableSkeletonData
的唯一一点,是在您从 PlaybackFrameHandler
获取 SkeletonDataArgs
时。SkeletonDataArgs
包含 SerializableSkeletonData
。
使用 SerializableSkeletonData
:过程几乎与使用 SkeletonData
相同!
例如,假设我们有以下用于 SkeletonData
的代码
private void recorder_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs skeletonFrameArgs)
{
//Get the first skeleton from SkeletonFrame
SkeletonData skeleton = skeletonFrameArgs.SkeletonFrame.Skeletons[0];
if (skeleton != null)
{
//Do something with your data
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)
{
//Do something with your data
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()
。再次使用相同的方法继续..!
//Pause or Resume recording
recorder.PlayPauseRecording();
//Pause or Resume playback
recorder.PlayPausePlayback();
使用 Status
来检查或查看录制接口的当前状态!
public enum KinectRecorderStatus
{
Idle = 0,
Initializing = 1,
Recording = 2,
Playing = 3,
Saving = 4,
Loading = 5,
NotConnected = 6,
PlayingPaused = 7,
RecordingPaused = 8
}
//Print the current status
statusLabel.Text = recorder.Status.ToString();
//Check 'Status'
if (recorder.Status == KinectRecorderStatus.Playing)
{
//Do something
}
应用程序已在后台运行 HotKey
标识!您可以设置最多 4 个 HotKeys
来处理
- 开始 / 停止录制:
RecordHotKey
- 开始 / 停止回放:
PlaybackHotKey
- 暂停 / 继续录制:
PauseRecordingHotKey
- 暂停 / 继续回放:
PausePlaybackHotKey
并非必须启用 HotKeys
,但您必须为它们分配一个 Key
值。
//Set 'F9' as HotKey for recording
recorder.RecordHotKey = System.Windows.Forms.Keys.F9;
应用程序的类图
仅包含 public
属性