在我们平时对点云的处理中,常常需要将整体点云中满足不同条件或要求的点云进行分离,再分别做不同的操作。所以,今天分享一下点云的条件分离。因为大家的需求不一,所以,这里我就用XYZRGB的格式去介绍了(这种格式的点云更加直观),类似的XYZ、XYZRGBA等等原理都是相通的,没什么区别。
使用颜色信息,我们就可以根据颜色值的不同,根据色彩值对点云进行分离。类似的,XYZ格式的可以通过坐标范围,对点云进行分离,以此联想类推。
这里使用三种不同的方式来对点云进行分离操作,就是想法思路的不同,就是可以多多发散思路,完成目标。
方式一:根据色彩值筛选,分离点云
#include <iostream>
#include <pcl/io/ply_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/extract_indices.h>
int main() {
// 读取点云文件
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
if (pcl::io::loadPLYFile<pcl::PointXYZRGB>("input.ply", *cloud) == -1) {
std::cerr << "Failed to open input.ply" << std::endl;
return -1;
}
// 创建提取器和索引容器
pcl::PointIndices::Ptr redIndices(new pcl::PointIndices);
pcl::PointIndices::Ptr blueIndices(new pcl::PointIndices);
// 分离不同颜色的点云
for (size_t i = 0; i < cloud->size(); ++i) {
pcl::PointXYZRGB& point = cloud->at(i);
if (point.r == 255 && point.g == 0 && point.b == 0)
redIndices->indices.push_back(i);
else if (point.r == 0 && point.g == 0 && point.b == 255)
blueIndices->indices.push_back(i);
}
// 创建红色点云并保存为新的ply文件
pcl::PointCloud<pcl::PointXYZRGB>::Ptr redCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
pcl::ExtractIndices<pcl::PointXYZRGB> extractRed;
extractRed.setInputCloud(cloud);
extractRed.setIndices(redIndices);
extractRed.filter(*redCloud);
pcl::io::savePLYFileBinary("red_points.ply", *redCloud);
// 创建蓝色点云并保存为新的ply文件
pcl::PointCloud<pcl::PointXYZRGB>::Ptr blueCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
pcl::ExtractIndices<pcl::PointXYZRGB> extractBlue;
extractBlue.setInputCloud(cloud);
extractBlue.setIndices(blueIndices);
extractBlue.filter(*blueCloud);
pcl::io::savePLYFileBinary("blue_points.ply", *blueCloud);
std::cout << "Red points saved as red_points.ply" << std::endl;
std::cout << "Blue points saved as blue_points.ply" << std::endl;
return 0;
}
方式二:创建滤波器分离点云
#include <iostream>
#include <pcl/io/ply_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>
int main() {
// 读取ply文件
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
if (pcl::io::loadPLYFile<pcl::PointXYZRGB>("input.ply", *cloud) == -1) {
std::cerr << "Failed to open input.ply" << std::endl;
return -1;
}
// 创建红色和蓝色滤波器
pcl::PassThrough<pcl::PointXYZRGB> redFilter;
pcl::PassThrough<pcl::PointXYZRGB> blueFilter;
// 设置滤波器参数
redFilter.setInputCloud(cloud);
redFilter.setFilterFieldName("r");
redFilter.setFilterLimits(1, 255);
redFilter.setNegative(true); // 保留非红色点云
blueFilter.setInputCloud(cloud);
blueFilter.setFilterFieldName("b");
blueFilter.setFilterLimits(1, 255);
blueFilter.setNegative(true); // 保留非蓝色点云
// 执行滤波操作
pcl::PointCloud<pcl::PointXYZRGB>::Ptr filteredCloud(new
pcl::PointCloud<pcl::PointXYZRGB>);
redFilter.filter(*filteredCloud);
blueFilter.filter(*filteredCloud);
// 保存滤波后的点云到新的ply文件
pcl::io::savePLYFileBinary("filtered_points.ply", *filteredCloud);
std::cout << "Filtered points saved as filtered_points.ply" << std::endl;
return 0;
}
方式三:反向分离
#include <iostream>
#include <pcl/io/ply_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>
int main() {
// 读取ply文件
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
if (pcl::io::loadPLYFile<pcl::PointXYZRGB>("input.ply", *cloud) == -1) {
std::cerr << "Failed to open input.ply" << std::endl;
return -1;
}
// 创建滤波器
pcl::PointCloud<pcl::PointXYZRGB>::Ptr filteredCloud(new
pcl::PointCloud<pcl::PointXYZRGB>);
// 遍历点云,将非红色和非蓝色点云加入到滤波器输出
for (size_t i = 0; i < cloud->size(); ++i) {
pcl::PointXYZRGB& point = cloud->at(i);
if (!(point.r == 0 && point.g == 0 && point.b == 255) && !(point.r == 255 && point.g == 0 && point.b == 0)) {
filteredCloud->push_back(point);
}
}
// 保存滤波后的点云到新的ply文件
pcl::io::savePLYFileBinary("filtered_points.ply", *filteredCloud);
std::cout << "Filtered points saved as filtered_points.ply" << std::endl;
return 0;
}
以上就是在XYZRGB格式下的点云分离(其他格式下的点云也是一样的),希望可以给到大家一点帮助。
草稿代码可能不是那么严谨,但运行起来问题不大。