点云模板匹配

        点云模板匹配是一种在点云数据中寻找特定形状或模式的方法。它通常用于计算机视觉和三维图像处理中,可以应用于物体识别、姿态估计、场景分析等任务。点云模板匹配的基本思想是将一个称为模板的小点云形状与输入的大点云进行匹配,以找到最佳的对应关系。通常,模板是由已知的目标对象或感兴趣的形状提取得到的。

以下是一般的点云模板匹配流程:

  1. 提取模板:从点云中选择一个目标对象或形状,提取出其特征或描述子作为模板。
  2. 预处理:对输入的大点云进行预处理,例如滤波、重采样、去噪等操作,以减少噪声和优化数据质量。
  3. 特征提取:为输入点云和模板点云提取特征或描述子。这些特征可以包括形状特征、几何属性、法线方向、表面曲率等。
  4. 匹配:使用匹配算法(如最近邻搜索、迭代最近点、ICP等)通过比较特征或描述子来寻找最佳的匹配。
  5. 评估与筛选:根据匹配得分或距离,对匹配结果进行评估并筛选出最佳的匹配结果。
  6. 可视化和应用(可选):可以将匹配结果可视化或应用于其他任务,如目标识别、姿态估计等。

        需要注意的是,点云模板匹配的性能受到许多因素的影响,如点云质量、噪声、特征选择、算法选择等。在实际应用中,可能需要尝试不同的方法和参数来获得最佳的匹配结果。

代码实现

