PCL小笔记

news2025/1/14 16:15:09

一、常用概念

1,过滤器Filters
消除噪音

2,特征Features
集合点属性:曲面的曲率估计和查询点的法线
通过k-neighborhood计算得到这两个属性作为特征
查找方法:KD-tress、八叉树等

3,关键点Keypoints
可以利用明确标准检测出来的稳定、独特的点,往往较少

4,注册Registration
将点云数据在统一的世界坐标系下进行组合起来

5,Kd-tree
使用FLANN以达到快速进行邻区搜索
FLANN快速最近邻搜索包(Fast_Library_for_Approximate_Nearest_Neighbors)

6,Octree
八叉树通常用于邻区搜索、K邻区搜索、指定半径内搜索等

7,分割Segmentation
一个点云切分成多个片段簇

二、PointT类型

1,PointXYZ,成员变量float x,y,z
每个点云都包含三个信息
points[i]表示第i个点云
points[i].x、points[i].y、points[i].z进行访问

2,PointXYZI,成员变量float x,y,z,intensity

3,PointXYZRGBA,成员变量float x,y,z、uint32_t rgba

4,PointXYZRGB,成员变量float x,y,z,rgb

5,PointXY,成员变量float x,y

6,InterestPoint,成员变量float x,y,z,strength,其中strength表示关键点的强度测量值

7,Normal,成员变量float normal[3], curvature,其中normal结构体表示给定点所在样本曲面上的法线方向以及对应的曲率的测量值
其中法线为normal,曲率为curvature
访问法向量的第一个坐标:points[i].normal[0]

8,PointNormal,成员变量float x,y,z,normal[3],curvature

三、IO模块和类

在这里插入图片描述

四、从PCD文件中读写点云数据

1,自定义点云数据并保存

#include <pcl/io/pcd_io.h> // PCD读写类相关的头文件
#include <pcl/point_types.h> // PCL中支持的点类型的头文件
#include <iostream> // 标准C++库中的输入输出的头文件

int main(int argc,char* argv[])
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = std::make_shared<pcl::PointCloud<pcl::PointXYZ>>();
	cloud->width = 5;
	cloud->height = 1;
	cloud->is_dense = false;
	cloud->points.resize(cloud->width * cloud->height); // 点云总数大小

	// 随机初始化点云数据
	for (size_t i = 0; i < cloud->points.size(); i++) {
		cloud->points[i].x = 1024 * rand() / (RAND_MAX + 10.f);
		cloud->points[i].y = 1024 * rand() / (RAND_MAX + 10.f);
		cloud->points[i].z = 1024 * rand() / (RAND_MAX + 10.f);
	}

	// 把点云进行保存
	pcl::io::savePCDFileASCII("test_pcd.pcd", *cloud);

	// 输出点云的信息
	for (size_t i = 0; i < cloud->size(); i++) {
		std::cerr << "  " << cloud->points[i].x << "  " << cloud->points[i].y << "  " << cloud->points[i].z << std::endl;
	}

	return 0;
}

在这里插入图片描述
在这里插入图片描述

2,加载自定义点云文件

#include <pcl/io/pcd_io.h> // PCD读写类相关的头文件
#include <pcl/point_types.h> // PCL中支持的点类型的头文件
#include <iostream> // 标准C++库中的输入输出的头文件

int main(int argc,char* argv[])
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = std::make_shared<pcl::PointCloud<pcl::PointXYZ>>();

	// 加载点云
	if (pcl::io::loadPCDFile<pcl::PointXYZ>("test_pcd.pcd",*cloud) == -1) 
	{
		PCL_ERROR("Can't read file test_pcd.pcd \n");
		return -1;
	}

	std::cerr << "Loaded " << cloud->width * cloud->height << " data points" << std::endl;

	for(size_t i=0;i<cloud->points.size();i++)
	{
		std::cerr << " " << cloud->points[i].x << " " << cloud->points[i].y << " " << cloud->points[i].z << std::endl;
	}

	return 0;
}

在这里插入图片描述

3,三个点云进行合并

①点云连接

