PCL 点云配准-改进的RANSAC算法(粗配准)

目录

一、概述

1.1原理

1.2实现步骤

1.3应用场景

二、代码实现

2.1关键函数

2.1.1 计算FPFH特征

2.1.2 RANSAC配准

2.1.3 可视化点云

2.2完整代码

三、实现效果


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

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


一、概述

        RANSAC(Random Sample Consensus)是一种通过迭代来估计数据集内数学模型参数的算法,用于处理包含大量离群点的场景。在点云配准中,RANSAC算法可以在未知的条件下配准两个不同视角的点云,找到最佳的匹配变换矩阵。本文结合FPFH(Fast Point Feature Histograms)特征计算和改进的RANSAC算法,实现点云的粗配准。

1.1原理

        FPFH特征描述子是一种局部几何特征,用于提高点云之间的特征匹配精度。它通过计算点与邻域点的法向量关系来描述局部几何特征。FPFH与RANSAC结合,通过特征匹配找到两个点云间的最佳配准矩阵。

RANSAC配准的主要步骤:

  1. 随机选择三个点进行配准计算。
  2. 根据这些点生成初步的配准矩阵。
  3. 使用该矩阵配准整个点云,计算内点数量。
  4. 迭代多次,选择最佳配准结果。

1.2实现步骤

  1. 加载点云数据:从文件中加载源点云和目标点云。
  2. 计算FPFH特征:计算源点云和目标点云的FPFH特征。
  3. RANSAC配准:使用RANSAC算法配准两组点云,得到最佳配准矩阵。
  4. 可视化结果:展示配准前后的点云

1.3应用场景

  1. 多视角的点云配准。
  2. 无序数据点的粗配准。
  3. 机器人视觉中环境地图的构建和配准。

二、代码实现

2.1关键函数

2.1.1 计算FPFH特征

用于计算输入点云的FPFH特征,计算法向量并基于邻域特征计算FPFH描述子。

fpfhFeature::Ptr compute_fpfh_feature(pointcloud::Ptr input_cloud)
{pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());// 法向量估计pointnormal::Ptr normals(new pointnormal);pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> n;n.setInputCloud(input_cloud);    // 设置输入点云n.setNumberOfThreads(8);         // 使用8线程加速计算n.setSearchMethod(tree);         // 设置搜索方法为KD树n.setKSearch(10);                // 设置K近邻点个数n.compute(*normals);             // 计算法向量// FPFH特征估计fpfhFeature::Ptr fpfh(new fpfhFeature);pcl::FPFHEstimationOMP<pcl::PointXYZ, pcl::Normal, pcl::FPFHSignature33> fest;fest.setNumberOfThreads(8);      // 使用8线程并行计算fest.setInputCloud(input_cloud); // 设置输入点云fest.setInputNormals(normals);   // 设置输入法线fest.setSearchMethod(tree);      // 使用KD树搜索fest.setKSearch(10);             // 设置K近邻点个数fest.compute(*fpfh);             // 计算FPFH特征return fpfh;
}

2.1.2 RANSAC配准

该函数使用改进的RANSAC算法,通过特征匹配对两组点云进行配准,并返回配准后的点云。

pointcloud::Ptr ransac_registration(pointcloud::Ptr source, pointcloud::Ptr target, fpfhFeature::Ptr source_fpfh, fpfhFeature::Ptr target_fpfh)
{pcl::SampleConsensusPrerejective<PointT, PointT, pcl::FPFHSignature33> r_sac;r_sac.setInputSource(source);            // 设置源点云r_sac.setInputTarget(target);            // 设置目标点云r_sac.setSourceFeatures(source_fpfh);    // 设置源点云的FPFH特征r_sac.setTargetFeatures(target_fpfh);    // 设置目标点云的FPFH特征r_sac.setCorrespondenceRandomness(5);    // 随机特征对应时使用的邻居数量r_sac.setInlierFraction(0.5f);           // 设置所需的内点比例r_sac.setNumberOfSamples(3);             // 设置采样点的数量r_sac.setSimilarityThreshold(0.1f);      // 设置边缘长度相似度阈值r_sac.setMaxCorrespondenceDistance(1.0f);// 设置最大对应点距离r_sac.setMaximumIterations(100);         // 设置最大迭代次数pointcloud::Ptr aligned(new pointcloud); // 配准后的点云r_sac.align(*aligned);                   // 执行配准pcl::transformPointCloud(*source, *aligned, r_sac.getFinalTransformation()); // 对源点云进行变换cout << "变换矩阵:\n" << r_sac.getFinalTransformation() << endl;            // 输出变换矩阵return aligned;
}

2.1.3 可视化点云

在两个窗口中显示点云,窗口1显示配准前的点云,窗口2显示配准后的点云

