0

有没有办法从 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: 在 SkeletalTracking.MainWindow.sensor_AllFramesReady(Object sender, AllFramesReadyEventArgs e)

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

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

4

3 回答 3

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 中,您将获得记录的骨架,因此,您可以获取骨架并使用保存的数据。

于 2012-11-28T23:09:03.573 回答
1

Kinect 工具箱提供骨骼数据的记录和回放功能。我不确定它是否支持“快照”模式,您可以在其中告诉它只拍摄当前帧,但代码当然可以适应这样做。

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 工具箱(在第一段中链接)已经有一个记录器。先试试看它是否会做你想做的事。

于 2012-11-28T23:07:43.663 回答
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

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

于 2016-02-05T16:34:33.213 回答