-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve pointcloud visualization with colormaps #1581
Conversation
* \note The list of available colormaps can be found in \ref pcl::visualization::LookUpTableRepresentationProperties. | ||
*/ | ||
PCL_EXPORTS bool | ||
getColormapLUT (int colormap_type, vtkSmartPointer<vtkLookupTable> &table); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use enum type LookUpTableRepresentationProperties
here for clarity?
Apart from the commented lines looks good to me. |
👍 in general, I'm glad my work inspired you to solve this issue. The only problem of this PR is that it duplicates the color map generation code (pcl_visualizer.cpp#L1644-L1672). Can you change |
Thanks for looking at the code @taketwo and @VictorLamoine. I have made the changes that you have suggested. |
Here is an example: cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(pcl-color_plane_distances)
find_package(PCL 1.8.0 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (color_plane_distances color_plane_distances.cpp)
target_link_libraries (color_plane_distances ${PCL_LIBRARIES}) #include <iostream>
#include <pcl/console/parse.h>
#include <pcl/point_cloud.h>
#include <pcl/common/centroid.h>
#include <pcl/io/vtk_lib_io.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/sample_consensus/sac_model_plane.h>
#include <pcl/visualization/pcl_visualizer.h>
/** @brief PCL point object */
typedef pcl::PointXYZ PointT;
/** @brief PCL Point cloud object */
typedef pcl::PointCloud<PointT> PointCloudT;
bool mesh_1_change_LUT = false;
bool mesh_2_change_LUT = false;
void
keyboardEventOccurred (const pcl::visualization::KeyboardEvent& event,
void* nothing)
{
if (event.getKeySym () == "a" && event.keyDown ())
mesh_1_change_LUT = true;
if (event.getKeySym () == "b" && event.keyDown ())
mesh_2_change_LUT = true;
}
int
main (int argc,
char *argv[])
{
// Parse the command line arguments for mesh files
std::vector<int> ply_file_indices = pcl::console::parse_file_extension_argument (argc, argv, ".ply");
std::vector<int> stl_file_indices = pcl::console::parse_file_extension_argument (argc, argv, ".stl");
if (ply_file_indices.size () != 0 && stl_file_indices.size () != 0)
{
PCL_ERROR("Please provide two meshes in the same format (PLY or STL).\n");
return (-1);
}
pcl::PolygonMesh mesh_1, mesh_2;
if (ply_file_indices.size () != 0)
{
if (pcl::io::loadPolygonFilePLY (argv[ply_file_indices[0]], mesh_1) == 0 ||
pcl::io::loadPolygonFilePLY (argv[ply_file_indices[1]], mesh_2) == 0 )
{
PCL_ERROR("Failed to read mesh file\n");
return -1;
}
}
else
{
if (pcl::io::loadPolygonFileSTL (argv[stl_file_indices[0]], mesh_1) == 0 ||
pcl::io::loadPolygonFileSTL (argv[stl_file_indices[1]], mesh_2) == 0 )
{
PCL_ERROR("Failed to read mesh file\n");
return -1;
}
}
// Segment plane
PointCloudT::Ptr cloud_1 (new PointCloudT),
cloud_2 (new PointCloudT);
pcl::fromPCLPointCloud2(mesh_1.cloud, *cloud_1);
pcl::fromPCLPointCloud2(mesh_2.cloud, *cloud_2);
pcl::ModelCoefficients::Ptr plane_1 (new pcl::ModelCoefficients),
plane_2 (new pcl::ModelCoefficients);
plane_1->values.resize (4);
plane_2->values.resize (4);
pcl::PointIndices::Ptr inliers_plane (new pcl::PointIndices);
pcl::SACSegmentation<PointT> seg;
seg.setOptimizeCoefficients (true);
seg.setMethodType (pcl::SAC_RANSAC);
seg.setModelType (pcl::SACMODEL_PLANE);
seg.setDistanceThreshold (.01f);
seg.setInputCloud (cloud_1);
seg.segment (*inliers_plane, *plane_1);
if (inliers_plane->indices.size () == 0)
{
PCL_ERROR ("Could not estimate a planar model for the given dataset.\n");
return (-1);
}
seg.setInputCloud (cloud_2);
seg.segment (*inliers_plane, *plane_2);
if (inliers_plane->indices.size () == 0)
{
PCL_ERROR ("Could not estimate a planar model for the given dataset.\n");
return (-1);
}
//std::cout << "Model coefficients (plane 1)\n" << *plane_1 << std::endl;
//std::cout << "Model coefficients (plane 2)\n" << *plane_2 << std::endl;
// Compute point to plane distances
vtkSmartPointer<vtkFloatArray> mesh_distances_1 = vtkSmartPointer<vtkFloatArray>::New ();
size_t i = 0;
for (PointCloudT::iterator cloud_it (cloud_1->begin ()); cloud_it != cloud_1->end (); ++cloud_it)
{
double distance;
distance = pcl::pointToPlaneDistanceSigned (*cloud_it, plane_1->values[0], plane_1->values[1], plane_1->values[2], plane_1->values[3]);
mesh_distances_1->InsertTuple1 (i, distance);
i++;
}
vtkSmartPointer<vtkFloatArray> mesh_distances_2 = vtkSmartPointer<vtkFloatArray>::New ();
i = 0;
for (PointCloudT::iterator cloud_it (cloud_2->begin ()); cloud_it != cloud_2->end (); ++cloud_it)
{
double distance;
distance = pcl::pointToPlaneDistanceSigned (*cloud_it, plane_2->values[0], plane_2->values[1], plane_2->values[2], plane_2->values[3]);
mesh_distances_2->InsertTuple1 (i, distance);
i++;
}
// Color mesh distances from the plane
vtkSmartPointer<vtkPolyData> poly_data_1 = vtkSmartPointer<vtkPolyData>::New ();
pcl::io::mesh2vtk (mesh_1, poly_data_1);
poly_data_1->GetPointData ()->SetScalars (mesh_distances_1);
vtkSmartPointer<vtkPolyData> poly_data_2 = vtkSmartPointer<vtkPolyData>::New ();
pcl::io::mesh2vtk (mesh_2, poly_data_2);
poly_data_2->GetPointData ()->SetScalars (mesh_distances_2);
// Display
pcl::visualization::PCLVisualizer viewer;
//viewer.addPolygonMesh (mesh_1, "mesh_1");
//viewer.addPolygonMesh (mesh_2, "mesh_2");
viewer.addModelFromPolyData (poly_data_1, "mesh_1");
viewer.addModelFromPolyData (poly_data_2, "mesh_2");
viewer.addCoordinateSystem(10);
viewer.registerKeyboardCallback (&keyboardEventOccurred, (void*) NULL);
viewer.resetCamera ();
int mesh_1_lut_color (1),
mesh_2_lut_color (1);
while (!viewer.wasStopped ())
{
viewer.spinOnce ();
// The user pressed "a" or "b" :
if (mesh_1_change_LUT)
{
viewer.setLookUpTableID ("mesh_1");
mesh_1_change_LUT = false;
mesh_1_lut_color > 4 ? mesh_1_lut_color = 1 : mesh_1_lut_color++;
switch (mesh_1_lut_color)
{
case 1:
viewer.setShapeRenderingProperties (pcl::visualization::PCL_VISUALIZER_LUT, pcl::visualization::PCL_VISUALIZER_LUT_JET, "mesh_1");
break;
case 2:
viewer.setShapeRenderingProperties (pcl::visualization::PCL_VISUALIZER_LUT, pcl::visualization::PCL_VISUALIZER_LUT_JET_INVERSE, "mesh_1");
break;
case 3:
viewer.setShapeRenderingProperties (pcl::visualization::PCL_VISUALIZER_LUT, pcl::visualization::PCL_VISUALIZER_LUT_HSV, "mesh_1");
break;
case 4:
viewer.setShapeRenderingProperties (pcl::visualization::PCL_VISUALIZER_LUT, pcl::visualization::PCL_VISUALIZER_LUT_HSV_INVERSE, "mesh_1");
break;
default:
viewer.setShapeRenderingProperties (pcl::visualization::PCL_VISUALIZER_LUT, pcl::visualization::PCL_VISUALIZER_LUT_GREY, "mesh_1");
break;
}
}
if (mesh_2_change_LUT)
{
viewer.setLookUpTableID ("mesh_2");
mesh_2_change_LUT = false;
mesh_2_lut_color > 4 ? mesh_2_lut_color = 1 : mesh_2_lut_color++;
switch (mesh_2_lut_color)
{
case 1:
viewer.setShapeRenderingProperties (pcl::visualization::PCL_VISUALIZER_LUT, pcl::visualization::PCL_VISUALIZER_LUT_JET, "mesh_2");
break;
case 2:
viewer.setShapeRenderingProperties (pcl::visualization::PCL_VISUALIZER_LUT, pcl::visualization::PCL_VISUALIZER_LUT_JET_INVERSE, "mesh_2");
break;
case 3:
viewer.setShapeRenderingProperties (pcl::visualization::PCL_VISUALIZER_LUT, pcl::visualization::PCL_VISUALIZER_LUT_HSV, "mesh_2");
break;
case 4:
viewer.setShapeRenderingProperties (pcl::visualization::PCL_VISUALIZER_LUT, pcl::visualization::PCL_VISUALIZER_LUT_HSV_INVERSE, "mesh_2");
break;
default:
viewer.setShapeRenderingProperties (pcl::visualization::PCL_VISUALIZER_LUT, pcl::visualization::PCL_VISUALIZER_LUT_GREY, "mesh_2");
break;
}
}
}
return 0;
}
Press |
👍 perfect |
👍 |
Could somebody please provide some usage examples? |
@Jaykob I have updated an old comment to add the code: I did not test this code with the latest PCL trunk! |
Hey I couldn't get this working. Can we please have some good examples of the color jet features to point clouds? |
Hi Victor, thanks for replying. But I had already tried the code and it isn't working. Have you tried it out? |
This pull request addresses #1574. The following functionality is added:
Here is a minimal example code to test the new functionality.
If the maintainers agree to these changes I would also like to update the colormaps for mesh visualization.
Here is an example of a pointcloud of a bicycle helmet visualized using different colormaps: