5

This is regarding unpacking the encoded rgb values in a pcl file. I did this with the procedure described in the pcl documentation, but the unpacked rgb values I get are not quite correct. When I plot them with R the representation given does not correspond to the colors in the real setting (I am to a certain degree sure the problem is not with the way it was plotted with R).

For example in the image attached the area demarcated should have colors gray and blue (two chairs and a table).unpacked pcl data plotted with the rgl library in R

Source pcl file could be found at: https://docs.google.com/open?id=0Bz5-HVcDiF6SanBZU0JWVmJwWHM and the file with the unpacked color values at: https://docs.google.com/open?id=0Bz5-HVcDiF6SV2pYQ0xUbTAwVmM. Also following is the code used for unpacking the color values in a c plus plus setting:

uint32_t rgbD = *reinterpret_cast<int*>(&kinectValue);

    uint16_t rD = (rgbD >> 16) & 0x0000ff;
    uint16_t gD = (rgbD >> 8)  & 0x0000ff;
    uint16_t bD = (rgbD)       & 0x0000ff;

I would really appreciate if you could let me know where I have gone wrong.

Update:

Following is the R code snippet I used in plotting the values in 3D:

library(rgl)
pcd <- read.table(file.choose(),sep="")
names(pcd) <- c("x","y","z","r","g","b")
plot3d(pcd$x,pcd$y,pcd$z,col=rgb(pcd$r,pcd$g,pcd$b,maxColorValue=255))

Update:

Following is the code I used to read data, in C++:

/*
Reads in a file from Kinect with unpacked color values, filter the color value component and
sends it to be unpacked
*/
int fileRead(){

  string line;
  int lineNum = 0;

  ifstream myfile ("res/OnePerson4.pcd");

  if (myfile.is_open())
  {
    while ( myfile.good() )
    {
      lineNum++;
      getline (myfile,line);

       // Exclude the header information in the kinect file from the unpacking process
      //if(lineNum > 10 && lineNum <20){//This for loop is activated when testing
      if(lineNum > 10){
        //Test code to extract the x,y,z values
        string xyzvalFromKinectStr = line.substr(0,line.find_last_of(' '));
        //cout<<xyzvalFromKinectStr<<"\n";
        //Extract the packed rgb value
        string valFromKinectStr = line.substr(line.find_last_of(' '));
        double kinectVal = ::atof(valFromKinectStr.c_str());
        kinectToRgb(kinectVal, xyzvalFromKinectStr);

      }
    }
    myfile.close();
  }
  else
  {
      cout << "Unable to open file";
  }

  return 0;
}
picmate 涅
  • 3,951
  • 5
  • 43
  • 52
  • 1
    Both links download zero bytes for me. – Michael Daum Apr 11 '12 at 20:21
  • @MichaelDaum, sorry about that. I will rectify the issue soon. Thanks for taking time to looking to the issue. – picmate 涅 Apr 11 '12 at 21:12
  • 1
    RGB is usually represented as RGBA. This can be different depending on platform but you should try (rgbD >> 24), >>16, and >>8 for R G and B respectively. But since that's probably not the problem... You're trying to get R-G-B in a sparse three dimensional space. You believe that it is the color unpacking that is incorrect, but are you completely sure it isn't the drawing code or the file I/O code? – std''OrgnlDave Apr 11 '12 at 21:16
  • @OrgnlDave, thanks for the response. I (along with some experts in R found in the R chat room in SO) plotted the output in several different ways to track the error and found that with all the methods the plot comes the same way. So I finalized the error should be with the unpacking. You suggest me to try rgbD >> 24, >>16, and >>8 for R G and B> – picmate 涅 Apr 11 '12 at 21:31
  • @OrgnlDave, I tried rgbD >> 24, >>16, and >>8 for R G and B. But it is still the same. I get a plot with wrong color values. What do you think? Thanks. – picmate 涅 Apr 11 '12 at 22:17
  • 1
    @picmate what software setup are you using to plot it? this might actually be fun to put some time into :-P – std''OrgnlDave Apr 12 '12 at 03:12
  • @OrgnlDave, I am using R. You need to use rgl library to plot it. Please refer to the updated question to find the R code snippet I used to plot it in 3D. Also I changed the data file locations and you can now download the source and the converted pcl files. – picmate 涅 Apr 12 '12 at 14:24
  • 1
    Could you post more code? How do you read `kinectValue`? What type is it of? – detunized Apr 12 '12 at 14:43
  • 1
    @picmate are they the *same* wrong colors, or a different random subset? Is there any way you can generate a really, really simple pcl file with only a few points in it, for experimentation (e.g. then you could look at it with a hex browser and see exactly how the representation really works). – Ben Bolker Apr 12 '12 at 14:44
  • @detunized, I read the kinectValue is from a pcd data file, a point cloud file generate through the kinect sensor. I use C++ standard data reading codes to read them. – picmate 涅 Apr 12 '12 at 15:00
  • @BenBolker, I will try to do that. – picmate 涅 Apr 12 '12 at 15:02
  • @picmate, it would be much easier for us if you showed the code. Otherwise we have to guess what you mean by "C++ standard data reading codes". There's simply no such thing in C++. Anyway, look below, I posted a working version. – detunized Apr 12 '12 at 15:20

1 Answers1

9

Here's my working solution. First I ran your input through grep to filter out NANs in coordinates:

$ grep -v nan OnePerson4.pcd > OnePerson4.pcd.filtered

Then I extracted the data via C++ code like this:

#include <stdio.h>

int main()
{
    if (FILE *f = fopen("OnePerson4.pcd.filtered", "rt"))
    {
        for (;;)
        {
            float x = 0;
            float y = 0;
            float z = 0;
            float color_float = 0;
            if (fscanf(f, "%f %f %f %f", &x, &y, &z, &color_float) != 4)
            {
                break;
            }

            unsigned color = *(unsigned const *)&color_float;
            unsigned r = color & 0xff;
            unsigned g = (color >> 8) & 0xff;
            unsigned b = (color >> 16) & 0xff;
            printf("%f,%f,%f,%d,%d,%d\n", x, y, z, r, g, b);
        }

        fclose(f);
    }

    return 0;
}

I didn't know in which byte order RGB is stored, so you might have to swap R and B. It's usually either RGB or BGR.

Then I used your code to plot the points (I changed read.table to read.csv):

library(rgl)
pcd <- read.csv(file.choose())
names(pcd) <- c("x","y","z","r","g","b")
plot3d(pcd$x,pcd$y,pcd$z,col=rgb(pcd$r,pcd$g,pcd$b,maxColorValue=255))

And this is what I get:

enter image description here

So I'm assuming the problem is with the code where you read your color from the pcd file. The rest looks fine to me.

Update: Your problem is the double type. Change it to float and it should work. Though storing unsigned int as a float is, at the very least, questionable. This is fragile and doesn't not guarantee the colors would be correct after you read them. Some bits might be off.

Another note: you could use >> stream operator to extract numbers from the file. It's much easier than manually parsing it with string methods. You can read about it, for example, here.

detunized
  • 15,059
  • 3
  • 48
  • 64
  • thank you very much for your answer. This looks very interesting. I will post the code I used too, then you might be able to see where I have gone wrong. – picmate 涅 Apr 12 '12 at 17:00