A+B=C
A,B,C三个点云类型均为pcl::PointXYZ,得到的点云C前几行是A后几行是B

*cloud_c = *cloud_a + *cloud_b; // 把cloud_a和cloud_b连接一起创建cloud_c 后输出

#include <pcl/io/pcd_io.h> // PCD读写类相关的头文件
#include <pcl/point_types.h> // PCL中支持的点类型的头文件
#include <iostream> // 标准C++库中的输入输出的头文件

int main(int agrc,char*agrv[])
{
	// 声明三个点云pcl::PointXYZ类型
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_a = std::make_shared<pcl::PointCloud<pcl::PointXYZ>>();
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_b = std::make_shared<pcl::PointCloud<pcl::PointXYZ>>();
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_c = std::make_shared<pcl::PointCloud<pcl::PointXYZ>>();

	// 创建点云为无需点云
	cloud_a->width = 5;
	cloud_a->height = cloud_b->height = 1;
	cloud_a->points.resize(cloud_a->height * cloud_a->width);


	// 点云连接 a有5个点,b有3个点,合并之后c有8个点
	cloud_b->width = 3;
	cloud_b->points.resize(cloud_b->height * cloud_b->width);
	for (size_t i = 0; i < cloud_a->points.size(); ++i)
	{  
		cloud_a->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
		cloud_a->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
		cloud_a->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
	}
	for (size_t i = 0; i < cloud_b->points.size(); ++i)
	{   
		cloud_b->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
		cloud_b->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
		cloud_b->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
	}

	std::cerr << "Cloud A(XYZ): " << std::endl;
	for (size_t i = 0; i < cloud_a->size(); i++) {
		std::cerr << "  " << cloud_a->points[i].x << "  " << cloud_a->points[i].y << "  " << cloud_a->points[i].z << std::endl;
	}
	std::cerr << "Cloud B(XYZ): " << std::endl;
	for (size_t i = 0; i < cloud_b->size(); i++) {
		std::cerr << "  " << cloud_b->points[i].x << "  " << cloud_b->points[i].y << "  " << cloud_b->points[i].z << std::endl;
	}
	*cloud_c = *cloud_a + *cloud_b;//把cloud_a和cloud_b连接一起创建cloud_c  后输出
	std::cerr << "Cloud C(XYZ): " << std::endl;
	for (size_t i = 0; i < cloud_c->points.size(); ++i){
		std::cerr << "    " << cloud_c->points[i].x << " " << cloud_c->points[i].y << " " << cloud_c->points[i].z << " " << std::endl;
	}

	return 0;
}

在这里插入图片描述

②字段间连接

A+B=C
A是pcl::PointXYZ类型,B是pcl::Normal类型,C是pcl::PointNormal类型
将A和B进行字段间连接,也就是C是XYZNormal,A是XYZ,B是Normal,C就是将A和B填到对应的C的位置即可

pcl::concatenateFields(*cloud_a, *cloud_b, *cloud_c);

#include <pcl/io/pcd_io.h> // PCD读写类相关的头文件
#include <pcl/point_types.h> // PCL中支持的点类型的头文件
#include <iostream> // 标准C++库中的输入输出的头文件

