0

Is there a way to obtain data, such as positioning of a joint, from the Kinect for specific times? I would like to get and save this data for a certain time of my choosing to use for other calculations. Example would be getting the position data of the head at time = 5 seconds after running program and at time = 10 seconds after running program and saving it to a variable.

Error while running: Here is part of the code ....

    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 
     }

This is the error message I get:

System.NullReferenceException was unhandled Message=Object reference not set to an instance of an object. Source=SkeletalTracking StackTrace: at SkeletalTracking.MainWindow.sensor_AllFramesReady(Object sender, AllFramesReadyEventArgs e)

Will this.Recorder.Record(skeletonFrame); start the recording or do I need to initialize and declare or call one of the functions to start recording and ask for a name of the file to save to?

Does the replay of the data allow me to pull out specific timestamp values and the data associated at those timestamps?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
user1773489
  • 45
  • 10

3 Answers3

1

The Kinect Toolbox offers recording and playback functionality for skeletal data. I am unsure if it supports a "snapshot" mode, where you tell it to take just the current frame, but the code could certainly be adapted to do so.

You can roll your own by setting up the appropriate checks in your SkeletonFrameReady callback. All the skeleton data is available to you in the SkeletonFrameReady callback. You simply need to save the appropriate data to a collection of some type -- you can save every skeleton, or you can set up a timer to check and only capture them ever ??-seconds.

A similar question and answer was addressed here: kinect c# draw and move skeleton from saved data

Something else you could try is to do all the work in a timer:

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

The _savedSkeletons variable keeps storing up skeletons every 5 seconds. If you want to save them to a file, you would serialize the data and write it out via a file stream (many examples of how to serialize and output objects out there).

The above code is a simple example and just stores the Skeleton object. To achieve all your goals, you may need to store additional information -- such as a timestamp. You would need to create a custom class to store all the information you want and store those objects.

Remember that the Kinect Toolbox (linked in the first paragraph) already has a recorder. Try it first to see if it will do what you want.

Community
  • 1
  • 1
