文章目录
- 前言
- 一、滤波、去除离散点方法
- 二、拟合成线
- 三、拟合多条线
前言
小白一枚,进行实验之前,首先要明确一下思路:
1、为何要进行拟合,首先搞清楚你的需求、你要实现的目标。
2、二维数据拟合成线,首先要做的就是滤波、去除离散点,否则对拟合的效果影响很大。
3、如何拟合单条【本文以直线为例】、拿到它的方程式,并进行可视化展示。
4、若要拟合多条线【本文以直线为例】是否可行?实现思路是怎样的。
一、滤波、去除离散点方法
我比较常用的是条件滤波,去除离散点常用的是StatisticalOutlierRemoval 和 RadiusOutlierRemoval
下面写几个例子,并给出了完整代码:
1、条件滤波:
条件滤波是拿到你给定x\y\z区间内的点云。
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/extract_indices.h>
#include <iostream>
#include <vector>
#include <cmath>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/filters/radius_outlier_removal.h>
#include <pcl/filters/conditional_removal.h>
using namespace std;
int main() {
// 读取点云文件 20230906_103819.pcd
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile<pcl::PointXYZ>("20230906_103603.pcd", *cloud) == -1) {
std::cerr << "Failed to load the PCD file." << std::endl;
return (-1);
}
std::cout << "Loaded "
<< cloud->width * cloud->height
<< " data points from the PCD file." << std::endl;
//创建容器保存过滤后的点
pcl::PointCloud<pcl::PointXYZ>::Ptr conditionCloud(new pcl::PointCloud<pcl::PointXYZ>);
//创建条件滤波,设置滤波条件
pcl::ConditionAnd<pcl::PointXYZ>::Ptr rangeCondOrigin(new pcl::ConditionAnd<pcl::PointXYZ>());
//这里我设置的范围是x从-2到1,y从-0.5到10.0,关于开闭区间,可以自行修改
rangeCondOrigin->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZ>("y", pcl::ComparisonOps::GT, -0.5)));
rangeCondOrigin->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZ>("y", pcl::ComparisonOps::LT, 10.0)));
rangeCondOrigin->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZ>("x", pcl::ComparisonOps::GT, -2)));
rangeCondOrigin->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZ>("x", pcl::ComparisonOps::LT, 1)));
// 执行点云移除处理,并将剩下的点添加到 conditionCloud(刚刚创建的容器,现在得到的就是过滤后的点云)
pcl::ConditionalRemoval<pcl::PointXYZ> condremOrigin(rangeCondOrigin, false);
condremOrigin.setInputCloud(cloud);
condremOrigin.setKeepOrganized(false);
condremOrigin.filter(*conditionCloud);
//可视化显示过滤后的点云
pcl::visualization::PCLVisualizer viewer("Point Cloud Viewer");
viewer.addPointCloud<pcl::PointXYZ>(conditionCloud, "conditionCloud");
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "conditionCloud");
viewer.setBackgroundColor(0, 0, 0); // 设置背景色为黑色
while (!viewer.wasStopped()) {
viewer.spinOnce(100);
}
return 0;
}
2、RadiusOutlierRemoval去除离散点
过滤掉不符合搜索半径内邻居点数目的将被过滤掉。
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/extract_indices.h>
#include <iostream>
#include <vector>
#include <cmath>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/filters/radius_outlier_removal.h>
#include <pcl/filters/conditional_removal.h>
using namespace std;
int main() {
// 读取点云文件
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile<pcl::PointXYZ>("20230906_103603.pcd", *cloud) == -1) {
std::cerr << "Failed to load the PCD file." << std::endl;
return (-1);
}
pcl::RadiusOutlierRemoval<pcl::PointXYZ> sorCloud; //创建滤波器对象
sorCloud.setInputCloud(cloud); //设置待滤波的点云
sorCloud.setRadiusSearch(0.01); // 设置搜索半径
sorCloud.setMinNeighborsInRadius(3); // 设置一个内点最少的邻居数目
// 创建一个容器对象来保存滤波后的点云
pcl::PointCloud<pcl::PointXYZ>::Ptr radiusCloud(new pcl::PointCloud<pcl::PointXYZ>);
sorCloud.filter(*radiusCloud);
//可视化窗口
pcl::visualization::PCLVisualizer viewer("Point Cloud Viewer");
viewer.addPointCloud<pcl::PointXYZ>(radiusCloud, "radiusCloud");
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "radiusCloud");
viewer.setBackgroundColor(0, 0, 0); // 设置背景色为黑色
while (!viewer.wasStopped()) {
viewer.spinOnce(100);
}
return 0;
}
二、拟合成线
三、拟合多条线
太累了,明天再写。。。。。。。。。。。