ThomasLengeling / KinectPV2

Kinect4W 2.0 library for Processing
MIT License
286 stars 105 forks source link

Recording a Colored Point Cloud #69

Open santoshnpl54 opened 6 years ago

santoshnpl54 commented 6 years ago

Hello! Not sure this is a good place to put this but I didn't know where else to. I'm trying to record a point cloud with color into the .obj frames to make a 3D model. I was using the ColorPointCloud and RecordPointCloud examples to try and accomplish this, but keep running across this error...

"OpenGL error 1281 at top endDraw(): invalid value"

It only happens when I add in ..

FloatBuffer colorBuffer = kinect.getColorChannelBuffer();
int vertColorData = kinect.WIDTHColor * kinect.HEIGHTColor * 3;

and..

// color
  {
    pgl.bindBuffer(PGL.ARRAY_BUFFER, colorVboId);
    // fill VBO with data
    pgl.bufferData(PGL.ARRAY_BUFFER, Float.BYTES * vertColorData, colorBuffer, PGL.DYNAMIC_DRAW);
    // associate currently bound VBO with shader attribute
    pgl.vertexAttribPointer(colorLoc, 3, PGL.FLOAT, false, Float.BYTES * 3, 0);
  }

I'm assuming it is because the depth and color buffers are colliding in a way, but I'm not sure how to combine them in the correct way. This is the current code I've pieced together (Leaving out the keys to record and such)...

/*
Thomas Sanchez Lengeling.
 http://codigogenerativo.com/

 KinectPV2, Kinect for Windows v2 library for processing

 How to record Point Cloud Data and store it in several obj files.
 Record with 'r'
 */

import java.util.ArrayList;
import java.nio.*;
import KinectPV2.*;

KinectPV2 kinect;

PGL pgl;
PShader sh;

int  vertLoc;
int colorLoc;

//transformations
float a = 7;
int zval = -50;
float scaleVal = 220;

//Distance Threashold
int maxD = 4500; // 4.5 m
int minD = 0;  //  50 cm

int numFrames =  30; // 30 frames  = 1s of recording
int frameCounter = 0; // frame counter

boolean recordFrame = false;  //recording flag
boolean doneRecording = false;

//Array where all the frames are allocated
ArrayList<FrameBuffer> mFrames;

//VBO buffer location in the GPU
int vertexVboId;
int colorVboId;

void setup() {
  size(1024, 768, P3D);

  kinect = new KinectPV2(this);

  //create arrayList
  mFrames = new ArrayList<FrameBuffer>();

  //Enable point cloud
  kinect.enableDepthImg(true);
  kinect.enablePointCloud(true);

  kinect.init();

  sh = loadShader("frag.glsl", "vert.glsl");

  PGL pgl = beginPGL();

  IntBuffer intBuffer = IntBuffer.allocate(2);
  pgl.genBuffers(2, intBuffer);

  //memory location of the VBO
  vertexVboId = intBuffer.get(0);
  colorVboId = intBuffer.get(1);

  endPGL();

  //set framerate to 30
  frameRate(30);
}

void draw() {
  background(0);
  background(0);

  //draw the depth capture images
  image(kinect.getDepthImage(), 0, 0, 320, 240);
  image(kinect.getColorImage(), 0, 0, 320, 240);
  image(kinect.getPointCloudDepthImage(), 320, 0, 320, 240);

  //translate the scene to the center
  translate(width / 2, height / 2, zval);
  scale(scaleVal, -1 * scaleVal, scaleVal);
  rotate(a, 0.0f, 1.0f, 0.0f);

  // Threahold of the point Cloud.
  kinect.setLowThresholdPC(minD);
  kinect.setHighThresholdPC(maxD);

  //get the points in 3d space
  FloatBuffer pointCloudBuffer = kinect.getPointCloudDepthPos();

  //get the color for each point of the cloud Points
  FloatBuffer colorBuffer      = kinect.getColorChannelBuffer();

  //data size, 512 x 424 x 3 (XYZ) coordinate
  int vertData = kinect.WIDTHDepth * kinect.HEIGHTDepth  * 3;
  int vertColorData = kinect.WIDTHColor * kinect.HEIGHTColor * 3;

  pgl = beginPGL();
  sh.bind();

  vertLoc = pgl.getAttribLocation(sh.glProgram, "vertex");
  colorLoc = pgl.getAttribLocation(sh.glProgram, "color");

  pgl.enableVertexAttribArray(colorLoc);
  pgl.enableVertexAttribArray(vertLoc);

  //vertex
  {
    pgl.bindBuffer(PGL.ARRAY_BUFFER, vertexVboId);

    pgl.bufferData(PGL.ARRAY_BUFFER, Float.BYTES * vertData, pointCloudBuffer, PGL.DYNAMIC_DRAW);

    pgl.vertexAttribPointer(vertLoc, 3, PGL.FLOAT, false, Float.BYTES * 3, 0);
  }

  // color
  {
    pgl.bindBuffer(PGL.ARRAY_BUFFER, colorVboId);
    // fill VBO with data
    pgl.bufferData(PGL.ARRAY_BUFFER, Float.BYTES * vertData, colorBuffer, PGL.DYNAMIC_DRAW);
    // associate currently bound VBO with shader attribute
    pgl.vertexAttribPointer(colorLoc, 3, PGL.FLOAT, false, Float.BYTES * 3, 0);
  }

  // unbind VBOs
  pgl.bindBuffer(PGL.ARRAY_BUFFER, 0);

  pgl.drawArrays(PGL.POINTS, 0, vertData);

  pgl.disableVertexAttribArray(vertLoc);

  sh.unbind();
  endPGL();

  //allocate the current pointCloudBuffer into an array of FloatBuffers
  allocateFrame(pointCloudBuffer);

  //when the allocation is done write the obj frames
  writeFrames();

  stroke(255, 0, 0);
  text(frameRate, 50, height - 50);
}

