当前位置: 首页 > news >正文

Python实现点云随机一致性(RANSAC)配准——粗配准

        今天我们来介绍精配准前的重要步骤——粗配准。大家使用前面ICP和各种变式时,有一个使用单位矩阵代替的部分。对于姿态一致,距离较近的两点云,使用单位矩阵一点问题都没有,可是姿态不对应,哪怕离的很近也会出现配准问题。那么今天我们就来解决这个问题。

        RANSAC(Random Sample Consensus)是一种迭代式鲁棒估计算法,专门用于在强噪声或高离群点比例的数据中估计模型参数。它在点云粗配准、图像拼接、3D 重建等任务中扮演着关键角色。RANSAC算法共可以分为七步(难道是七步诗?),表示如下:

1. 特征提取  
分别在源点云和目标点云中检测关键点,并计算每个点的局部特征描述符(常用 FPFH、SHOT 等)。

2. 初始匹配  
基于特征距离(如欧氏距离或余弦距离)建立两组特征之间的初始对应关系,结果往往包含大量误匹配。

3. 随机采样  
在全部匹配对中随机抽取最小子集,该子集的大小需恰好能唯一确定一个刚体变换(通常 3 对匹配点即可求解 3D 刚体变换)。

4. 模型估计  
利用当前子集计算刚体变换矩阵(旋转 R 与平移 t)。

5. 内点检验  
将剩余所有匹配对按此变换投影,计算投影误差。误差小于给定阈值的匹配被视为内点。

6. 模型评估  
统计当前模型的内点数目,并与历史最优模型比较。若内点更多,则更新最优模型及其参数。

7. 迭代收敛  
重复步骤 3–6,直至达到预设迭代次数或找到满足置信度的模型。迭代次数可根据离群点比例与期望成功率自适应确定。最终输出内点最多的刚体变换,即为源点云到目标点云的配准结果。

        本次实验为了和前面的ICP对应上,依旧使用的是我们的老朋友——兔砸,显示如下:

一、RANSAC算法程序

import copy
import open3d as o3d
import numpy as np# -------------传入点云数据,计算FPFH------------
def FPFH_Compute(pcd):radius_normal = 0.01  # kdtree参数,用于估计法线的半径,pcd.estimate_normals(o3d.geometry.KDTreeSearchParamHybrid(radius=radius_normal, max_nn=30))# 估计法线的1个参数,使用混合型的kdtree,半径内取最多30个邻居radius_feature = 0.02  # kdtree参数,用于估计FPFH特征的半径pcd_fpfh = o3d.pipelines.registration.compute_fpfh_feature(pcd,o3d.geometry.KDTreeSearchParamHybrid(radius=radius_feature,max_nn=100))  # 计算FPFH特征,搜索方法kdtreereturn pcd_fpfh  # 返回FPFH特征# ----------------RANSAC配准--------------------
def execute_global_registration(source, target, source_fpfh,target_fpfh):  # 传入两个点云和点云的特征distance_threshold = 10  # 设定距离阈值# 2个点云,两个点云的特征,距离阈值,一个函数,4,# 一个list[0.9的两个对应点的线段长度阈值,两个点的距离阈值],# 一个函数设定最大迭代次数和最大验证次数result = o3d.pipelines.registration.registration_ransac_based_on_feature_matching(source, target, source_fpfh, target_fpfh, True, distance_threshold,o3d.pipelines.registration.TransformationEstimationPointToPoint(False),4, [o3d.pipelines.registration.CorrespondenceCheckerBasedOnEdgeLength(0.9),o3d.pipelines.registration.CorrespondenceCheckerBasedOnDistance(distance_threshold)], o3d.pipelines.registration.RANSACConvergenceCriteria(4000000, 500))return resultif __name__ == "__main__":# -------------------读取点云数据--------------------source = o3d.io.read_point_cloud("E:/CSDN/规则点云/bunny.pcd")# 原始点云x轴平移0.1,y轴平移0.15,z轴平移0.2,然后加上噪声,最后新的点云作为目标点云# 平移target = copy.deepcopy(source)points = np.asarray(target.points)t = np.array([0.1, 0.15, 0.2])target = target.translate(t, relative=True)  # relative=True 表示“增量”平移# 加噪声mu, sigma = 0, 0.001  # 均值和标准差根据密度调节random_numbers = np.random.normal(mu, sigma, size=(points.shape[0], 3))points += random_numberstarget.points = o3d.utility.Vector3dVector(points)target.paint_uniform_color([0, 1, 0])  # 给目标点云赋予单色# --------------------计算法向量---------------------source.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.01, max_nn=30))target.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.01, max_nn=30))# 复制点云,防止更改source1 = copy.deepcopy(source)target1 = copy.deepcopy(target)# -----------------计算的FPFH---------------source_fpfh = FPFH_Compute(source1)target_fpfh = FPFH_Compute(target1)# ---------------调用RANSAC执行配准------------result_ransac = execute_global_registration(source1, target1,source_fpfh, target_fpfh)print("配准后信息:", result_ransac)  # 输出RANSAC配准信息print("两块点云之间的配准矩阵:", result_ransac.transformation)source2 = copy.deepcopy(source1)source2.transform(result_ransac.transformation)o3d.visualization.draw_geometries([source1, target1],window_name="两点云初始位置",width=1200, height=800,left=50, top=50)o3d.visualization.draw_geometries([source2, target1],window_name="配准后两点云初始位置",width=1200, height=800,left=50, top=50)

