PCL——Visualzer可视化类

目录

1. 可视化单个点云

2. 可视化点云颜色特征

3. 可视化点云自定义颜色特征

4. 可视化点云法线和其他特征

5. 绘制普通形状

6. 多视口显示

7. 表面法线估计

代码


1. 可视化单个点云

创建视窗对象并给标题栏定义名称"3D Viewer"

【注】定义"boost :: shared_ptr"智能共享指针,保证该指针在整个程序全局使用。

boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));

视窗背景色设置

viewer->setBackgroundColor(0, 0, 0);

点云添加到视窗对象并定义唯一字符串作为ID

利用此字符串保证在其他成员方法中也能标志引用该点云

多次调用 addPointCloud() ,可实现多个点云的添加,每调用一次就创建一个新的ID

更新一个已经显示的点云,用户必须调用 removePointCloud() ,并提供需要更新的点云ID

viewer->addPointCloud<pcl::PointXYZ>(cloud, "sample cloud");

改变点云的尺寸,控制点云在视窗中的显示方式

通过使用 X(红色)、Y(绿色)、Z(蓝色)圆柱体代表坐标轴来显示坐标系统的方向

圆柱体的大小通过 scale 参数控制

本例将 scale 参数设置为1.0,该值为默认值

viewer->addCoordinateSystem(1.0);

设置照相机参数,使用户从默认的角度和方向观察点云

viewer->initCameraParameters();

执行一个 while 循环,每次调用 spinOnce 都给视窗处理事件的时间,允许鼠标键盘等交互操作

	while (!viewer->wasStopped())
	{
		viewer->spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(100000));
	}

显示如下:

2. 可视化点云颜色特征

常用点云类型:XYZRGB

【注】PCL Visualizer 可根据所存储的颜色数据为点云赋色,或者按照用户自定义的颜色为点云着色。

创建颜色处理对象 PointCloudColorHandlerRGB ,PCL Visualizer 类利用这样的对象显示自定义颜色数据

本例中,PointCloudColorHandlerRGB 对象得到每个点云的 RGB 颜色字段

pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb(cloud);

添加点云,可以指定添加到视窗中点云的 PointCloudColorHandlerRGB 着色处理对象

viewer->addPointCloud<pcl::PointXYZRGB>(cloud, rgb, "sample cloud");

显示如下:

3. 可视化点云自定义颜色特征

本例中,所使用的点云类型是 XYZ 类型

【注】在自定义着色处理对象 PointCloudColorHandlerCustom 中,没有 RGB 颜色字段,不论所用点云是什么类型,都可以为点云着自定义颜色

创建自定义颜色处理器 PointCloudColorHandlerCustom ,设置颜色为纯绿色(0, 255, 0)

pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color(cloud, 0, 255, 0);

显示如下:

4. 可视化点云法线和其他特征

【注】PCL Visualizer 可视化类可用于绘制法线,也可绘制表征点云的其他特征,比如主曲率和几何特征。

用户一旦得到法线,需要另一行程序在视窗中显示这些法线

本例中,法线显示的个数(10个点显示一个),每个法线的长度(0.05)

viewer->addPointCloudNormals<pcl::PointXYZRGB, pcl::Normal>(cloud, normals, 10, 0.05, "normals");

显示如下:

5. 绘制普通形状

1. 绘制点之间连线

【注】此方法可以使得在显示两组点云之间的对应点关系时,方便用户直观的观看点云之间的对应关系

本例中,添加从点云第一个点到最后一个点的连线,线用默认颜色

viewer->addLine<pcl::PointXYZRGB>(cloud->points[0],cloud->points[cloud->size() - 1],"line");

2. 添加球体

本例中,添加以点云中第一个点 points[0] 为中心,半径为 0.2 的球体,也可以为该球体进行自定义颜色设置。

viewer->addSphere(cloud->points[0], 0.2, 0.5, 0.5, 0.0, "sphere");

3. 绘制平面

使用标准平面方程 ax+by+cz+d=0 来定义平面

本例中,这个平面以原点为中心,方向沿 Z 方向

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. 绘制锥形

添加锥形,利用模型系数指定锥形的参数

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");

显示如下:

6. 多视口显示

【注】PCL Visualizer 可视化类允许用户通过不同视口 Viewport 绘制多个点云

在本例中,利用不同的搜索半径,基于同一点云计算出对应不同的两组法线

第一组搜索半径为0.05,基于该半径计算的法线用黑色背景显示

第二组搜索半径为0.1,基于该半径计算的法线用灰色背景显示

创建新的视口 v1(0)

所需要的4个参数:X轴的最小值、最大值、Y轴的最小值、最大值,取值在 0 ~ 1

创建的视口在窗口的左半部分

最后一个字符串参数,用来唯一标志该视口

利用 RGB 颜色着色并添加至点云到当前视口

int v1(0);
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1);
viewer->setBackgroundColor(0, 0, 0, v1);
viewer->addText("Radius: 0.05", 10, 10, "v1 text", v1);
pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb(cloud);
viewer->addPointCloud<pcl::PointXYZRGB>(cloud, rgb, "sample cloud1", v1);

创建第二视口 v2(0)

创建的视口在窗口的右半部分

将视口背景赋予灰色

利用自定义颜色着色并添加至点云到当前视口

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);

为所有视口设置属性

【注】大多数 PCL Visualizer 类的方法成员都有一个可以选择的视口 ID 参数。当设置该参数时,该方法值作用于所设置的视口,不设置该参数的话,该方法作用于所有视口。

viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud1");
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);

显示如下:

7. 表面法线估计

对所有输入点云数据集中的点估计一组表面法线

创建法线估计对象(ne),并将输入数据集(point_cloud_ptr)传递给这个对象