int main(int agrc,char*agrv[])
{
	// 声明三个点云pcl::PointXYZ类型
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_a = std::make_shared<pcl::PointCloud<pcl::PointXYZ>>();
	// 声明存储连接时需要的点云类型为pcl::Normal
	pcl::PointCloud<pcl::Normal>::Ptr cloud_b = std::make_shared<pcl::PointCloud<pcl::Normal>>();
	// 声明最终合并的点云类型为pcl::PointNormal
	pcl::PointCloud<pcl::PointNormal>::Ptr cloud_c = std::make_shared<pcl::PointCloud<pcl::PointNormal>>();

	// 创建点云为无序点云
	cloud_a->width = 5;
	cloud_a->height = cloud_b->height = 1;
	cloud_a->points.resize(cloud_a->height * cloud_a->width);


	// 因为cloud_a是5,因为要字段间连接,故需要将cloud_b转换成cloud_bb,且cloud_bb也应该与cloud_a保持一致都是5
	cloud_b->width = 5;
	cloud_b->points.resize(cloud_b->height * cloud_b->width);
	for (size_t i = 0; i < cloud_a->points.size(); ++i)
	{  
		cloud_a->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
		cloud_a->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
		cloud_a->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
	}
	for (size_t i = 0; i < cloud_b->points.size(); ++i)
	{   
		cloud_b->points[i].normal_x = 1024 * rand() / (RAND_MAX + 1.0f);
		cloud_b->points[i].normal_y = 1024 * rand() / (RAND_MAX + 1.0f);
		cloud_b->points[i].normal_z = 1024 * rand() / (RAND_MAX + 1.0f);
	}

	std::cerr << "Cloud A(XYZ): " << std::endl;
	for (size_t i = 0; i < cloud_a->size(); i++) {
		std::cerr << "  " << cloud_a->points[i].x << "  " << cloud_a->points[i].y << "  " << cloud_a->points[i].z << std::endl;
	}
	std::cerr << "Cloud B(normal): " << std::endl;
	for (size_t i = 0; i < cloud_b->size(); i++) {
		std::cerr << "  " << cloud_b->points[i].normal_x << "  " << cloud_b->points[i].normal_y << "  " << cloud_b->points[i].normal_z << std::endl;
	}
	
	pcl::concatenateFields(*cloud_a, *cloud_b, *cloud_c); // 把cloud_a和cloud_b字段间连接一起创建cloud_c后输出
	std::cerr << "Cloud C(XYZnormal): " << std::endl;
	for (size_t i = 0; i < cloud_c->points.size(); i++){
		std::cerr << "    " << cloud_c->points[i].x << " " << cloud_c->points[i].y << " " << cloud_c->points[i].z << " "
			                << cloud_c->points[i].normal_x << " " << cloud_c->points[i].normal_y << " " << cloud_c->points[i].normal_z << std::endl;
	}

	return 0;
}

在这里插入图片描述

五,kd-tree搜索

1,KNN最小近邻搜索

kdtree.setInputCloud(cloud);
kdtree.nearestKSearch(beyond, K, pointIdxKNN, pointKNNSquareDistance)
查找在cloud点云中,找离beyond这个点最近的K个点的坐标位置,查找出来的点是K个

#include <pcl/point_cloud.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <iostream>
#include <vector>
#include <ctime>

int main(int agrc, char* agrv[])
{
	srand(time(NULL)); // 使用系统时间初始化随机种子
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = std::make_shared<pcl::PointCloud<pcl::PointXYZ>>();

	// 随机生成点云
	cloud->width = 100;
	cloud->height = 1;
	cloud->points.resize(cloud->width * cloud->height);

	// 点云数据填充
	for (size_t i = 0; i < cloud->points.size(); i++)
	{
		cloud->points[i].x = 1024.0f * rand() / (RAND_MAX)+(float)1.0f;
		cloud->points[i].y = 1024.0f * rand() / (RAND_MAX)+(float)1.0f;
		cloud->points[i].z = 1024.0f * rand() / (RAND_MAX)+(float)1.0f;
	}

	// 创建KdTreeFlann对象,并把创建的点云作为输入,创建一个searchPoint变量作为查询点
	pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;
	// 要搜索的点云
	kdtree.setInputCloud(cloud);
	// 设置查询的点云并赋值
	pcl::PointXYZ beyond;
	beyond.x = 1024.0f * rand() / (RAND_MAX)+(float)1.0f;
	beyond.y = 1024.0f * rand() / (RAND_MAX)+(float)1.0f;
	beyond.z = 1024.0f * rand() / (RAND_MAX)+(float)1.0f;

	// 上述表示,在点云cloud中搜索beyond这个点云

	// k-neighborhood
	int K = 10; // 查找beyond这个点附近的K个点
	std::vector<int> pointIdxKNN(K); // 存放查询点附近的点的索引
	std::vector<float> pointKNNSquareDistance(K); // 存放附件点对应距离的平方
	std::cerr << "K nearest neighbor at( " << beyond.x << " " << beyond.y << " " << beyond.z << " ) with K= " << K << std::endl;

	// 在cloud这个点云中找beyond这个点最接近的周围K个点的索引pointIdxKNN和距离距离平方和pointKNNSquareDistance
	if (kdtree.nearestKSearch(beyond, K, pointIdxKNN, pointKNNSquareDistance) > 0)
	{
		for (size_t i = 0; i < pointIdxKNN.size(); i++)
		{
			// 输出所有近邻点的坐标
			std::cerr << "  " << cloud->points[pointIdxKNN[i]].x
				<< "  " << cloud->points[pointIdxKNN[i]].y
				<< "  " << cloud->points[pointIdxKNN[i]].z
				<< " (squared distance : " << pointKNNSquareDistance[i] << " )"
				<< std::endl;
		}
	}

	return 0;
}

