Search code examples
c++c++11point-cloud-librarypoint-clouds

Point Cloud Library - How to assign a single RGB value to an entire point cloud?


I would like to assign a single RGB value to all of the points in a point cloud dataset of type:

pcl::PointCloud<pcl::PointXYZRGB>

I'm guessing you could iterate through the points and change each value? Using something like this:

uint32_t rgb = (static_cast<uint32_t>(r) << 16 |
  static_cast<uint32_t>(g) << 8 | static_cast<uint32_t>(b));
point.rgb = *reinterpret_cast<float*>(&rgb);

However, considering I would like to give all points the same value is there a better approach?

The RGB value needs to be associated with each point or at least the collection of points so more than one point cloud can be combined in one output; each with their own distinct colour.

As there are multiple point clouds I am unable to set the colour through PCLVisualizer using:

pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> 

One idea I had was to just make a high level association with the point cloud:

std::tie(rgb, pointcloud) = std::make_tuple(
                                uint32_t, pcl::PointCloud<pcl::PointXYZ>);

Then maybe I could use PointCloudColorHandlerCustom multiple times to display the different coloured point clouds on the same PCLVisualizer instance? Not sure if this is possible.

Any help is much appreciated!


Solution

  • It seems like PCL itself is doing a for loop. Look here: https://github.com/PointCloudLibrary/pcl/blob/46cb8fe5589e88e36d79f9b8b8e5f4ff4fceb5de/visualization/src/point_cloud_handlers.cpp#L63

    So I guess it's not really worth the effort. However, if you use C++11 you can do it in 1 line (with for_each, transform, range-loop). Something like this (untested):

    int32_t rgb = (static_cast<uint32_t>(r) << 16 |
      static_cast<uint32_t>(g) << 8 | static_cast<uint32_t>(b));
    std::transform(cloud->points.begin(), cloud->points.end(), cloud->points.begin(), [rgb](pcl::PointXYZRGB p) { p.rgb = rgb; return p;});
    

    or even better a simple range loop

    int32_t rgb = (static_cast<uint32_t>(r) << 16 |
          static_cast<uint32_t>(g) << 8 | static_cast<uint32_t>(b));
    for(auto &p: cloud->points) p.rgb=rgb;