SLAM之数据关联(RANSAC以及其相关的改进/特征匹配)

13 篇文章 29 订阅

本文翻译自维基百科,英文原文地址是:http://en.wikipedia.org/wiki/ransac
    RANSAC是“RANdom SAmple Consensus(随机抽样一致)”的缩写。它可以从一组包含“局外点”的观测数据集中,通过迭代方式估计数学模型的参数。它是一种不确定的算法——它有一定的概率得出一个合理的结果;为了提高概率必须提高迭代次数。该算法最早由Fischler和Bolles于1981年提出。他们使用该算法来解决3D重建中的位置确定问题(Location Determination Problem, LDP)。目前RANSAC算法被广泛用于计算机视觉领域中图像匹配、全景拼接等问题,比如从数对匹配的特征点中求得两幅图片之间的射影变换矩阵,OPENCV实现stitching类时即使用了该算法。 
RANSAC算法与最小二乘法的不同之处主要有以下两点: 
1. 最小二乘法总是使用所有的数据点来估计参数,而RANSAC算法仅使用局内点; 
2. 最小二乘法是一种确定性算法,给定数据集,每一次所得到的模型参数都是相同的;而RANSAC算法是一种随机算法,受迭代次数等的影响,每一次得到的参数一般都不相同。 
3. 一般而言,RANSAC算法先根据一定的准则筛选出局内点和局外点,然后对得到的局内点进行拟合,拟合方法可以是最小二乘法,也可以是其他优化算法,从这个角度来说,RANSAC算法是最小二乘法的扩展。
    RANSAC的基本假设是:
(1)数据由“局内点”组成,例如:数据的分布可以用一些模型参数来解释;
(2)“局外点”是不能适应该模型的数据;
(3)除此之外的数据属于噪声。
    局外点产生的原因有:噪声的极值;错误的测量方法;对数据的错误假设。

    RANSAC也做了以下假设:给定一组(通常很小的)局内点,存在一个可以估计模型参数的过程;而该模型能够解释或者适用于局内点。

算法的求解过程如下:

  1. 首先从数据集中随机选出一组局内点(其数目要保证能够求解出模型的所有参数),计算出一套模型参数。
  2. 用得到的模型去测试其他所有的数据点,如果某点的误差在设定的误差阈值之内,就判定其为局内点,否则为局外点,只保留目前为止局内点数目最多的模型,将其记录为最佳模型。
  3. 重复执行1,2步足够的次数(即达到预设的迭代次数)后,使用最佳模型对应的局内点来最终求解模型参数,该步可以使用最小二乘法等优化算法。
  4. 最后可以通过估计局内点与模型的错误率来评估模型。

本文内容
1 示例
2 概述

3 part1 算法

3 part2算法实例

4 参数
5 优点与缺点
6 应用
7 参考文献
8 外部链接

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

左图:包含很多局外点的数据集       右图:RANSAC找到的直线(局外点并不影响结果)


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


三、part one 算法
    伪码形式的算法如下所示:
输入:
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

    RANSAC算法的可能变化包括以下几种:
    (1)如果发现了一种足够好的模型(该模型有足够小的错误率),则跳出主循环。这样可能会节约计算额外参数的时间。
    (2)直接从maybe_model计算this_error,而不从consensus_set重新估计模型。这样可能会节约比较两种模型错误的时间,但可能会对噪声更敏感。

三、part two算法实例

C++代码实现

Ziv Yaniv以最简单的直线拟合为例,写过一版RANSAC算法的C++实现,没有依赖任何其他库,但该版代码对C++的依赖较重,使用了C++的一些高级数据结构,比如vector, set,在遍历时还使用了递归算法。详细代码可参见RANSAC代码示例 
部分代码及相关注释如下:

//顶层变量定义
vector<double> lineParameters;//存储模型参数
LineParamEstimator lpEstimator(0.5);//误差阈值设置为0.5
vector<Point2D> pointData;//数据点集
int numForEstimate=2;//进行一次参数估计所需的最小样本点数,因为是直线拟合,所以可以直接设为2