在这里插入图片描述

2,半径R内搜索

kdtree.setInputCloud(cloud);
kdtree.radiusSearch(beyond, radius, pointIdxRadiusKNN, pointRadiusKNNSquareDistance)

查找在cloud点云中,以beyond这个点为圆心,radius为半径找在这个范围内的所有点的坐标位置

#include <pcl/point_cloud.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <iostream>
#include <vector>
#include <ctime>

int main(int agrc,char* agrv[])
{
	srand(time(NULL)); // 使用系统时间初始化随机种子
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = std::make_shared<pcl::PointCloud<pcl::PointXYZ>>();

	// 随机生成点云
	cloud->width = 100;
	cloud->height = 1;
	cloud->points.resize(cloud->width * cloud->height);

	// 点云数据填充
	for(size_t i=0;i<cloud->points.size();i++)
	{
		cloud->points[i].x = 1024.0f * rand() / (RAND_MAX)+(float)1.0f;
		cloud->points[i].y = 1024.0f * rand() / (RAND_MAX)+(float)1.0f;
		cloud->points[i].z = 1024.0f * rand() / (RAND_MAX)+(float)1.0f;
	}

	// 创建KdTreeFlann对象,并把创建的点云作为输入,创建一个searchPoint变量作为查询点
	pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;
	// 要搜索的点云
	kdtree.setInputCloud(cloud);
	// 设置查询的点云并赋值
	pcl::PointXYZ beyond;
	beyond.x = 1024.0f * rand() / (RAND_MAX)+(float)1.0f;
	beyond.y = 1024.0f * rand() / (RAND_MAX)+(float)1.0f;
	beyond.z = 1024.0f * rand() / (RAND_MAX)+(float)1.0f;

	// 上述表示,在点云cloud中搜索beyond这个点云
	int K = 10; // 查找beyond这个点附近的K个点
	
	// 最小半径搜索
	std::vector<int> pointIdxRadiusKNN(K); // 存放查询点附近的点的索引
	std::vector<float> pointRadiusKNNSquareDistance(K); // 存放附件点对应距离的平方
	float radius = 256.0f * rand() / (RAND_MAX + 1.0f); // 随机生成的半径
	std::cerr << "K within radius neighbor at( " << beyond.x << " " << beyond.y << " " << beyond.z << "  ) with radius= " << radius << std::endl;

	// 在cloud这个点云中以beyond这个点为圆心半径为radius内的点的索引pointIdxRadiusKNN和距离距离平方和pointRadiusKNNSquareDistance
	if (kdtree.radiusSearch(beyond, radius, pointIdxRadiusKNN, pointRadiusKNNSquareDistance) > 0)
	{
		for (size_t i = 0; i < pointIdxRadiusKNN.size(); i++)
		{
			// 输出所有近邻点的坐标
			std::cerr << "  " << cloud->points[pointIdxRadiusKNN[i]].x
				      << "  " << cloud->points[pointIdxRadiusKNN[i]].y
				      << "  " << cloud->points[pointIdxRadiusKNN[i]].z
				      << " (squared distance : " << pointRadiusKNNSquareDistance[i] <<" )"
				      << std::endl;
		}
	}
	return 0;
}

