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 floatoperator () (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或其他精细配准方法来进行最后的对齐。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

『 C++ 』海量数据处理

文章目录 &#x1f996; 快速找出海量数据中是否存在该整型数据&#x1f996; 有限内存情况下两个文件(海量query)中找出交集&#x1f996; 海量数据中找出只出现1次的数据&#x1f996; 有限内存情况下两个文件(整型)找出交集&#x1f996; 海量数据中找出出现次数不超过2次的…

挑战杯 YOLOv7 目标检测网络解读

文章目录 0 前言1 yolov7的整体结构2 关键点 - backbone关键点 - head3 训练4 使用效果5 最后 0 前言 世界变化太快&#xff0c;YOLOv6还没用熟YOLOv7就来了&#xff0c;如果有同学的毕设项目想用上最新的技术&#xff0c;不妨看看学长的这篇文章&#xff0c;学长带大家简单的…

5G——小区搜索流程

小区搜索流程 小区搜索目标&#xff1a;读取到SIB1. 小区搜索流程概述&#xff1a;SIB1在PDSCH信道承载&#xff0c;承载SIB1的信道在哪个位置由PDCCH告诉&#xff0c;而PDCCH的基本信息由MIB告诉&#xff0c;MIB信息由广播信道PBCH广播出去&#xff0c;物理信道解调需要解调…

vue3-组合式 API

什么是组合式 API&#xff1f; 组合式 API (Composition API) 是一系列 API 的集合&#xff0c;使我们可以使用函数而不是声明选项的方式书写 Vue 组件。它是一个概括性的术语&#xff0c;涵盖了以下方面的 API&#xff1a; 响应式 API&#xff1a;例如 ref() 和 reactive()&a…

HttpRunner自动化测试之实现参数化传递

参数化实现及重复执行 参数化测试&#xff1a;在接口测试中&#xff0c;为了实现不同组数据对同一个功能模块进行测试&#xff0c;需要准备多组测试数据对模块进行测试的过程。 在httprunner中可以通过如下方式实现参数化&#xff1a; 1、在YAML/JSON 中直接指定参数列表 2、…

【C++】C++入门

关于C是什么 C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的问题&#xff0c;规模较大的程序&#xff0c;需要高度的抽象和建模时&#xff0c;C语言则不合适。为了解决软件危机&#xff0c;20世纪80年代&#xff0c;计算机界提出了OOP(object or…

静态时序分析:SDC约束命令set_clock_latency详解

相关阅读 静态时序分析https://blog.csdn.net/weixin_45791458/category_12567571.html?spm1001.2014.3001.5482 时钟的延迟可以使用set_clock_latency命令设置&#xff0c;这里的时钟延迟包括源延迟(source latency)&#xff0c;即时钟对象到时钟源对象&#xff08;时钟定义…

Linux——网络通信TCP通信常用的接口和tcp服务demo

文章目录 TCP通信所需要的套接字socket()bind()listen()acceptconnect() 封装TCP socket TCP通信所需要的套接字 socket() socket()函数主要作用是返回一个描述符&#xff0c;他的作用就是打开一个网络通讯端口&#xff0c;返回的这个描述符其实就可以理解为一个文件描述符&a…

抖音关键词搜索爬虫,抖音API数据接口,抖音商品详情数据采集

抖音商品API接口抖音关键词搜索抖音直播间小黄车抖店商品数据采集 除了微博&#xff0c;小红书&#xff0c;抖音也是一个巨大的流量池。 除了评论&#xff0c;其实关键词搜索视频是更为常见的一个需求&#xff0c;于是上周末抽空开发了下&#xff0c;完成了 mvp。

数据结构——lesson3单链表介绍及实现

目录 1.什么是链表&#xff1f; 2.链表的分类 &#xff08;1&#xff09;无头单向非循环链表&#xff1a; &#xff08;2&#xff09;带头双向循环链表&#xff1a; 3.单链表的实现 &#xff08;1&#xff09;单链表的定义 &#xff08;2&#xff09;动态创建节点 &#…

【数据结构】链表OJ面试题5《链表的深度拷贝》(题库+解析)

1.前言 前五题在这http://t.csdnimg.cn/UeggB 后三题在这http://t.csdnimg.cn/gbohQ 给定一个链表&#xff0c;判断链表中是否有环。http://t.csdnimg.cn/Rcdyc 给定一个链表&#xff0c;返回链表开始入环的第一个结点。 如果链表无环&#xff0c;则返回 NULLhttp://t.cs…

OpenCV识别人脸案例实战

使用级联函数 基本流程 函数介绍 在OpenCV中&#xff0c;人脸检测使用的是cv2.CascadeClassifier.detectMultiScale()函数&#xff0c;它可以检测出图片中所有的人脸。该函数由分类器对象调用&#xff0c;其语法格式为&#xff1a; objects cv2.CascadeClassifier.detectMul…

vue-进阶语法(四)

目录 v-model原理 v-model应用于组件 sync修饰符 ref 和 $refs&#xff08;重点&#xff09; $nextTick v-model原理 原理&#xff1a;v-model本质上是一个语法糖。例如应用在输入框上&#xff0c;就是 value属性 和 input事件 的合写。 作用&#xff1a;提供数据的双向…

[NSSRound#16 Basic]Web

1.RCE但是没有完全RCE 显示md5强比较&#xff0c;然后md5_3随便传 md5_1M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2&md5_2M%C9h%FF%0E%E3%5C%20%95r%D4w…

ClickHouse--08--SQL DDL 操作

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 SQL DDL 操作1 创建库2 查看数据库3 删除库4 创建表5 查看表6 查看表的定义7 查看表的字段8 删除表9 修改表9.1 添加列9.2 删除列9.3 清空列9.4 给列修改注释9.5 修…

大数据01-导论

零、文章目录 大数据01-导论 1、数据与数据分析 **数据&#xff1a;是事实或观察的结果&#xff0c;是对客观事物的逻辑归纳&#xff0c;是用于表示客观事物的未经加工的原始素材。**数据可以是连续的值&#xff0c;比如声音、图像&#xff0c;称为模拟数据&#xff1b;也可…

【网络安全】什么样的人适合学?该怎么学?

有很多想要转行网络安全或者选择网络安全专业的人在进行决定之前一定会有的问题&#xff1a; 什么样的人适合学习网络安全&#xff1f;我适不适合学习网络安全&#xff1f; 当然&#xff0c;产生这样的疑惑并不奇怪&#xff0c;毕竟网络安全这个专业在2017年才调整为国家一级…

Web 扫描神器:WhatWeb 保姆级教程(附链接)

一、介绍 WhatWeb 是一款用于识别网站技术栈和特征的开源Web扫描工具。它可以自动分析网站的响应并识别出使用的Web框架、CMS、服务器、JavaScript库等技术组件。WhatWeb的目标是通过分析网站的内容&#xff0c;提供有关目标的技术信息&#xff0c;这对于安全测试、漏洞评估和…

Jetpack Compose 第 2 课:布局

点击查看&#xff1a;Jetpack Compose 教程 点击查看&#xff1a;Composetutorial 代码 简介 Jetpack Compose 是用于构建原生 Android 界面的新工具包。它使用更少的代码、强大的工具和直观的 Kotlin API&#xff0c;可以帮助您简化并加快 Android 界面开发。 在本教程中&a…

Quartz---基础

1.概述 Quartz是一个完全由Java编写的开源任务调度框架&#xff0c;通过触发器来设置作业定时运行规则&#xff0c;控制作业的运行时间。Quartz框架的主要核心组件包括调度器、触发器和作业。调度器作为作业的总指挥&#xff0c;触发器作为作业的操作者&#xff0c;而作业则为应…