【问题标题】:Inconsistency in RANSAC implementation from Scipy CookbookScipy Cookbook 的 RANSAC 实施不一致
【发布时间】:2014-06-30 19:50:03
【问题描述】:

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

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

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

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

感谢您的帮助!

干杯, 阿列克谢

【问题讨论】:

    标签: python image-processing scipy


    【解决方案1】:

    不,这与 RANSAC 的想法并不矛盾。不过剧情有点误导。

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

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

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

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

    这是修改后的绘图代码:

    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() 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-17
      • 2012-11-04
      • 1970-01-01
      • 2016-03-05
      • 2015-05-28
      • 2016-12-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多