因为点和半径都是随机的,不一定每次运行就能找到
有可能这个半径内没有点,所以有可能没有点的输出
多尝试几次
在这里插入图片描述

六、Octree八叉树搜索

数学原理有点多,后期再补充学习

七、Visualizer点云可视化

显示自己的点云数据

#include <pcl\visualization\cloud_viewer.h>
#include <iostream>
#include <pcl\io\io.h>
#include <pcl\io\pcd_io.h>

int main(int agrc,char*agrv[])
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = std::make_shared<pcl::PointCloud<pcl::PointXYZ>>();
	pcl::io::loadPCDFile("1_part.pcd",*cloud);

	pcl::visualization::PCLVisualizer visulaizer;
	visulaizer.setBackgroundColor(0, 0, 0); // RGB设置背景颜色
	visulaizer.addPointCloud(cloud);
	visulaizer.addCoordinateSystem(1.0);
	visulaizer.initCameraParameters(); // 显示坐标系 红x绿y蓝z
	// visulaizer.resetCamera(); // 不显示坐标系
	visulaizer.spin();

	return 0;
}

在这里插入图片描述

八、Filter点云滤波

1,直通滤波

说白了就是可以根据指定某个轴给定范围进行保留
pcl::PassThrough<pcl::PointXYZ> pass; // 定义直通滤波对象
pass.setInputCloud(cloud); // 对加载的原始点云进行处理
pass.setFilterFieldName("z"); // 直通滤波Z轴
pass.setFilterLimits(700, 920); // Z轴的范围为700-920
pass.filter(*result_z); // 滤波之后的结果为result_z点云

#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>
#include <pcl/io/pcd_io.h>
#include <pcl\visualization\pcl_visualizer.h>

int main(int agrc ,char* agrv[])
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = std::make_shared<pcl::PointCloud<pcl::PointXYZ>>();
	pcl::PointCloud<pcl::PointXYZ>::Ptr result_z = std::make_shared<pcl::PointCloud<pcl::PointXYZ>>();
	pcl::PointCloud<pcl::PointXYZ>::Ptr result_y = std::make_shared<pcl::PointCloud<pcl::PointXYZ>>();
	pcl::PointCloud<pcl::PointXYZ>::Ptr result_x = std::make_shared<pcl::PointCloud<pcl::PointXYZ>>();
	pcl::io::loadPCDFile("1_model_xyz.pcd", *cloud);

	pcl::PassThrough<pcl::PointXYZ> pass; // 定义直通滤波对象
	pass.setInputCloud(cloud); // 对加载的原始点云进行处理
	pass.setFilterFieldName("z"); // 直通滤波Z轴
	pass.setFilterLimits(700, 920); // Z轴的范围为700-920
	pass.filter(*result_z); // 滤波之后的结果为result_z点云
	
	// 对Y轴和X轴进行直通滤波的时候是基于得到的结果进行再次操作
	pass.setInputCloud(result_z);
	pass.setFilterFieldName("y");
	pass.setFilterLimits(-200, 100);
	pass.filter(*result_y);

	pass.setInputCloud(result_y);
	pass.setFilterFieldName("x");
	pass.setFilterLimits(-200, 200);
	pass.filter(*result_x);

/*
	std::cerr << "Cloud after filtering: " << std::endl;
	for (size_t i = 0; i < result_x->points.size(); ++i)
		std::cerr << "    " << result_x->points[i].x << " "
		<< result_x->points[i].y << " "
		<< result_x->points[i].z << std::endl;
*/


	pcl::visualization::PCLVisualizer visualizer;
	visualizer.addPointCloud(result_x);
	visualizer.initCameraParameters();
	visualizer.resetCamera();
	visualizer.spin();

	return 0;
}

原点云
在这里插入图片描述
通过直通滤波进行XYZ各个方向进行过滤,得到只包含红色目标的物体
先对Z轴进行直通滤波,然后依次对Y轴和X轴进行直通滤波操作
在这里插入图片描述

2,VoxelGrid滤波器