//顶层函数的定义
        /**
    * Estimate the model parameters using the maximal consensus set by going over ALL possible
    * subsets (brute force approach).
    * Given: n -  data.size()
    *        k - numForEstimate
    * We go over all n choose k subsets       n!
    *                                     ------------
    *                                      (n-k)! * k!
    * @param parameters A vector which will contain the estimated parameters.
    *                   If there is an error in the input then this vector will be empty.
    *                   Errors are: 1. Less data objects than required for an exact fit.
    * @param paramEstimator An object which can estimate the desired parameters using either an exact fit or a
    *                       least squares fit.
    * @param data The input from which the parameters will be estimated.
    * @param numForEstimate The number of data objects required for an exact fit.
    * @return Returns the percentage of data used in the least squares estimate.
    *
    * NOTE: This method should be used only when n choose k is small (i.e. k or (n-k) are approximatly equal to n)
    *
    *///T是数据的类型,该例子中是二维坐标点,作者自己定义了一个类Point2D来表示;S是参数的类型,此处为双精度double型
template  <class T, class S>
double Ransac<T, S>::compute(std::vector<S> &parameters,ParameterEsitmator<T, S> *paramEstimator,
std::vector<T> &data,
int numForEstimate)
{
    std::vector<T *> leastSquaresEstimateData;
    int numDataObjects = data.size();//数据集的大小,100
    int numVotesForBest = -1;//最佳模型所对应的局内点数目初始化为-1
    int *arr = new int[numForEstimate];//要进行一次计算所需的样本数:2
short *curVotes = new short[numDataObjects];  //one if data[i] agrees with the current model, otherwise zero
 short *bestVotes = new short[numDataObjects];  //one if data[i] agrees with the best model, otherwise zero


     //there are less data objects than the minimum required for an exact fit
    if (numDataObjects < numForEstimate)
        return 0;

//computeAllChoices函数寻找局内点数目最多的模型,并将局内点信息存储在bestVotes数组中,作为最终的模型
    computeAllChoices(paramEstimator, data, numForEstimate,
        bestVotes, curVotes, numVotesForBest, 0, data.size(), numForEstimate, 0, arr);

//将所有的局内点取出,存储在leastSquareEstimateData数组中
for (int j = 0; j<numDataObjects; j++) {
    if (bestVotes[j])
                            leastSquaresEstimateData.push_back(&(data[j]));
    }
//利用所有局内点进行最小二乘参数估计,估计的结果存储在parameters数组中
    paramEstimator->leastSquaresEstimate(leastSquaresEstimateData, parameters);

//释放动态数组
    delete[] arr;
    delete[] bestVotes;
    delete[] curVotes;
//返回值为局内点占所有数据点的比值
    return (double)leastSquaresEstimateData.size() / (double)numDataObjects;
}

//寻找最佳模型的函数定义如下:
//使用递归算法来对数据集进行n!/((n-k)!k!)次遍历
template<class T, class S>
void Ransac<T, S>::computeAllChoices(ParameterEsitmator<T, S> *paramEstimator, std::vector<T> &data, int numForEstimate,
    short *bestVotes, short *curVotes, int &numVotesForBest, int startIndex, int n, int k, int arrIndex, int *arr)
{

    //we have a new choice of indexes
    //每次k从2开始递减到0的时候,表示新取了2个数据点,可以进行一次参数估计
    if (k == 0) {
        estimate(paramEstimator, data, numForEstimate, bestVotes, curVotes, numVotesForBest, arr);
        return;
    }

    //continue to recursivly generate the choice of indexes
    int endIndex = n - k;
    for (int i = startIndex; i <= endIndex; i++) {
        arr[arrIndex] = i;
        computeAllChoices(paramEstimator, data, numForEstimate, bestVotes, curVotes, numVotesForBest,
            i + 1, n, k - 1, arrIndex + 1, arr);//递归调用 
    }

}
//进行参数估计,并根据情况更新当前最佳模型的函数,最佳模型的局内点信息存储在数组bestVotes中,而局内点的数目则是由numVotesForBest存储
//arr数组存储的是本轮两个样本点在data中的索引值
template<class T, class S>
void Ransac<T, S>::estimate(ParameterEsitmator<T, S> *paramEstimator, std::vector<T> &data, int numForEstimate,
    short *bestVotes, short *curVotes, int &numVotesForBest, int *arr)

