自学内容网 自学内容网

PCL 计算点云的高斯曲率

目录

一、概述

1.1原理

1.2实现步骤

1.3应用场景

二、代码实现

2.1关键函数

2.1.1 法向量计算

2.1.2 主曲率和高斯曲率计算

2.1.3 可视化函数

2.2完整代码

三、实现效果


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

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


一、概述

        高斯曲率是点云表面几何特性的一个重要指标,表明点云局部区域的弯曲程度。在计算高斯曲率之前,通常会通过法向量估计和主曲率计算得到局部表面的曲率信息。本文将介绍如何通过法向量和主曲率的计算来获得点云的高斯曲率,并在可视化窗口中显示法向量和主曲率,允许控制法向量和曲率的显示间隔及长度。

1.1原理

        高斯曲率 K 基于点云的最大曲率和最小曲率来计算,其公式如下:

        在计算高斯曲率之前,首先需要计算点云的法向量和主曲率。法向量用于表示表面点的方向,主曲率则是局部表面的最大和最小曲率。

1.2实现步骤

  1. 读取点云数据:从PCD文件中读取点云。
  2. 计算法向量:使用 pcl::NormalEstimation 计算点云中每个点的法向量。
  3. 计算主曲率和高斯曲率:通过 pcl::PrincipalCurvaturesEstimation 计算主曲率,并使用公式计算高斯曲率。
  4. 可视化:在一个窗口中显示原始点云,在另一个窗口中显示带有法向量和主曲率的点云,并可以控制法向量和曲率的显示长度和间隔。

1.3应用场景

  1. 三维建模与重建:高斯曲率帮助检测表面的凸凹变化,辅助构建精细模型。
  2. 表面特征提取:表面凸起、凹陷等特征的识别。
  3. 机器人路径规划:通过理解物体表面的几何特性,优化路径规划和抓取。

二、代码实现

2.1关键函数

2.1.1 法向量计算

使用 pcl::NormalEstimation 计算点云的法向量:

pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
ne.setInputCloud(cloud);
ne.setSearchMethod(tree);
ne.setRadiusSearch(0.03);
ne.compute(*normals);

2.1.2 主曲率和高斯曲率计算

通过 pcl::PrincipalCurvaturesEstimation 计算主曲率,再计算高斯曲率:

pcl::PrincipalCurvaturesEstimation<pcl::PointXYZ, pcl::Normal, pcl::PrincipalCurvatures> pce;
pce.setInputCloud(cloud);
pce.setInputNormals(normals);
pce.setSearchMethod(tree);
pce.setRadiusSearch(0.03);
pce.compute(*curvatures);

// 计算高斯曲率
for (size_t i = 0; i < curvatures->size(); ++i) {
    float k1 = curvatures->points[i].pc1;  // 最大曲率
    float k2 = curvatures->points[i].pc2;  // 最小曲率
    float gaussian_curvature = k1 * k2;    // 高斯曲率
    gauss_curvature_cloud->points[i].curvature = gaussian_curvature;
}

2.1.3 可视化函数

使用 pcl::visualization::PCLVisualizer 进行可视化,允许控制法向量和曲率显示的长度与间隔:

void visualizePointCloudAndGaussianCurvature(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::Normal>::Ptr normals, pcl::PointCloud<pcl::PrincipalCurvatures>::Ptr curvatures)
{
    pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Gaussian Curvature Viewer"));
    int vp_1, vp_2;

    // 第一个视口:显示原始点云
    viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp_1);
    viewer->setBackgroundColor(0.0, 0.0, 0.0, vp_1);
    viewer->addText("Original PointCloud", 10, 10, "vp1_text", vp_1);
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color_handler(cloud, 255, 0, 0);  // 红色
    viewer->addPointCloud(cloud, cloud_color_handler, "original_cloud", vp_1);

    // 第二个视口:显示法向量与主曲率,同时显示点云
    viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp_2);
    viewer->setBackgroundColor(0.08, 0.08, 0.08, vp_2);
    viewer->addText("Normals and Principal Curvatures", 10, 10, "vp2_text", vp_2);

    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color_handler_2(cloud, 0, 255, 0);  // 绿色
    viewer->addPointCloud(cloud, cloud_color_handler_2, "cloud_with_curvature", vp_2);

    // 添加法向量,控制显示间隔和长度
    viewer->addPointCloudNormals<pcl::PointXYZ, pcl::Normal>(cloud, normals, 20, 0.02, "normals", vp_2);

    // 添加主曲率,控制显示间隔和长度
    viewer->addPointCloudPrincipalCurvatures<pcl::PointXYZ, pcl::Normal>(cloud, normals, curvatures, 10, 0.02, "Curvatures", vp_2);

    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/features/normal_3d.h>