#include <limits>
#include <fstream>
#include <vector>
#include <Eigen/Core>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/filters/passthrough.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/features/normal_3d.h>
#include <pcl/features/fpfh.h>
#include <pcl/registration/ia_ransac.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/search/impl/search.hpp>typedef pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> PCLHandler;class FeatureCloud {
public:typedef pcl::PointCloud<pcl::PointXYZ> PointCloud;typedef pcl::PointCloud<pcl::Normal> SurfaceNormals;typedef pcl::PointCloud<pcl::FPFHSignature33> LocalFeatures;typedef pcl::search::KdTree<pcl::PointXYZ> SearchMethod;FeatureCloud() :search_method_xyz_(new SearchMethod),normal_radius_(0.02f),feature_radius_(0.02f) {}~FeatureCloud() {}// 处理给定的点云voidsetInputCloud(PointCloud::Ptr xyz) {xyz_ = xyz;processInput();}// 加载并处理给定PCD文件中的点云voidloadInputCloud(const std::string& pcd_file) {xyz_ = PointCloud::Ptr(new PointCloud);pcl::io::loadPCDFile(pcd_file, *xyz_);processInput();}// 获取指向点云的指针PointCloud::PtrgetPointCloud() const {return (xyz_);}// 获取指向三维曲面法线的点云的指针SurfaceNormals::PtrgetSurfaceNormals() const {return (normals_);}// 获取指向特征描述点云的指针LocalFeatures::PtrgetLocalFeatures() const {return (features_);}protected:// 计算表面法线和局部特征voidprocessInput() {computeSurfaceNormals();computeLocalFeatures();}// 计算表面法线voidcomputeSurfaceNormals() {// 创建表面法向量normals_ = SurfaceNormals::Ptr(new SurfaceNormals);// 计算表面法向量pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> norm_est;norm_est.setInputCloud(xyz_);norm_est.setSearchMethod(search_method_xyz_);norm_est.setRadiusSearch(normal_radius_);norm_est.compute(*normals_);}// 计算局部特征描述子/*** 根据表面法向量 计算本地特征描述*/voidcomputeLocalFeatures() {features_ = LocalFeatures::Ptr(new LocalFeatures);pcl::FPFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::FPFHSignature33> fpfh_est;fpfh_est.setInputCloud(xyz_);fpfh_est.setInputNormals(normals_);fpfh_est.setSearchMethod(search_method_xyz_);fpfh_est.setRadiusSearch(feature_radius_);fpfh_est.compute(*features_);}private:// 点云数据PointCloud::Ptr xyz_;SurfaceNormals::Ptr normals_;LocalFeatures::Ptr features_; // 快速点特征直方图 Fast Point Feature HistogramSearchMethod::Ptr search_method_xyz_; // KDTree方法查找邻域// 参数float normal_radius_;float feature_radius_;
};class TemplateAlignment {
public:// 用于存储对齐结果的结构struct Result {// 匹配分数float fitness_score;// 转换矩阵Eigen::Matrix4f final_transformation;EIGEN_MAKE_ALIGNED_OPERATOR_NEW};TemplateAlignment() :min_sample_distance_(0.05f),max_correspondence_distance_(0.01f * 0.01f),nr_iterations_(500) {// 初始化随机采样一致性(SAC-IA)算法中的参数sac_ia_.setMinSampleDistance(min_sample_distance_);sac_ia_.setMaxCorrespondenceDistance(max_correspondence_distance_);sac_ia_.setMaximumIterations(nr_iterations_);}~TemplateAlignment() {}// 将给定的点云设置为模板将与之对齐的目标void setTargetCloud(FeatureCloud& target_cloud) {target_ = target_cloud;// 设置输入target点云sac_ia_.setInputTarget(target_cloud.getPointCloud());// 设置特征targetsac_ia_.setTargetFeatures(target_cloud.getLocalFeatures());}// 将给定点云添加到模板点云列表中void addTemplateCloud(FeatureCloud& template_cloud) {templates_.push_back(template_cloud);}// 将给定的模板点云与setTargetCloud()指定的目标对齐// 对齐的核心代码void align(FeatureCloud& template_cloud, TemplateAlignment::Result& result) {// 设置输入源sac_ia_.setInputSource(template_cloud.getPointCloud());// 设置特征源sac_ia_.setSourceFeatures(template_cloud.getLocalFeatures());pcl::PointCloud<pcl::PointXYZ> registration_output;sac_ia_.align(registration_output);// 根据最远相应距离计算匹配分数result.fitness_score = (float)sac_ia_.getFitnessScore(max_correspondence_distance_);// 获取最终转换矩阵result.final_transformation = sac_ia_.getFinalTransformation();}// 将addTemplateCloud设置的所有模板点云与setTargetCloud()指定的目标对齐void alignAll(std::vector<TemplateAlignment::Result, Eigen::aligned_allocator<Result> >& results) {results.resize(templates_.size());for (size_t i = 0; i < templates_.size(); ++i) {align(templates_[i], results[i]);}}// 将所有模板点云与目标点云对齐,以找到具有最佳对齐分数的模板云int findBestAlignment(TemplateAlignment::Result& result) {// 将所有模板与目标点云对齐std::vector<Result, Eigen::aligned_allocator<Result> > results;alignAll(results);// 找到最合适的模板float lowest_score = std::numeric_limits<float>::infinity();int best_template = 0;for (size_t i = 0; i < results.size(); ++i) {const Result& r = results[i];if (r.fitness_score < lowest_score) {lowest_score = r.fitness_score;best_template = (int)i;}}// 输出最佳匹配result = results[best_template];return (best_template);}private:// 模板云及其将要对齐的目标的列表std::vector<FeatureCloud> templates_;FeatureCloud target_;// 随机采样一致性(SAC-IA)算法注册例程及其参数pcl::SampleConsensusInitialAlignment<pcl::PointXYZ, pcl::PointXYZ, pcl::FPFHSignature33> sac_ia_;float min_sample_distance_;float max_correspondence_distance_;int nr_iterations_;
};/*** 对齐对象模板集合到一个示例点云* 通过直通滤波框定范围(得到感兴趣区域)* 将感兴趣区域进行降采样(提高模板匹配效率)*/
int main(int argc, char** argv) 
{// 加载对象模板std::vector<FeatureCloud> object_templates;object_templates.resize(0);// 加载特征云FeatureCloud template_cloud;template_cloud.loadInputCloud("G:/vsdata/PCLlearn/PCDdata/bun0.pcd");object_templates.push_back(template_cloud);// 加载目标点云pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::PCDReader reader;reader.read("G:/vsdata/PCLlearn/PCDdata/bun0.pcd", *cloud);// 移除离群点const float depth_limit = 1.0;pcl::PassThrough<pcl::PointXYZ> pass;pass.setInputCloud(cloud);pass.setFilterFieldName("z");pass.setFilterLimits(0, depth_limit);pass.filter(*cloud);// 降采样点云, 减少计算量// 定义体素大小 5mmconst float voxel_grid_size = 0.005f;pcl::VoxelGrid<pcl::PointXYZ> vox_grid;vox_grid.setInputCloud(cloud);// 设置叶子节点的大小lx, ly, lzvox_grid.setLeafSize(voxel_grid_size, voxel_grid_size, voxel_grid_size);//vox_grid.filter (*cloud); // Please see this http://www.pcl-developers.org/Possible-problem-in-new-VoxelGrid-implementation-from-PCL-1-5-0-td5490361.htmlpcl::PointCloud<pcl::PointXYZ>::Ptr tempCloud(new pcl::PointCloud<pcl::PointXYZ>);vox_grid.filter(*tempCloud);cloud = tempCloud;// 保存滤波&降采样后的点云图pcl::io::savePCDFileBinary("pass_through_voxel.pcd", *tempCloud);std::cout << "pass_through_voxel.pcd saved" << std::endl;// 对齐到目标特征点云FeatureCloud target_cloud;target_cloud.setInputCloud(cloud);// 设置TemplateAlignment输入TemplateAlignment template_align;for (size_t i = 0; i < object_templates.size(); i++) {FeatureCloud& object_template = object_templates[i];// 添加模板点云template_align.addTemplateCloud(object_template);}// 设置目标点云template_align.setTargetCloud(target_cloud);std::cout << "findBestAlignment" << std::endl;// 查找最佳模板对齐方式// 核心代码TemplateAlignment::Result best_alignment;int best_index = template_align.findBestAlignment(best_alignment);const FeatureCloud& best_template = object_templates[best_index];// 打印匹配度分数(小于0.00002的值是好的)printf("Best fitness score: %f\n", best_alignment.fitness_score);printf("Best fitness best_index: %d\n", best_index);// 打印旋转矩阵和平移向量Eigen::Matrix3f rotation = best_alignment.final_transformation.block<3, 3>(0, 0);Eigen::Vector3f translation = best_alignment.final_transformation.block<3, 1>(0, 3);Eigen::Vector3f euler_angles = rotation.eulerAngles(2, 1, 0) * 180 / M_PI;printf("\n");printf("    | %6.3f %6.3f %6.3f | \n", rotation(0, 0), rotation(0, 1), rotation(0, 2));printf("R = | %6.3f %6.3f %6.3f | \n", rotation(1, 0), rotation(1, 1), rotation(1, 2));printf("    | %6.3f %6.3f %6.3f | \n", rotation(2, 0), rotation(2, 1), rotation(2, 2));printf("\n");cout << "yaw(z) pitch(y) roll(x) = " << euler_angles.transpose() << endl;printf("\n");printf("t = < %0.3f, %0.3f, %0.3f >\n", translation(0), translation(1), translation(2));// 保存对齐的模板以进行可视化pcl::PointCloud<pcl::PointXYZ> transformed_cloud;// 将模板中保存的点云图进行旋转矩阵变换,把变换结果保存到transformed_cloudpcl::transformPointCloud(*best_template.getPointCloud(), transformed_cloud, best_alignment.final_transformation);//pcl::io::savePCDFileBinary("output.pcd", transformed_cloud);pcl::visualization::PCLVisualizer viewer("example");// 设置坐标系系统viewer.addCoordinateSystem(0.5, "cloud", 0);// 设置背景色viewer.setBackgroundColor(0.05, 0.05, 0.05, 0); // Setting background to a dark grey// 旋转后的点云rotated --------------------------------pcl::PointCloud<pcl::PointXYZ>::Ptr t_cloud(&transformed_cloud);PCLHandler transformed_cloud_handler(t_cloud, 255, 255, 255);viewer.addPointCloud(t_cloud, transformed_cloud_handler, "transformed_cloud");// 设置渲染属性(点大小)viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "transformed_cloud");// 目标点云target --------------------------------PCLHandler target_cloud_handler(cloud, 255, 100, 100);viewer.addPointCloud(cloud, target_cloud_handler, "target_cloud");// 设置渲染属性(点大小)viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "target_cloud");// 模板点云template --------------------------------PCLHandler template_cloud_handler(cloud, 100, 255, 255);viewer.addPointCloud(best_template.getPointCloud(), template_cloud_handler, "template_cloud");// 设置渲染属性(点大小)viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "template_cloud");while (!viewer.wasStopped()) {viewer.spinOnce();}return (0);
}

