PCL从理解到应用【09】 点云特征 | 关键点提取 | 方法汇总

news2024/9/20 21:16:12

前言

在PCL中,有多种方法和函数可以用来提取点云特征,本文介绍关键点提取。

提取点云关键点,本文介绍的方法包括:SIFT、Harris、NARF、ISS和SUSAN。

Harris 提取点云关键点,效果如下图所示:

白色点是原始的点云(兔子),绿色点是Harris提取的点云关键点。

1、SIFT 提取点云关键点

基本原理:

  • SIFT算法的设计目的是在点云中,不同尺度旋转角度下稳定地检测特征点
  • 主要步骤包括:
    1. 构建尺度空间,通过高斯模糊和降采样生成不同尺度的图像。
    2. 在不同尺度图像中计算高斯差分(Difference of Gaussian, DoG),检测极值点。
    3. 对每个极值点进行精确定位,通过滤除低对比度点和边缘响应点,保留稳定的关键点。
    4. 为每个关键点分配主方向,使其具有旋转不变性。
    5. 基于关键点周围的梯度方向和幅值,生成特征描述子。

使用场景:

  • SIFT关键点适用于需要在尺度和旋转变化下保持不变的应用,例如物体识别和点云匹配。

示例代码:

#include <pcl/point_types.h>
#include <pcl/keypoints/sift_keypoint.h>
#include <pcl/io/pcd_io.h>

// 提取SIFT关键点的函数
pcl::PointCloud<pcl::PointWithScale>::Ptr extractSIFTKeypoints(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud) {
    // 创建SIFT关键点检测对象
    pcl::SIFTKeypoint<pcl::PointXYZ, pcl::PointWithScale> sift;

    // 创建KdTree用于加速搜索
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
    sift.setSearchMethod(tree);

    // 设置尺度参数
    // 第一个参数是初始尺度,
    // 第二个参数是尺度的数量,
    // 第三个参数是尺度之间的倍数关系
    sift.setScales(0.01f, 3, 2);

    // 设置最小对比度(用于过滤掉对比度太低的关键点)
    sift.setMinimumContrast(0.0f);

    // 设置输入点云
    sift.setInputCloud(cloud);

    // 创建一个点云对象用于存储关键点
    pcl::PointCloud<pcl::PointWithScale>::Ptr keypoints(new pcl::PointCloud<pcl::PointWithScale>);

    // 计算SIFT关键点
    sift.compute(*keypoints);

    // 返回关键点
    return keypoints;
}

2、Harris 提取点云关键点

基本原理:

  • Harris角点检测器通过计算图像中每个点云的自相关矩阵来找到角点(特征点)。
  • 主要步骤包括:
    1. 计算每个像素点的梯度信息。
    2. 根据梯度信息构建自相关矩阵。
    3. 计算响应函数R,响应函数R的高值表示可能的角点。
    4. 对响应函数进行非极大值抑制,得到角点位置。

使用场景:

  • Harris关键点适用于需要检测点云中局部几何特征显著点的应用,如点云配准和运动检测。

示例代码:

#include <pcl/point_types.h>
#include <pcl/keypoints/harris_3d.h>
#include <pcl/io/pcd_io.h>

// 提取Harris关键点的函数
pcl::PointCloud<pcl::PointXYZI>::Ptr extractHarrisKeypoints(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud) {
    // 创建Harris关键点检测对象
    pcl::HarrisKeypoint3D<pcl::PointXYZ, pcl::PointXYZI> harris;

    // 设置非极大值抑制(用于去除非局部最大值点)
    harris.setNonMaxSupression(true);

    // 设置搜索半径
    harris.setRadius(0.01);

    // 设置输入点云
    harris.setInputCloud(cloud);

    // 创建一个点云对象用于存储关键点
    pcl::PointCloud<pcl::PointXYZI>::Ptr keypoints(new pcl::PointCloud<pcl::PointXYZI>);

    // 计算Harris关键点
    harris.compute(*keypoints);

    // 返回关键点
    return keypoints;
}

3、NARF 提取点云关键点

基本原理:

  • NARF关键点检测器结合点云边界特征法线方向来检测关键点。
  • 主要步骤包括:
    1. 将点云转换为深度图像(Range Image)。
    2. 提取深度图像的边界信息。
    3. 基于边界信息和法线方向,检测具有显著特征的关键点。

使用场景:

  • NARF关键点适用于环境感知和机器人导航等需要高鲁棒性的场景。

示例代码:

