当前位置:网站首页>【PCL自学:PCLVisualizer】点云可视化工具PCLVisualizer
【PCL自学:PCLVisualizer】点云可视化工具PCLVisualizer
2022-06-27 20:59:00 【斯坦福的兔子】
点云可视化PCLVisualizer
一、什么是PCLVisualizer
PCLVisualizer是PCL的全功能可视化类。虽然使用起来比CloudViewer更复杂,但它也更强大,提供了显示法线、绘制形状和多个视图等功能。
二、使用案例
本节我们会使用历程展示PCLVisualizer的使用方法和一些特性,包括可视化单片点云,添加颜色,自定义颜色,显示法线和其他信息、多视窗显示等功能。
请参考如下代码,注释非常清晰。
/* 示例代码作者: Geoffrey Biggs */
#include <iostream>
#include <thread>
#include <pcl/common/angles.h> // for pcl::deg2rad
#include <pcl/features/normal_3d.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/console/parse.h>
using namespace std::chrono_literals;
// ---------------------
// -----显示帮助信息-----
// ---------------------
void
printUsage (const char* progName)
{
std::cout << "\n\nUsage: "<<progName<<" [options]\n\n"
<< "Options:\n"
<< "-------------------------------------------\n"
<< "-h this help\n"
<< "-s Simple visualisation example\n"
<< "-r RGB colour visualisation example\n"
<< "-c Custom colour visualisation example\n"
<< "-n Normals visualisation example\n"
<< "-a Shapes visualisation example\n"
<< "-v Viewports example\n"
<< "-i Interaction Customization example\n"
<< "\n\n";
}
pcl::visualization::PCLVisualizer::Ptr simpleVis (pcl::PointCloud<pcl::PointXYZ>::ConstPtr cloud)
{
// -------------------------------------------------
// -----打开三维可视化工具PCLVisualizer并添加普通点云-----
// -------------------------------------------------
pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer ("3D Viewer"));
viewer->setBackgroundColor (0, 0, 0);// 设置背景颜色
viewer->addPointCloud<pcl::PointXYZ> (cloud, "sample cloud");// 添加点云到窗口sample cloud
viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "sample cloud"); // 设置点云单点的尺寸
viewer->addCoordinateSystem (1.0);// 添加坐标系
viewer->initCameraParameters (); // 初始化相机参数
return (viewer);
}
pcl::visualization::PCLVisualizer::Ptr rgbVis (pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr cloud)
{
// -------------------------------------------------
// -----打开三维可视化工具PCLVisualizer并添加RGB颜色点云-----
// -------------------------------------------------
pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer ("3D Viewer"));
viewer->setBackgroundColor (0, 0, 0);
pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb(cloud); // 创建RGB点云句柄,用于添加RGB点云
viewer->addPointCloud<pcl::PointXYZRGB> (cloud, rgb, "sample cloud");
viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud");
viewer->addCoordinateSystem (1.0);
viewer->initCameraParameters ();
return (viewer);
}
pcl::visualization::PCLVisualizer::Ptr customColourVis (pcl::PointCloud<pcl::PointXYZ>::ConstPtr cloud)
{
// -----------------------------------------------
// ----打开三维可视化工具PCLVisualizer并添加指定颜色点云----
// -----------------------------------------------
pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer ("3D Viewer"));
viewer->setBackgroundColor (0, 0, 0);
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color(cloud, 0, 255, 0); // 设置指定颜色的点云(绿色)
viewer->addPointCloud<pcl::PointXYZ> (cloud, single_color, "sample cloud");
viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud");
viewer->addCoordinateSystem (1.0);
viewer->initCameraParameters ();
return (viewer);
}
pcl::visualization::PCLVisualizer::Ptr normalsVis (
pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr cloud, pcl::PointCloud<pcl::Normal>::ConstPtr normals)
{
// --------------------------------------------------------
// -----打开三维可视化工具PCLVisualizer并添加点云和法向-----
// --------------------------------------------------------
pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer ("3D Viewer"));
viewer->setBackgroundColor (0, 0, 0);
pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb(cloud);
viewer->addPointCloud<pcl::PointXYZRGB> (cloud, rgb, "sample cloud");
viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud");
viewer->addPointCloudNormals<pcl::PointXYZRGB, pcl::Normal> (cloud, normals, 10, 0.05, "normals");// 显示法向,10表示只显示1/10的点的法向,0.05表示法向显示长度。
viewer->addCoordinateSystem (1.0);
viewer->initCameraParameters ();
return (viewer);
}
pcl::visualization::PCLVisualizer::Ptr shapesVis (pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr cloud)
{
// --------------------------------------------
// -----打开三维可视化工具PCLVisualizer并添加点云-----
// --------------------------------------------
pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer ("3D Viewer"));
106 viewer->setBackgroundColor (0, 0, 0);
107 pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb(cloud);
108 viewer->addPointCloud<pcl::PointXYZRGB> (cloud, rgb, "sample cloud");
109 viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud");
viewer->addCoordinateSystem (1.0);
viewer->initCameraParameters ();
//------------------------------------
//-----Add 添加指定形状的点云-----
//------------------------------------
viewer->addLine<pcl::PointXYZRGB> ((*cloud)[0],
(*cloud)[cloud->size() - 1], "line"); // 添加线状点云(点云的第一个点和最后一个点的连线)
viewer->addSphere ((*cloud)[0], 0.2, 0.5, 0.5, 0.0, "sphere");
// 添加球状点云,中心为第一个点位置,半径为0.5,后三个参数是颜色
//---------------------------------------
//-----在其他位置添加形状-----
//---------------------------------------
pcl::ModelCoefficients coeffs; // 添加模型的多项式系数
coeffs.values.push_back (0.0);
coeffs.values.push_back (0.0);
coeffs.values.push_back (1.0);
coeffs.values.push_back (0.0);
viewer->addPlane (coeffs, "plane"); // 4个系数ABCD可以确定一个平面
coeffs.values.clear ();
coeffs.values.push_back (0.3);
coeffs.values.push_back (0.3);
coeffs.values.push_back (0.0);
coeffs.values.push_back (0.0);
coeffs.values.push_back (1.0);
coeffs.values.push_back (0.0);
coeffs.values.push_back (5.0);
viewer->addCone (coeffs, "cone"); // 7个系数ABCDEFG可以确定一个圆锥体
return (viewer);
}
pcl::visualization::PCLVisualizer::Ptr viewportsVis (
pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr cloud, pcl::PointCloud<pcl::Normal>::ConstPtr normals1, pcl::PointCloud<pcl::Normal>::ConstPtr normals2)
{
// --------------------------------------------------------
// -----在同一窗口添加不同的点云和法向并列显示-----
// --------------------------------------------------------
pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer ("3D Viewer"));
viewer->initCameraParameters ();
int v1(0);
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1); // 添加视角V1,四个参数分别是X轴和Y轴的显示最大最小范围
viewer->setBackgroundColor (0, 0, 0, v1);
viewer->addText("Radius: 0.01", 10, 10, "v1 text", v1);
pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb(cloud);
viewer->addPointCloud<pcl::PointXYZRGB> (cloud, rgb, "sample cloud1", v1);
int v2(0);
viewer->createViewPort(0.5, 0.0, 1.0, 1.0, v2);
viewer->setBackgroundColor (0.3, 0.3, 0.3, v2);
viewer->addText("Radius: 0.1", 10, 10, "v2 text", v2);
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZRGB> single_color(cloud, 0, 255, 0);
viewer->addPointCloud<pcl::PointXYZRGB> (cloud, single_color, "sample cloud2", v2);
viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud1");
167 viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud2");
viewer->addCoordinateSystem (1.0);
viewer->addPointCloudNormals<pcl::PointXYZRGB, pcl::Normal> (cloud, normals1, 10, 0.05, "normals1", v1);
viewer->addPointCloudNormals<pcl::PointXYZRGB, pcl::Normal> (cloud, normals2, 10, 0.05, "normals2", v2);
return (viewer);
}
// 以下是键盘输入响应
unsigned int text_id = 0;
void keyboardEventOccurred (const pcl::visualization::KeyboardEvent &event,
void* viewer_void)
{
pcl::visualization::PCLVisualizer *viewer = static_cast<pcl::visualization::PCLVisualizer *> (viewer_void);
if (event.getKeySym () == "r" && event.keyDown ())
{
std::cout << "r was pressed => removing all text" << std::endl;
char str[512];
for (unsigned int i = 0; i < text_id; ++i)
{
sprintf (str, "text#%03d", i);
viewer->removeShape (str);
}
text_id = 0;
}
}
// 鼠标事件响应
void mouseEventOccurred (const pcl::visualization::MouseEvent &event,
void* viewer_void)
{
pcl::visualization::PCLVisualizer *viewer = static_cast<pcl::visualization::PCLVisualizer *> (viewer_void);
if (event.getButton () == pcl::visualization::MouseEvent::LeftButton &&
event.getType () == pcl::visualization::MouseEvent::MouseButtonRelease)
{
std::cout << "Left mouse button released at position (" << event.getX () << ", " << event.getY () << ")" << std::endl;
char str[512];
sprintf (str, "text#%03d", text_id ++);
viewer->addText ("clicked here", event.getX (), event.getY (), str);
}
}
pcl::visualization::PCLVisualizer::Ptr interactionCustomizationVis ()
{
pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer ("3D Viewer"));
viewer->setBackgroundColor (0, 0, 0);
viewer->addCoordinateSystem (1.0);
// 注册键盘和和鼠标响应回调函数
viewer->registerKeyboardCallback (keyboardEventOccurred, (void*)viewer.get ());
viewer->registerMouseCallback (mouseEventOccurred, (void*)viewer.get ());
return (viewer);
}
// --------------
// -----Main-----
// --------------
int
main (int argc, char** argv)
{
// --------------------------------------
// -----命令行解析-----
// --------------------------------------
if (pcl::console::find_argument (argc, argv, "-h") >= 0)
{
printUsage (argv[0]);
return 0;
}
bool simple(false), rgb(false), custom_c(false), normals(false),
shapes(false), viewports(false), interaction_customization(false);
if (pcl::console::find_argument (argc, argv, "-s") >= 0)
{
simple = true;
std::cout << "Simple visualisation example\n";
}
else if (pcl::console::find_argument (argc, argv, "-c") >= 0)
{
custom_c = true;
std::cout << "Custom colour visualisation example\n";
}
else if (pcl::console::find_argument (argc, argv, "-r") >= 0)
{
rgb = true;
std::cout << "RGB colour visualisation example\n";
}
else if (pcl::console::find_argument (argc, argv, "-n") >= 0)
{
normals = true;
std::cout << "Normals visualisation example\n";
}
else if (pcl::console::find_argument (argc, argv, "-a") >= 0)
{
shapes = true;
std::cout << "Shapes visualisation example\n";
}
else if (pcl::console::find_argument (argc, argv, "-v") >= 0)
{
viewports = true;
std::cout << "Viewports example\n";
}
else if (pcl::console::find_argument (argc, argv, "-i") >= 0)
{
interaction_customization = true;
std::cout << "Interaction Customization example\n";
}
else
{
printUsage (argv[0]);
return 0;
}
// ------------------------------------
// -----创建示例点云-----
// ------------------------------------
pcl::PointCloud<pcl::PointXYZ>::Ptr basic_cloud_ptr (new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr point_cloud_ptr (new pcl::PointCloud<pcl::PointXYZRGB>);
std::cout << "Generating example point clouds.\n\n";
// 我们要做一个沿z轴挤压的椭圆。XYZRGB云的颜色将逐渐从红色到绿色再到蓝色。
std::uint8_t r(255), g(15), b(15);
for (float z(-1.0); z <= 1.0; z += 0.05)
{
for (float angle(0.0); angle <= 360.0; angle += 5.0)
{
pcl::PointXYZ basic_point;
basic_point.x = 0.5 * std::cos (pcl::deg2rad(angle));
basic_point.y = sinf (pcl::deg2rad(angle));
basic_point.z = z;
basic_cloud_ptr->points.push_back(basic_point);
pcl::PointXYZRGB point;
point.x = basic_point.x;
point.y = basic_point.y;
point.z = basic_point.z;
point.r = r;
point.g = g;
point.b = b;
point_cloud_ptr->points.push_back (point);
}
if (z < 0.0)
{
r -= 12;
g += 12;
}
else
{
g -= 12;
b += 12;
}
}
basic_cloud_ptr->width = basic_cloud_ptr->size ();
basic_cloud_ptr->height = 1;
point_cloud_ptr->width = point_cloud_ptr->size ();
point_cloud_ptr->height = 1;
// ----------------------------------------------------------------
// -----计算表面法向,搜索半径0.05-----
// ----------------------------------------------------------------
pcl::NormalEstimation<pcl::PointXYZRGB, pcl::Normal> ne;
ne.setInputCloud (point_cloud_ptr);
pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGB> ());
ne.setSearchMethod (tree);
pcl::PointCloud<pcl::Normal>::Ptr cloud_normals1 (new pcl::PointCloud<pcl::Normal>);
ne.setRadiusSearch (0.05);
ne.compute (*cloud_normals1);
// ---------------------------------------------------------------
// -----计算表面法向,搜索半径0.1-----
// ---------------------------------------------------------------
pcl::PointCloud<pcl::Normal>::Ptr cloud_normals2 (new pcl::PointCloud<pcl::Normal>);
ne.setRadiusSearch (0.1);
ne.compute (*cloud_normals2);
// 开始显示点云
pcl::visualization::PCLVisualizer::Ptr viewer;
if (simple)
{
viewer = simpleVis(basic_cloud_ptr);
}
else if (rgb)
{
viewer = rgbVis(point_cloud_ptr);
}
else if (custom_c)
{
viewer = customColourVis(basic_cloud_ptr);
}
else if (normals)
{
viewer = normalsVis(point_cloud_ptr, cloud_normals2);
}
else if (shapes)
{
viewer = shapesVis(point_cloud_ptr);
}
else if (viewports)
{
viewer = viewportsVis(point_cloud_ptr, cloud_normals1, cloud_normals2);
}
else if (interaction_customization)
{
viewer = interactionCustomizationVis();
}
//--------------------
// -----Main loop-----
//--------------------
while (!viewer->wasStopped ())
{
viewer->spinOnce (100);
std::this_thread::sleep_for(100ms);
}
}
以上操作的视图显示如下:
1.普通点云
2.RGB点云
3.单色点云
4.RGB点云带法向
5.RGB点云带法向,并创建线、圆锥和球点云
6. 一个视图内两片点云
7.鼠标响应和键盘响应
【博主简介】
斯坦福的兔子,男,天津大学工学硕士。毕业至今从事光学三维成像及点云处理相关工作。因工作中使用的三维处理库为公司内部库,不具有普遍适用性,遂自学开源PCL库及其相关数学知识以备使用。谨此将自学过程与君共享。
博主才疏学浅,尚不具有指导能力,如有问题还请各位在评论处留言供大家共同讨论。
边栏推荐
- 量化交易入门教程
- ClickOnce error deploying ClickOnce application - the reference in the manifest does not match the identity of the downloaded assembly
- MySQL删除表后如何使ID从1开始
- How vivado adds timing constraints
- Aggregation and index optimization of mongodb basic operations
- 捷码赋能案例:湖南天辰产研实力迅速提升!实战玩转智慧楼宇/工地等项目
- Summary of solutions to cross system data consistency problems
- The latest cloud development wechat balance charger special effect applet source code
- 文献综述如何挑选文献进行阅读,比如我的检索结果有200多篇根本看不完,如何进行文献挑选呢?...
- 沉寂了一段时间 ,我又出来啦~
猜你喜欢

