VFH特征的使用(一)

一、SHOT特征描述符可视化

C++

#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/normal_3d_omp.h>
#include <pcl/registration/correspondence_estimation.h>
#include <boost/thread/thread.hpp>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/registration/transformation_estimation_svd.h> 
#include <pcl/features/3dsc.h>
#include <pcl/keypoints/sift_keypoint.h>
#include <pcl/features/vfh.h>
using namespace std;

namespace pcl
{
    template<>
    struct SIFTKeypointFieldSelector<PointXYZ>
    {
        inline float
            operator () (const PointXYZ& p) const
        {
            return p.z;
        }

    };
}

typedef pcl::PointCloud<pcl::PointXYZ> pointcloud;
typedef pcl::PointCloud<pcl::Normal> pointnormal;
typedef pcl::PointCloud<pcl::VFHSignature308> VFHFeature;

VFHFeature::Ptr compute_pfh_feature(pointcloud::Ptr input_cloud, pcl::search::KdTree<pcl::PointXYZ>::Ptr tree)
{

    pointnormal::Ptr normals(new pointnormal);
    pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> n;
    n.setInputCloud(input_cloud);
    n.setNumberOfThreads(6);
    n.setSearchMethod(tree);
    n.setKSearch(10);
    n.compute(*normals);


    pcl::PointCloud<pcl::VFHSignature308>::Ptr vfh_fe_vfh(new pcl::PointCloud<pcl::VFHSignature308>);
    pcl::VFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::VFHSignature308> vfh;
    vfh.setInputCloud(input_cloud);
    vfh.setInputNormals(normals);
    vfh.setSearchMethod(tree);
    vfh.compute(*vfh_fe_vfh);
    return vfh_fe_vfh;



}

void extract_keypoint(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr& keypoint)
{
    pcl::PointCloud<pcl::PointWithScale> result;
    const float min_scale = 5.f;
    const int n_octaves = 3;
    const int n_scales_per_octave = 15;
    const float min_contrast = 0.01f;
    pcl::SIFTKeypoint<pcl::PointXYZ, pcl::PointWithScale> sift;
    sift.setInputCloud(cloud);
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
    sift.setSearchMethod(tree);
    sift.setScales(min_scale, n_octaves, n_scales_per_octave);
    sift.setMinimumContrast(min_contrast);
    sift.compute(result);
    copyPointCloud(result, *keypoint);

}

int main(int argc, char** argv)
{
    pointcloud::Ptr source_cloud(new pointcloud);
    pointcloud::Ptr target_cloud(new pointcloud);
    pcl::io::loadPCDFile<pcl::PointXYZ>("pcd/pig_view1.pcd", *source_cloud);
    pcl::io::loadPCDFile<pcl::PointXYZ>("pcd/pig_view2.pcd", *target_cloud);

    pcl::PointCloud<pcl::PointXYZ>::Ptr s_k(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr t_k(new pcl::PointCloud<pcl::PointXYZ>);
    extract_keypoint(source_cloud, s_k);
    extract_keypoint(target_cloud, t_k);


    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
    VFHFeature::Ptr source_pfh = compute_pfh_feature(s_k, tree);
    VFHFeature::Ptr target_pfh = compute_pfh_feature(t_k, tree);
    pcl::registration::CorrespondenceEstimation<pcl::VFHSignature308, pcl::VFHSignature308> crude_cor_est;
    boost::shared_ptr<pcl::Correspondences> cru_correspondences(new pcl::Correspondences);
    crude_cor_est.setInputSource(source_pfh);
    crude_cor_est.setInputTarget(target_pfh);
    crude_cor_est.determineCorrespondences(*cru_correspondences);
    Eigen::Matrix4f Transform = Eigen::Matrix4f::Identity();
    pcl::registration::TransformationEstimationSVD<pcl::PointXYZ, pcl::PointXYZ, float>::Ptr trans(new pcl::registration::TransformationEstimationSVD<pcl::PointXYZ, pcl::PointXYZ, float>);

    trans->estimateRigidTransformation(*source_cloud, *target_cloud, *cru_correspondences, Transform);



    boost::shared_ptr<pcl::visualization::PCLVisualizer>viewer(new pcl::visualization::PCLVisualizer("v1"));
    viewer->setBackgroundColor(0, 0, 0);
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>target_color(target_cloud, 255, 0, 0);
    viewer->addPointCloud<pcl::PointXYZ>(target_cloud, target_color, "target cloud");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "target cloud");
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>input_color(source_cloud, 0, 255, 0);
    viewer->addPointCloud<pcl::PointXYZ>(source_cloud, input_color, "input cloud");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "input cloud");
    viewer->addCorrespondences<pcl::PointXYZ>(s_k, t_k, *cru_correspondences, "correspondence");
    while (!viewer->wasStopped())
    {
        viewer->spinOnce(100);
        boost::this_thread::sleep(boost::posix_time::microseconds(100000));
    }


    return 0;
}

