版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/itworld123/article/details/79097214
2018-01-18 创建人:Ruo_Xiao
开发环境:Matlab 2010
邮箱:[email protected]
- RANSAC是“RANdom SAmple Consensus(随机抽样一致)”的缩写。
- 使用条件:
(1)大部分数据满足一定模型(局内点),例如:都在一条直线上。
(2)局外点:不在这条直线上。产生的原因有:极值噪声等。 - 基本原理:以二维平面拟合直线方程为例
随即找到两个点组成一条直线,计算其他所有的点与这条直线的距离,太大则抛弃,否则认为该点在直线上,最后统计直线上的点的数量。遍历所有点组合,直线上点的数量最多的组合就是真正的直线。 - 源码:
%ransan测试函数
%生成n个随机样本点
clear all;
clc
a = 1; b = 0; n = 30;
x = linspace(0,30,n);
y = a*x + b + rand(1,n);
%添加误差点
xx=[12,13,14,15,50];
yy=[2,1,5,2,18];
datax=[x,xx];
datay=[y,yy];
%直接用最小二乘进行拟合
p = polyfit(datax, datay, 1);
%用RANSAC方法进行拟合
k = 800; t = 0.1; d = n * 0.8;
p1 = ransac(datax,datay,k,t,d);
%图形结果
figure(1)
plot(datax, datay,'k.');
px = linspace(0,30,1000);
py = p(1)*px+p(2);
p1y= p1(1)*px+p1(2);
figure(1)
hold on
plot(px, py,'b');
hold on
plot(px, p1y,'r');
function p1 = ransac(datax,datay,k,t,d)
% k 是循环的最多次数
% t 阈值
% d 概率数 多少点落入拟合的线周围,超过该概率,直接认为找到了真正的直线。
max_num = 0;
i = 0;
number= length(datax);
while i<k && max_num < d
i = i+1;
%随机产生两个点
tt = unidrnd(number);
ss = mod(unidrnd(number),number)+1;
x1 = datax(tt);
y1 = datay(tt);
x2 = datax(ss);
y2 = datay(ss);
if x1 == x2
continue;
end
%计算一些参数
%y = kx+b;
slope = (y2 - y1)/(x2 - x1); %k
ytrunc = y2 - x2 * slope; %b
%t是斜边,slope/(1+slope^2)^0.5是sin,故delta就是y方向上的距离阈值。
delta = t*slope/(1+slope^2)^0.5;
count = 0;
%遍历所有的点,若距离小于t,将其加入。
for index=1:number
%实际点的x0带入直线中,得到的y1,实际点的y0若满足:(y1 - delta) < y0 < (y1 +
%delta),则认为该点是在线上的。
if datay(index) < datax(index)*slope +ytrunc+ delta && datay(index) > datax(index)*slope +ytrunc - delta
count = count + 1;
result_point(count) = index;
end
end
%计算内点的个数
if(count > max_num)
result_point1 = result_point;
max_num = count;
ms = ss;
mt = tt;
end
end
%用选取有效点进行拟合
p1 = polyfit(datax(result_point1(1:max_num)), datay(result_point1(1:max_num)), 1);
end
结果: