PCL中点云可视化:坐标字段、随机、单一颜色、某一属性值设置颜色、带RGB数据、法向量显示

PCL中viewer添加并显示的点云过于简单,现总结常见的几种点云渲染方式,便于点云结果的显示。

(1)按照点云坐标x、y、z坐标值中字段给点云进行赋值渲染

#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr Cloud(new pcl::PointCloud<pcl::PointXYZ>);
	
	pcl::io::loadPCDFile("XX.pcd", *Cloud);//读入点云数据

	pcl::visualization::PCLVisualizer viewer("点云");
	viewer.setBackgroundColor(0, 0, 0);
	
	pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> fildColor(Cloud, "z");//按照z字段进行渲染
	viewer.addPointCloud<pcl::PointXYZ>(Cloud, fildColor, "sample");//显示点云,其中fildColor为颜色显示
	viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample");//设置点云大小

	while (!viewer.wasStopped())
	{
		viewer.spinOnce();
	}


	return 0;
}

按照z高程渲染图:

按照x坐标渲染图:

(2)给点云单独赋予某一颜色

#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr Cloud(new pcl::PointCloud<pcl::PointXYZ>);
	
	pcl::io::loadPCDFile("XX.pcd", *Cloud);//读入点云数据

	pcl::visualization::PCLVisualizer viewer("点云");
	viewer.setBackgroundColor(0, 0, 0);
	
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> singleColor(Cloud, 0,255,0);//0-255  设置成绿色
	viewer.addPointCloud<pcl::PointXYZ>(Cloud, singleColor, "sample");//显示点云,其中fildColor为颜色显示
	viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample");//设置点云大小

	while (!viewer.wasStopped())
	{
		viewer.spinOnce();
	}


	return 0;
}

点云设置成绿色的结果:

(3)随机生成颜色

int main(int argc, char* argv[])
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr Cloud(new pcl::PointCloud<pcl::PointXYZ>);
	
	pcl::io::loadPCDFile("xx.pcd", *Cloud);//读入点云数据

	pcl::visualization::PCLVisualizer viewer("点云");
	viewer.setBackgroundColor(0, 0, 0);
	
	pcl::visualization::PointCloudColorHandlerRandom<pcl::PointXYZ> RandomColor(Cloud);//随机给点云生成颜色
	viewer.addPointCloud<pcl::PointXYZ>(Cloud, RandomColor, "sample");//显示点云,其中fildColor为颜色显示
	viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample");//设置点云大小

	while (!viewer.wasStopped())
	{
		viewer.spinOnce();
	}


	return 0;
}

随机生成的颜色结果图:

(4)采用某一属性值进行显示

在实际中会遇到根据某一特征对点集进行分类,为便于从视觉上直接判断该特征的区别度,可以依据该特征值设置成点的颜色,进行渲染,看其效果。

如下代码是依据法向量方差特征的显示图,代码及图如下:

#include"CalculateFeatures.h"
#include<iostream>
#include<sstream>
#include<vector>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/visualization/pcl_visualizer.h>
#include"IO.h"
using namespace std;
#define e 2.718
void main()
{

	CalculateFeatures CalExample;
	IO IOExample;

	ifstream infile("Area1.txt", ios::in);
	pcl::PointXYZ temp;
	char line[128];
	int label;
	vector<pcl::PointXYZ> AllPoints;
	vector<int> LabelArr;
	vector<pcl::PointXYZ> UnclassPoints;//未分类点 格网化高程点特征只针对未分类的点
	vector<pcl::PointXYZ> GroundPoints;//已经分类的点,为地面点

	while (infile.getline(line, sizeof(line)))
	{
		stringstream word(line);
		word >> temp.x;
		word >> temp.y;
		word >> temp.z;
		word >> label;
		AllPoints.push_back(temp);
		LabelArr.push_back(label);
		if (label == 1)
		{
			UnclassPoints.push_back(temp);
		}
		else if (label == 2)
		{
			GroundPoints.push_back(temp);
		}
	}

	pcl::PointCloud<pcl::PointXYZ>::Ptr UnclassPointsPtr(new pcl::PointCloud<pcl::PointXYZ>);
	UnclassPointsPtr = IOExample.PointXYZ2Ptr(UnclassPoints);
	vector<double> NormalHis;
	NormalHis = CalExample.AngleHistogramZ(UnclassPointsPtr, 60, 15, 6);
	

	pcl::PointCloud<pcl::PointXYZRGB>::Ptr new_cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
	new_cloud->width = UnclassPoints.size();
	new_cloud->height = 1;
	new_cloud->is_dense = false;
	new_cloud->points.resize(new_cloud->width*new_cloud->height);


	for (int i = 0; i < UnclassPoints.size(); i++)
	{
		new_cloud->points[i].x = UnclassPoints[i].x;
		new_cloud->points[i].y = UnclassPoints[i].y;
		new_cloud->points[i].z = UnclassPoints[i].z;	
		new_cloud->points[i].rgb = -NormalHis[i];//
	}

	pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZRGB> fildColor(new_cloud, "rgb");

	pcl::visualization::PCLVisualizer viewer("点云特征");
	//pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb(new_cloud);
	viewer.setBackgroundColor(0, 0, 0);
	viewer.addPointCloud<pcl::PointXYZRGB>(new_cloud, fildColor, "inCloud");
	viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, "inCloud");
	while (!viewer.wasStopped())
	{
		viewer.spinOnce();
	}

}