#include <pcl/features/principal_curvatures.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>

using namespace std;

void visualizePointCloudAndGaussianCurvature(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::Normal>::Ptr normals, pcl::PointCloud<pcl::PrincipalCurvatures>::Ptr curvatures);



void visualizePointCloudAndGaussianCurvature(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::Normal>::Ptr normals, pcl::PointCloud<pcl::PrincipalCurvatures>::Ptr curvatures)
{
    pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Gaussian Curvature Viewer"));
    int vp_1, vp_2;

    // 第一个视口:显示原始点云
    viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp_1);
    viewer->setBackgroundColor(0.0, 0.0, 0.0, vp_1);
    viewer->addText("Original PointCloud", 10, 10, "vp1_text", vp_1);
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color_handler(cloud, 255, 0, 0);  // 红色
    viewer->addPointCloud(cloud, cloud_color_handler, "original_cloud", vp_1);

    // 第二个视口:显示法向量与主曲率,同时显示点云
    viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp_2);
    viewer->setBackgroundColor(0.08, 0.08, 0.08, vp_2);
    viewer->addText("Normals and Principal Curvatures", 10, 10, "vp2_text", vp_2);

    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color_handler_2(cloud, 0, 255, 0);  // 绿色
    viewer->addPointCloud(cloud, cloud_color_handler_2, "cloud_with_curvature", vp_2);

    // 添加法向量,控制显示间隔和长度
    viewer->addPointCloudNormals<pcl::PointXYZ, pcl::Normal>(cloud, normals, 20, 0.02, "normals", vp_2);

    // 添加主曲率,控制显示间隔和长度
    viewer->addPointCloudPrincipalCurvatures<pcl::PointXYZ, pcl::Normal>(cloud, normals, curvatures, 10, 0.02, "Curvatures", vp_2);
    
    while (!viewer->wasStopped())
    {
        viewer->spinOnce(100);
        boost::this_thread::sleep(boost::posix_time::microseconds(100000));
    }
}
int main(int argc, char** argv)
{
    // 1. 读取点云数据
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::io::loadPCDFile<pcl::PointXYZ>("bunny.pcd", *cloud);

    // 2. 计算法向量
    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
    pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
    ne.setInputCloud(cloud);              // 设置输入点云
    ne.setSearchMethod(tree);             // 设置搜索方法
    ne.setRadiusSearch(0.03);             // 设置搜索半径
    ne.compute(*normals);                 // 计算法向量

    // 3. 计算主曲率和高斯曲率
    pcl::PrincipalCurvaturesEstimation<pcl::PointXYZ, pcl::Normal, pcl::PrincipalCurvatures> pce;
    pcl::PointCloud<pcl::PrincipalCurvatures>::Ptr curvatures(new pcl::PointCloud<pcl::PrincipalCurvatures>);
    pce.setInputCloud(cloud);             // 设置输入点云
    pce.setInputNormals(normals);         // 设置法向量
    pce.setSearchMethod(tree);            // 设置搜索方法
    pce.setRadiusSearch(0.03);            // 设置搜索半径
    pce.compute(*curvatures);             // 计算主曲率

    // 4. 可视化
    visualizePointCloudAndGaussianCurvature(cloud, normals, curvatures);

    return 0;
}

三、实现效果


原文地址:https://blog.csdn.net/qq_47947920/article/details/142751706

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!