#include <pcl/point_types.h>
#include <pcl/range_image/range_image.h>
#include <pcl/keypoints/narf_keypoint.h>
#include <pcl/io/pcd_io.h>

// 提取NARF关键点的函数
pcl::PointCloud<int>::Ptr extractNARFKeypoints(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud) {
    // 设置角度分辨率(以弧度为单位)
    float angular_resolution = pcl::deg2rad(1.0f);

    // 设置坐标系框架
    pcl::RangeImage::CoordinateFrame coordinate_frame = pcl::RangeImage::CAMERA_FRAME;

    // 设置噪声水平
    float noise_level = 0.0;

    // 设置最小范围
    float min_range = 0.0f;

    // 设置边界大小
    int border_size = 1;

    // 创建范围图像对象
    pcl::RangeImage range_image;

    // 从点云创建范围图像
    range_image.createFromPointCloud(*cloud, angular_resolution, pcl::deg2rad(360.0f), pcl::deg2rad(180.0f), Eigen::Affine3f::Identity(), coordinate_frame, noise_level, min_range, border_size);

    // 创建边界提取器对象
    pcl::RangeImageBorderExtractor range_image_border_extractor;

    // 创建NARF关键点检测对象
    pcl::NarfKeypoint narf_keypoint_detector;

    // 设置范围图像边界提取器
    narf_keypoint_detector.setRangeImageBorderExtractor(&range_image_border_extractor);

    // 设置范围图像
    narf_keypoint_detector.setRangeImage(&range_image);

    // 设置支持大小参数
    narf_keypoint_detector.getParameters().support_size = 0.2f;

    // 创建一个点云对象用于存储关键点索引
    pcl::PointCloud<int>::Ptr keypoints_indices(new pcl::PointCloud<int>);

    // 计算NARF关键点
    narf_keypoint_detector.compute(*keypoints_indices);

    // 返回关键点索引
    return keypoints_indices;
}

4、ISS 提取点云关键点

基本原理:

  • ISS关键点检测器通过分析点的局部几何特征来确定关键点。
  • 主要步骤包括:
    1. 计算每个点的局部协方差矩阵。
    2. 通过协方差矩阵的特征值和特征向量,分析局部几何特征。
    3. 根据特征值的显著性和稳定性,选择关键点。

使用场景:

  • ISS关键点适用于点云数据噪声较少,且需要提取稳定几何特征的场景。

示例代码:

#include <pcl/point_types.h>
#include <pcl/keypoints/iss_3d.h>
#include <pcl/io/pcd_io.h>

// 提取ISS关键点的函数
pcl::PointCloud<pcl::PointXYZ>::Ptr extractISSKeypoints(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud) {
    // 创建ISS关键点检测对象
    pcl::ISSKeypoint3D<pcl::PointXYZ, pcl::PointXYZ> iss_detector;

    // 设置显著半径(影响关键点的选择)
    iss_detector.setSalientRadius(0.05);

    // 设置非极大值抑制半径(用于抑制局部非最大值)
    iss_detector.setNonMaxRadius(0.05);

    // 设置两个阈值,用于控制特征值之间的比率
    iss_detector.setThreshold21(0.975); // 阈值21
    iss_detector.setThreshold32(0.975); // 阈值32

    // 设置最小邻居数(用于过滤孤立点)
    iss_detector.setMinNeighbors(5);

    // 设置输入点云
    iss_detector.setInputCloud(cloud);

    // 创建一个点云对象用于存储关键点
    pcl::PointCloud<pcl::PointXYZ>::Ptr keypoints(new pcl::PointCloud<pcl::PointXYZ>);

    // 计算ISS关键点
    iss_detector.compute(*keypoints);

    // 返回关键点
    return keypoints;
}

5、SUSAN 提取点云关键点

基本原理:

  • SUSAN关键点检测器通过分析云点周围的强度距离一致性来检测特征点。
  • 主要步骤包括:
    1. 为每个点定义一个圆形邻域。
    2. 计算邻域内与中心点强度或距离相似的点的数量。
    3. 基于相似点的数量,判断该点是否为特征点。

使用场景:

  • SUSAN关键点适用于需要提取局部特征显著点的应用,如点云处理中的特征检测。

示例代码:

#include <pcl/point_types.h>
#include <pcl/keypoints/susan.h>
#include <pcl/io/pcd_io.h>