体素化网格方法实现下采样,减少点云数据
原理:创建一个三位体素栅格,每个体素内的所有点的重心来近似表示体素中的其他点,这个体素内的所有点都可以用重心点表示,可以减少数据量
在这里插入图片描述
使用VoxelGrid滤波器加载的数据必须是pcl::PCLPointCloud2格式

pcl::VoxelGrid<pcl::PCLPointCloud2> sor; // 定义VoxelGrid对象
sor.setInputCloud(cloud); //加载原始点云数据进行处理
sor.setLeafSize(1.0f, 1.0f, 1.0f); // 设置滤波时创建的体素体积为1m的立方体,这样相当于1立方米内的体素栅格内的点归一成重心点,可以下采样减少点云数据量
sor.filter(*cloud_filtered); // 输出结果,类型也必须是pcl::PCLPointCloud2

pcl::fromPCLPointCloud2(*cloud_filtered, *src);//可以将pcl::PCLPointCloud2格式转换为pcl::PointXYZ格式,通过可视化进行显示

#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/io/pcd_io.h>
#include <pcl\visualization\pcl_visualizer.h>

int main(int agrc, char* agrv[])
{
	pcl::PCLPointCloud2::Ptr cloud = std::make_shared<pcl::PCLPointCloud2>();;
	pcl::PCLPointCloud2::Ptr cloud_filtered = std::make_shared<pcl::PCLPointCloud2>();
	pcl::io::loadPCDFile("1_model_xyz.pcd", *cloud);

	pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
	sor.setInputCloud(cloud);
	sor.setLeafSize(1.0f, 1.0f, 1.0f); // 设置滤波时创建的体素体积为1m的立方体,这样相当于1立方米内的体素栅格内的点归一成重心点,可以下采样减少点云数据量
	sor.filter(*cloud_filtered);

	pcl::PointCloud<pcl::PointXYZ>::Ptr src = std::make_shared<pcl::PointCloud<pcl::PointXYZ>>();
	pcl::fromPCLPointCloud2(*cloud_filtered, *src);

	std::cerr << "voxelgrid filter is: "<< src->points.size() << std::endl; // 

	pcl::visualization::PCLVisualizer visualizer;
	visualizer.addPointCloud(src);
	visualizer.initCameraParameters();
	visualizer.resetCamera();
	visualizer.spin();

	return 0;
}

原始点云大小为:1063964
在这里插入图片描述
下采样之后的点云大小为:925246
在这里插入图片描述

3,statisticalOutlierRemoval滤波器

statisticalOutlierRemoval滤波器移除离群点,emmm说真的,没看懂,先放个案例在这吧

pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor; // 定义滤波器对象
sor.setInputCloud(cloud); // 放入待处理的点云
sor.setMeanK(200); //设置考虑临界点点数
sor.setStddevMulThresh(1.0); // 考虑离群点的阈值
sor.filter(*cloud_result); // 得出结果点云

#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/io/pcd_io.h>
#include <pcl\visualization\pcl_visualizer.h>

int main(int agrc, char* agrv[])
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = std::make_shared<pcl::PointCloud<pcl::PointXYZ>>();
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_result = std::make_shared<pcl::PointCloud<pcl::PointXYZ>>();
	pcl::io::loadPCDFile("1_model_xyz.pcd", *cloud);

	pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
	sor.setInputCloud(cloud);                           //设置待滤波的点云
	sor.setMeanK(200);                                  //设置在进行统计时考虑查询点临*点数
	sor.setStddevMulThresh(1.0);                        //设置判断是否为离群点的阀值
	sor.filter(*cloud_result);

	std::cerr << "StatisticalOutlierRemoval filter is: " << cloud_result->points.size() << std::endl; // 

	pcl::visualization::PCLVisualizer visualizer;
	visualizer.addPointCloud(cloud);
	visualizer.initCameraParameters();
	visualizer.resetCamera();
	visualizer.spin();

	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1890031.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ios-实验室暑假培训(1)

