从Kinect获取特定时间的数据

时间:2012-11-28 22:38:47

标签: time position kinect

有没有办法从Kinect获取特定时间的数据,例如关节的定位?我想获取并保存这些数据一段时间,我选择用于其他计算。例如,在运行程序后的时间= 5秒和运行程序后的时间= 10秒获取磁头的位置数据并将其保存到变量。

运行时出错: 这是代码的一部分......

    void sensor_AllFramesReady(object sender, AllFramesReadyEventArgs e)
    {
        if (closing)
        {
            return;
        }

        //Get a skeleton
        Skeleton first = GetFirstSkeleton(e);

        if (first == null)
        {
            return;
        }

        GetCameraPoint(first, e);

        using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
        {
            if (skeletonFrame == null)
            {
                return;
            }

            this.Recorder.Record(skeletonFrame); // I get an error after the RGB camera view freezes

        }
         // some more stuff 
     }

这是我收到的错误消息:

  

System.NullReferenceException未处理Message = Object引用未设置为对象的实例。 Source = SkeletalTracking StackTrace:at SkeletalTracking.MainWindow.sensor_AllFramesReady(Object sender,AllFramesReadyEventArgs e)

this.Recorder.Record(skeletonFrame);是否会开始录制,还是需要初始化并声明或调用其中一个函数来开始录制并要求保存文件的名称?

数据的重放是否允许我提取特定时间戳值以及与这些时间戳相关联的数据?

3 个答案:

答案 0 :(得分:1)

Kinect Toolbox为骨架数据提供录制和播放功能。我不确定它是否支持“快照”模式,你告诉它只采用当前帧,但代码当然可以适应这样做。

您可以通过在SkeletonFrameReady回调中设置相应的检查来自行推广。 SkeletonFrameReady回调中可以使用所有骨架数据。您只需要将适当的数据保存到某种类型的集合中 - 您可以保存每个骨架,或者您可以设置一个计时器来检查并仅捕获它们 - 秒。

此处提出了类似的问题和答案: kinect c# draw and move skeleton from saved data

你可以尝试的其他事情是在计时器中完成所有工作:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    _savedSkeletons = new List<Skeleton>();

    _timer = new DispatcherTimer();
    _timer.Interval = TimeSpan.FromSeconds(5);
    _timer.Tick += (s, o) =>
    {
        using (SkeletonFrame skeletonFrame = KinectSensorManager.KinectSensor.SkeletonStream.OpenNextFrame(15))
        {
            if (skeletonFrame == null || skeletonFrame.SkeletonArrayLength == 0)
                return;

            // resize the skeletons array if needed
            if (_skeletons.Length != skeletonFrame.SkeletonArrayLength)
                _skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];

            // get the skeleton data
            skeletonFrame.CopySkeletonDataTo(_skeletons);

            foreach (var skeleton in _skeletons)
            {
                if (skeleton.TrackingState != SkeletonTrackingState.Tracked)
                    continue;

                _savedSkeletons.Add(skeleton);
            }
        }
    };

    _timer.Start();
}

_savedSkeletons变量每5秒钟一直存储骨架。如果要将它们保存到文件中,可以序列化数据并通过文件流将其写出(许多如何序列化和输出对象的示例)。

上面的代码是一个简单的例子,只存储Skeleton对象。要实现所有目标,您可能需要存储其他信息 - 例如时间戳。您需要创建一个自定义类来存储所需的所有信息并存储这些对象。

请记住,Kinect工具箱(在第一段中链接)已经有一个录像机。先试试看它是否会做你想要的。

答案 1 :(得分:1)

是的,有可能,我使用了Kinect.Toolbox 此库具有Recorder和Replay类,允许您将帧记录到磁盘并重放保存的帧。 我成功使用了这个库,如果你想要一些示例代码,请告诉我。

这个讨论越来越大,我将编辑这个来解释一些问题

编辑1。 KINECT.TOOLBOX的快速补习

在应用程序中创建3个按钮(开始录制,停止录制,开始重播)

您的Form.cs代码

    Stream recordStream;
    KinectRecorder Recorder;
    KinectReplay Replay;

开始录制按钮代码:

 protected void StartRecord(object sender, RoutedEventArgs e)
    {
        string generatedName = Guid.NewGuid().ToString();
        string recordStreamPathAndName = @"C:\" + generatedName + ".recorded";            
        this.recordStream = File.Create(recordStreamPathAndName);
        this.Recorder = new KinectRecorder(KinectRecordOptions.Color | KinectRecordOptions.Skeletons, recordStream);
    }

停止录制代码按钮

 if (Recorder != null)
        {
            Recorder.Stop();
            Recorder = null;
        }

重播按钮代码

try
{
    recordStream = File.OpenRead(this.recordStreamPathAndName);
}
catch (Exception ex)
{
    throw ex;
}

    this.Replay = new KinectReplay(recordStream);
    this.Replay.ColorImageFrameReady += Replay_ColorImageFrameReady;
    this.Replay.SkeletonFrameReady += Replay_SkeletonFrameReady;
    this.Replay.Start();
}

这里我们启用颜色和骨架记录器,现在,让我们只记录骨架数据,例如porposes。 在您的SkeletonFrameReady事件处理程序中,您需要执行类似这样的操作

using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
{
    if (skeletonFrame == null)
        return;
        // any other validations...
    this.Recorder.Record(skeletonFrame);
}

好的,你录制了帧。 看看Replay按钮代码,你为ReplaySkeletonFrameReady创建了一个事件处理程序,还记得吗? (this.Replay.SkeletonFrameReady + = Replay_SkeletonFrameReady;)

    void Replay_SkeletonFrameReady(object sender, ReplaySkeletonFrameReadyEventArgs e)
    {
        // do your stuff.
    }

因此,在您的SkeletonFrameReady中,您将获得记录的骨架,因此,您可以获取骨架并使用保存的数据。

答案 2 :(得分:0)

以C#最简单的方式等待x秒

System.Threading.Thread.Sleep(x000);//where x is the time in seconds for which you want app to wait

示例:

System.Threading.Thread.Sleep(4000);//will wait for 4 seconds

另一种方法是使用计时器对象并启用禁用它们,并在循环代码中读取表单静态值,如果必须记录某些内容则检查该布尔值