关键代码解析:

    pcl::PointCloud<pcl::VFHSignature308>::Ptr vfh_fe_vfh(new pcl::PointCloud<pcl::VFHSignature308>);
    pcl::VFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::VFHSignature308> vfh;
    vfh.setInputCloud(input_cloud);
    vfh.setInputNormals(normals);
    vfh.setSearchMethod(tree);
    vfh.compute(*vfh_fe_vfh);
  1. pcl::PointCloud<pcl::VFHSignature308>::Ptr vfh_fe_vfh(new pcl::PointCloud<pcl::VFHSignature308>);:这行代码定义了一个指向 pcl::PointCloud<pcl::VFHSignature308> 类型的智能指针 vfh_fe_vfh,用于存储计算得到的VFH描述符。

  2. pcl::VFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::VFHSignature308> vfh;:这行代码创建了一个VFH估计器对象 vfh,用于计算VFH描述符。参数说明如下:

    • pcl::PointXYZ:输入点云的点类型,这里使用的是三维坐标点 PointXYZ
    • pcl::Normal:输入点云的法线类型,用于计算VFH描述符时需要输入点云的法线信息。
    • pcl::VFHSignature308:VFH描述符的类型,这里使用的是308维的VFH描述符。
  3. vfh.setInputCloud(input_cloud);:设置输入点云。input_cloud 是指向输入点云的指针或智能指针,其中包含了点的三维坐标信息。

  4. vfh.setInputNormals(normals);:设置输入法线。normals 是指向输入点云法线的指针或智能指针,其中包含了点云的法线信息。

  5. vfh.setSearchMethod(tree);:设置搜索方法。tree 是指向用于邻域搜索的搜索树对象的指针或智能指针。这个搜索树用于查找每个点的邻域以计算其VFH描述符。

  6. vfh.compute(*vfh_fe_vfh);:计算VFH描述符。这行代码会使用输入的点云和法线信息,以及设置的搜索方法,来计算每个点的VFH描述符,并将结果存储在 vfh_fe_vfh 中。

参数设置的影响如下:

  • 输入点云的质量和分辨率会直接影响到计算得到的VFH描述符的准确性。
  • 输入法线的准确性和一致性对VFH描述符的计算也有很大影响。
  • 搜索方法的选择会影响计算VFH描述符时的邻域搜索效率和准确性,不同的搜索方法可能适用于不同场景下的点云数据。

确保输入数据的准确性和适用性,并根据实际情况选择合适的参数设置,可以得到高质量的VFH描述符。

结果:

我把上面的图片转了个向,可以清楚的发现只有一条对应线 

 

由于VFH(视点特征直方图)是一种全局描述符,它为整个点云生成单一的描述子,这与pcl::SampleConsensusInitialAlignment需要源点云和特征点之间一对一对应的要求不匹配。使用VFH时,你只会得到一个全局特征向量,这意味着不适用于那些需要点对点对应关系的方法。 

可以采用的某些策略:

  1. 使用VFH进行预筛选: 如果有多个目标点云,可以使用VFH描述子来快速筛选出与源点云最相似的目标点云,然后再使用局部特征进行精确配准。这种方法在数据库搜索或者配准多个点云时很有用。

  2. 结合局部特征: 对于每个点云,你可以计算VFH描述子,用于全局配准的粗略定位。随后,对于每个点云,你也计算局部特征描述子,如FPFH,用于精细配准。你可以先用VFH找到大致的配准位置,然后用FPFH做为局部搜索的依据,两者相结合可以提高配准的精度。

  3. 多模态数据融合: 如果你有额外的传感器数据,比如RGB颜色信息,可以考虑将这些信息融入到配准过程中。这种情况下,你可以使用颜色信息来增加点云之间的匹配可能性。

  4. 使用VFH进行快速筛选后的模板匹配: 在已知模板的情况下,可以使用VFH描述子来快速缩小搜索范围,找到最有可能的匹配目标。这种快速筛选可以大幅度减少后续计算量。一旦筛选到合适的候选模板,就可以使用ICP或其他精细配准方法来进行最后的对齐。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软件测试项目测试报告总结