{
    std::vector<T *> exactEstimateData;
    std::vector<S> exactEstimateParameters;
    int numDataObjects;
    int numVotesForCur;//initalize with -1 so that the first computation will be set to best
    int j;

    numDataObjects = data.size();
    memset(curVotes, '\0', numDataObjects * sizeof(short));//数组中的点全部初始化为局外点
    numVotesForCur = 0;

    for (j = 0; j<numForEstimate; j++)
        exactEstimateData.push_back(&(data[arr[j]]));// 取出两个数据的地址
    paramEstimator->estimate(exactEstimateData, exactEstimateParameters);//用取出的两点来拟合出一组参数

    for (j = 0; j<numDataObjects; j++) {
    //依次判断是否为局内点
        if (paramEstimator->agree(exactEstimateParameters, data[j])) {
            curVotes[j] = 1;
            numVotesForCur++;
        }
    }
    //如果当前模型inlier的数目大于目前最佳模型inlier的数目,则取代目前最佳模型,并更新信息
    if (numVotesForCur > numVotesForBest) {
        numVotesForBest = numVotesForCur;
        memcpy(bestVotes, curVotes, numDataObjects * sizeof(short));
    }
}

RANSAC算法的优缺点

  • 该算法最大的优点就是具有较强的鲁棒性,即使数据集中存在明显错误的数据时,也可以得到较好的模型参数。但是要求局外点的数目不能太多,虽然我没有做过具体的实验,一般而言,局外点所占比例不能超过50%。当然后来又出现了一些改进的RANSAC算法,比如2013年Anders Hast提出的:Optimal RANSAC算法。
  • 同时,RANSAC算法的缺点也是显而易见的,在本文给出的示例中,N个数据点,每次估计需要K个数据点,那么如果要遍历所有的情况,需要进行N!(N−K)!K!N!(N−K)!K!次参数估计过程,十分耗费资源。实际中一般不会全部遍历,而是根据经验设置一个合理的迭代次数,这显然不能保证最终得到的是最佳参数。此外,还涉及到误差阈值的选取问题,增加了算法的复杂度。

四、参数
    我们不得不根据特定的问题和数据集通过实验来确定参数t和d。然而参数k(迭代次数)可以从理论结果推断。当我们从估计模型参数时,用p表示一些迭代过程中从数据集内随机选取出的点均为局内点的概率;此时,结果模型很可能有用,因此p也表征了算法产生有用结果的概率。用w表示每次从数据集中选取一个局内点的概率,如下式所示:
    w = 局内点的数目 / 数据集的数目
    通常情况下,我们事先并不知道w的值,但是可以给出一些鲁棒的值。假设估计模型需要选定n个点,wn是所有n个点均为局内点的概率;1 − wn是n个点中至少有一个点为局外点的概率,此时表明我们从数据集中估计出了一个不好的模型。 (1 − wn)k表示算法永远都不会选择到n个点均为局内点的概率,它和1-p相同。因此,
    1 − p = (1 − wn)k
    我们对上式的两边取对数,得出
    
    值得注意的是,这个结果假设n个点都是独立选择的;也就是说,某个点被选定之后,它可能会被后续的迭代过程重复选定到。这种方法通常都不合理,由此推导出的k值被看作是选取不重复点的上限。例如,要从上图中的数据集寻找适合的直线,RANSAC算法通常在每次迭代时选取2个点,计算通过这两点的直线maybe_model,要求这两点必须唯一。
    为了得到更可信的参数,标准偏差或它的乘积可以被加到k上。k的标准偏差定义为:
    