(5)带RGB值的可视化

有些点云数据的RGB值是分开的,为R、G、B,将RGB赋值给该点作为颜色进行显示,代码如下

#include"CalculateFeatures.h"
#include<iostream>
#include<sstream>
#include<vector>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/kdtree/kdtree_flann.h>
#include"IO.h"
using namespace std;
#define e 2.718
#include"DataStruct.h"
#include"EuclideanCluster.h"
#include"NearestKD.h"
#include"stdint.h"
void main()
{

	IO IOExample;
	CalculateFeatures CalExample;
	arrayoperation ArrExample;


	ifstream infile("D:\\XX.txt", ios::in);
	struct ColorRGB
	{
		double R;
		double G;
		double B;
	};
	vector<pcl::PointXYZ> PointCluster;
	vector<ColorRGB>RGBVec;

	pcl::PointXYZ TemPoint;
	ColorRGB TempRGB;
	char line[256];
	while (infile.getline(line, sizeof(line)))
	{
		stringstream word(line);
		word >> TemPoint.x;
		word >> TemPoint.y;
		word >> TemPoint.z;
		word >> TempRGB.R;
		word >> TempRGB.G;
		word >> TempRGB.B;
		RGBVec.push_back(TempRGB);
		PointCluster.push_back(TemPoint);
	}
	
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr new_cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
	new_cloud->width = PointCluster.size();
	new_cloud->height = 1;
	new_cloud->is_dense = false;
	new_cloud->points.resize(new_cloud->width*new_cloud->height);


	for (int i = 0; i < PointCluster.size(); i++)
	{
		new_cloud->points[i].x = PointCluster[i].x;
		new_cloud->points[i].y = PointCluster[i].y;
		new_cloud->points[i].z = PointCluster[i].z;
		int R = RGBVec[i].R;
		int G = RGBVec[i].G;
		int B = RGBVec[i].B;



		new_cloud->points[i].r = R;
		new_cloud->points[i].g = G;
		new_cloud->points[i].b = B;
		
	}

	pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB>fildColor(new_cloud);

	pcl::visualization::PCLVisualizer viewer("彩色点云数据");
	viewer.setBackgroundColor(0, 0, 0);
	viewer.addPointCloud<pcl::PointXYZRGB>(new_cloud, fildColor, "inCloud");
	viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, "inCloud");
	while (!viewer.wasStopped())
	{
		viewer.spinOnce();
	}

}

(6)法向量的颜色表示

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/gp3.h>
#include <pcl/visualization/pcl_visualizer.h>
void main()
{
	//定义一个点云cloud
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

	pcl::io::loadPCDFile("E:\\program_study\\C++\\pcd_data\\bunny.pcd", *cloud);//读入点云数据

	// Normal estimation*
	//法向计算
	pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> n;
	pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
	//建立kdtree来进行近邻点集搜索
	pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
	//为kdtree添加点云数据
	tree->setInputCloud(cloud);

	n.setInputCloud(cloud);
	n.setSearchMethod(tree);
	//点云法向计算时,需要搜索的近邻点大小
	n.setKSearch(20);
	//开始进行法向计算
	n.compute(*normals);
	//* normals should not contain the point normals + surface curvatures
	
	//显示类
	pcl::visualization::PCLVisualizer viewer("Cloud Viewer");

	//设置背景色
	viewer.setBackgroundColor(0, 0, 0);

	//按照z值进行渲染点的颜色
	pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> fildColor(cloud, "z");

	//添加需要显示的点云数据
	viewer.addPointCloud<pcl::PointXYZ>(cloud, fildColor, "sample cloud");

	//设置点显示大小
	viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud");

	//添加需要显示的点云法向。cloud为原始点云模型,normal为法向信息,1表示需要显示法向的点云间隔,即每1个点显示一次法向,0.01表示法向长度。
	viewer.addPointCloudNormals<pcl::PointXYZ, pcl::Normal>(cloud, normals, 1, 0.01, "normals");

	while (!viewer.wasStopped())
	{
		viewer.spinOnce();
	}

}