测试计划概念&#xff1a;就在软件测试工作实施之前明确测试对象&#xff0c;并且通过资源、时间、风险、测试范围和预算等方面的综合分析和规划&#xff0c;保证有效的实施软件测试。 需求挖掘的6个方面&#xff1a; 1、输入方面 2、处理方面 3、结果输出方面 4、性能需求…

C语言学习day15:数组强化训练

题目一&#xff1a; 称体重&#xff1a;分别给10个值&#xff0c;来获得最大值 思路&#xff1a; 定义数组&#xff0c;给数组内赋10个值第一个下标的值与第二个下标的值进行比较定义max&#xff0c;将比较得来的较大的值赋值给max一直比较直到比较到最后一个下标&#xff0…

ubuntu22.04-磁盘管理-虚拟机动态扩容-系统monitor

文章目录 1.虚拟机2.ubuntu设置3.命令查看4.系统资源管理器1.虚拟机 关闭ubuntu22.04,然后修改虚拟机设置,如下图所示: 修改容量 2.ubuntu设置 搜索打开disks,如下图所示: 选择目标磁盘,选择调整大小到目标大小即可。

萝卜大杂烩 | 把微信接入ChatGPT,变成聊天机器人竟然这么简单!(一起来尝试吧~)

本文来源公众号“萝卜大杂烩”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;把微信接入ChatGPT&#xff0c;变成聊天机器人竟然这么简单&#xff01; 最近的 ChatGPT 又再次火热起来了&#xff0c;各种周边工具也是层出不穷&…

离谱!用ChatGPT进行审稿!

离谱&#xff01;用ChatGPT进行审稿&#xff01; 关注微信公众号: DeepGoAI 在这个信息爆炸的时代&#xff0c;AI已经跑到了学术会议的后台&#xff0c;偷偷摸摸地开始“帮忙”审稿了&#xff01;&#x1f916; 最近&#xff0c;一位教授的LinkedIn动态可谓是火了一把&#xf…

蜂蜜器实验-驱动代码测试

一. 简介 上一篇文章实现了蜂鸣器驱动代码&#xff0c;实现关闭蜂鸣器与打开功能。文章地址如下&#xff1a; 蜂鸣器驱动代码完善-CSDN博客 本文对所实现的蜂鸣器驱动代码进行测试。 二. 蜂鸣器驱动代码测试 1. 准备应用程序 这里应用程序还使用 前面实现所使用的Led应用…

2.18 day5 C++

以下是一个简单的比喻&#xff0c;将多态概念与生活中的实际情况相联系:比喻:动物园的讲解员和动物表演 想象一下你去了一家动物园&#xff0c;看到了许多不同种类的动物&#xff0c;如狮子、大象、猴子等。现在&#xff0c;动物园里有一位讲解员&#xff0c;他会为每种动物表演…

【C++初阶】值得一刷的字符串string相关oj题

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…

Visual Studio+C#实现信道与信息率失真函数

1. 要求 设计一款信道与信息率失真函数计算系统&#xff0c;要求如下&#xff1a; 系统能够通过输入的转移概率矩阵计算对称以及非对称离散无记忆信道的信道容量系统能够通过输入的概率分布以及失真矩阵来计算与信息率失真函数有关的相关参数&#xff0c;例如Dmin&#xff0c…

【初始RabbitMQ】发布订阅的实现

发布确认原理 生产者将信道设置成 confirm 模式&#xff0c;一旦信道进入 confirm 模式&#xff0c;所有在该信道上面发布的消息都将会被指派一个唯一的 ID(从 1 开始)&#xff0c;一旦消息被投递到所有匹配的队列之后&#xff0c;broker 就会发送一个确认给生产者(包含消息的…

Java并发之死锁详解