五、优点与缺点
    RANSAC的优点是它能鲁棒的估计模型参数。例如,它能从包含大量局外点的数据集中估计出高精度的参数。RANSAC的缺点是它计算参数的迭代次数没有上限;如果设置迭代次数的上限,得到的结果可能不是最优的结果,甚至可能得到错误的结果。RANSAC只有一定的概率得到可信的模型,概率与迭代次数成正比。RANSAC的另一个缺点是它要求设置跟问题相关的阀值。
    RANSAC只能从特定的数据集中估计出一个模型,如果存在两个(或多个)模型,RANSAC不能找到别的模型。


六、应用
    RANSAC算法经常用于计算机视觉,例如同时求解相关问题与估计立体摄像机的基础矩阵。


七、参考文献

八、外部链接

1. 经典RANSAC

       由Fischer和Bolles在1981年的文章[1]中首先提出,简要的说经典RANSAC的目标是不断尝试不同的目标空间参数,使得目标函数 最大化的过程。这个过程是随机(Random)、数据驱动(data-driven)的过程。通过反复的随机选择数据集的子空间来产生一个模型估计,然后利用估计出来的模型,使用数据集剩余的点进行测试,获得一个得分,最终返回一个得分最高的模型估计作为整个数据集的模型。

1.1 目标函数

        在经典的RANSAC流程中,目标函数可以被看作:在第k次迭代过程中,在当前变换参数作用下,数据集中满足变换参数的点的个数,也就是在当前变换条件下类内点的个数,而RANSAC就是最大化 的的过程。而判断当前某个点是否为类内需要一个阈值t。

1.2 子集大小

        在迭代的过程中,当前变换参数 θ 的计算需要 中的一个子集  来计算,RANSAC是一个随机从 中采样一个子集,然后对参数“估计-确认”的循环。每一个子集应是一个大小为 的最小采样。所谓最小采样,就是 的大小刚好满足计算 θ 的个数即可。

1.3 循环终止条件

        按照参考文献[1]中的说明,在置信度为的条件下,在循环过程中,至少有一次采样,使得采样出的个点均为类内点,这样才能保证在循环的过程中,至少有一次采样能取得目标函数的最大值。因此,采样次数k应该满足以下条件:

        这里除了置信度外,为子集大小,ε 为类内点在中的比例,其中置信度一般设置为[0.95, 0.99]的范围内。然而在一般情况下,ε 显然是未知的,因此 ε 可以取最坏条件下类内点的比例,或者在初始状态下设置为最坏条件下的比例,然后随着迭代次数,不断更新为当前最大的类内点比例。

        另外一种循环终止条件可以将选取的子集看做为“全部是类内点”或“不全部是类内点”这两种结果的二项分布,而前者的概率为。对于 足够小的情况下,可以将其看作为一种泊松分布,因此,在 次循环中,有 n个“子集全部是类内点”的概率可以表达为:

                                                                                                                        

        λ 表示在 次循环中,“子集全都是类内点”的选取次数的期望。例如在RANSAC中,我们希望在这k次循环中所选子集“没有一个全是类内点”的概率小于某个置信度,即:,以置信度为95%为例,λ约等于3,表示在95%置信度下,在 次循环中,平局可以选到3次“好”的子集。

1.4 判断阈值的选取

       阈值  是判断在当前的获得的参数  θ 下, 中某一点是类内点还是类外点的判断依据。在这里,假定类外点是高斯白噪声,其均值为0,方差为 σ,误差的残差(residuals)符合  维的卡方分布(chi-square)。而误差阈值的选取即可以按照以下的公式计算[2]。
                                                               

        α为置信概率,若 α=0.95,那么一个真实的类内点被误分类为类外点的概率为5%。

         经典RANSAC算法的流程如下图所示:

