Bootstrap

点云拟合直线轨迹(CloudComapre+PCL) 原创

  1. ui添加

  1. 添加connect连接槽函数

connect(m_UI->actionLinePathFit, &QAction::triggered, this, &MainWindow::doActionLinePathFit);
  1. 添加函数声明

void doActionLinePathFit(); //直线轨迹
  1. 添加PCL头文件

#include <pcl/keypoints/uniform_sampling.h>            // 均匀采样
#include <pcl/sample_consensus/ransac.h>            //随机采样一致性算法实现
#include <pcl/sample_consensus/sac_model_line.h>    //直线采样
  1. 添加函数实现

void MainWindow::doActionLinePathFit()
{
    if (getSelectedEntities().size() != 1)
    {
        ccLog::Print(QStringLiteral("只能选择一个点云实体"));
        return;
    }
    ccHObject* entity = getSelectedEntities()[0];
    ccPointCloud* ccCloud = ccHObjectCaster::ToPointCloud(entity);
    // ---------------------------读取数据到PCL----------------------------------
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    cloud->resize(ccCloud->size());
    for (int i = 0; i < cloud->size(); ++i)
    {
        const CCVector3* point = ccCloud->getPoint(i);
        cloud->points[i].x = point->x;
        cloud->points[i].y = point->y;
        cloud->points[i].z = point->z;
    }


    //----------------------------- 空间直线拟合 -----------------------------
    pcl::SampleConsensusModelLine<pcl::PointXYZ>::Ptr model_line(new pcl::SampleConsensusModelLine<pcl::PointXYZ>(cloud));    //指定拟合点云与几何模型
    pcl::RandomSampleConsensus<pcl::PointXYZ> ransac(model_line);    //创建随机采样一致性对象
    ransac.setDistanceThreshold(1);    //设置容忍范围,也就是阈值
    ransac.setMaxIterations(10000);        //最大迭代次数
    ransac.computeModel();                //执行RANSAC空间直线拟合

    vector<int> inliers;                //存储内点索引的向量
    ransac.getInliers(inliers);            //提取内点对应的索引

    /// 根据索引提取内点
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_line(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::copyPointCloud<pcl::PointXYZ>(*cloud, inliers, *cloud_line);

    /// 模型参数
    Eigen::VectorXf coefficient;
    ransac.getModelCoefficients(coefficient);

    ccLog::Print(QStringLiteral("直线点向式方程为\n(x -%1) / %2 = (y - %3) / %4 = (z - %5) / %6").arg(coefficient[0]).arg(coefficient[1]).arg(coefficient[2]).arg(coefficient[3]).arg(coefficient[4]).arg(coefficient[5]));

    // ------------------------PCL->CloudCompare--------------------------------
    if (!cloud_line->empty())
    {
        ccPointCloud* Path = new ccPointCloud(QString("Path"));
        for (int i = 0; i < cloud_line->size(); ++i)
        {
            double x = cloud_line->points[i].x;
            double y = cloud_line->points[i].y;
            double z = cloud_line->points[i].z;
            Path->addPoint(CCVector3(x, y, z));
        }
        Path->setColor(ccColor::Rgba(rand() % 255, rand() % 255, 0, 255));
        Path->showColors(true);
        if (ccCloud->getParent())
        {
            ccCloud->getParent()->addChild(Path);
        }
        ccCloud->setEnabled(false);
        addToDB(Path);


        ccPointCloud* PointCloudafterPCL = new ccPointCloud(QString("PCL计算后的点云"));
        for (int i = 0; i < cloud->size(); ++i)
        {
            double x = cloud->points[i].x;
            double y = cloud->points[i].y;
            double z = cloud->points[i].z;
            PointCloudafterPCL->addPoint(CCVector3(x, y, z));
        }
        PointCloudafterPCL->setColor(ccColor::Rgba(rand() % 255, rand() % 255, 0, 255));
        PointCloudafterPCL->showColors(true);
        if (ccCloud->getParent())
        {
            ccCloud->getParent()->addChild(PointCloudafterPCL);
        }
        ccCloud->setEnabled(false);
        addToDB(PointCloudafterPCL);



        refreshAll();
        updateUI();
    }
    else
    {
        ccCloud->setEnabled(true);
        // Display a warning message in the console
        dispToConsole("Warning: example shouldn't be used as is", ccMainAppInterface::WRN_CONSOLE_MESSAGE);
    }

}

结果显示1

主视图

左视图

显示结果2

主视图

左视图

;