void visualize_pcd(pointcloud::Ptr pcd_src, pointcloud::Ptr pcd_tgt, pointcloud::Ptr pcd_final)
{pcl::visualization::PCLVisualizer viewer("registration Viewer");// 创建两个显示窗口并设置背景颜色int v1, v2;viewer.createViewPort(0, 0.0, 0.5, 1.0, v1);viewer.createViewPort(0.5, 0.0, 1.0, 1.0, v2);viewer.setBackgroundColor(255, 255, 255, v1);viewer.setBackgroundColor(255, 255, 255, v2);// 设置点云颜色pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> src_h(pcd_src, 0, 255, 0);   // 源点云绿色pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> tgt_h(pcd_tgt, 255, 0, 0);   // 目标点云红色pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> final_h(pcd_final, 0, 255, 0); // 配准后的点云绿色// 添加点云到显示窗口viewer.addPointCloud(pcd_src, src_h, "source cloud", v1);viewer.addPointCloud(pcd_tgt, tgt_h, "target cloud", v1);viewer.addPointCloud(pcd_tgt, tgt_h, "tgt cloud", v2);viewer.addPointCloud(pcd_final, final_h, "final cloud", v2);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/features/normal_3d_omp.h>
#include <pcl/features/fpfh_omp.h>
#include <boost/thread/thread.hpp>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/registration/sample_consensus_prerejective.h> // RANSAC配准using namespace std;
typedef pcl::PointXYZ PointT;
typedef pcl::PointCloud<pcl::PointXYZ> pointcloud;
typedef pcl::PointCloud<pcl::Normal> pointnormal;
typedef pcl::PointCloud<pcl::FPFHSignature33> fpfhFeature;
typedef pcl::PointCloud<pcl::PointXYZ> pointcloud;// 计算FPFH特征
fpfhFeature::Ptr compute_fpfh_feature(pointcloud::Ptr input_cloud)
{pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());// 法向量估计pointnormal::Ptr normals(new pointnormal);pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> n;n.setInputCloud(input_cloud);    // 设置输入点云n.setNumberOfThreads(8);         // 使用8线程加速计算n.setSearchMethod(tree);         // 设置搜索方法为KD树n.setKSearch(10);                // 设置K近邻点个数n.compute(*normals);             // 计算法向量// FPFH特征估计fpfhFeature::Ptr fpfh(new fpfhFeature);pcl::FPFHEstimationOMP<pcl::PointXYZ, pcl::Normal, pcl::FPFHSignature33> fest;fest.setNumberOfThreads(8);      // 使用8线程并行计算fest.setInputCloud(input_cloud); // 设置输入点云fest.setInputNormals(normals);   // 设置输入法线fest.setSearchMethod(tree);      // 使用KD树搜索fest.setKSearch(10);             // 设置K近邻点个数fest.compute(*fpfh);             // 计算FPFH特征return fpfh;
}// RANSAC配准
pointcloud::Ptr ransac_registration(pointcloud::Ptr source, pointcloud::Ptr target, fpfhFeature::Ptr source_fpfh, fpfhFeature::Ptr target_fpfh)
{pcl::SampleConsensusPrerejective<PointT, PointT, pcl::FPFHSignature33> r_sac;r_sac.setInputSource(source);            // 设置源点云r_sac.setInputTarget(target);            // 设置目标点云r_sac.setSourceFeatures(source_fpfh);    // 设置源点云的FPFH特征r_sac.setTargetFeatures(target_fpfh);    // 设置目标点云的FPFH特征r_sac.setCorrespondenceRandomness(5);    // 随机特征对应时使用的邻居数量r_sac.setInlierFraction(0.5f);           // 设置所需的内点比例r_sac.setNumberOfSamples(3);             // 设置采样点的数量r_sac.setSimilarityThreshold(0.1f);      // 设置边缘长度相似度阈值r_sac.setMaxCorrespondenceDistance(1.0f);// 设置最大对应点距离r_sac.setMaximumIterations(100);         // 设置最大迭代次数pointcloud::Ptr aligned(new pointcloud); // 配准后的点云r_sac.align(*aligned);                   // 执行配准pcl::transformPointCloud(*source, *aligned, r_sac.getFinalTransformation()); // 对源点云进行变换cout << "变换矩阵:\n" << r_sac.getFinalTransformation() << endl;            // 输出变换矩阵return aligned;
}// 可视化
void visualize_pcd(pointcloud::Ptr pcd_src, pointcloud::Ptr pcd_tgt, pointcloud::Ptr pcd_final)
{pcl::visualization::PCLVisualizer viewer("registration Viewer");int v1, v2;viewer.createViewPort(0, 0.0, 0.5, 1.0, v1);viewer.createViewPort(0.5, 0.0, 1.0, 1.0, v2);viewer.setBackgroundColor(255, 255, 255, v1);viewer.setBackgroundColor(255, 255, 255, v2);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> src_h(pcd_src, 0, 255, 0);   // 源点云绿色pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> tgt_h(pcd_tgt, 255, 0, 0);   // 目标点云红色pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> final_h(pcd_final, 0, 255, 0); // 配准后的点云绿色viewer.addPointCloud(pcd_src, src_h, "source cloud", v1);viewer.addPointCloud(pcd_tgt, tgt_h, "target cloud", v1);viewer.addPointCloud(pcd_tgt, tgt_h, "tgt cloud", v2);viewer.addPointCloud(pcd_final, final_h, "final cloud", v2);while (!viewer.wasStopped()){viewer.spinOnce(100);boost::this_thread::sleep(boost::posix_time::microseconds(100000));}
}int main(int argc, char** argv)
{pcl::PointCloud<PointT>::Ptr source(new pcl::PointCloud<PointT>);pcl::io::loadPCDFile("1.pcd", *source);pcl::PointCloud<PointT>::Ptr target(new pcl::PointCloud<PointT>);pcl::io::loadPCDFile("2.pcd", *target);fpfhFeature::Ptr source_fpfh = compute_fpfh_feature(source);fpfhFeature::Ptr target_fpfh = compute_fpfh_feature(target);pointcloud::Ptr align = ransac_registration(source, target, source_fpfh, target_fpfh);visualize_pcd(source, target, align);return 0;
}