2. Universal-RANSAC

        经典RANSAC有以下三个主要的局限性:
        (1) 效率:经典方法效率与子集大小、类内点比例以及数据集大小有关,因此在某些场景下效率较低。

        (2) 精度:经典方法计算参数时选取最小子集是从效率的角度考虑,往往得到的是非最佳参数,在应用产参数 之前还需要再经过细化处理。

        (3) 退化:经典方法的目标函数求取最大化的过程基于一个假设:“选取的最小子集中如果有类外点,那么在这种情况下估计的参数获得的目标函数(数据集中点的个数)往往较少“但这种情况在退化发生时有可能是不对的。

         针对经典方法的这几项局限性,有很多改进,在这里提出了一种全局RANSAC(Universal-RANSAC)的结构图,每一种改进方法都可以看做是这种USAC的特例,如下图所示。

2.1 预滤波(Stage 0)

       输入数据集含有 个点,在这一步中,SCRNMSAC[3],用一个一致性滤波器对初始的数据集进行滤波减少数量,然后将数据根据梯度排序。

2.2 最小子集采样(Stage 1)

       对进行采样时,经典算法采用完全随机的方式,这种方式的前提是我们对数据的情况完全不知道,在实际应用中,很多情况对数据的先验知识是了解的,这对减少采样次数,尤其是类内点比例较低的数据集,有很大帮助,以下是几种在最小集采样当中对经典算法进行改进的方法。

  Stage 1.a 采样

2.2.1 NAPSAC[4]

       N-Adjacent points sample consensus(NAPSAC)算法认为:”数据集中,一个类内点与数据集中其他类内点的距离比类外点要近。”在一个n维空间中,假定:将数据集的n维空间看做一个超球面,随着半径的减少,类外点减少的速度比类内点要快(类外点距离球心更远)。这种算法可以描述为:

       a. 中随机选取一个点 ,设定一个半径 r,以 为中心 为半径建立超球面;

       b.  超球面内包裹的点少于最小数据集的个数?返回 a,否则c

       c.   均匀的从球体内取点,直至满足最小集中的个数。

       这种方法对高维、类内点比例低的数据集效果明显,但是容易产生退化,且对于距离都很近的数据集效果差。

2.2.2 PROSAC[5]

       The progressive sample consensus(PROSAC)将点初始集匹配的结果作为排序的依据,使得在采样时根据匹配结果由高到低的得分进行排序,这样最有可能得到最佳参数的采样会较早出现,提高了速度。

2.2.3 GroupSAC[6]

       与NAPSAC类似,GroupSAC认为类内点更加的“相似”,根据某种相似性将数据集中的点分组。以图像匹配为例,分组可以基于光流聚类(optical flow-based clustering)、图像分割等,然后按照PROSAC思想,采样可以从最大的聚类开始,因为这里应该有更高的类内点比例。但是这种方法首先要保证有一种先验知识可以用于分类,还有就是要保证分类算法的有效性和实时性。

  Stage 1.b 采样验证

       经典算法在采样完成后开始进行参数计算,而有的算法在采样完成后加了一步验证采样结果适不适合进行参数计算的步骤。比如参数是计算单映性矩阵(4个点),可以根据chirality constraints 来首先验证采样是否合法。这种验证计算量小,比多余的一次参数计算划算。

2.3 根据最小集产生模型(参数计算)(Stage 2)

  Stage 2.a 模型计算

        在这一步骤根据上一步选取的最小集计算参数,获得模型。

  Stage 2.b 模型验证

        还是利用先验知识,比如点集与圆形匹配,验证时候没必要将数据集中所有的点进行验证,而只是在得到模型(圆)的一个半径范围左右验证即可。

2.4 验证参数(Stage 3)

       传统的方法在得到最小集产生的参数后计算全部集合中满足参数点的个数(目标函数),在此,加两步验证,分为两点:第一,验证当前的模型是否可能获得最大的目标函数。第二,当前模型是非退化的。

  Stage 3.a 可能性验证

2.4.1 T(d,d)测试[5]

        选取远小于数据集综述的 个点作为测试,只有当这 个点全都为类内点时,再对剩余的点进行测试,否则抛弃当前的模型。具体选取办法见论文[5].

