RANSAC LMedS 详细分析

RANSAC的经典步骤是

1. 随机采样

2. 计算模型参数

3. 阈值分类inlier outlier

4. 迭代2. 3.步直至获得符合阈值的最优解

5. 精确优化模型参数(LM算法迭代优化)


RANSAC的函数接口 参照opencv来说主要需要3-4个参数(第四个不是必须的)

1. 误差阈值ransacThreshold:区分inlier和outliner的依据

2. 置信度confidence:设置之后代表RANSAC采样n次过程中会出现(至少一次)采样点数据集中的点都为内点的概率

这个值设置的太大,会增加采样次数。太小,会使结果不太理想。一般取0.95-0.99

3. 最大采样迭代次数maxIters:为了防止一直在采样计算

4.*最大精细迭代次数refineIters:在采样之后,选取最优解。可以增加精确优化,比如使用LM算法获得更优解。


以上4个参数,有三个是经验值。其中最大采样迭代次数maxIters是可以有数值解的。

在RANSAC计算中,在已经采样计算之后,可以根据inlier num 和 outlier num求得一个更准确的maxIters


这里先列出一个等式:

1 − p = (1 − wn)k                           (1)

其中

p 表示置信度confidence

w 表示数据集中outlier占的比例

n 表示采样点数

k 表示需要迭代采样的最少次数

1 − w表示采样一次,n个点中至少有一个outlier的概率

(1 − wn)表示采样k次,n个点中至少有一个outlier的概率

因为p为采样k次,能有至少一次n个点都是inlier的概率

所以(1 − p)(1 − wn)k相等时,k 为需要迭代采样的最少次数

下面是k的解析解:

                                (2)


关于这个部分的实现 opencv中代码如下

        for( iter = 0; iter < niters; iter++ )
        {
            int i, nmodels;
            if( count > modelPoints )
            {
                bool found = getSubset( m1, m2, ms1, ms2, rng, 10000 );
                if( !found )
                {
                    if( iter == 0 )
                        return false;
                    break;
                }
            }

            nmodels = cb->runKernel( ms1, ms2, model );
            if( nmodels <= 0 )
                continue;
            CV_Assert( model.rows % nmodels == 0 );
            Size modelSize(model.cols, model.rows/nmodels);

            for( i = 0; i < nmodels; i++ )
            {
                Mat model_i = model.rowRange( i*modelSize.height, (i+1)*modelSize.height );
                int goodCount = findInliers( m1, m2, model_i, err, mask, threshold );

                if( goodCount > MAX(maxGoodCount, modelPoints-1) )
                {
                    std::swap(mask, bestMask);
                    model_i.copyTo(bestModel);
                    maxGoodCount = goodCount;
                    niters = RANSACUpdateNumIters( confidence, (double)(count - goodCount)/count, modelPoints, niters );
                }
            }
        }

可以看到在采样迭代的环节中,最大迭代次数niters是动态更新的。在循环内,会被修改。

int RANSACUpdateNumIters( double p, double ep, int modelPoints, int maxIters )
{
    if( modelPoints <= 0 )
        CV_Error( Error::StsOutOfRange, "the number of model points should be positive" );

    p = MAX(p, 0.);
    p = MIN(p, 1.);
    ep = MAX(ep, 0.);
    ep = MIN(ep, 1.);

    // avoid inf's & nan's
    double num = MAX(1. - p, DBL_MIN);
    double denom = 1. - std::pow(1. - ep, modelPoints);
    if( denom < DBL_MIN )
        return 0;

    num = std::log(num);
    denom = std::log(denom);

    return denom >= 0 || -num >= maxIters*(-denom) ? maxIters : cvRound(num/denom);
}

这里的实现也是按照上面的公式(2)书写的。

末尾增加了一个功能,当求得的迭代次数比之前的大,就更新迭代次数。



LMedS的经典步骤是

1. 随机采样

2. 计算模型参数

3. 计算相对模型的点集偏差err,并求出偏差中值Med(err)

4. 迭代2. 3.步直至获得符合阈值的最优解:Med(err)最小

5. 精确优化模型参数(LM算法迭代优化)


LMedS的函数接口 参照opencv来说主要需要2-3个参数(第三个不是必须的)

1. 置信度confidence:设置之后代表RANSAC采样n次过程中会出现(至少一次)采样点数据集中的点都为内点的概率

