RANSAC

RANSAC

RANSAC是“RANdom SAmple Consensus(随机抽样一致)”的缩写。它可以从一组包含“局外点”的观测数据集中,通过迭代方式估计数学模型的参数。它是一种不确定的算法——它有一定的概率得出一个合理的结果;为了提高概率必须提高迭代次数。

RANSAC的基本假设是:
(1)数据由“局内点”组成,例如:数据的分布可以用一些模型参数来解释;
(2)“局外点”是不能适应该模型的数据;
(3)除此之外的数据属于噪声。
局外点产生的原因有:噪声的极值;错误的测量方法;对数据的错误假设。
RANSAC也做了以下假设:给定一组(通常很小的)局内点,存在一个可以估计模型参数的过程;而该模型能够解释或者适用于局内点。

##一、示例
一个简单的例子是从一组观测数据中找出合适的2维直线。假设观测数据中包含局内点和局外点,其中局内点近似的被直线所通过,而局外点远离于直线。简单的最小二乘法不能找到适应于局内点的直线,原因是最小二乘法尽量去适应包括局外点在内的所有点。相反,RANSAC能得出一个仅仅用局内点计算出模型,并且概率还足够高。但是,RANSAC并不能保证结果一定正确,为了保证算法有足够高的合理概率,我们必须小心的选择算法的参数。

在这里插入图片描述在这里插入图片描述

##二、概述
RANSAC算法的输入是一组观测数据,一个可以解释或者适应于观测数据的参数化模型,一些可信的参数。
RANSAC通过反复选择数据中的一组随机子集来达成目标。被选取的子集被假设为局内点,并用下述方法进行验证:
1.有一个模型适应于假设的局内点,即所有的未知参数都能从假设的局内点计算得出。
2.用1中得到的模型去测试所有的其它数据,如果某个点适用于估计的模型,认为它也是局内点。
3.如果有足够多的点被归类为假设的局内点,那么估计的模型就足够合理。
4.然后,用所有假设的局内点去重新估计模型,因为它仅仅被初始的假设局内点估计过。
5.最后,通过估计局内点与模型的错误率来评估模型。
这个过程被重复执行固定的次数,每次产生的模型要么因为局内点太少而被舍弃,要么因为比现有的模型更好而被选用。

##三、算法

输入:
data —— 一组观测数据
model —— 适应于数据的模型
n —— 适用于模型的最少数据个数
k —— 算法的迭代次数
t —— 用于决定数据是否适应于模型的阀值
d —— 判定模型是否适用于数据集的数据数目
输出:
best_model —— 跟数据最匹配的模型参数(如果没有找到好的模型,返回null)
best_consensus_set —— 估计出模型的数据点
best_error —— 跟数据相关的估计出的模型错误

iterations = 0
best_model = null
best_consensus_set = null
best_error = 无穷大
while ( iterations < k )
	maybe_inliers = 从数据集中随机选择n个点
  maybe_model = 适合于maybe_inliers的模型参数
  consensus_set = maybe_inliers

  for ( 每个数据集中不属于maybe_inliers的点 )
    if ( 如果点适合于maybe_model,且错误小于t )
    将点添加到consensus_set
  if ( consensus_set中的元素数目大于d )
  已经找到了好的模型,现在测试该模型到底有多好
  better_model = 适合于consensus_set中所有点的模型参数
  this_error = better_model究竟如何适合这些点的度量
    if ( this_error < best_error )
  我们发现了比以前好的模型,保存该模型直到更好的模型出现
  best_model =  better_model
  best_consensus_set = consensus_set
  best_error =  this_error
	增加迭代次数
返回 best_model, best_consensus_set, best_error

四、官方文档

We use RANSAC for global registration. In each RANSAC iteration, ransac_n random points are picked from the source point cloud. Their corresponding points in the target point cloud are detected by querying the nearest neighbor in the 33-dimensional FPFH feature space. A pruning step takes fast pruning algorithms to quickly reject false matches early.

