PCL专栏目录及须知
注意:用于点云上采样。
大致思想:即使用一个类似窗口,不停移动窗口,对窗口内的点云点进行最小二乘法平面计算,按照计算出的平面方程往点云内插值。
1.最小二乘法
通过拟合数据点来找到最佳拟合曲线或平面。
其核心思想是最小化观测数据点与拟合曲线之间的垂直距离的平方和,即最小化残差的平方和。
通过最小二乘法,我们可以找到一条曲线或平面,使得观测数据点到该曲线或平面的距离最短。
如下图:
空间二维点散列的分布在一条直线附近,设置直线f(x),计算到各散列点垂直距离最近的f(x)的方程参数,该直线方程即为拟合出的结果点。
2.MLS移动最小二乘上采样
(1)遍历点云,对每个点云点P,按照固定半径搜索邻近点,并对这些邻近点使用最小二乘法拟合平面。
(2)根据拟合出的平面方程,进行插值,得到上采样点。
(3)计算拟合出的平面的法向量,沿着法向量的方向,按照设置好的固定步长,进行移动。
(4)不停重复(1)-(3),直到遍历完所有点云。
3.使用场景
用于点云上采样。
4.关键函数
(1)半径搜索范围
segmentation.setSearchRadius(0.01);
(2)设置上采样方法
segmentation.setUpsamplingMethod(pcl::MovingLeastSquares<pcl::PointXYZRGB, pcl::PointXYZRGB>::SAMPLE_LOCAL_PLANE);
(3)将被采样的局部点平面的圆的半径(仅在SAMPLE_LOCAL_PLANE上采样的情况下使用)
segmentation.setUpsamplingRadius(0.004);
(4)移动步长
segmentation.setUpsamplingStepSize(0.002);
5.完整代码
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/surface/mls.h>
#include <pcl/search/kdtree.h>
#include <boost/thread/thread.hpp>
#include <pcl/visualization/pcl_visualizer.h>
int main()
{
/****************移动最小二乘上采样********************/
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>); // 源点云
pcl::io::loadPCDFile("D:/code/csdn/data/bunny2.pcd", *cloud);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr resultCloud(new pcl::PointCloud<pcl::PointXYZRGB>); // 源点云
// 移动最小二乘上采样
pcl::MovingLeastSquares<pcl::PointXYZRGB, pcl::PointXYZRGB> segmentation;
segmentation.setInputCloud(cloud);
pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree;
segmentation.setSearchMethod(tree);
segmentation.setSearchRadius(0.01); // 半径搜索范围
segmentation.setUpsamplingMethod(pcl::MovingLeastSquares<pcl::PointXYZRGB, pcl::PointXYZRGB>::SAMPLE_LOCAL_PLANE); // 设置上采样方法
segmentation.setUpsamplingRadius(0.004); // 将被采样的局部点平面的圆的半径(仅在SAMPLE_LOCAL_PLANE上采样的情况下使用)
segmentation.setUpsamplingStepSize(0.002); // 移动步长
segmentation.process(*resultCloud);
/****************展示********************/
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("cloud"));
viewer->addPointCloud(cloud, "cloud");
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer0(new pcl::visualization::PCLVisualizer("resultCloud"));
viewer0->addPointCloud(resultCloud, "resultCloud");
while (!viewer->wasStopped() || !viewer0->wasStopped())
{
viewer->spinOnce(100);
viewer0->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
return (0);
}
6.结果展示
原始点云
结果点云