RANSAC算法——过程及代码

1 篇文章 0 订阅

一、RANSAC算法概述

RANSAC(RANdom SAmple Consensus)算法是一种可以去除噪声影响,估计模型的算法。它比类似的最小二乘法更robust。
RANSAC使用数据的子集(inlier)来估计模型,然后通过现有模型参数,尽可能扩大模型在样本集合中的影响,拟合较多的点。

二、算法过程

1. RANSAC算法的过程如下:

对于 N N N个点构成的集合 P P P,我们假定最少通过 n n n个点可以拟合出正确的模型,也就是说样本集合中有 N − n N-n Nn个噪声点。具体的执行下列操作:

  1. 从数据集中随机选择一组样本构建成内点集合,拟合基础模型 H H H
  2. 使用剩余数据对 H H H进行测试,将落在预定误差( σ \sigma σ)范围内的点划到内点集合中。
  3. 使用全部的内点集合拟合模型 H H H
  4. 使用内点集合来估计模型的误差
  5. 如果模型的性能达到了设定的阈值,或者达到了预定的迭代次数,则算法终止,否则跳转到第2步继续执行。

2. 参数说明

a. 初始内点的确定

算法第1步中选择内点时,通常选择能确定模型的最少点,比如两点确定一条直线,3点确定一个平面。在求解单应性矩阵的时候,就是4个点对8个点确定一个矩阵模型。

b. 迭代次数的确定

通常来说 N N N的值比较大,那么随机选择点的时候,点与点的组合就很多,如果不对迭代次数进行限制,运算量就会很大。因为算法第2步要用剩余点对模型进行测试,如果点的数量较多,这一步的运算量很大。包括后面的第3,4步。其实我们只要保证我们估计模型的时候使用的都是内点即可。
假设是内点的概率为 t t t
t = n i n i + n o t=\frac{n_i}{n_i + n_o} t=ni+noni
n i n_i ni为内点数量, n o n_o no为外点数量。那么我们每次计算模型使用 n n n个点的情况下,选取的点集中至少有一个外点的概率就是: 1 − t n 1-t^n 1tn。那么在迭代 k k k次的情况下, ( 1 − t n ) k (1-t^n)^k (1tn)k就是 k k k次迭代都至少有个为外点的概率。
那么能够得到 n n n个正确的点来估计模型的概率就是:
P = 1 − ( 1 − t n ) k P = 1-(1-t^n)^k P=1(1tn)k
两边取对数,就可以得到最少迭代次数:
k = l o g ( 1 − P ) l o g ( 1 − t n ) k=\frac{log(1-P)}{log(1-t^n)} k=log(1tn)log(1P)
这里 P P P是希望通过算法得到正确模型的最少概率, k k k是关于 P P P单调递增的, k k k就是在 P P P确定情况下的最少迭代次数。 t t t通常未知,那么我们可以采用自适应的办法,在开始的时候设置一个较大的迭代次数 k k k,然后通过每次迭代中更新 t t t来更新迭代次数。

三、代码示例

这里使用RANSAC算法来拟合直线,代码如下:

import numpy as np
import matplotlib.pyplot as plt
import random
import math

class ransacMatchingTest(object):

    def __init__(self, X, Y, sigma=0.2, prob=0.95):

        self.X = X
        self.Y = Y
        self.sigma = sigma
        self.prob = prob

    def runMatch(self):

        preInlier = 0
        iters = 10000
        best_a = 0
        best_b = 0
        for i in range(iters):
            # sample points
            sampleIndex = random.sample(range(self.X.shape[0]), 2)
            x1 = self.X[sampleIndex[0]]
            y1 = self.Y[sampleIndex[0]]

            x2 = self.X[sampleIndex[1]]
            y2 = self.Y[sampleIndex[1]]

            # Compute mode
            a = (y2 - y1) / (x2 - x1)
            b = y1 - a * x1

            # Get number of inlier
            inlier = 0
            for index in range(self.X.shape[0]):
                y_estimate = a * self.X[index] + b
                if abs(y_estimate - self.Y[index]) < self.sigma:
                    inlier = inlier + 1

            if inlier > preInlier:
                # Update iteration times
                iters = math.log(1-self.prob) / math.log(1 - pow(inlier / self.X.shape[0], 2))
                preInlier = inlier
                best_a = a
                best_b = b
            # While inliers over half of input set then break
            if inlier > (self.X.shape[0] / 2):
                break

        return best_a, best_b


if __name__ == '__main__':
    X = np.linspace(0, 10, 50)
    Y = 4 * X + 6

    randomX = []
    randomY = []
    # Add mode noise
    for i in range(50):
        randomX.append(X[i] + random.uniform(-0.5, 0.5))
        randomY.append(Y[i] + random.uniform(-0.5, 0.5))
    # Add random noise
    for _ in range(50):
        randomX.append(random.uniform(0, 6))
        randomY.append(random.uniform(6, 30))

    RANDOMX = np.array(randomX)
    RANDOMY = np.array(randomY)

    ransac = ransacMatchingTest(RANDOMX, RANDOMY, sigma=0.2, prob=0.95).runMatch()

    preY = ransac[0] * RANDOMX + ransac[1]

    fig = plt.figure()
    ax1 = fig.add_subplot(1, 1, 1)
    ax1.scatter(RANDOMX, RANDOMY)

    ax1.plot(RANDOMX, preY)
    plt.show()
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值