三、实现效果

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

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

相关文章

FlinkCDC 实现 MySQL 数据变更实时同步

文章目录 1、基本介绍2、代码实战2.1、数据源准备2.2、代码实战2.3、数据格式 1、基本介绍 Flink CDC 是 Apache Flink 提供的一个功能强大的组件&#xff0c;用于实时捕获和处理数据库中的数据变更。可以实时地从各种数据库&#xff08;如MySQL、PostgreSQL、Oracle、MongoDB…

【图论】(一)图论理论基础与岛屿问题

图论理论基础与岛屿问题 图论理论基础深度搜索&#xff08;dfs&#xff09;广度搜索&#xff08;bfs&#xff09;岛屿问题概述 岛屿数量岛屿数量-深搜版岛屿数量-广搜版 岛屿的最大面积孤岛的总面积沉没孤岛建造最大人工岛水流问题岛屿的周长 图论理论基础 这里仅对图论相关核…

java学习--集合(大写五.5)

5.collection子接口&#xff1a;Set 5.1Set及其实现类特点 java.util.Collection:存储一个一个的数据 子接口&#xff1a;Set:存储无序的、不可重复的数据(高中学习的集合) 1&#xff09;HashsSet主要实现类 底层使用的是HashMap&#xff0c;即使用数组单向链表红黑树结构进行…

netron安装(windows linux)

目录 netron简介 不同操作系统的安装方式 linux windows mac系统 netron简介 netron可视化工具&#xff0c;是一个可以清晰的看到神经网络模型的每一层的输入输出&#xff0c;网络总体的架构&#xff0c;而且支持各种不同网络框架&#xff0c;简单好用。 效果如下所示 不…

【视频笔记】408新增知识点信号——里昂视频

文章目录 **2.信号****3.信号的实现**4.信号的处理**①忽略信号****②执行信号的默认操作****③捕获井处理信号**几个Linux支持的典型信号&#xff1a; **5.信号的产生**① **通过终端按键(键盘)产生信号**例如&#xff0c;CtrlC发送2号信号SIGINT、Ctrl\发送3号信号SIGQUIT② …

爬虫逆向-js进阶

1.作用域和闭包 //作用域 // var a 3 // // function test(a){ // var a 1; // console.log(函数内部,a) // } // test(2) // // console.log(a)//闭包 // function jiami(){ // function encrypt(){ // console.log(在这里进行加密了) // } // p…

五个必备的高清无水印视频素材库推荐

做抖音、短视频创作的朋友都知道&#xff0c;优质的素材往往决定了作品能否获得更多关注。如果你还不知道在哪里下载高清无水印的视频素材&#xff0c;不用担心&#xff01;今天为你推荐5个高品质的视频素材库&#xff0c;助你轻松创作出爆款视频。 蛙学网 是国内领先的视频素材…

Mysql常用sql语句与刷题知识点

目录 1. 常用sql2. 刷题知识点 1. 常用sql #查询MySQL中所有的数据库 SHOW DATABASES; #查询当前正在使用的数据库 SELECT DATABASE();#普通创建&#xff08;创建已经存在的数据库会报错&#xff09; CREATE DATABASE 数据库名称; #创建并判断&#xff08;该数据库不存在才创建…

