ransac的原理,有一些不错的资料已经详细的叙述,刚开始学习的时候我看的是Marco Zuliani的<<Ransac for Dummies>>,这份资料讲得不错,想要详细了解其原理的同学不妨看看这份资料。本着实用为主的原则,此处,主要描绘具体怎么实现ransac算法。
ransac算法的输入为:需要处理的点集;以及可能符合的函数模型, 选择的模型决定了需要计算模型参数的点的个数。
ransac算法的输出为:满足某种关系的过滤点集 ;函数模型的参数。
ransac算法的实现步骤:
- 根据你设定的函数模型,选定足够的点
- 使用选定的点,计算得到函数模型参数
- 判定其他点是否符合该函数,并统计满足的点的个数
- 反复1-3步,最后,具有最多点满足的函数为求取的函数,满足该函数的点为inlier,反之,不满足该函数的点为outlier。
以特征点对的几何去噪这一应用为例,具体实现代码如下:
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
|
//输入:
// 需要去噪的特征点对:vector<pair<CvPoint CvPoint> > matcher_ori
// 点对估计应该满足的特征点对几何模型:xform_fn = 投影、仿射、RST或者其他
// 对应的计算模型参数需要特征点对个数:sample_n
// 误差求取函数: err_fn
// 误差阈值: err_w
// 另外还有几个特别重要的参数:infrac, p_badxform, RANSAC_PROB_BAD_SUPP
//输出:
// 去噪后的特征点对 vector<pair<CvPoint CvPoint> > matcher_dst
// 应满足的实际几何模型参数: Ptr<CvMat> H_matrix
int
k = 0;
double
p =
pow
(1.0 -
pow
(in_frac, MSS_n), k);
int
mather_n = (
int
)mather_ori.size();
int
done_n = 0;
while
(p > p_badxform && (((matcher_n - done_n) - sample_n) >= 0) )
{
matcher_sample.clear();
// 随机选择足够的点对
choice_ransac_sample(matcher_ori, matcher_sample, sample_n);
done_n += sample_n;
// 使用选择的点对计算模型的参数
H_matrix = xform_fn(matcher_sample);
if
(NULL == H_matrix)
{
p =
pow
(1.0 -
pow
(in_frac, sample_n, ++k);
continue
;
}
matcher_inliners.clear();
// 检测有哪些点对满足当前的几何模型
find_consensus( matcher_ori, H_matrix, err_fn, err_w, matcher_inliners);
// 选择最多点对符合的几何模型
if
(matcher_dst.size() < matcher_inliners.size())
{
matcher_dst.clear();
matcher_dst = matcher_inliners;
in_frac =
double
(matcher_dst.size())/
double
(matcher_ori.size());
}
p =
pow
(1.0 -
pow
(in_frac, sample_n), ++k);
}
|
结果示例图:
ransac之前的匹配点 : 共有20个匹配点
ransac之后的匹配点:共有17个匹配点