Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unpacking RGB values in a Point Cloud Data Set

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;
}
like image 634
picmate 涅 Avatar asked Apr 11 '12 20:04

picmate 涅


People also ask

What is RGB point cloud?

The Color Point Cloud tool uses RGB data from a raster to colorize a LAS file of the same location. Each point of the point cloud receives the RGB value of the raster pixel that has the same location. You can also write a script to color point clouds using the ColorPointCloud task.

Can LiDAR capture color?

Advanced LiDAR scanner devices can be equipped with laser diodes (red, green, blue) and avalanche photodetectors (red, green, blue) that capture the colour intensity returning from the target by illuminating those colours during scanning.

What are 3D point clouds?

A Point Cloud is a 3D visualization made up of thousands or even millions of georeferenced points. Point clouds provide high-resolution data without the distortion sometimes present in 3D mesh models and are commonly used in industry-standard software.


1 Answers

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.

like image 97
detunized Avatar answered Sep 24 '22 00:09

detunized