//allocate all the frame in a temporary array
void allocateFrame(FloatBuffer buffer) {
  if (recordFrame) {
    if ( frameCounter < numFrames) {
      FrameBuffer frameBuffer = new FrameBuffer(buffer);
      frameBuffer.setFrameId(frameCounter);
      mFrames.add(frameBuffer);
    } else {
      recordFrame = false;
      doneRecording = true;
    }
    frameCounter++;
  }
}

//Write all the frames recorded
void writeFrames() {
  if (doneRecording) {
    for (int i = 0; i < mFrames.size(); i++) {
      FrameBuffer fBuffer =  (FrameBuffer)mFrames.get(i);
      fBuffer.saveOBJFrame();
    }
    doneRecording = false;
    println("Done Recording frames: "+numFrames);
  }
}

Would anyone have a better idea of what to do, or what I'm doing wrong?

Thanks!

Phaidonas commented 5 years ago

Did you find solution?Obj does not record color, you have to use ply

Phaidonas commented 5 years ago

my code is somehow different, i used kinect.enableColorPointCloud(true) and then tried to see the values that are stored in the buffer with a for loop:

import java.util.ArrayList;
import java.nio.*;
import KinectPV2.*;

KinectPV2 kinect;

PGL pgl;
PShader sh;

int  vertLoc;
int colorLoc;

//transformations
float a = 7;
int zval = -50;
float scaleVal = 220;

//Distance Threashold
int maxD = 4500; // 4.5 m
int minD = 0;  //  50 cm

int numFrames =  100; // 30 frames  = 1s of recording
int frameCounter = 0; // frame counter

boolean recordFrame = false;  //recording flag
boolean doneRecording = false;

//Array where all the frames are allocated
ArrayList<FrameBuffer> mFrames;

//VBO buffer location in the GPU
int vertexVboId;
int colorVboId;

void setup() {
  size(1024, 768, P3D);

  kinect = new KinectPV2(this);

  //create arrayList
  mFrames = new ArrayList<FrameBuffer>();

  //Enable point cloud
  kinect.enableDepthImg(true);
  kinect.enableColorImg(true);
  kinect.enableColorPointCloud(true);

  kinect.init();

  sh = loadShader("frag.glsl", "vert.glsl");

  PGL pgl = beginPGL();

  IntBuffer intBuffer = IntBuffer.allocate(2);
  pgl.genBuffers(2, intBuffer);

  //memory location of the VBO
  vertexVboId = intBuffer.get(0);
  colorVboId = intBuffer.get(1);

  endPGL();

  //set framerate to 30
  frameRate(30);
}