(/≧▽≦)/~┴┴ 嗨~我叫小奥 ✨✨✨ &#x1f440;&#x1f440;&#x1f440; 个人博客&#xff1a;小奥的博客 &#x1f44d;&#x1f44d;&#x1f44d;&#xff1a;个人CSDN ⭐️⭐️⭐️&#xff1a;传送门 &#x1f379; 本人24应届生一枚&#xff0c;技术和水平有限&am…

拿捏c语言指针(中)

前言 书接上回 拿捏c语言指针&#xff08;上&#xff09; 此篇主要讲解的是指针与数组之间的爱恨情仇&#xff0c;跟着我的脚步一起来看看吧~ 创造不易&#xff0c;可以帮忙点点赞吗 如有差错&#xff0c;欢迎指出 理解数组名 数组名是首元素地址 例外 1.sizeof&#xff0…

【SQL注入】小白手把手入门SQL注入1-数据库基础

前言 本文以SQL注入为核心&#xff0c;讲解MySQL数据库的基本知识&#xff0c;和在SQL注入过程中可能会用到的部分重要语法。 什么是数据库 数据库是“按照数据结构来组织、存储和管理数据的仓库”。是一个长期存储在计算机内的、有组织的、可共享的、统一管理的大量数据的集…

【电路笔记】-感抗

感抗 文章目录 感抗1、概述2、感抗示例13、通过 LR 串联电路的交流电源4、感抗示例25、交流电感器的功率三角形线圈的感抗取决于所施加电压的频率,因为电抗与频率成正比。 1、概述 感抗是电感线圈的一种特性,它抵抗通过它的交流电 (AC) 的变化,类似于电阻中对抗直流电 (DC)…

LCR 127. 跳跃训练【简单】

LCR 127. 跳跃训练 题目描述&#xff1a; 今天的有氧运动训练内容是在一个长条形的平台上跳跃。平台有 num 个小格子&#xff0c;每次可以选择跳 一个格子 或者 两个格子。请返回在训练过程中&#xff0c;学员们共有多少种不同的跳跃方式。 结果可能过大&#xff0c;因此结果…

OpenAI超级视频模型Sora技术报告解读,虚拟世界涌现了

昨天白天&#xff0c;「现实不存在了」开始全网刷屏。 「我们这么快就步入下一个时代了&#xff1f;Sora简直太炸裂了」。 「这就是电影制作的未来」&#xff01; 谷歌的Gemini Pro 1.5还没出几个小时的风头&#xff0c;天一亮&#xff0c;全世界的聚光灯就集中在了OpenAI的So…

php 函数(方法)、日期函数、static关键字

php 函数、日期函数 1. php函数2. 日期函数3. static 1. php函数 函数是一段可重复使用的代码块&#xff0c;可以将一系列操作封装起来&#xff0c;使代码更加模块化、可维护和可重用&#xff0c;来大大节省我们的开发时间和代码量&#xff0c;提高编程效率。 <?php// …

基于SpringBoot+WebSocket+Spring Task的前后端分离外卖项目-订单管理(十七)

订单管理 1. Spring Task1.1 介绍1.2 cron表达式1.3 入门案例1.3.1 Spring Task使用步骤1.3.2 代码开发1.3.3 功能测试 2.订单状态定时处理2.1 需求分析2.2 代码开发2.3 功能测试 3. WebSocket3.1 介绍3.2 入门案例3.2.1 案例分析3.2.2 代码开发3.2.3 功能测试 4. 来单提醒4.1 …

167基于matlab的根据《液体动静压轴承》编写的有回油槽径向静压轴承的程序

基于matlab的根据《液体动静压轴承》编写的有回油槽径向静压轴承的程序&#xff0c;可显示承载能力、压强、刚度及温升等图谱.程序已调通&#xff0c;可直接运行。 167 显示承载能力、压强、刚度及温升 (xiaohongshu.com)https://www.xiaohongshu.com/explore/65d212b200000000…

【uCore 操作系统】1. 应用程序与基本执行环境

文章目录 【 1. 代码框架简述 】1.1 OS 是怎么跑起来的&#xff1f;1.1.1 qemu 的作用1.1.2 rustsbi.bin 的作用 1.2 qemu 是怎么跑起来的&#xff1f;1.3 OS 文件夹1.3.1 kernel.ld1.3.2 entry.S1.3.3 main.c1.3.4 sbi.c 1.4 bootloader 文件夹 【 2. makefile 和 qemu 】2.1 …