一 组队 在正式培训之前&#xff0c;也是数模比赛的众中之重。 一定要商讨好组队的相关事宜&#xff01;要求建模/编程/写作/写作三方能力交叉&#xff01; 而这三个当中&#xff0c;决定比赛拿奖上限的是编程手&#xff0c;决定比赛能不能拿奖的是写作手。而建模的更像是一个…

【JavaWeb】登录校验-会话技术(一)Cookie与Session

登录校验 实现登陆后才能访问后端系统页面&#xff0c;不登陆则跳转登陆页面进行登陆。 首先我们在宏观上先有一个认知&#xff1a; HTTP协议是无状态协议。即每一次请求都是独立的&#xff0c;下一次请求并不会携带上一次请求的数据。 因此当我们通过浏览器访问登录后&#…

Cyuyan中的自定义类型——结构体

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、结构体基础知识&#xff08;一&#xff09;、结构体类型的声明、变量的创建与初始化&#xff08;二&#xff09;、结构成员访问操作符&#xff08;三&#…

近红外光谱脑功能成像(fNIRS):1.光学原理、变量选取与预处理

一、朗伯-比尔定律与修正的朗伯-比尔定律 朗伯-比尔定律 是一个描述光通过溶液时被吸收的规律。想象你有一杯有色液体&#xff0c;比如一杯红茶。当你用一束光照射这杯液体时&#xff0c;光的一部分会被液体吸收&#xff0c;导致透过液体的光变弱。朗伯-比尔定律告诉我们&#…

如何在主动动态安全中使用人工智能驱动的威胁分类提高防御精准度

面对当今世界不断演变的网络威胁&#xff0c;人工智能和网络安全将会发挥重要的防护作用。在数据泄露和网络攻击日益突出的时代&#xff0c;人工智能和网络安全之间的合作成为数字安全战场上的强大盟友。 本文将深入研究这两个领域的融合&#xff0c;揭示它们在彻底改变威胁检测…

未来的钥匙在于过去:学历史的真正意义,震惊!历史竟然是偶然的?从历史中寻找未来的方向!

我们自幼接受的教育是&#xff0c;学历史是为了相信历史是必然的。中国人民必然战胜日寇的侵略&#xff0c;解放思想和改革开放必定会发生&#xff0c;和平和发展必定是世界的主题&#xff0c;中国经济必定是高速增长…… 然而&#xff0c;在真正的历史学家眼中&#xff0c;历史…

什么是 Socks5 代理?了解和使用 SOCKS5 代理的终极指南

SOCKS5是什么以及它如何工作&#xff1f; 在网络和互联网协议领域&#xff0c;有多种工具和技术在确保安全高效的通信方面发挥着至关重要的作用。 SOCKS5 就是这样一个工具&#xff0c;它代表套接字安全版本 5。 在这篇博文中&#xff0c;我们将深入探讨 SOCKS5 的细节&…

实战项目——用Java实现图书管理系统

前言 首先既然是管理系统&#xff0c;那咱们就要实现以下这几个功能了--> 分析 1.首先是用户分为两种&#xff0c;一个是管理员&#xff0c;另一个是普通用户&#xff0c;既如此&#xff0c;可以定义一个用户类&#xff08;user&#xff09;&#xff0c;在定义管理员类&am…

【后端面试题】【中间件】【NoSQL】MongoDB提高可用性的方案(主从结构、仲裁节点、分片、写入语义)

主从结构 MongoDB的高可用和别的中间件的高可用方案基本类似。比如在MySQL里&#xff0c;接触了分库分表和主从同步&#xff1b;在Redis里&#xff0c;Redis也有主从结构&#xff1b;在Kafka里&#xff0c;分区也是有主从结构的。 所以先介绍启用了主从同步 我们的系统有一个关…

【AIGC】DiffuToon:稳定的视频卡通化技术方案

论文&#xff1a;https://arxiv.org/pdf/2401.16224 github&#xff1a;https://github.com/modelscope/DiffSynth-Studio/tree/main/examples/Diffutoon 网络结构 两个主要分支&#xff1a;主要的卡通化管线和编辑分支 重要技术 使用了fastblend(无需模型的视频帧之间的平滑…