// 提取SUSAN关键点的函数
pcl::PointCloud<pcl::PointXYZI>::Ptr extractSUSANKeypoints(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud) {
    // 创建SUSAN关键点检测对象
    pcl::SUSANKeypoint<pcl::PointXYZ, pcl::PointXYZI> susan;

    // 设置搜索半径
    susan.setRadius(0.01);

    // 设置输入点云
    susan.setInputCloud(cloud);

    // 创建一个点云对象用于存储关键点
    pcl::PointCloud<pcl::PointXYZI>::Ptr keypoints(new pcl::PointCloud<pcl::PointXYZI>);

    // 计算SUSAN关键点
    susan.compute(*keypoints);

    // 返回关键点
    return keypoints;
}

6、方法总结

提取点云关键点,本文介绍的方法包括:

  1. SIFT (Scale-Invariant Feature Transform)
  2. Harris Keypoints
  3. NARF (Normal Aligned Radial Feature)
  4. ISS (Intrinsic Shape Signatures)
  5. SUSAN (Smallest Univalue Segment Assimilating Nucleus)

对比一下5种点云关键点算法,如下表格所示:

方法简介特点时间复杂度优点缺点
SIFT基于尺度不变特征变换,检测不同尺度和旋转不变的关键点尺度不变性、旋转不变性在尺度和旋转变化下稳定,对噪声有较强的鲁棒性计算复杂度高,占用内存大
Harris基于自相关矩阵计算角点,检测局部几何特征显著点非极大值抑制检测速度快,能有效检测角点对噪声敏感,缺乏尺度不变性
NARF结合点云的边界特征和法线方向,通过深度图像提取关键点法线和边界信息结合,鲁棒性高对边界和法线特征敏感,适用于环境感知和机器人导航需要生成深度图像,计算复杂度较高
ISS通过分析点的局部几何特征,选择特征值显著且稳定的关键点几何特征分析,特征值比率能检测出稳定的几何特征点,对噪声不敏感计算复杂度较高,在密集点云上效率较低
SUSAN通过分析邻域内与中心点强度或距离相似的点,检测局部特征显著点基于强度或距离一致性计算简单,适用于实时处理对特征点的准确性依赖于参数设置,对不同数据集需要调整参数

7、实践应用——Harris 提取点云关键点

对输入的PLY文件进行Harris特征提取,并分别可视化原图和特征提取后的效果。

代码思路:

  • 包含头文件:包含PCL的点类型、IO操作、可视化和Harris关键点提取的头文件。
  • 提取Harris关键点的函数:定义extractHarrisKeypoints函数,用于从输入点云中提取Harris关键点。
  • 主函数
    • 直接在代码中指定PLY文件的路径。
    • 创建点云对象并读取PLY文件。
    • 调用extractHarrisKeypoints函数提取Harris关键点。
    • 创建PCL可视化对象viewer,设置背景颜色。
    • 添加原始点云和关键点到可视化对象中,并设置关键点的渲染属性。
    • 启动可视化循环,显示原始点云和关键点。

示例代码:

#include <pcl/point_types.h>
#include <pcl/io/ply_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/keypoints/harris_3d.h>
#include <thread> // 添加此头文件
#include <chrono> // 添加此头文件

// 提取Harris关键点的函数
pcl::PointCloud<pcl::PointXYZI>::Ptr extractHarrisKeypoints(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud) {
    // 创建Harris关键点检测对象
    pcl::HarrisKeypoint3D<pcl::PointXYZ, pcl::PointXYZI> harris;
    harris.setNonMaxSupression(true); // 设置非极大值抑制
    harris.setRadius(0.01); // 设置搜索半径
    harris.setInputCloud(cloud); // 设置输入点云

    // 创建一个点云对象用于存储关键点
    pcl::PointCloud<pcl::PointXYZI>::Ptr keypoints(new pcl::PointCloud<pcl::PointXYZI>);

    // 计算Harris关键点
    harris.compute(*keypoints);

    return keypoints;
}