法向量估算渲染图:

修改法向量的代码:

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/gp3.h>
#include <pcl/visualization/pcl_visualizer.h>
void main()
{
	IO IOExample;
	//定义一个点云cloud
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

	ifstream infile("littleregion_15_new.off", ios::in);
	double x, y, z, nx, ny, nz;
	vector<double> nxVec, nyVec, nzVec;
	char line[128];
	pcl::PointXYZ point;
	vector<pcl::PointXYZ> pointVec;
	while (infile.getline(line, sizeof(line)))
	{
		stringstream word(line);
		word >> point.x;
		word >> point.y;
		word >> point.z;
		pointVec.push_back(point);

		word >> nx;
		word >> ny;
		word >> nz;
		nxVec.push_back(nx);
		nyVec.push_back(ny);
		nzVec.push_back(nz);
	}


	pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
	normals->width = pointVec.size();
	normals->height = 1;
	normals->is_dense = false;
	normals->resize(normals->width*normals->height);
	for (int i = 0; i < pointVec.size(); i++)
	{
		(*normals)[i].normal_x = nxVec[i];
		(*normals)[i].normal_y = nyVec[i];
		(*normals)[i].normal_z = nzVec[i];
	}

	cloud = IOExample.PointXYZ2Ptr(pointVec);


	//显示类
	pcl::visualization::PCLVisualizer viewer("法向量可视化");

	//设置背景色
	viewer.setBackgroundColor(0, 0, 0);

	//按照z值进行渲染点的颜色
	pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> fildColor(cloud, "z");

	//添加需要显示的点云数据
	viewer.addPointCloud<pcl::PointXYZ>(cloud, fildColor, "sample cloud");

	//设置点显示大小
	viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud");

	//添加需要显示的点云法向。cloud为原始点云模型,normal为法向信息,1表示需要显示法向的点云间隔,即每1个点显示一次法向,1表示法向长度。
	viewer.addPointCloudNormals<pcl::PointXYZ, pcl::Normal>(cloud, normals, 1, 1, "normals");

	while (!viewer.wasStopped())
	{
		viewer.spinOnce();
	}

}

附快捷键:

  • 13
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
计算向量可以使用 pcl::NormalEstimation 类,可视化可以使用 pcl::visualization::PCLVisualizer 类。 以下是一个简单的示例代码: ```cpp #include <iostream> #include <pcl/point_types.h> #include <pcl/features/normal_3d.h> #include <pcl/io/pcd_io.h> #include <pcl/visualization/pcl_visualizer.h> int main(int argc, char** argv) { // Load point cloud data from file pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::io::loadPCDFile<pcl::PointXYZ>("cloud.pcd", *cloud); // Estimate normals pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne; ne.setInputCloud(cloud); pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>()); ne.setSearchMethod(tree); pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>); ne.setRadiusSearch(0.03); // set the radius of the sphere for normal estimation ne.compute(*cloud_normals); // Visualize the point cloud and its normals pcl::visualization::PCLVisualizer viewer("Point Cloud Viewer"); viewer.setBackgroundColor(0.0, 0.0, 0.0); viewer.addPointCloud<pcl::PointXYZ>(cloud, "cloud"); viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "cloud"); viewer.addPointCloudNormals<pcl::PointXYZ, pcl::Normal>(cloud, cloud_normals, 10, 0.05, "normals"); viewer.spin(); return 0; } ``` 在这个例子,我们首先从文件加载点云数据,然后使用 pcl::NormalEstimation 类估计点云向量。接着,我们使用 pcl::visualization::PCLVisualizer 类将点云向量可视化。在可视化,我们使用 addPointCloud() 函数将点云添加到可视化窗口,并使用 setPointCloudRenderingProperties() 函数设置点云的大小。然后,我们使用 addPointCloudNormals() 函数将向量添加到点云,并设置向量的长度和大小。最后,我们使用 spin() 函数显示可视化窗口并等待用户交互。 注意,在使用 PCL 可视化库时,可能需要在编译时链接对应的库文件。例如,在 Ubuntu 系统,可以使用以下命令编译上述代码: ``` g++ -o main main.cpp -I/usr/include/pcl-1.8 -lpcl_visualization -lboost_system ``` 其 -I 指定了 PCL 库的头文件路径,-l 指定了需要链接的库文件。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

点云实验室lab

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值