当前位置: 首页 > article >正文

PCL 计算点云的平均曲率

目录

一、概述

1.1原理

1.2实现步骤

1.3应用场景

二、代码实现

2.1关键函数

2.1.1 法向量计算

1.2 主曲率与平均曲率计算

2.1.3 可视化函数

2.2完整代码

三、实现效果


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

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


一、概述

        点云的平均曲率是表征点云表面局部几何特性的重要指标,反映了表面在某一点的平均弯曲程度。通过计算点云的法向量和主曲率,我们可以进一步得出平均曲率并进行可视化展示。本文介绍如何利用PCL库计算点云的平均曲率,并在可视化窗口中显示原始点云、法向量和曲率信息。

1.1原理

        平均曲率 H 是通过点云的主曲率计算得到的,公式如下:

        平均曲率反映了点云表面在某一点处的局部几何形态,是点云表面平滑度的重要度量。

1.2实现步骤

  1. 读取点云数据:加载待处理的点云数据。
  2. 计算法向量:通过 pcl::NormalEstimation 计算每个点的法向量。
  3. 计算主曲率和平均曲率:通过 pcl::PrincipalCurvaturesEstimation 计算主曲率,并通过公式计算平均曲率。
  4. 可视化:在一个可视化窗口中同时展示原始点云、法向量和主曲率信息。

1.3应用场景

  1. 表面检测与质量控制:检测物体表面不平整区域,识别表面异常。
  2. 3D表面建模:在3D模型重建过程中,平均曲率可帮助识别特征区域。
  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);                  // 计算法向量

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 average_curvature = (k1 + k2) / 2;  // 平均曲率
    avg_curvature_cloud->points[i].curvature = average_curvature;
}

2.1.3 可视化函数

在可视化窗口中同时展示原始点云、法向量、主曲率以及平均曲率:

void visualizePointCloudAndAverageCurvature(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("Average Curvature Viewer"));
    int vp_1, vp_2;
    
    // 创建第一个视口:显示原始点云
    viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp_1);
    viewer->setBackgroundColor(1.0, 1.0, 1.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.98, 0.98, 0.98, vp_2);
    viewer->addText("Normals and Average 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, 2, "normals", vp_2);

    // 添加主曲率
    viewer->addPointCloudPrincipalCurvatures<pcl::PointXYZ, pcl::Normal>(cloud, normals, curvatures, 10, 10, "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 visualizePointCloudAndAverageCurvature(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::Normal>::Ptr normals, pcl::PointCloud<pcl::PrincipalCurvatures>::Ptr curvatures);



void visualizePointCloudAndAverageCurvature(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("Average 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 Average 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. 计算平均曲率
    pcl::PointCloud<pcl::PointXYZ>::Ptr avg_curvature_cloud(new pcl::PointCloud<pcl::PointXYZ>);
    for (size_t i = 0; i < curvatures->size(); ++i) {
        float k1 = curvatures->points[i].pc1;  // 最大曲率
        float k2 = curvatures->points[i].pc2;  // 最小曲率
        float average_curvature = (k1 + k2) / 2;  // 平均曲率
        avg_curvature_cloud->push_back(cloud->points[i]);
        avg_curvature_cloud->points[i].z = average_curvature;  // 用z值来存储曲率信息
    }

    // 5. 可视化
    visualizePointCloudAndAverageCurvature(cloud, normals, curvatures);

    return 0;
}

三、实现效果


http://www.kler.cn/news/338823.html

相关文章:

  • win11远程连接MySQL(linux版),不需安装docker容器
  • 什么是变阻器?
  • 超声波清洗机什么品牌洗眼镜好用?四款高品质眼镜清洗机力荐!
  • 基于Java语言的充电桩平台+云快充协议+充电桩管理后台+充电桩小程序
  • 【Docker】05-Docker部署前端项目
  • 电子摄像头分割系统源码&数据集分享
  • RKMEDIA画面质量调节-QP调节
  • 电脑怎么卸载软件?学会这6个卸载软件技巧就够了(精选)
  • 基于Tensorrt C++ API 构建YOLOV5实现engine以及推理
  • PhpStudy-PHP5.4.45后门漏洞应用程序(C++/base64/winhttp)
  • OmniCorpus数据集:最大(百亿级别)多模态数据集
  • 深入理解C语言中的内存分配函数:malloc、calloc、realloc
  • Modern CMake 简明教程(5)- 安装
  • Redis篇(面试题 - 连环16炮)(持续更新迭代)
  • 【笔记】I/O总结王道强化视频笔记
  • WSL--安装各种软件包
  • 《Linux从小白到高手》进阶实操篇:Linux找回Root用户密码
  • 掌握这17个Python自动化操作,简化你的日常工作流程,提升工作效率!
  • FDS-112 土壤盐分传感器 三针 自带温度补偿功能
  • 【爬虫】网站反debugger、内存爆破以及网站限制开发者工具