pcl::NormalEstimation<pcl::PointXYZRGB, pcl::Normal> ne;// 创建法线估计对象 ne
ne.setInputCloud(point_cloud_ptr);// 将输入数据集传递给这个对象

创建空的 Kd-tree 对象(tree),并将它传递给法线估计对象(ne

pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZRGB>());
ne.setSearchMethod(tree);

建立存储输出数据集(cloud_normals1

pcl::PointCloud<pcl::Normal>::Ptr cloud_normals1(new pcl::PointCloud<pcl::Normal>);

设置以查询点为原点半径为 5 cm 范围内的所有邻元素进行计算(同理 10 cm

ne.setRadiusSearch(0.05);

计算特征值,并存储在输出数据集(cloud_normals1)内(将10 cm 对应结果存储在 cloud_normals2

ne.compute(*cloud_normals1);

代码

#include <iostream>
#include <boost/thread/thread.hpp>
#include <pcl/common/common_headers.h>
#include <pcl/features/normal_3d.h>				// 法线估计类头文件声明
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/console/parse.h>

// --------------
// -----Help-----
// --------------
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"
		<< "\n\n";
}

/*可视化单个点云*/
boost::shared_ptr<pcl::visualization::PCLVisualizer> simpleVis(pcl::PointCloud<pcl::PointXYZ>::ConstPtr cloud)
{
	/*创建视图对象并定义标题栏“3D Viewer”*/
	//boost::shared_ptr 智能共享指针,保证该指针在整个程序全局使用
	boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
	viewer->setBackgroundColor(0, 0, 0);//视窗背景色设置
	viewer->addPointCloud<pcl::PointXYZ>(cloud, "sample cloud");//添加点云到视窗对象
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "sample cloud");//渲染属性
	viewer->addCoordinateSystem(1.0);//显示点云的尺寸设置
	viewer->initCameraParameters();//照相机参数设置
	return (viewer);
}

/*可视化点云颜色特征*/
boost::shared_ptr<pcl::visualization::PCLVisualizer> rgbVis(pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr cloud)
{
	boost::shared_ptr<pcl::visualization::PCLVisualizer> 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->addCoordinateSystem(1.0);
	viewer->initCameraParameters();
	return (viewer);
}

/*可视化点云自定义颜色特征*/
boost::shared_ptr<pcl::visualization::PCLVisualizer> customColourVis(pcl::PointCloud<pcl::PointXYZ>::ConstPtr cloud)
{
	boost::shared_ptr<pcl::visualization::PCLVisualizer> 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);
}


/*可视化点云法线和其他特征*/
boost::shared_ptr<pcl::visualization::PCLVisualizer> normalsVis(
	pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr cloud, pcl::PointCloud<pcl::Normal>::ConstPtr normals)
{
	boost::shared_ptr<pcl::visualization::PCLVisualizer> 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");//显示点云法线
	viewer->addCoordinateSystem(1.0);
	viewer->initCameraParameters();
	return (viewer);
}

/*绘制普通形状*/
boost::shared_ptr<pcl::visualization::PCLVisualizer> shapesVis(pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr cloud)
{
	boost::shared_ptr<pcl::visualization::PCLVisualizer> 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->addCoordinateSystem(1.0);
	viewer->initCameraParameters();

	//------------------------------------
	//-----Add shapes at cloud points-----
	//------------------------------------
	viewer->addLine<pcl::PointXYZRGB>(cloud->points[0],cloud->points[cloud->size() - 1], "line");//点之间连线
	viewer->addSphere(cloud->points[0], 0.2, 0.5, 0.5, 0.0, "sphere");//

	//---------------------------------------
	//-----Add shapes at other locations-----
	//---------------------------------------
	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");
	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");

	return (viewer);
}

/*多视口显示点云法线*/
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewportsVis(
	pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr cloud, pcl::PointCloud<pcl::Normal>::ConstPtr normals1, pcl::PointCloud<pcl::Normal>::ConstPtr normals2)
{
	boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
	viewer->initCameraParameters();

	int v1(0);
	viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1);
	viewer->setBackgroundColor(0, 0, 0, v1);
	viewer->addText("Radius: 0.05", 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");
	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);
}

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
	{
		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 点云的颜色会逐渐从红到绿到蓝
	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 * cosf(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;
			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);
			point_cloud_ptr->points.push_back(point);
		}
		if (z < 0.0)
		{
			r -= 12;
			g += 12;
		}
		else
		{
			g -= 12;
			b += 12;
		}
	}
	basic_cloud_ptr->width = (int)basic_cloud_ptr->points.size();
	basic_cloud_ptr->height = 1;
	point_cloud_ptr->width = (int)point_cloud_ptr->points.size();
	point_cloud_ptr->height = 1;

	// ----------------------------------------------------------------
	// -----——————计算搜索半径为0.05的曲面法线————————---
	// ----------------------------------------------------------------
	pcl::NormalEstimation<pcl::PointXYZRGB, pcl::Normal> ne;// 创建法线估计对象 ne
	ne.setInputCloud(point_cloud_ptr);						// 将输入数据集传递给这个对象
	// 创建空的Kd-tree对象,并将它传递给法线估计对象
	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>);
	// 使用半径为5cm范围内的所有邻元素
	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);

	boost::shared_ptr<pcl::visualization::PCLVisualizer> 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);
	}

	//--------------------
	// -----—循环---——-
	//--------------------
	while (!viewer->wasStopped())
	{
		viewer->spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(100000));
	}
}

【注】在运行时,要在CMD中输入命令 “pcl_visualizer_demo.exe -h”

用户可通过改变选项(h、s、r、c、r、a、v)改变所运行的不同可视化特征实例

按住 q 键退出视窗应用程序,按住 r 键居中并缩放以可见整个点云

 

 

 

 

  • 6
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值