巴图自动化Profinet协议转Modbus协议模块接称重模块与PLC通讯

巴图自动化Profinet协议转Modbus协议模块&#xff08;BT-MDPN10&#xff09;是一种能够实现Modbus协议和Profinet协议之间转换的设备。Profinet协议转Modbus协议模块可提供单个或多个RS485接口&#xff0c;使得不同设备之间可以顺利进行通信&#xff0c;进一步提升了工业自动化…

IPFoxy Tips:为什么要选择动态住宅代理IP?

在大数据时代的背景下&#xff0c;代理IP成为了很多企业顺利开展的重要工具。代理IP地址可以分为住宅代理IP地址和数据中心代理IP地址。选择住宅代理IP的好处是可以实现真正的高匿名性&#xff0c;而使用数据中心代理IP可能会暴露自己使用代理的情况。 住宅代理IP是指互联网服务…

花两天手撸海纳嗨数数据分析系统,实现数据分析自给自足

我发现一款超好用的数据分析营销系统&#xff0c;且支持免费私有化部署。 机器准备 机器角色配置10.0.21.85主8核&#xff0c;12G&#xff0c;100G&#xff0c;Centos7.910.0.221.51辅8核&#xff0c;12G&#xff0c;100G&#xff0c;Centos7.910.0.221.55辅8核&#xff0c;12…

x86芯片定制,Ethercat芯片定制,适用于运动控制,工业总线等软硬一体机

x86芯片定制&#xff0c;Ethercat芯片定制 X86平台 我们的研发工程师已经积累了非常丰富的主板、整机设计经验&#xff0c;对接您的产品规格场景需求&#xff0c;快速交付样机&#xff0c;包含主板、BOX整机、平板电脑、CPCI等形态产品。降本、长生命周期、快速交付、及时响应…

电影院售票管理系统(小白)大佬求解

最近在写一个关于电影院售票管理系统的sm项目&#xff0c;但是在买票的环节出现了问题及点击选座购票&#xff0c;没有数据渲染出来&#xff0c;我不知道什么情况&#xff0c;所以问问。有没有大佬可以帮我解决这个问题&#xff1f;下面是我的。控制层&#xff0c;服务层&#…

systemctl命令使用

systemctl 作用&#xff1a;可以控制软件&#xff08;服务&#xff09;的启动、关闭、开机自启动 系统内置服务均可被systemctl控制第三方软件&#xff0c;如果自动注册了可以被systemctl控制第三方软件&#xff0c;如果没有自动注册&#xff0c;可以手动注册 语法 systemct…

《数据结构与算法基础 by王卓老师》学习笔记——2.5线性表的链式表示与实现1

1.链式表示 2.链表举例 3.链式存储的相关术语 4.三个讨论题

生成式人工智能与虚拟资产成为BGOV 2024的焦点议题

香港&#xff0c;2024年7月2日 — 一年一度的创新科技盛事BUSINESS GOVirtual (BGOV) 科技博览及会议将于2024年7月11日至12日在香港会议展览中心隆重举行。 展览及会议焦点两大科技趋势&#xff1a;生成式人工智能 (Generative AI) 和虚拟资产 生成式人工智能( Generative A…

【CT】LeetCode手撕—199. 二叉树的右视图

目录 题目1- 思路2- 实现⭐199. 二叉树的右视图——题解思路 3- ACM 实现 题目 原题连接&#xff1a;199. 二叉树的右视图 1- 思路 使用二叉树的层序遍历 2- 实现 ⭐199. 二叉树的右视图——题解思路 class Solution {public List<Integer> rightSideView(TreeNode ro…

【高级篇】第9章 Elasticsearch 监控与故障排查

9.1 引言 在现代数据驱动的应用架构中,Elasticsearch不仅是海量数据索引和搜索的核心,其稳定性和性能直接影响到整个业务链路的健康度。因此,建立有效的监控体系和掌握故障排查技能是每一位Elasticsearch高级专家的必备能力。 9.2 监控工具:洞察与优化的利器 在Elastics…