2.html编辑器介绍

html编辑器介绍 HTML 编辑器推荐 理论上我们可以使用记事本进行html编码和开发&#xff0c;但是在实际开发html页面的时候&#xff0c;使用一些专业的开发工具可以使我们更加快速和高效的进行开发&#xff0c;下面介绍几种开发工具&#xff1a; VS Code&#xff1a;https://…

006_django基于Python的二手房源信息爬取与分析2024_l77153d4

目录 系统展示 开发背景 代码实现 项目案例 获取源码 博主介绍&#xff1a;CodeMentor毕业设计领航者、全网关注者30W群落&#xff0c;InfoQ特邀专栏作家、技术博客领航者、InfoQ新星培育计划导师、Web开发领域杰出贡献者&#xff0c;博客领航之星、开发者头条/腾讯云/AW…

【uniapp】实现触底加载数据

前言&#xff1a;实现界面触底数据加载。后端接口得支持翻页传参&#xff08;本案例使用django&#xff09; 1、后端接口 1.1 封装翻页公共方法standardPagination.py # -*- coding: utf-8 -*- # Time : 2024/10/15 13:15 # Author : super # File : standardPaginat…

全托自闭症教育,关注孩子每个细节

原文文章&#xff1a;http://www.zibizhengwang.com/page37.html 自闭症&#xff0c;这一复杂的神经发育障碍&#xff0c;影响着无数孩子的成长与未来。然而&#xff0c;在广州&#xff0c;有一座特别的灯塔——星贝育园自闭症儿童寄宿制学校&#xff0c;它不仅照亮了自闭症儿…

SpringBoot使用esayExcel根据模板导出excel

1、依赖 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.3</version></dependency> 2、模板 3、实体类 package com.skybird.iot.addons.productionManagement.qualityTesting…

配置MAC地址安全

概述 MAC地址安全配置是确保网络设备和通信安全的重要措施&#xff0c;通过限制、监控和管理设备的物理地址来防止未授权访问和潜在的网络威胁。以下是对MAC地址安全的概述&#xff1a; 基本概念 定义&#xff1a;MAC地址&#xff08;Media Access Control Address&#xff09…

Jenkins整合Docker实现CICD自动化部署(若依项目)

前期准备 提前准备好jenkins环境 并且jenkins能使用docker命令&#xff0c;并且已经配置好了jdk、node、maven环境&#xff0c;我之前写了安装jenkins的博客&#xff0c;里面讲得比较详细&#xff0c;推荐用我这种方式安装 docker安装jenkins&#xff0c;并配置jdk、node和m…

CEP 复杂事件处理引擎进阶:股票中高频 CTA 策略实现与并行回测

在 CEP 复杂事件处理引擎入门&#xff1a;初级高频量价因子策略的实现 中&#xff0c;我们详细介绍了 CEP 引擎和它的一些关键概念&#xff0c;如复杂事件和事件监听器等。随后又通过两个初级的 CEP 引擎使用案例介绍了创建并运行一个最简单结构的 CEP 引擎所需的步骤和模块&am…

骨传导耳机哪个牌子最好?五大高口碑骨传导耳机揭秘!

骨传导耳机作为一种创新的音频设备&#xff0c;通过振动头骨直接将声音传递到内耳&#xff0c;不仅为用户提供了全新的听音体验&#xff0c;还能在保持环境音的情况下享受音乐&#xff0c;特别适合户外运动和日常通勤。然而&#xff0c;在众多品牌和型号中选择最适合自己的骨传…

人工智能正在扼杀云计算的可持续性

可持续性曾是公共云计算中备受推崇的优势。企业和云提供商大肆宣扬他们的绿色计划&#xff0c;推广采用可再生能源的数据中心&#xff0c;以减少碳足迹。 近几个月来&#xff0c;这个话题已悄然淡出人们的视线。罪魁祸首是什么&#xff1f;对人工智能功能的无限需求正在推动云…

为何云渲染成为3D设计的首选?效率解析

在3D设计领域&#xff0c;建模和渲染是两个不可或缺的步骤。3D建模软件如3ds Max让设计师能够创造出精美的三维模型&#xff0c;而渲染则是将这些模型转化为逼真图像或动画的过程。 渲染的重要性在于&#xff0c;它能够直观地展示设计的最终效果&#xff0c;使得设计师能够及时…

MongoDB未授权访问

mongodb未授权访问漏洞 复现 MongoDB[//]: # (忙够DB)是一种流行的开源文档数据库管理系统&#xff08;DBMS&#xff09;&#xff0c;基于分布式文件存储的数据库属于NoSQL数据库的一种。 开启MongoDB服务时不添加任何参数时,默认是没有权限验证的 登录的用户可以通过默认端口…