PCL 将点云投影到拟合平面

PCL点云算法汇总及实战案例汇总的目录地址链接:

PCL点云算法与项目实战案例汇总(长期更新)


一、概述

        点云投影到拟合平面是指将三维点云数据中的点投影到与其最接近的二维平面上。通过投影到平面,可以消除数据的高度变化或Z轴信息,使得点云数据在平面上更加集中和规整。这在点云简化、平面特征提取和2D视觉分析中非常有用。

1.1原理

        平面拟合和投影的过程通常涉及以下几个步骤:

        1.平面拟合:使用最小二乘法拟合点云的主平面,即找到一个平面,使得所有点到该平面的距离之和最小。拟合平面的方程为:

                                                ax+by+cz+d=0

        其中(a,b,c)是平面法向量,d是平面的偏移量。

        2.点云投影:将点云投影到该平面上,计算每个点到平面的垂直投影。投影点的计算公式为:

1.2实现步骤

  1. 加载点云数据。
  2. 通过PCA或最小二乘法拟合一个平面
  3. 将点云数据投影到拟合平面上。
  4. 可视化原始点云和投影后的点云。

1.3应用场景

  1. 数据降维:在三维点云中,通过将点云投影到二维平面,可以实现数据降维处理。
  2. 形状分析:在表面分析中,通过平面投影可以分析平面内的特征。
  3. 点云简化:将曲面简化为平面后,便于进行后续特征分析或轮廓提取。

二、代码实现

2.1关键函数

2.1.1 平面投影

#include <pcl/filters/project_inliers.h>
#include <pcl/ModelCoefficients.h>

// 将点云投影到平面
void projectPointCloudToPlane(
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,
    pcl::PointCloud<pcl::PointXYZ>::Ptr projectedCloud)
{
    pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
    coefficients->values.resize(4);
    coefficients->values[0] = 0;  // 设置平面系数 a
    coefficients->values[1] = 0;  // 设置平面系数 b
    coefficients->values[2] = 1.0;  // 设置平面系数 c,投影到 X-Y 平面
    coefficients->values[3] = 0;  // 设置平面常数 d

    pcl::ProjectInliers<pcl::PointXYZ> proj;
    proj.setModelType(pcl::SACMODEL_PLANE);
    proj.setInputCloud(cloud);
    proj.setModelCoefficients(coefficients);
    proj.filter(*projectedCloud);  // 将点云投影到平面上
}

 2.1.2 可视化原始点云和投影点云

#include <pcl/visualization/pcl_visualizer.h>

// 可视化原始点云和投影点云
void visualizePointClouds(
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,
    pcl::PointCloud<pcl::PointXYZ>::Ptr projectedCloud)
{
    pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Point Cloud Visualization"));

    int vp1, vp2;
    viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp1);
    viewer->setBackgroundColor(1.0, 1.0, 1.0, vp1);  // 白色背景
    viewer->addText("Original Point Cloud", 10, 10, "vp1_text", vp1);
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color(cloud, 255, 0, 0);  // 红色
    viewer->addPointCloud(cloud, cloud_color, "original_cloud", vp1);

    viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp2);
    viewer->setBackgroundColor(0.98, 0.98, 0.98, vp2);  // 浅灰色背景
    viewer->addText("Projected Point Cloud", 10, 10, "vp2_text", vp2);
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> projected_color(projectedCloud, 0, 255, 0);  // 绿色
    viewer->addPointCloud(projectedCloud, projected_color, "projected_cloud", vp2);

    while (!viewer->wasStopped())
    {
        viewer->spinOnce(100);
        boost::this_thread::sleep(boost::posix_time::microseconds(100000));
    }
}

2.2完整代码

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/ModelCoefficients.h>
#include <pcl/filters/project_inliers.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>

// 将点云投影到平面
void projectPointCloudToPlane(
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,
    pcl::PointCloud<pcl::PointXYZ>::Ptr projectedCloud)
{
    pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
    coefficients->values.resize(4);
    coefficients->values[0] = 0;  // 设置平面系数 a
    coefficients->values[1] = 0;  // 设置平面系数 b
    coefficients->values[2] = 1.0;  // 设置平面系数 c,投影到 X-Y 平面
    coefficients->values[3] = 0;  // 设置平面常数 d

    pcl::ProjectInliers<pcl::PointXYZ> proj;
    proj.setModelType(pcl::SACMODEL_PLANE);
    proj.setInputCloud(cloud);
    proj.setModelCoefficients(coefficients);
    proj.filter(*projectedCloud);  // 将点云投影到平面上
}

// 可视化原始点云和投影点云
void visualizePointClouds(
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,
    pcl::PointCloud<pcl::PointXYZ>::Ptr projectedCloud)
{
    pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Point Cloud Visualization"));

    int vp1, vp2;
    viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp1);
    viewer->setBackgroundColor(1.0, 1.0, 1.0, vp1);  // 白色背景
    viewer->addText("Original Point Cloud", 10, 10, "vp1_text", vp1);
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color(cloud, 255, 0, 0);  // 红色
    viewer->addPointCloud(cloud, cloud_color, "original_cloud", vp1);

    viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp2);
    viewer->setBackgroundColor(0.98, 0.98, 0.98, vp2);  // 浅灰色背景
    viewer->addText("Projected Point Cloud", 10, 10, "vp2_text", vp2);
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> projected_color(projectedCloud, 0, 255, 0);  // 绿色
    viewer->addPointCloud(projectedCloud, projected_color, "projected_cloud", vp2);

    while (!viewer->wasStopped())
    {
        viewer->spinOnce(100);
        boost::this_thread::sleep(boost::posix_time::microseconds(100000));
    }
}

int main(int argc, char** argv)
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projected(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::io::loadPCDFile<pcl::PointXYZ>("bunny.pcd", *cloud);

    // 将点云投影到平面
    projectPointCloudToPlane(cloud, cloud_projected);

    // 保存投影后的点云
    pcl::io::savePCDFileBinary("cloud_projected.pcd", *cloud_projected);

    // 可视化原始点云和投影后的点云
    visualizePointClouds(cloud, cloud_projected);

    return 0;
}

三、实现效果

pcl(Point Cloud Library)是一款用于处理点云数据的开源库。点云是由大量的点组成的三维数据集,可以用来描述物体的形状和表面信息。 在pcl中,可以通过计算点云中的三角网格来估算平面的面积。三角网格是一个由连接点的三角形组成的网格,可以将平面分割成不同的小面片。计算平面的面积可以通过对这些小面片的面积进行求和来实现。 首先,需要从点云中提取平面。可以使用pcl的分割算法,例如RANSAC算法,来拟合平面模型并提取点云中的平面。得到平面的参数方程后,可以将平面上的点集投影到XY平面上,得到二维的点集。 接下来,可以使用pcl中的三角化算法,例如Delaunay三角化算法,将这些二维的点集转化成三角网格。在得到三角网格后,需要计算每个三角形的面积。可以使用三角形的顶点坐标计算三角形的边长,并应用海伦公式来计算三角形的面积。 最后,对所有三角形的面积进行求和,就可以得到平面的面积。这个面积是以点的单位为基准的,如果需要得到物理单位的面积(如平方米),则需要考虑点云的尺度转换以及单位换算。 总的来说,pcl可以通过提取平面、三角化和计算每个三角形的面积,来估算点云数据中平面的面积。这对于一些需要对点云进行分析和表征的应用非常有用,例如建筑物测量、地形分析等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值