Vivado FFT IP的使用说明

基于 ESXi 的黑群晖 DSM 7.0.1 安装 VMware Tools

未能加载文件或程序集“CefSharp.Core.Runtime.dll”或它的某一个依赖项。 不是有效的 Win32 应用程序。 (异常来自 HRESULT:0x800700C1)

捷码赋能案例:湖南天辰产研实力迅速提升!实战玩转智慧楼宇/工地等项目

To build a "strong core" in Nansha, the first IC Nansha conference was held in Nansha

最新云开发微信余额充电器特效小程序源码

Online JSON to plaintext tool

Working at home is more tiring than going to work at the company?

"Top stream Aidou manufacturing machine" cooperates with four industrial capitals to become LP

Stream + Nacos
随机推荐
思源笔记订阅停止直接删云端数据嘛?
c语言之字符串数组
Usage of vivado vio IP
[网络]常见的请求方法
C WinForm reads the resources picture
MySQL十八:写语句的执行过程
Brief introduction to game phone platform
2022年PMP项目管理考试敏捷知识点(3)
[sword finger offer] 47 Maximum value of gifts
图的存储结构
未能加载文件或程序集“CefSharp.Core.Runtime.dll”或它的某一个依赖项。 不是有效的 Win32 应用程序。 (异常来自 HRESULT:0x800700C1)
ClickOnce error deploying ClickOnce application - the reference in the manifest does not match the identity of the downloaded assembly
Livox lidar+apx15 real-time high-precision radar map reproduction and sorting
Discuz small fish game wind shadow legend business gbk+utf8 version template /dz game website template
Introduction to quantitative trading
第一性原理(最优解理论)
Zabbix6.0 upgrade Guide - how to synchronize database upgrades?
【IDEA】IDEA 格式化 代码技巧 idea 格式化 会加 <p> 标签
浙江大学课程攻略共享计划
凌云出海记 | 沐融科技&华为云:打造非洲金融SaaS解决方案样板