Nicholas Pappas
  • 10,439
  • 12
  • 54
  • 87
  • How would I save the data with the timer, if I am running the skeletal tracking sample code and want to modify within the skeletal tracking sample code to automatically capture that data? – user1773489 Nov 29 '12 at 00:04
  • I have updated my answer with additional details and information. – Nicholas Pappas Nov 29 '12 at 21:45
  • Thanks for the update. If I were to use this code, does it go in the same function that is found in the skeletal tracking sample code? I have tried using that exact code and it gives an error about not knowing what the _savedSkeletons is in that context I am trying to get it to do something like what the recorder does but only grab information from certain joints that I have called in the code already. I want to be able to store it so I can call upon certain values to calculate velocity of a joint and centroid (using head and shoulder joints). – user1773489 Nov 29 '12 at 23:17
  • `_savedSkeleton`, `_skeletons` and `_timer` are all global variables I declared earlier in the class, but just did not include in the example code. You'll need to declare them globally. If you execute the code in the timer callback you can put it anywhere that makes sense for you. Because you want velocity you'll need to create your own class to store joint data and time stamps. The Kinect Toolbox class is a good example. – Nicholas Pappas Nov 30 '12 at 00:18
  • what variable type would those be and what do i set them to when declaring them? so those lines of code would be best placed in the FramesReady section of code? how do i create a class to store those data?thanks – user1773489 Nov 30 '12 at 10:10
  • `_savedSkeleton` is a `List`; `_skeletons` is a `Skeleton` array; `_timer` is a `DispatcherTimer` -- all these should be evident from the initialization in the example code (e.g., `_timer = new DispatcherTimer()`. You don't set a variable to anything when you "declare" it, you do when you "initialize" it -- you can "declare" and "initialize" at the same time, but don't have to. You want to set up a timer *once* - where you decide to do that (so it only happens once) is up to you. Creating a class to store this is another question and there are many examples already out there. – Nicholas Pappas Nov 30 '12 at 18:12
1

Yes, it is possible, i used the Kinect.Toolbox for this This library have Recorder and Replay class that allow you to Record the frames to the disk and replay the saved frames. I used this library with success, if you want some example code, please let me know.

This discussion are getting bigger, i will edit this to explain some questions

EDIT 1. QUICK TUTORIAL OF KINECT.TOOLBOX

Create 3 buttons in your application (Start Recording, Stop Recording, Start Replay)

Code for your Form.cs

    Stream recordStream;
    KinectRecorder Recorder;
    KinectReplay Replay;

Code for Start Recording Button:

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

Code for Stop Recording button

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

Code for Replay Button

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

Here we enable the color and skeleton Recorders, now, lets record only the skeleton data, for example porposes. In your SkeletonFrameReady event handler, you need to do something like this

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

Ok, you recorded the frames. Look at the Replay button code, you created a event handler for the ReplaySkeletonFrameReady, remember? (this.Replay.SkeletonFrameReady += Replay_SkeletonFrameReady;)

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

So in your SkeletonFrameReady you will get the recorded skeleton, so, you can get the skeleton and use the saved data.

Ewerton
  • 4,046
  • 4
  • 30
  • 56
  • If you want just an snapshot of some frames, you could serialize the frames to the memory. http://stackoverflow.com/questions/10390356/c-sharp-serializing-deserializing-with-memory-stream then retrieve it later. – Ewerton Nov 28 '12 at 23:13
  • sure, the code will be appreciated. How would I incorporate it into the skeletal tracking code from the SDK sample code. I am working with that code. Does the Kinect Toolbox have to be manually run to save the data or is there a way to grab the data automatically when the skeletal tracking code is run? – user1773489 Nov 29 '12 at 00:02
  • In my case, i just referenced the Kinect.Toolbox project, and when needed, instantiated a Recorder or a Replay and used it, like in te example code provided with the Kinect.Toolbox. You could do the same, so, you still working with the skeletal trackin project, just reference the Kinect.Toolbox on it and use it. Try, if you didnt do it suceffully, please, let me know and i will hel you. – Ewerton Nov 30 '12 at 01:37
  • i have downloaded the Kinect.Toolbox files and added a reference to my project to the Kinect.Toolbox. I see sample code related to the recorder and replay on each of the stream of data I could pull from. How and what do I call out in my skeletal tracking project to record and where would be the best place to place this code? How do I save what i record to a file? And then pull out values from what is recorded? – user1773489 Nov 30 '12 at 01:55
  • man, 10 minutes ago a sugested you to look at the kinect toolbox `code samples` and now you asking me for the code to write? Please take a look at the samples, they have answer for all your questions. – Ewerton Nov 30 '12 at 02:18
  • is this a correct start? System.IO.Stream stream = new System.IO.MemoryStream(); KinectRecorder kinectRecorder = new KinectRecorder(KinectRecordOptions.Skeletons, stream); does this record the data? if it does, how do i save this data so I can use it for calculation of velocity and centroid? – user1773489 Nov 30 '12 at 09:55
  • @user1773489 I updated my answer, to show to you a quick tutorial for the KinectToolbox. Check edits, and if it help you, mark it as answer. – Ewerton Nov 30 '12 at 15:38
  • I have start implementing your code into the skeletal tracking code I am using but I have ran into an issue while it runs that I have pasted above – user1773489 Dec 02 '12 at 03:11
  • this.Recorder.Record(skeletonFrame); // I get an error after the RGB camera view freezes. The code would run, but no skeleton image appears and then after maybe a short time, the camera view freezes and an error pops up on my code. – user1773489 Dec 02 '12 at 22:26
  • If you post your code on github i could review it for you. Your original question was about to get data from Kinect for specific time, and this questions was answered, please, mark it as answer and lets start new stack overflow question for your other doubts :) . – Ewerton Dec 03 '12 at 11:55
0

To wait for x seconds in C# easiest way is

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

Example:

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

Another way is to use timer objects and enable disable them, and read a form static value inside your looping code, check that boolean if something has to be recorded or not

Peter
  • 2,043
  • 1
  • 21
  • 45