当前位置:   article > 正文

RANSAC算法——过程及代码_random ransac参数说明

random ransac参数说明

一、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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/611224
推荐阅读
相关标签
  

闽ICP备14008679号