Best way of saving an array of pointclouds in a file

942 Views Asked by At

I am using a Kinect V2 to make volumetric recordings. I am using the Kinect sdk version 2 (in C#). I would like to save a file that contains several pointcloud "frames". I am going to import the file in Unity and play the frames as a "Pointcloud animation". I have done this in the past inside Unity (https://vimeo.com/140683403), but this time I am using VisualStudio in order to access all methods in the SDK.

The file should contain:

  1. An array of vertices (the points)
  2. An array of colors (the colors of each point)

Eventually it should be possible to add:

  1. An array of triangles
  2. User joints (I am currently using it to record humans)

In my first try I programmed a very simple UserFrame class that contained a List of vertices. I then serialized a List of UserFrames, which I could succesfully import in Unity. However, deserializing it in Unity takes ages (around a minute for a couple of seconds of recording) so I wonder if there is a better approach.

  • Should I rather write and parse an ASCII file?
  • In a previous attempt my vertices were an Array instead of a List. Would this improve the speed of deserialization?

This is an edited version of the class:

public class UserFrame
{

    //Frame time-stamp. Could be long int in milliseconds
    //public float time;


    // Each element in the vertexList contains an array of 3 floats.    
    public List<float[]> vertexList;


    public UserFrame(List<float[]> _vertexList) {
        vertexList = _vertexList;
    }


}

The code for serialization:

Stream stream;

stream = File.Open(finalPath, FileMode.Create);

BinaryFormatter bf = new BinaryFormatter();

bf.Serialize(stream, userFrameList);
stream.Close();

and deserialization (this is the slow part):

Stream stream = File.Open (fileName, FileMode.Open);
BinaryFormatter bf = new BinaryFormatter ();

dummyFrames = (List <UserFrame>)bf.Deserialize (stream);
stream.Close ();        
2

There are 2 best solutions below

0
On BEST ANSWER

I tried several two ways of saving the data.

First Approach A 2-dimensional array of floats with size 3xN, where N is the number of vertices. A 2-dimensional array of bytes of size 4xN, where each of the four components referred to the R,G,B and A components of the color. This was very slow.

Second Approach I decided to give Protbuf-net a try. However, protbuf does not work with 2-dimensional arrays so I had to convert my data to one dimensional arrays:

public float[] vertexX;
public float[] vertexY;
public float[] vertexZ;

public float [] r;
public float [] g;
public float [] b;
public float [] a;

It turned out that changing to this data-structure dramatically improved the speed of deserialization, even with the BinaryFormatter approach. So I ended using that.

0
On

Using a custom serializer instead of BinaryFormatter will make your data smaller and faster to deserialize. It takes more code, true since you need to know the exact order but in your case it could be worth the shot.

See this benchmark:

http://codebetter.com/gregyoung/2008/08/24/fast-serialization/

So you'd have to implement a method that iterate through the whole array and place each float, next to each other. Then on the other side, you deserialize by doing the opposite. That means you need to add one extra information, the length of the array so you know how many values are to be collected for a specific collection.