PCL点云算法汇总及实战案例汇总的目录地址链接:
PCL点云算法与项目实战案例汇总(长期更新)
一、概述
点云投影到拟合平面是指将三维点云数据中的点投影到与其最接近的二维平面上。通过投影到平面,可以消除数据的高度变化或Z轴信息,使得点云数据在平面上更加集中和规整。这在点云简化、平面特征提取和2D视觉分析中非常有用。
1.1原理
平面拟合和投影的过程通常涉及以下几个步骤:
1.平面拟合:使用最小二乘法拟合点云的主平面,即找到一个平面,使得所有点到该平面的距离之和最小。拟合平面的方程为:
ax+by+cz+d=0
其中(a,b,c)是平面法向量,d是平面的偏移量。
2.点云投影:将点云投影到该平面上,计算每个点到平面的垂直投影。投影点的计算公式为:
1.2实现步骤
- 加载点云数据。
- 通过PCA或最小二乘法拟合一个平面。
- 将点云数据投影到拟合平面上。
- 可视化原始点云和投影后的点云。
1.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;
}