void draw() {
  background(0);
  background(0);

  //draw the depth capture images
  //image(kinect.getColorImage(), 0, 0, 320, 240);
  //image(kinect.getDepthImage(), 0, 0, 320, 240);
  image(kinect.getPointCloudDepthImage(), 320, 0, 320, 240);

  pushMatrix();
  //translate the scene to the center
  translate(width / 2, height / 2, zval);
  scale(scaleVal, -1 * scaleVal, scaleVal);
  rotate(a, 0.0f, 1.0f, 0.0f);

  // Threahold of the point Cloud.
  //kinect.setLowThresholdPC(minD);
  //kinect.setHighThresholdPC(maxD);
  pgl = beginPGL();
  sh.bind();
  //get the points in 3d space
  FloatBuffer pointCloudBuffer = kinect.getPointCloudColorPos();

  FloatBuffer colorBuffer      = kinect.getColorChannelBuffer();

  //data size, 512 x 424 x 3 (XYZ) coordinate
  int vertData = kinect.WIDTHColor * kinect.HEIGHTColor  * 3;

  vertLoc = pgl.getAttribLocation(sh.glProgram, "vertex");

  pgl.enableVertexAttribArray(vertLoc);

  //vertex
  {
    pgl.bindBuffer(PGL.ARRAY_BUFFER, vertexVboId);

    pgl.bufferData(PGL.ARRAY_BUFFER, Float.BYTES * vertData, pointCloudBuffer, PGL.DYNAMIC_DRAW);

    pgl.vertexAttribPointer(vertLoc, 3, PGL.FLOAT, false, Float.BYTES * 3, 0);
  }

    {
    pgl.bindBuffer(PGL.ARRAY_BUFFER, colorVboId);
    // fill VBO with data
    pgl.bufferData(PGL.ARRAY_BUFFER, Float.BYTES * vertData, colorBuffer, PGL.DYNAMIC_DRAW);
    // associate currently bound VBO with shader attribute
    pgl.vertexAttribPointer(colorLoc, 3, PGL.FLOAT, false, Float.BYTES * 3, 0);
  }

  // unbind VBOs
  pgl.bindBuffer(PGL.ARRAY_BUFFER, 0);

  pgl.drawArrays(PGL.POINTS, 0, vertData);

  pgl.disableVertexAttribArray(vertLoc);
  pgl.disableVertexAttribArray(colorLoc);

  sh.unbind();
  endPGL();

popMatrix();
  //allocate the current pointCloudBuffer into an array of FloatBuffers
  allocateFrame(pointCloudBuffer);
for (int i = 0; i < 5000; i++) {
  println("r :"+colorBuffer.get(i*3 + 0));
  println("g :"+colorBuffer.get(i*3 + 1));
  println("b :"+colorBuffer.get(i*3 + 2));
    println("x :"+pointCloudBuffer.get(i*3 + 0));
  println("y :"+pointCloudBuffer.get(i*3 + 1));
  println("z :"+pointCloudBuffer.get(i*3 + 2));
}
  //when the allocation is done write the obj frames
  writeFrames();

  stroke(255, 0, 0);
  text(frameRate, 50, height - 50);
}

//allocate all the frame in a temporary array
void allocateFrame(FloatBuffer buffer) {
  if (recordFrame) {
    if ( frameCounter < numFrames) {
      FrameBuffer frameBuffer = new FrameBuffer(buffer);
      frameBuffer.setFrameId(frameCounter);
      mFrames.add(frameBuffer);
    } else {
      recordFrame = false;
      doneRecording = true;
    }
    frameCounter++;
  }
}

//Write all the frames recorded
void writeFrames() {
  if (doneRecording) {
    for (int i = 0; i < mFrames.size(); i++) {
      FrameBuffer fBuffer =  (FrameBuffer)mFrames.get(i);
      fBuffer.saveOBJFrame();
    }
    doneRecording = false;
    println("Done Recording frames: "+numFrames);
  }
}

public void mousePressed() {

  println(frameRate);
  // saveFrame();
}

public void keyPressed() {

  //start recording 30 frames with 'r'
  if (key == 'r') {
    recordFrame = true;
  }
  if (key == 'a') {
    zval +=1;
    println(zval);
  }
  if (key == 's') {
    zval -= 1;
    println(zval);
  }

  if (key == 'z') {
    scaleVal += 0.1;
    println(scaleVal);
  }
  if (key == 'x') {
    scaleVal -= 0.1;
    println(scaleVal);
  }

  if (key == 'q') {
    a += 0.1;
    println(a);
  }
  if (key == 'w') {
    a -= 0.1;
    println(a);
  }

  if (key == '1') {
    minD += 10;
    println("Change min: "+minD);
  }

  if (key == '2') {
    minD -= 10;
    println("Change min: "+minD);
  }

  if (key == '3') {
    maxD += 10;
    println("Change max: "+maxD);
  }

  if (key == '4') {
    maxD -= 10;
    println("Change max: "+maxD);
  }
}

Now the main problem is that some of the values of pointCloudBuffer return - infinity, but in the record point cloud return regular, also the color is not rendered.