Open3D provides the following pruning algorithms:

  • CorrespondenceCheckerBasedOnDistance checks if aligned point clouds are close (less than the specified threshold).
  • CorrespondenceCheckerBasedOnEdgeLength checks if the lengths of any two arbitrary edges (line formed by two vertices) individually drawn from source and target correspondences are similar. This tutorial checks that ||edgesource||>0.9⋅||edgetarget||||edgesource||>0.9⋅||edgetarget|| and ||edgetarget||>0.9⋅||edgesource||||edgetarget||>0.9⋅||edgesource|| are true.
  • CorrespondenceCheckerBasedOnNormal considers vertex normal affinity of any correspondences. It computes the dot product of two normal vectors. It takes a radian value for the threshold.

Only matches that pass the pruning step are used to compute a transformation, which is validated on the entire point cloud. The core function is registration_ransac_based_on_feature_matching. The most important hyperparameter of this function is RANSACConvergenceCriteria. It defines the maximum number of RANSAC iterations and the confidence probability. The larger these two numbers are, the more accurate the result is, but also the more time the algorithm takes.

We set the RANSAC parameters based on the empirical value provided by [Choi2015].

def execute_global_registration(source_down, target_down, source_fpfh,
                                target_fpfh, voxel_size):
    distance_threshold = voxel_size * 1.5
    print(":: RANSAC registration on downsampled point clouds.")
    print("   Since the downsampling voxel size is %.3f," % voxel_size)
    print("   we use a liberal distance threshold %.3f." % distance_threshold)
    result = o3d.pipelines.registration.registration_ransac_based_on_feature_matching(
        source_down, target_down, source_fpfh, target_fpfh, True,
        distance_threshold,
        o3d.pipelines.registration.TransformationEstimationPointToPoint(False),
        3, [
            o3d.pipelines.registration.CorrespondenceCheckerBasedOnEdgeLength(
                0.9),
            o3d.pipelines.registration.CorrespondenceCheckerBasedOnDistance(
                distance_threshold)
        ], o3d.pipelines.registration.RANSACConvergenceCriteria(100000, 0.999))
    return result
result_ransac = execute_global_registration(source_down, target_down,
                                            source_fpfh, target_fpfh,
                                            voxel_size)
print(result_ransac)
draw_registration_result(source_down, target_down, result_ransac.transformation)
:: RANSAC registration on downsampled point clouds.
   Since the downsampling voxel size is 0.050,
   we use a liberal distance threshold 0.075.
RegistrationResult with fitness=6.726891e-01, inlier_rmse=3.179655e-02, and correspondence_set size of 3202
Access transformation to get result.

参考代码

import open3d as o3d
import numpy as np
import copy


def draw_registration_result(source, target, transformation):
    source_temp = copy.deepcopy(source)  # 由于函数transformand paint_uniform_color会更改点云,
    target_temp = copy.deepcopy(target)  # 因此调用copy.deepcoy进行复制并保护原始点云。
    source_temp.paint_uniform_color([1, 0, 0])  # 点云着色
    target_temp.paint_uniform_color([0, 1, 0])
    source_temp.transform(transformation)
    o3d.io.write_point_cloud("trans_of_source.pcd", source_temp)  # 保存点云
    o3d.visualization.draw_geometries([source_temp, target_temp], width=600, height=600)


def execute_global_registration(source_down, target_down, source_fpfh,
                                target_fpfh, voxel_size):
    distance_threshold = voxel_size * 1.5
    print(":: RANSAC registration on downsampled point clouds.")
    print("   Since the downsampling voxel size is %.3f," % voxel_size)
    print("   we use a liberal distance threshold %.3f." % distance_threshold)
    result = o3d.pipelines.registration.registration_ransac_based_on_feature_matching(
        source_down, target_down, source_fpfh, target_fpfh, True,
        distance_threshold,
        o3d.pipelines.registration.TransformationEstimationPointToPoint(False),
        3, [
            o3d.pipelines.registration.CorrespondenceCheckerBasedOnEdgeLength(
                0.9),
            o3d.pipelines.registration.CorrespondenceCheckerBasedOnDistance(
                distance_threshold)
        ], o3d.pipelines.registration.RANSACConvergenceCriteria(100000, 0.999))
    return result