int main(int argc, char** argv) {
    // 指定PLY文件路径
    std::string file_path = "../../bunny/data/bun000.ply"; // 请将此路径替换为你的PLY文件路径

    // 创建点云对象
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());

    // 读取PLY文件
    if (pcl::io::loadPLYFile<pcl::PointXYZ>(file_path, *cloud) == -1) {
        std::cerr << "Couldn't read file " << file_path << std::endl;
        return -1;
    }

    // 提取Harris关键点
    pcl::PointCloud<pcl::PointXYZI>::Ptr keypoints = extractHarrisKeypoints(cloud);

    // 创建PCL可视化对象
    pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));

    // 设置背景颜色为黑色
    viewer->setBackgroundColor(0, 0, 0);

    // 添加原始点云
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color_handler(cloud, 255, 255, 255);
    viewer->addPointCloud(cloud, cloud_color_handler, "original cloud");

    // 添加Harris关键点
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZI> keypoints_color_handler(keypoints, 0, 255, 0);
    viewer->addPointCloud<pcl::PointXYZI>(keypoints, keypoints_color_handler, "keypoints");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, "keypoints");

    // 启动可视化
    // viewer->addCoordinateSystem(1.0);
    // viewer->initCameraParameters();
    while (!viewer->wasStopped()) {
        viewer->spinOnce(100);
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }

    return 0;
}

可视化效果:

白色点是原始的点云(兔子),绿色点是Harris提取的点云关键点。

分享完成~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1974926.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MATLAB预测模型(2)

一、前言 在MATLAB中&#xff0c;进行线性回归、非线性回归以及统计回归预测可以通过多种方法实现&#xff0c;包括使用内置函数和自定义函数。下面&#xff0c;我将分别给出线性回归、非线性回归和基于统计回归进行预测的基本示例代码。 二、实现 1. 线性回归 MATLAB中的poly…

机器人主板维修|ABB机械手主板元器件故障

【ABB机器人电路板故障原因诊断】 针对上述故障现象&#xff0c;我们需要对ABB机器人IO板进行详细的故障诊断。以下是一些可能的故障原因&#xff1a; 1. 元器件老化或损坏&#xff1a;ABB机械手安全面板上的元器件在长期使用过程中可能出现老化、损坏或接触不良等问题&#xf…

PyCharm运行Python的Flask项目时,愚蠢的执行了默认Flask框架默认配置处理

一&#xff1a;问题描述 因为上半年开始学习完python后&#xff0c;开始转人工智能方向的工作内容&#xff0c;所以这半年几乎在攻关python以及人工智能方向的技能&#xff0c;但是我有喜欢用Java的一些开发的爽点。 最近整Flask的框架时发现了一个问题&#xff0c;我就在Fla…

【数据结构算法经典题目刨析(c语言)】反转链表(图文详解)

&#x1f493; 博客主页&#xff1a;C-SDN花园GGbond ⏩ 文章专栏&#xff1a;数据结构经典题目刨析(c语言) 目录 一、题目描述 二、思路分析 三、代码实现 一、题目描述&#xff1a; 二、思路分析 &#xff1a; 通过三个指针n1,n2,n3来实现链表的反转 1.首先初始化 n1为…

IO流相关

1. IO概述 Java中I/O操作主要是指使用java.io包下的内容&#xff0c;进行输入、输出操作。输入也叫做读取数据&#xff0c;输出也叫做作写出数据。 1.1 IO的分类 根据数据的流向分为&#xff1a;输入流和输出流。 输入流 &#xff1a;把数据从其他设备上读取到内存中的流。 …

力扣SQL50 好友申请 II :谁有最多的好友 UNION ALL

Problem: 602. 好友申请 II &#xff1a;谁有最多的好友 &#x1f468;‍&#x1f3eb; 参考题解 功能概述&#xff1a; 该查询统计 RequestAccepted 表中用户&#xff08;作为请求方或接受方&#xff09;出现的总次数&#xff0c;并找出出现次数最多的用户ID。 执行步骤&a…

PHP语言的学习(ctfshow中web入门web93~web104)

PHP语言基础知识&#xff08;超详细&#xff09;_php开发知识-CSDN博客 PHP特性之CTF中常见的PHP绕过-CSDN博客 浅谈PHP代码执行中出现过滤限制的绕过执行方法_php过滤绕过-CSDN博客 php代码审计(适合小白入门)_php审计入门-CSDN博客 什么是PHP&#xff1f; PHP 是一种脚本…

File 类练习

练习1&#xff1a;在当前模块下的aaa文件夹中创建一个a.txt文件。 分析&#xff1a;当前模块下是没有aaa文件夹的&#xff0c;这里我是手动在当前模块下创建了aaa文件夹&#xff0c;然后在指定a.txt的路径&#xff0c;再createNewFile()的。 public class File1 {public stat…

一键重装系统哪个软件好用_2024年一键重装系统工具排行榜

一键重装系统哪个软件好&#xff1f;现在市面上重装软件五花八门&#xff0c;有些网友不知道哪些好用&#xff0c;下面小编就为大家整理几款不错的电脑一键重新系统软件供大家选择&#xff0c;现整理2024年一键重装系统软件排行。 一键重装系统哪个软件好用&#xff1f; 一键重…