2.4.2 Bail-Out测试[7]

        选取集合中的若干点进行测试,若类内点的比例显著低于当前最佳模型类内点的比例,抛弃此模型。

2.4.3 SPRT测试[8,9]

       挨个点测试,表示随机选取一个点符合当前模型的概率(good),为“bad”的概率。根据以下公式,当阈值λ超过某阈值的时候抛弃当前模型。

 

2.4.4 Preemptive测试[10]

       ARRSAC算法[11],首先产生多个模型,而不是产生一个后即对其评价,然后根据选取的一部分子集对所产生的模型按照目标函数得分排序,选取前若干个,做若干轮类似排序,选取最佳模型。  

  Stage 3.b 退化验证

        数据退化的意思是无法提供足够的限制条件产生唯一解。传统RANSAC即没有这种安全的保障。

2.5 模型细化(Stage 4)

        含有噪声的数据集有两个重要特点:1,即使子集中全都是类内点,产生的模型也并不一定适用于数据集中所有的类内点,这个现象增加了迭代的次数;2,最终收敛的RANSAC结果可能受到噪声未完全清理的影响,并不是全局最优的结果。

        第一个影响往往被忽略,因为虽然增加了迭代次数,但是仍然返回的是一个准确的模型。而第二种影响就要增加一种模型细化的后处理。

2.5.1 局部最优化[12]

        Lo-RANSAC,局部最优RANSAC。在迭代过程中,出现当前最优解,进行Lo-RANSAC。一种方法是从返回结果的类内点中再进行采样计算模型,设置一个固定的迭代次数(10-20次)然后选取最优的局部结果作为改进的结果,另一种方法是设置一个优化参数K(2~3),选取结果中判断阈值(t)小于等于Kt 的结果作为优化结果,减小,直至减小至 终止。

2.5.1 错误传播法[13]

       思想与Lo-RANSAC一致,但是更为直接,因为初始的RANSAC结果产生自含有噪声的数据集,因此这个错误“传播”到了最终的模型,协方差可以看做是估计两个数据集关系是一种不确定的信息(而如上所述,判断阈值的计算是固定的)。具体方法参见文献[13]。

2.6 最终方案--USAC-1.0

      最终选取的结果如下图所示:

stage1: 最小集采样方法采用2.2.2节中的PROSAC。

stage3: 模型(参数)验证采用2.4.3的SPRT测试。

stage4: 产生最终模型,采用2.5.1介绍的Lo-RANSAC。

论文翻译自:文献[0]。

----------------------------参考文献---------------------------

[0]  Raguram R, Chum O, Pollefeys M, et al. USAC: A Universal Framework for Random Sample Consensus[J]. Pattern Analysis & Machine Intelligence IEEE Transactions on, 2013, 35(8):2022-2038.

[1] M.A. Fischler and R.C. Bolles, “Random Sample Consensus: A Paradigm for Model Fitting  with Applications to Image Analysis and Automated Cartography,” Comm. ACM, vol. 24, no. 6, pp. 381- 395,1981.

[2] R.I. Hartley and A. Zisserman, Multiple View Geometry in Computer Vision. Cambridge Univ. Press, 2000

[3] T. Sattler, B. Leibe, and L. Kobbelt, “SCRAMSAC: Improving RANSAC’s Efficiency with a Spatial  Consistency Filter,” Proc. 12th IEEE Int’l Conf. Computer Vision, 2009.

[4] D.R. Myatt, P.H.S. Torr, S.J. Nasuto, J.M. Bishop, and R. Craddock,“NAPSAC: High Noise, High  Dimensional Robust Estimation,”Proc. British Machine Vision Conf., pp. 458-467, 2002.

[5] O. Chum and J. Matas, “Matching with PROSAC—Progressive Sample Consensus,” Proc. IEEE Conf. Computer Vision and Pattern Recognition, 2005.

[6] K. Ni, H. Jin, and F. Dellaert, “GroupSAC: Efficient Consensus in the Presence of Groupings,” Proc. 12th IEEE Int’l Conf. Computer Vision, Oct. 2009.

