终端输出:
Cloud before filtering:
-1.23392 1.81505 -0.968005
-0.00934529 1.36497 0.158734
0.488435 1.96851 -0.0534078
1.27135 1.16404 -1.00462
-0.249089 -0.0815883 1.13229
0.448447 1.48914 1.78378
1.14143 1.77363 1.68965
1.08544 -1.01664 -1.13041
1.1199 0.9951 -1.13308
1.44268 -1.44434 -0.391739
Cloud after filtering:
-1.23392 1.81505 -0.968005
-0.00934529 1.36497 0.158734
0.488435 1.96851 -0.0534078
1.27135 1.16404 -1.00462
1.14143 1.77363 1.68965
1.08544 -1.01664 -1.13041
1.1199 0.9951 -1.13308
1.44268 -1.44434 -0.391739
这段代码使用C++和点云库(PCL)进行点云的处理。下面是代码详细解析:
首先,代码包含了PCL库的一些必要头文件,用于生成和处理点云数据:
<pcl/common/generate.h>
:用于生成点云数据。<pcl/filters/experimental/functor_filter.h>
:提供一个函数式过滤器,用于根据自定义条件过滤点云。<pcl/point_types.h>
:定义了PCL中的点类型。<iostream>
:用于输出信息到标准错误流中。
在main
函数中,首先定义了使用pcl::PointXYZ
点类型的点云别名XYZCloud
。
创建两个shared_ptr
类型的XYZCloud
对象cloud
和filtered_cloud
,分别用于存储原始点云和过滤后的点云。
使用pcl::common::CloudGenerator
和pcl::common::UniformGenerator
生成随机点云数据。这里参数{-2.0, 2, 1234}
分别代表随机生成点的坐标范围和种子,然后将生成的10个点填充到cloud
点云中。
通过循环输出原始点云中的点坐标。
设置一个圆形区域的中心和半径,用于过滤点云中的点。此处中心设为(0, 0, 2)
,半径设为2
。
定义一个过滤条件filter
,该条件为一个lambda函数,接受点云和索引号,计算点云中点与设定圆心的欧氏距离,若大于等于半径,则该点满足条件。
使用pcl::experimental::FunctionFilter
根据上述过滤条件对原始点云进行过滤,得到过滤后的点云。
循环输出过滤后点云中的点坐标。
总之,这段代码的功能是生成一个随机的点云,并使用自定义的过滤条件(本例中是一个以(0, 0, 2)
为中心,半径为2
的圆形区域外的点)对该点云进行过滤。过滤后的点云中只包含满足条件的点,然后输出过滤前后的点云信息。这种过滤方式非常灵活,可以根据需要定制过滤条件,非常适合在点云预处理中使用。
#include <pcl/common/generate.h> // 包含生成点云的功能函数
#include <pcl/filters/experimental/functor_filter.h> // 包含过滤点云的函数
#include <pcl/point_types.h> // 包含PCL中点类型的定义
#include <iostream> // 包含输入输出流的库
int
main()
{
using XYZCloud = pcl::PointCloud<pcl::PointXYZ>; // 定义一个别名XYZCloud用于表示pcl::PointXYZ类型的点云
const auto cloud = pcl::make_shared<XYZCloud>(); // 创建一个新的点云共享指针
const auto filtered_cloud = pcl::make_shared<XYZCloud>(); // 创建一个新的用于存放过滤后点云的共享指针
// 创建一个随机数生成器填充点云
pcl::common::CloudGenerator<pcl::PointXYZ, pcl::common::UniformGenerator<float>>
generator{{-2.0, 2, 1234}}; // 初始化随机数发生器,范围是-2到2,种子是1234
generator.fill(10, 1, *cloud); // 使用随机数生成器生成10个点填充点云
std::cerr << "Cloud before filtering: " << std::endl; // 输出过滤前的点云
for (const auto& pt : *cloud)
std::cerr << " " << pt.x << " " << pt.y << " " << pt.z << std::endl; // 遍历并输出点云中的每个点
// 设置一个条件来拒绝滤波器内的点
const Eigen::Vector3f center{0, 0, 2}; // 定义一个中心点
const float radius = 2; // 定义一个半径
pcl::experimental::FilterFunction<pcl::PointXYZ> filter; // 定义一个过滤函数
filter = [=](const XYZCloud& cloud, pcl::index_t idx) {
return ((cloud[idx].getVector3fMap() - center).norm() >= radius); // 如果点到中心的欧式距离大于或等于半径则保留
};
// 构建过滤器
pcl::experimental::FunctionFilter<pcl::PointXYZ> func_filter(filter); // 用上面定义的过滤条件创建过滤器
func_filter.setInputCloud(cloud); // 设置输入点云
// 应用过滤器
func_filter.filter(*filtered_cloud); // 执行过滤操作并把结果点云存储在filtered_cloud中
// 显示过滤后的点云
std::cerr << "Cloud after filtering: " << std::endl; // 输出过滤后的点云
for (const auto& pt : *filtered_cloud)
std::cerr << " " << pt.x << " " << pt.y << " " << pt.z << std::endl; // 遍历并输出过滤后点云中的每个点
return (0); // 程序正常结束
}
这段代码的功能是创建一个含有随机生成的点云数据的点云对象,然后通过一个自定义的过滤条件来过滤点云中某个区域内的点。过滤条件是点到一个中心点的距离大于或等于一个指定的半径。过滤操作之后,输出过滤前和过滤后的点云数据。
const auto cloud = pcl::make_shared<XYZCloud>();
与 pcl::PointCloud<pcl::PointXYZ>::Ptr 区别
pcl::common::CloudGenerator<pcl::PointXYZ, pcl::common::UniformGenerator<float>>
generator{{-2.0, 2, 1234}};// 定义一个名为generator的CloudGenerator对象
generator.fill(10, 1, *cloud);// 使用generator填充点云
filter = [=](const XYZCloud& cloud, pcl::index_t idx) {
return ((cloud[idx].getVector3fMap() - center).norm() >= radius); // 如果点到中心的欧式距离大于或等于半径则保留
};
这行代码定义了一个过滤器的行为,具体来说就是一个lambda表达式,用来决定点云中的哪些点应该被保留。
filter
:这是一个pcl::experimental::FilterFunction<pcl::PointXYZ>
类型的变量,它用作点云过滤的条件。[=]
:这是lambda表达式的捕获列表。[=]
表示以值捕获的方式捕获所有外部作用域中的变量(在这个例子中,主要是center
和radius
)。(const XYZCloud& cloud, pcl::index_t idx)
:这是lambda表达式的参数列表。cloud
是一个对点云的引用,idx
是点云中点的索引。这意味着这个lambda表达式将对点云中的每一个点进行操作。cloud[idx].getVector3fMap() - center
:这部分代码通过点的索引idx
访问点云中的点,并获取该点的坐标(使用getVector3fMap()
方法获得一个Eigen::Vector3f
类型的向量),然后计算该点与一个中心点center
的向量差。.norm()
:这是Eigen
库中的方法,用于计算向量的欧几里得范数,即从原点到向量指定中心点的直线距离。>= radius
:这是条件判断,如果点到center
的距离大于或等于radius
,则表达式的结果为true
,这表示这个点应被保留;如果小于radius
,则为false
,表示这个点应被过滤掉。
综上所述,这个lambda表达式定义的过滤器的作用是检查点云中的每一个点,如果点到一个给定中心center
的距离大于或等于指定的半径radius
,则这个点满足条件,应被保留;否则,这个点不满足条件,应被过滤掉。这种过滤方式常用于去除一个区域内的所有点,例如,去除距离传感器特定距离内的所有点,以清除噪声或其他不需要的数据。