Ransac

1
2
3
流程:
在所有point中选择一组计算line参数,通过设置k_min与k_max保留局内点,
下一轮中重新选点,若得分更高则认为该模型更好,如此循环直到达到设置阈值或者最大迭代
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
//RANSAC 拟合2D 直线
//输入参数:points--输入点集
// iterations--迭代次数
// sigma--数据和模型之间可接受的差值,车道线像素宽带一般为10左右
// (Parameter use to compute the fitting score)
// k_min/k_max--拟合的直线斜率的取值范围.
// 考虑到左右车道线在图像中的斜率位于一定范围内,
// 添加此参数,同时可以避免检测垂线和水平线
//输出参数:line--拟合的直线参数,It is a vector of 4 floats
// (vx, vy, x0, y0) where (vx, vy) is a normalized
// vector collinear to the line and (x0, y0) is some
// point on the line.
//返回值:无
void fitLineRansac(const std::vector<cv::Point2f>& points,
cv::Vec4f &line,
int iterations = 1000,
double sigma = 1.,
double k_min = -7.,
double k_max = 7.)
{
unsigned int n = points.size();

if(n<2)
{
return;
}

cv::RNG rng;
double bestScore = -1.;
for(int k=0; k<iterations; k++)
{
int i1=0, i2=0;
while(i1==i2)
{
i1 = rng(n);
i2 = rng(n);
}
const cv::Point2f& p1 = points[i1];
const cv::Point2f& p2 = points[i2];

cv::Point2f dp = p2-p1;//直线的方向向量
dp *= 1./norm(dp);
double score = 0;

if(dp.y/dp.x<=k_max && dp.y/dp.x>=k_min )
{
for(uint i=0; i<n; i++)
{
cv::Point2f v = points[i]-p1;
double d = v.y*dp.x - v.x*dp.y;//向量a与b叉乘/向量b的摸.||b||=1./norm(dp),形成模越小说明匹配度越高
//score += exp(-0.5*d*d/(sigma*sigma));//误差定义方式的一种
if( fabs(d)<sigma )
score += 1;
}
}
if(score > bestScore)
{
line = cv::Vec4f(dp.x, dp.y, p1.x, p1.y);
bestScore = score;
}
}
}