如何系统地自学Python?AI的回答让你少走三年弯路!

系统地自学Python是一个循序渐进的过程&#xff0c;需要掌握基础知识、进阶技能以及实践项目。以下是一个详细的自学Python的指南&#xff1a; 一、学习准备<末尾有AI整理的学习资料、电子书籍、实战项目> 了解Python&#xff1a; Python是一种流行的编程语言&#xff…

入门 PyQt6 看过来(案例)22~ 图表案例

​ ​ def showPie(self):"""绘制饼状图"""# &#xff08;1&#xff09;创建图表和视图chart QChart()chart.setTitle(中国高等教育普及率)chart.legend().setAlignment(Qt.AlignmentFlag.AlignLeft)chartView QChartView(self) # 必须有sel…

CookieMaker工作室合作开发C++项目十一:拟态病毒

&#xff08;注&#xff1a;本文章使用了“无标题技术”&#xff09; 一天&#xff0c;我和几个同事&#xff0c;平台出了点BUG&#xff0c;居然给我刷出了千年杀&#xff0c;同事看得瑕疵欲裂&#xff0c;发誓要将我挫骨扬灰—— &#xff08;游戏入口&#xff1a;和平精英31.…

iOS技术之安装nvmnode完整步骤

1.前提 首先电脑里得有brew、git、vscode这些工具, 当然了要用nvm&node肯定是需要这些基本开发工具 2.删除node环境 如果mac里没有安装过node、npm可以无视直接去 3 安装nvm。 为了保证安装nvm能够成功管理node&#xff0c;必须把电脑里之前安装的node全部清理&#xf…

微信小程序css中配置了文字超出一行或两行则显示省略号对纯数字或纯字母或小数点无效的解决办法

配置了文字超出一行或两行则显示省略号对纯数字或纯字母或小数点无效的解决办法 overflow_title{display: -webkit-box;-webkit-line-clamp: 1;-webkit-box-orient: vertical;overflow: hidden;text-overflow: ellipsis; }只需要加上这两行css代码即可 word-break:break-all;…

Spring泛型的依赖注入

泛型依赖注入就是允许我们在使用spring进行依赖注入的同时&#xff0c;利用泛型的优点对代码进行精简&#xff0c;将可重复使用的代码全部放到一个类之中&#xff0c;方便以后的维护和修改。同时在不增加代码的情况下增加代码的复用性。

Go切片深入学习

Go切片专项学习 go切片扩容机制 go1.18 之前&#xff1a; 1.如果期望容量大于当前容量的两倍就会使用期望容量&#xff1b; 2.如果当前切片的长度小于 1024 就会将容量翻倍&#xff1b; 3.如果当前切片的长度大于 1024 就会每次增加 25% 的容量&#xff0c;直到新容量大于期…

基于AI大模型的数据治理

— 01— 什么是大模型&#xff1f; 大模型是指具有数千万甚至数亿参数的深度学习模型。近年来&#xff0c;随着计算机技术和大数据的快速发展&#xff0c;深度学习在各个领域取得了显著的成果&#xff0c;如自然语言处理&#xff0c;图片生成&#xff0c;工业数字化等。为了提…

如何快速下载huggingface大模型

Stackoverflow 上有个AI开发入门的最常见问题 How to download model from huggingface?&#xff0c;回答五花八门&#xff0c;可见下载 huggingface 模型的方法是十分多样的。 其实网络快、稳的话&#xff0c;随便哪种方法都挺好&#xff0c;然而结合国内的网络环境&#xf…

如何给微信小程序商城增加直播购物功能

作者&#xff1a;阿龙 当前&#xff0c;随着抖音、快手、淘宝、拼多多等平台直播卖货的崛起&#xff0c;消费者已经习惯了在直播间购物模式&#xff0c;它可以实现卖家和用户之间的互动&#xff0c;实时解答用户的疑问&#xff0c;让用户可以放心下单购买。东方甄选、董宇辉、李…

LeetCode每日一题_3143.正方形中的最多点数

解题思路&#xff1a;自己&#xff1a;先把points里的点拿来求出坐标系的离原点最远的点&#xff0c;然后根据最远距离新建一个数组&#xff0c;然后把points的点都在新建的数组上标记出来。然后再便利从边长为0的正方形开始&#xff0c;里面是否有重复的标签。但是代码写不出来…