二、RANSAC算法结果

        从上面可以看出,经过RANSAC粗配准以后,点云可以很好的对齐。所以说明什么,有时候精配准和粗配准是相对的,不一定需要精配准!

        还有一点,上面的程序运行起来不快,因为是全局寻找特征点并且配准,所以速度就下来了。如果同学们想加快速度,可以使用前面咱们介绍的点云各种滤波,最好使用减少点云个数的。

就酱,下次见^-^

http://www.dtcms.com/a/319555.html

相关文章:

  • 软件测试中,pytest 运行完成后,如何自动发送邮件?
  • vscode 打开设置
  • OpenCV 入门实战:从环境配置到图像 / 视频处理
  • Java 八大经典排序算法全解析
  • Redis持久化存储
  • 2025 年华数杯赛题浅析-助攻快速选题
  • Centos6停止服务后yum改用阿里云
  • Syzkaller实战教程10: MoonShine复现Trace2syz功能演示
  • 手动开发一个TCP服务器调试工具(三):使用 QWidget 构建 TCP 服务控制界面
  • 强化学习详解:从理论到前沿的全面解析
  • 【Redis面试精讲 Day 15】Redis分布式锁实现与挑战
  • C++ 类和对象(2)
  • Kubernetes学习
  • 安卓开发:网络状态监听封装的奥秘
  • 根据浏览器语言判断wordpress访问不同语言的站点
  • 计算机视觉前言-----OpenCV库介绍与计算机视觉入门准备
  • Python 偏函数(functools.partial)详解
  • MySQL ORDER BY 语句详细说明
  • SVG组件
  • 96-基于Flask的酷狗音乐数据可视化分析系统
  • 微信小程序常见功能实现
  • OpenCV 入门教程:开启计算机视觉之旅
  • uwsgi 启动 django 服务
  • Next.js 15 重磅发布:React 19 集成 + 性能革命,开发者必看新特性指南
  • CentOS 7 安装 Anaconda
  • 秋招笔记-8.7
  • Redis的三种特殊类型
  • 硬盘哨兵pe版本 v25.70.6 中文免费版
  • 【R语言】 高清美观的 MaxEnt 刀切图(Jackknife)绘制——提升论文质量
  • 基于Qt的Live2D模型显示以及控制