65.9K
CodeProject 正在变化。 阅读更多。
Home

Kinect 录制界面

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2012 年 10 月 1 日

GPL3

4分钟阅读

viewsIcon

23111

downloadIcon

1794

一个应用程序,可以录制 Kinect 的数据并在之后回放。

引言

自从我开始使用 Kinect 开发桌面应用程序以来,我不得不通过站在传感器前进行代码测试。起初这很有趣,但很快我就不得不一天进行几十次,这开始变得令人厌烦。因此,我决定创建一个可以录制和回放任何动作的应用程序!

背景

在本文中,我们假设您对使用 Kinect 传感器和 Kinect SDK(非 OpenNI)有基本了解,并且熟悉 C#。该应用程序是为 Kinect Beta 2 SDK 驱动程序版本 1.0.0.45 编写的。

如果您不熟悉 Kinect,请查看一系列很棒的 教程

必备组件

使用 KinectRecorderInterface

使用 KinectRecorderInterface 类非常简单。首先,让我们看一下该类的 public 成员/方法/事件。

它的使用目的是尽可能简单!

像大多数类一样声明创建该类。

 KinectRecorderInterface recorder = new KinectRecorderInterface();

通过录制器初始化打开 Kinect 传感器,并选择适当的 ImageResolutionDepthImage 最高可达 640x480)。
注意:一次只有一个应用程序可以使用 Kinect!!

用于仅打开 DepthStream

recorder.InitializeSensor(ImageResolution.Resolution320x240);

用于打开 DepthStreamVideoStream

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); 

现在,您可以像往常一样(实时)从 SkeletonTrackingDepthStream 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 属性

© . All rights reserved.