PCL最小二乘法拟合平面

PCL最小二乘法拟合平面

效果

过滤掉不属于拟合平面的点(点到平面距离处于阈值外的点)

请添加图片描述

原理参考

最小二分法拟合平面
过程推导如下
请添加图片描述

PCL实现
#include <QCoreApplication>
#include<opencv2\opencv.hpp>
#include<pcl/io/io.h>
#include<pcl/io/pcd_io.h>//pcd 读写类相关的头文件。
#include<pcl/io/ply_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include<Eigen/Dense>
#include <dl_planefitting.h>


//点云可视化
void showCloud(std::string windowname,pcl::PointCloud<pcl::PointXYZ>::Ptr cloud){
    pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer (windowname));
    viewer->setBackgroundColor (0.5, 0.5, 0.5);  //设置背景
    viewer->addPointCloud<pcl::PointXYZ> (cloud, "sample cloud");  //显示点云
    viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "sample cloud");  //设置点尺寸
    viewer->addCoordinateSystem (100.0);  //设置坐标轴尺寸
//    while (!viewer->wasStopped ())
//    {
//      viewer->spinOnce (100);
//      boost::this_thread::sleep (boost::posix_time::microseconds (100000));
//    }
    //cout<<"Point couting in "<<windowname<<": "<<cloud->size()<<endl;
}


// 算点到平面距离
//设平面方程为Ax+By+Cz+D=0
//则有A/D X+B/D Y+ C/D Z+1=0 即 a0/a2 X+ a1/a2 Y +-1/a2 Z +1=0
double getDistance(double a0,double a1,double a2,pcl::PointXYZ point){
    double A=a0/a2;
    double B=a1/a2;
    double C=-1/a2;
    double up = std::abs(A*point.x+B*point.y+C*point.z+1);
    double down = std::sqrt(std::pow(A,2)+std::pow(B,2)+std::pow(C,2));
    double dis = up/down;
    return dis;
}


//平面拟合算法
Eigen::Vector3d getFlat(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud){
    Eigen::Matrix3d rot;
    double x2,xy,x,y2,y,zx,zy,z;
    for(int i=0;i<cloud->points.size();i++){
        x2 += cloud->points[i].x * cloud->points[i].x;
        xy += cloud->points[i].x * cloud->points[i].y;
        x += cloud->points[i].x;
        y2 += cloud->points[i].y * cloud->points[i].y;
        y += cloud->points[i].y;
        zx += cloud->points[i].x * cloud->points[i].z;
        zy += cloud->points[i].y * cloud->points[i].z;
        z += cloud->points[i].z;
    }
    //为矩阵赋值
    rot<<x2,  xy,  x,
         xy,  y2,  y,
         x,   y,   cloud->points.size();
    //为列向量赋值
    Eigen::Vector3d eq(zx,zy,z);
    Eigen::Vector3d X = rot.colPivHouseholderQr().solve(eq);
    std::cout<<X<<std::endl;
    std::cout<<X[0]<<" "<<X[1]<<" "<<X[2]<<std::endl;
    return X;
}


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
    pcl::io::loadPCDFile<pcl::PointXYZ>("D:\\Qt_Project\\flat.pcd",*cloud);
    showCloud("原点云",cloud);
    Eigen::Vector3d flat = getFlat(cloud);
    pcl::PointCloud<pcl::PointXYZ>::Ptr flatPoints(new pcl::PointCloud<pcl::PointXYZ>);
    int n=0;
    for (int i=0;i<cloud->points.size();i++){
        if(getDistance(flat[0],flat[1],flat[2],cloud->points[i])<0.15){  //阈值可调 
             flatPoints->points.push_back(cloud->points[i]);
        }
        else{
            //std::cout<<"dis:"<<getDistance(flat[0],flat[1],flat[2],cloud->points[i])<<std::endl;
        }
    }
    std::cout<<"原size:"<<cloud->size()<<std::endl;
    std::cout<<"平面size:"<<flatPoints->size()<<std::endl;
    showCloud("符合要求的平面",flatPoints);
    return a.exec();
}
  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
pcl最小二乘法是一种常用的曲线拟合方法。在拟合曲线时,我们希望找到一个函数,使得该函数与给定的数据点最为接近。 最小二乘法是通过最小化误差的平方和来寻找拟合曲线的。对于给定的数据点集合,我们假设拟合函数为一个形式已知的函数,如多项式函数或指数函数。然后,通过调整函数的参数,使得该函数与数据点的误差最小。 pcl库是一个用于点云处理的开源库,其中包含了最小二乘法的实现。使用pcl库进行曲线拟合,我们首先需要将数据点转换为pcl库中的点云数据结构。然后,可以通过pcl::SampleConsensusModelLine类中的setInputCloud()函数将点云数据传递给拟合模型。 接下来,我们可以选择使用pcl::SACSegmentation类中的setModelType()函数来指定拟合模型的类型,例如直线、平面或圆等。然后,通过调用pcl::SACSegmentation类的segment()函数,可以得到拟合结果。 最小二乘法拟合曲线的好处是可以在近似数据的同时最小化误差。然而,拟合结果很大程度上依赖于数据点的选择和拟合函数的选取。因此,在使用最小二乘法进行曲线拟合时,我们应该根据实际情况选择合适的数据点和拟合函数。 综上所述,pcl最小二乘法是一种有效的曲线拟合方法。通过使用pcl库中的相关函数,我们可以方便地实现曲线拟合,并得到拟合结果。然而,在使用时需要注意选择合适的数据点和拟合函数,以得到较准确的拟合结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mai0026

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值