RANSAC算法简介
随机抽样一致性算法(Random sample consensus,RANSAC)是一种使用迭代的方法,从受噪声污染的数据集中估计数学模型参数的算法,与最小二乘法所起作用相同,各自的适用情况不同。RANSAC算法假设数据集中存在局内点(inlier)和局外点(outlier),并且假设只有判定的局内点才可以用来计算模型,局外点不应该对模型参数的求解产生任何影响。该算法是Fischler和Bolles 1981年在SRI International上提出的,他们使用该算法来解决3D重建中的位置确定问题(Location Determination Problem, LDP)。目前RANSAC算法被广泛用于计算机视觉领域中图像匹配、全景拼接等问题,比如从数对匹配的特征点中求得两幅图片之间的射影变换矩阵,OPENCV实现stitching类时即使用了该算法。
RANSAC算法与最小二乘法的不同之处主要有以下两点:
1. 最小二乘法总是使用所有的数据点来估计参数,而RANSAC算法仅使用局内点;
2. 最小二乘法是一种确定性算法,给定数据集,每一次所得到的模型参数都是相同的;而RANSAC算法是一种随机算法,受迭代次数等的影响,每一次得到的参数一般都不相同。
3. 一般而言,RANSAC算法先根据一定的准则筛选出局内点和局外点,然后对得到的局内点进行拟合,拟合方法可以是最小二乘法,也可以是其他优化算法,从这个角度来说,RANSAC算法是最小二乘法的扩展。
算法的求解过程如下:
- 首先从数据集中随机选出一组局内点(其数目要保证能够求解出模型的所有参数),计算出一套模型参数。
- 用得到的模型去测试其他所有的数据点,如果某点的误差在设定的误差阈值之内,就判定其为局内点,否则为局外点,只保留目前为止局内点数目最多的模型,将其记录为最佳模型。
- 重复执行1,2步足够的次数(即达到预设的迭代次数)后,使用最佳模型对应的局内点来最终求解模型参数,该步可以使用最小二乘法等优化算法。
- 最后可以通过估计局内点与模型的错误率来评估模型。
C++代码实现
Ziv Yaniv以最简单的直线拟合为例,写过一版RANSAC算法的C++实现,没有依赖任何其他库,但该版代码对C++的依赖较重,使用了C++的一些高级数据结构,比如vector, set,在遍历时还使用了递归算法。详细代码可参见RANSAC代码示例
部分代码及相关注释如下:
//顶层变量定义
vector<double> lineParameters;//存储模型参数
LineParamEstimator lpEstimator(0.5);//误差阈值设置为0.5
vector<Point2D> pointData;//数据点集
int numForEstimate=2;//进行一次参数估计所需的最小样本点数,因为是直线拟合,所以可以直接设为2
//顶层函数的定义
/**
* Estimate the model parameters using the maximal consensus set by going over ALL possible
* subsets (brute force approach).
* Given: n - data.size()
* k - numForEstimate
* We go over all n choose k subsets n!
* ------------
* (n-k)! * k!
* @param parameters A vector which will contain the estimated parameters.
* If there is an error in the input then this vector will be empty.
* Errors are: 1. Less data objects than required for an exact fit.
* @param paramEstimator An object which can estimate the desired parameters