def preprocess_point_cloud(pcd, voxel_size):
    # 降采样
    pcd_down = pcd.voxel_down_sample(voxel_size)
    pcd_down.estimate_normals(
        o3d.geometry.KDTreeSearchParamHybrid(radius=voxel_size * 2.0,
                                             max_nn=30))
    pcd_fpfh = o3d.pipelines.registration.compute_fpfh_feature(
        pcd_down,
        o3d.geometry.KDTreeSearchParamHybrid(radius=voxel_size * 5.0,
                                             max_nn=100))
    return (pcd_down, pcd_fpfh)


# 体素大小默认0.05
voxel_size = 0.05

source = o3d.io.read_point_cloud("cloud_bin_1.pcd")
target = o3d.io.read_point_cloud("cloud_bin_0.pcd")

source_down, source_fpfh = preprocess_point_cloud(source, voxel_size)
target_down, target_fpfh = preprocess_point_cloud(target, voxel_size)

result_ransac = execute_global_registration(source_down, target_down,
                                            source_fpfh, target_fpfh,
                                            voxel_size)
print(result_ransac)
print(result_ransac.transformation)
draw_registration_result(source, target, result_ransac.transformation)

运行结果

在这里插入图片描述

代码输出的Transformation matrix

在这里插入图片描述

我们利用cloudcompare的fgr进行检验

在这里插入图片描述

cloudcompare fgr求出的transformation matrix是

0.853857636452 -0.150674119592 0.498221188784 0.347479939461
0.015181323513 0.963986754417 0.265515118837 -0.407920837402
-0.520284831524 -0.219148412347 0.825395226479 1.666101574898
0.000000000000 0.000000000000 0.000000000000 1.000000000000

参考

open3d官网

148412347 0.825395226479 1.666101574898
0.000000000000 0.000000000000 0.000000000000 1.000000000000

参考

open3d官网

csdnRanSac

RANSAC(Random Sample Consensus)是一种用于估计数学模型参数的迭代方法,它可以有效地从包含噪声和异常值的数据中找到最佳拟合模型。在C++中,你可以使用不同的库来实现RANSAC算法,如PCL(Point Cloud Library)、CGAL(Computational Geometry Algorithms Library)和OpenCV。 如果你主要处理点云数据,PCL可能是一个不错的选择。PCL是一个功能强大的点云处理库,其中包含了许多用于3D点云处理的算法,包括RANSAC。它提供了一组现成的数据结构和算法,可用于点云滤波、分割、重建等应用中。 如果你需要进行更一般的计算几何任务,CGAL可能更适合你。CGAL是一个计算几何算法库,提供了一系列高效和可靠的算法,包括RANSAC。它支持2D和3D几何计算,并提供了丰富的数据结构和算法。 另外,如果你已经熟悉OpenCV,它也可以作为一个选择。OpenCV是一个广泛使用的计算机视觉库,它提供了许多图像处理和计算几何的函数和算法,包括RANSAC。你可以使用OpenCV的函数来实现RANSAC算法,并根据你的具体需求进行适当的调整。 以下是一个使用PCL库实现RANSAC算法的示例代码: ```cpp #include <iostream> #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/sample_consensus/ransac.h> #include <pcl/sample_consensus/sac_model_plane.h> int main() { // 读取点云数据 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::io::loadPCDFile<pcl::PointXYZ>("input_cloud.pcd", *cloud); // 创建RANSAC对象 pcl::SampleConsensusModelPlane<pcl::PointXYZ>::Ptr model(new pcl::SampleConsensusModelPlane<pcl::PointXYZ>(cloud)); pcl::RandomSampleConsensus<pcl::PointXYZ> ransac(model); ransac.setDistanceThreshold(0.01); // 设置距离阈值 // 执行RANSAC算法 pcl::PointIndices inliers; ransac.computeModel(); ransac.getInliers(inliers); // 输出结果 std::cout << "Inliers: " << inliers.indices.size() << std::endl; return 0; } ``` 这段代码使用PCL库实现了RANSAC算法来拟合点云数据中的平面模型。首先,它读取了一个点云文件(input_cloud.pcd),然后创建了一个RANSAC模型对象,并设置了距离阈值。接下来,它执行RANSAC算法,并获取内点的索引。最后,它输出了内点的数量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值