这个值设置的太大,会增加采样次数。太小,会使结果不太理想。一般取0.95-0.99

2. 最大采样迭代次数maxIters:为了防止一直在采样计算

3.*最大精细迭代次数refineIters:在采样之后,选取最优解。可以增加精确优化,比如使用LM算法获得更优解。


注意: 相对于RANSAC,LMedS有一个优点:不需要指定 - 误差阈值ransacThreshold:区分inlier和outliner的依据

RANSAC的阈值在具有物理意义或者几何意义的时候比较容易确定,

但是当阈值不具有这些特征的时候,就成了一个不太好调整的参数了。

这时LMedS可以自适应迭代获得最优解。


此外,LMedS也能自适应获得inlier和outliner

这里要引用 Robust Regression Methods for Computer Vision_A Review【1】


这里先列出一个等式:


其中

n 表示点集的个数

p 表示计算模型一次采样的点个数

ri2  表示误差

med(ri2 ) 表示误差中值


筛选条件为




关于这个部分的实现 opencv中代码如下

            double sigma = 2.5*1.4826*(1 + 5./(count - modelPoints))*std::sqrt(minMedian);
            sigma = MAX( sigma, 0.001 );

            count = findInliers( m1, m2, bestModel, err, mask, sigma );
findInliers的计算如下

    int findInliers( const Mat& m1, const Mat& m2, const Mat& model, Mat& err, Mat& mask, double thresh ) const
    {
        cb->computeError( m1, m2, model, err );
        mask.create(err.size(), CV_8U);

        CV_Assert( err.isContinuous() && err.type() == CV_32F && mask.isContinuous() && mask.type() == CV_8U);
        const float* errptr = err.ptr<float>();
        uchar* maskptr = mask.ptr<uchar>();
        float t = (float)(thresh*thresh);
        int i, n = (int)err.total(), nz = 0;
        for( i = 0; i < n; i++ )
        {
            int f = errptr[i] <= t;
            maskptr[i] = (uchar)f;
            nz += f;
        }
        return nz;
    }
可以看到 里面用的是二阶范数,sigma输入到thresh参数入口之后会和err的计算一样,使用二阶范数来衡量

由于LMedS会需要对整个点集的err求中值,当点集很大的时候,求中值的过程会很消耗时间

文【1】中提到可以使用Monte Carlo方法,利用局部采样来模拟全局。

这里的式子和上面的式(1)是一样的 :1 − p = (1 − wn)k   

使用多次采样,得到至少一次采样全是inlier的最少采样次数k。详细过程可以看论文。



【1】Robust Regression Methods for Computer Vision_A Review


  • 4
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
RANSACRandom Sample Consensus)算法是一种经典的模型参数估计方法,用于从数据中识别出liers(噪声点)并拟合出一个最优的模型。该算法可以被用于许多领域,例如计算机视觉、机器人学、计算机图形学、地理信息系统等。 RANSAC算法的基本思想是:从样本数据中随机选择一小部分数据作为内点集合,根据这些内点拟合出一个模型,然后用这个模型来测试所有数据,将与模型拟合程度高的数据归为内点,低的归为外点。重复这个过程多次,最终选择内点数最多的模型作为最终模型。 RANSAC算法的具体步骤如下: 1. 随机从数据集中选取一小部分数据作为内点集合,根据这些内点拟合出一个模型。 2. 用这个模型来测试所有数据,将与模型拟合程度高的数据归为内点,低的归为外点。 3. 计算内点的数目,如果内点数目大于某个预设的阈值,则认为这个模型是好的,否则重新从数据集中随机选取一小部分数据,重复以上步骤。 4. 重复执行一定的次数,选择内点数目最多的模型作为最终模型。 需要注意的是,RANSAC算法的效果与内点数目的选择有关,选择的内点数目太小会导致模型拟合不准确,选择的内点数目太大会导致计算量增加,影响算法效率。因此,在实际应用中,需要进行多次试验,选择最优的内点数目和迭代次数。 RANSAC算法的优点是能够快速、准确地处理包含噪声的数据集,并且适用于多种模型拟合问题。但是,该算法也存在一些缺点,例如对于数据集中outliers较多的情况,算法的效果较差。此外,该算法也无法保证求得的模型是全局最优解。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值