[7] D. Capel, “An Effective Bail-Out Test for RANSAC Consensus Scoring,” Proc. British Machine Vision Conf., 2005.

[8] O. Chum and J. Matas, “Optimal Randomized RANSAC,” IEEE Trans. Pattern Analysis and Machine  Intelligence, vol. 30, no. 8,pp. 1472-1482, Aug. 2008.

[9] J. Matas and O. Chum, “Randomized RANSAC with Sequential Probability Ratio Test,” Proc. 10th IEEE Int’l Conf. Computer Vision,vol. 2, pp. 1727-1732, Oct. 2005.

[10] D. Niste´r, “Preemptive RANSAC for Live Structure and Motion Estimation,” Proc. Ninth IEEE Int’l Conf. Computer Vision, 2003.

[11] R. Raguram, J.-M. Frahm, and M. Pollefeys, “A Comparative Analysis of RANSAC Techniques Leading to Adaptive Real-Time Random Sample Consensus,” Proc. European Conf. Computer Vision, pp. 500- 513. 2008,

[12] O. Chum, J. Matas, and J. Kittler, “Locally Optimized RANSAC,”Proc. DAGM-Symp. Pattern Recognition, pp. 236-243, 2003.

[13] R. Raguram, J.-M Frahm, and M. Pollefeys, “Exploiting Uncertainty in Random Sample Consensus,” Proc. 12th IEEE Int’l Conf. Computer Vision, Oct. 2009.

  • 6
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
以下是一个基于RANSAC改进的GroupSAC算法的示例代码,用于估计平面模型: ``` import numpy as np from sklearn.cluster import DBSCAN from sklearn.decomposition import PCA from sklearn.metrics.pairwise import pairwise_distances from sklearn.utils import check_random_state class GroupSAC: def __init__(self, estimator, min_samples, threshold, max_trials, epsilon, metric='euclidean', random_state=None): self.estimator = estimator self.min_samples = min_samples self.threshold = threshold self.max_trials = max_trials self.epsilon = epsilon self.metric = metric self.random_state = check_random_state(random_state) def fit(self, X, y=None): n_samples = X.shape[0] best_score = -np.inf for i in range(self.max_trials): # 1. 随机选择 min_samples 个点 indices = self.random_state.permutation(n_samples)[:self.min_samples] # 2. 估计模型 model = self.estimator.fit(X[indices]) # 3. 计算当前模型的得分 score = self.score(X, model) if score > best_score: best_score = score best_model = model # 4. 根据得分阈值和 epsilon 聚类 distance_matrix = pairwise_distances(X, model.predict(X).reshape(-1, 1), metric=self.metric).ravel() clusterer = DBSCAN(eps=self.epsilon, min_samples=self.min_samples) clusters = clusterer.fit_predict(distance_matrix.reshape(-1, 1)) # 5. 计算每个簇的得分 pca = PCA(n_components=1) for label in np.unique(clusters): if label == -1: continue cluster_indices = np.where(clusters == label)[0] cluster_X = X[cluster_indices] cluster_distance = distance_matrix[cluster_indices] cluster_X_pca = pca.fit_transform(cluster_X) cluster_inliers = cluster_X[cluster_distance < self.threshold] score = len(cluster_inliers) if score > best_score: best_score = score best_model = self.estimator.fit(cluster_inliers) self.best_model_ = best_model return self def score(self, X, model): distance_matrix = pairwise_distances(X, model.predict(X).reshape(-1, 1), metric=self.metric).ravel() return np.sum(distance_matrix < self.threshold) ``` 该算法的思路是先使用RANSAC随机选择一些点来估计模型,然后根据得分阈值和epsilon将数据点分为若干簇,对每个簇进行拟合,最终选择具有最高得分的模型作为最终模型。其中,得分的计算方式为模型预测出的点到对应样本点的距离小于阈值的数量。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大江东去浪淘尽千古风流人物

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值