结果输出 

pass_through_voxel.pcd saved
findBestAlignment
Best fitness score: 0.000008
Best fitness best_index: 0|  1.000 -0.020 -0.007 |
R = |  0.020  0.999  0.026 ||  0.007 -0.027  1.000 |yaw(z) pitch(y) roll(x) =   1.17069 -0.385805  -1.52169t = < 0.000, 0.000, 0.002 >

实现效果 

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

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

相关文章

OCR让点读笔如虎添翼

点读笔是一种智能学习工具&#xff0c;它可以通过识别文字来提供相应的语音或图像反馈。在实现文字识别功能时&#xff0c;点读笔通常会借助OCR&#xff08;Optical Character Recognition&#xff0c;光学字符识别&#xff09;技术。下面将详细介绍点读笔如何利用OCR技术实现文…

SMOS数据处理,投影变换,‘EPSG:6933‘转为‘EPSG:4326‘

在处理SMOS数据时&#xff0c;遇到了读取nc数据并存为tif后&#xff0c;影像投影无法改变&#xff0c;因此全球数据无法重叠。源数据的投影为EPSG:6933&#xff0c;希望转为EPSG:4326。 解决代码。 python import os import netCDF4 as nc import numpy as np from osgeo impo…

水库大坝除险加固安全监测系统解决方案

