python - Scipy Cookbook 中 RANSAC 实现的不一致

标签 python image-processing scipy

最近我检查了 Cookbook 中的 RANSAC 实现:http://wiki.scipy.org/Cookbook/RANSAC , 但它似乎与 RANSAC 算法本身不一致。

看那里的图,为什么有些数据点离最佳模型很远(见底部的点),被认为是“RANSAC数据”,而其他一些点更接近模型不是?

在我看来,它与 RANSAC 算法的主要思想相矛盾,在该算法中,预定义阈值区域内的所有点都被视为内点。

为什么在这个实现中不是这样,还有 Python 中的任何其他 RANSAC 实现吗?

感谢您的帮助!

干杯, 阿列克谢

最佳答案

不,这与 RANSAC 的想法并不矛盾。虽然情节有点误导。

绘制为蓝色十字的是样本点(best_inlier_idxs = maybeinliers + alsoinliers),其中一些(正是中的点code>alsoinliers,即共识集)支持模型(maybemodel),该模型适用于数据的随机样本(maybeinliers)。这意味着 alsoinliers 给出的所有点确实应该比不支持它的最近点更接近 maybemodel

但是,maybemodel 拟合显示在图中。显示的是 bettermodel(蓝线,“RANSAC fit”),它是通过将模型参数拟合到 best_inlier_idxs 中的all 点获得的(不是只是 maybeinliers 中的那些。

此外,best_inlier_idxs 包含alsoinliersmaybeinliers。随机选择的样本 maybeinliers 中很可能有一些点实际上不支持 maybemodel 拟合(即它们不在阈值范围内)。这些点也显示为蓝色十字,即使它们比不在支持集中的其他点更远。

我稍微修改了绘图,以在“RANSAC 数据”中指出最佳建议模型 (maybemodel) 和随机样本 (maybeinliers)。重要的是一些十字周围的圆圈突出了随机样本包含在 RANSAC 数据中这一事实。

enter image description here

enter image description here

修改后的绘图代码如下:

iterations = 0
bestfit = None
besterr = numpy.inf
best_inlier_idxs = None
while iterations < k:
    maybe_idxs, test_idxs = random_partition(n,data.shape[0])
    maybeinliers = data[maybe_idxs,:]
    test_points = data[test_idxs]
    maybemodel = model.fit(maybeinliers)
    test_err = model.get_error( test_points, maybemodel)
    also_idxs = test_idxs[test_err < t] # select indices of rows with accepted points
    alsoinliers = data[also_idxs,:]
    if debug:
        print 'test_err.min()',test_err.min()
        print 'test_err.max()',test_err.max()
        print 'numpy.mean(test_err)',numpy.mean(test_err)
        print 'iteration %d:len(alsoinliers) = %d'%(
            iterations,len(alsoinliers))
    if len(alsoinliers) > d:
        betterdata = numpy.concatenate( (maybeinliers, alsoinliers) )
        bettermodel = model.fit(betterdata)
        better_errs = model.get_error( betterdata, bettermodel)
        thiserr = numpy.mean( better_errs )
        if thiserr < besterr:
            bestfit = bettermodel
            besterr = thiserr
            best_inlier_idxs = numpy.concatenate( (maybe_idxs, also_idxs) )
    best_maybe_model = maybemodel
    best_random_set = maybe_idxs
    iterations+=1
if bestfit is None:
    raise ValueError("did not meet fit acceptance criteria")
if return_all:
    return bestfit, {'inliers':best_inlier_idxs, 'best_random_set':best_random_set,'best_maybe_model':best_maybe_model}
else:
    return bestfit

def test():
    # generate perfect input data

    n_samples = 500
    n_inputs = 1
    n_outputs = 1
    A_exact = 20*numpy.random.random((n_samples,n_inputs) )
    perfect_fit = 60*numpy.random.normal(size=(n_inputs,n_outputs) ) # the model
    B_exact = scipy.dot(A_exact,perfect_fit)
    assert B_exact.shape == (n_samples,n_outputs)

    # add a little gaussian noise (linear least squares alone should handle this well)
    A_noisy = A_exact + numpy.random.normal(size=A_exact.shape )
    B_noisy = B_exact + numpy.random.normal(size=B_exact.shape )

    if 1:
        # add some outliers
        n_outliers = 100
        all_idxs = numpy.arange( A_noisy.shape[0] )
        numpy.random.shuffle(all_idxs)
        outlier_idxs = all_idxs[:n_outliers]
        non_outlier_idxs = all_idxs[n_outliers:]
        A_noisy[outlier_idxs] =  20*numpy.random.random((n_outliers,n_inputs) )
        B_noisy[outlier_idxs] = 50*numpy.random.normal(size=(n_outliers,n_outputs) )

    # setup model

    all_data = numpy.hstack( (A_noisy,B_noisy) )
    input_columns = range(n_inputs) # the first columns of the array
    output_columns = [n_inputs+i for i in range(n_outputs)] # the last columns of the array
    debug = True
    model = LinearLeastSquaresModel(input_columns,output_columns,debug=debug)

    linear_fit,resids,rank,s = scipy.linalg.lstsq(all_data[:,input_columns],
                                                  all_data[:,output_columns])

    # run RANSAC algorithm
    ransac_fit, ransac_data = ransac(all_data,model,
                                     50, 1000, 7e3, 300, # misc. parameters
                                     debug=debug,return_all=True)
    if 1:
        import pylab

        sort_idxs = numpy.argsort(A_exact[:,0])
        A_col0_sorted = A_exact[sort_idxs] # maintain as rank-2 array

        if 1:
            pylab.plot( A_noisy[:,0], B_noisy[:,0], 'k.', label='data' )
            pylab.plot( A_noisy[ransac_data['inliers'],0], B_noisy[ransac_data['inliers'],0], 'bx', label='RANSAC data' )
        pylab.plot( A_noisy[ransac_data['best_random_set'],0], B_noisy[ransac_data['best_random_set'],0], 'ro', mfc='none',label='best random set (maybeinliers)' )
        else:
            pylab.plot( A_noisy[non_outlier_idxs,0], B_noisy[non_outlier_idxs,0], 'k.', label='noisy data' )
            pylab.plot( A_noisy[outlier_idxs,0], B_noisy[outlier_idxs,0], 'r.', label='outlier data' )
        pylab.plot( A_col0_sorted[:,0],
                    numpy.dot(A_col0_sorted,ransac_fit)[:,0],
                    label='RANSAC fit' )
        pylab.plot( A_col0_sorted[:,0],
                    numpy.dot(A_col0_sorted,perfect_fit)[:,0],
                    label='exact system' )
        pylab.plot( A_col0_sorted[:,0],
                    numpy.dot(A_col0_sorted,linear_fit)[:,0],
                    label='linear fit' )
        pylab.plot( A_col0_sorted[:,0],
                    numpy.dot(A_col0_sorted,ransac_data['best_maybe_model'])[:,0],
                    label='best proposed model (maybemodel)' )
        pylab.legend()
        pylab.show()

if __name__=='__main__':
    test() 

关于python - Scipy Cookbook 中 RANSAC 实现的不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23626156/

相关文章:

python - 访问redis键时如何重置TTL?

python 请求发送数组中的文件显示 ValueError : too many values to unpack

python - BeautifulSoup 中的 selfClosingTags

python - 奇怪的 SciPy Gamma 概率分布函数

python - 如何使用 scipy.optimize.linprog 获得整数解?

python - AWS::RDS - 使用对流层的多可用区

javascript - 如何使用 JavaScript 检测图像中的感兴趣区域

Android 从相机获取全尺寸图像

python - PIL中的图像转换,pgm文件错误

python - 如何在python中生成特定范围内的n维随机变量