一、系统背景 为贯彻落实《办公厅关于切实加强水库除险加固和运行管护工作的通知》&#xff08;〔2021〕8号&#xff09;要求&#xff0c;完成“十四五”小型病险水库除险加固、雨水情测报和大坝安全监测设施建设任务&#xff0c;规范项目管理&#xff0c;消除安全隐患&#xf…

【通信系列 5 -- HTTPS 介绍】

文章目录 1.1 HTTPS链接网址1.1.1 HTTPS 产生背景1.1.2 HTTPS工作内容1.1.3 SSL/TLS1.1.4 TLS 的命名规范1.1.5 TLS 加密算法1.1.6 分组模式1.1.7 摘要算法1.1.8 非对称加密1.1.9 CA认证 1.2 openssl1.2.1 RSA 签名验签 1.1 HTTPS链接网址 HTTP 是一种 超文本传输协议(Hyperte…

c#设计模式-行为型模式 之 中介者模式

&#x1f680;简介 又叫调停模式&#xff0c;定义一个中介角色来封装一系列对象之间的交互&#xff0c;使原有对象之间的耦合松散&#xff0c;且可以独立地改变它们之间的交互。 从下右图中可以看到&#xff0c;任何一个类的变 动&#xff0c;只会影响的类本身&#xff0c;以及…

198、RabbitMQ 的核心概念 及 工作机制概述; Exchange 类型 及 该类型对应的路由规则

JMS 也是一种消息机制 AMQP ( Advanced Message Queuing Protocol ) 高级消息队列协议 ★ RabbitMQ的核心概念 Connection&#xff1a; 代表客户端&#xff08;包括消息生产者和消费者&#xff09;与RabbitMQ之间的连接。 Channel&#xff1a; 连接内部的Channel。 Exch…

Git基础使用

Git基础使用 1、git的本质2 Gitlab账号申请、免密设置2.1 申请Gitlab账号2.2 免密设置2.2.1 公钥及私钥路径2.2.2 免密设置 3、常用命令3.1 git全局配置信息3.2 初始化项目3.3 拉取项目 将日常笔记记录上传&#xff0c;方便日常使用翻阅。 1、git的本质 git对待数据更像是一个快…

k8s修改集群IP--重置集群

原来IP地址 192.168.10.138 k8s-master 192.168.10.139 k8s-node1 192.168.10.140 k8s-node2 新IP地址 192.168.10.148 k8s-master 192.168.10.149 k8s-node1 192.168.10.150 k8s-node2 cp -Rf /etc/kubernetes/ /etc/kubernetes-bak pki 证书目录保留下来&#xff1a; rm -rf …

【设计模式】使用原型模式完成业务中“各种O”的转换

文章目录 1.原型模式概述2.浅拷贝与深拷贝2.1.浅拷贝的实现方式2.2.深拷贝的实现方式 3.结语 1.原型模式概述 原型模式是一种非常简单易懂的模型&#xff0c;在书上的定义是这样的&#xff1a; Specify the kinds of objects to create using a prototypical instance,and cre…

几种预训练模型微调方法和peft包的使用介绍

文章目录 微调方法Lora(在旁边添加训练参数)Adapter&#xff08;在前面添加训练参数&#xff09;Prefix-tuning&#xff08;在中间添加训练参数&#xff09;Prompt tuning PEFTPEFT 使用PeftConfigPeftModel保存和加载模型 微调方法 现流行的微调方法有&#xff1a;Lora,promp…

基于Java+SpringBoot+Vue民宿管理系统的设计与实现 前后端分离【Java毕业设计·文档报告·代码讲解·安装调试】

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

Linux基本指令(1)

Linux基本指令&#xff08;1&#xff09; 1.ls指令1.1ls的用法 2. pwd指令3.cd指令3.1 cd3.2补充内容3.3 cd - 指令3.4 cd ~ 指令 4. touch指令4.1stat指令 5.mkdir 指令6.rmdir/rm指令6.1补充内容 7.man指令8.nano 指令9.cat指令10 cp指令11 mv指令12 echo指令12.1 > 输出重…

[CSAWQual 2019]Web_Unagi - 文件上传+XXE注入(XML编码绕过)

[CSAWQual 2019]Web_Unagi 1 解题流程1.1 分析1.2 解题2 思考总结1 解题流程 这篇博客讲了xml进行编码转换绕过的原理:https://www.shawroot.cc/156.html 1.1 分析 页面可以上传,上传一句话php失败,点击示例发现是xml格式,那么就是XXE注入了 点击about得到flag位置: Fla…

【数据结构-字符串 四】【字符串识别】字符串转为整数、比较版本号

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【字符串转换】&#xff0c;使用【字符串】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为&…

redis-6.2.7 集群安装3主3从

因为资源有限准备了3 台 服务器&#xff0c;先查看防火墙的端口是否开放&#xff0c;如果没有开放先开放端口我使用的 6379 和 6380 这两个端口 所以将这两个端口放开。去redis 官网下载redis 安装包。下载地址 &#xff1a; redis 安装包下载 3. 安装redis 上传上去之后 3 台…

4年测试经验,面试却突破不了20K,真是太卷了····

先说一个插曲&#xff1a;上个月我有同学在深圳被裁员了&#xff0c;和我一样都是软件测试&#xff0c;不过他是平安外包&#xff0c;所以整个组都撤了&#xff0c;他工资和我差不多都是14K。 现在IT互联网已经比较寒冬&#xff0c;特别是软件测试&#xff0c;裁员先裁测试&am…

IOday3作业

#include <head.h> int get_filePerrmison(mode_t mode)//获取文件权限 {char per[] "rwx";for(int i0;i<9;i){if((mode&(0400>>i))0){putchar(-);continue;}putchar(per[i%3]);}} int get_fileType(mode_t m) //获取文件类型 {switch(m&S_IF…

【ComfyUI】MacBook Pro 安装(Intel 集成显卡)

文章目录 环境概述配置pip镜像配置pip代理git配置&#xff08;选配&#xff09;下载comfyUI代码创建、激活虚拟环境下载依赖安装torchvision启动comfyUI为什么Mac不支持CUDA&#xff0c;即英伟达的显卡&#xff1f;安装Intel工具包 环境 显卡&#xff1a;Intel Iris Plus Grap…

快速学习微服务保护框架--Sentinel

学习一个框架最好的方式就是查看官方地址,sentinel是国内阿里巴巴公司的,官网更方便官网 官网 微服务保护框架 Sentinel 1.初识Sentinel 1.1.雪崩问题及解决方案 1.1.1.雪崩问题 微服务中&#xff0c;服务间调用关系错综复杂&#xff0c;一个微服务往往依赖于多个其它微…

[Mono Depth/3DOD]单目3D检测基础

1.数据增强 图像放缩和裁剪后&#xff0c;相机内参要做相应变化 import random def random_scale(image, calib, scale_range(0.8, 1.2)):scale random.uniform(*scale_range)width, height image.sizeimage image.resize((int(width * scale), int(height * scale)))cali…