RANSAC算法详解Word格式文档下载.docx
《RANSAC算法详解Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《RANSAC算法详解Word格式文档下载.docx(13页珍藏版)》请在冰点文库上搜索。
C代码
#include
<
math.h>
"
LineParamEstimator.h"
LineParamEstimator:
:
LineParamEstimator(double
delta)
m_deltaSquared(delta*delta)
{}
/*****************************************************************************/
/*
*
Compute
the
line
parameters
[n_x,n_y,a_x,a_y]
通过输入的两点来确定所在直线,采用法线向量的方式来表示,以兼容平行或垂直的情况
其中n_x,n_y为归一化后,与原点构成的法线向量,a_x,a_y为直线上任意一点
*/
void
estimate(std:
vector<
Point2D
*>
&
data,
std:
double>
parameters)
{
parameters.clear();
if(data.size()<
2)
return;
double
nx
=
data[1]->
y
-
data[0]->
y;
ny
x
x;
//
原始直线的斜率为K,则法线的斜率为-1/k
norm
sqrt(nx*nx
+
ny*ny);
parameters.push_back(nx/norm);
parameters.push_back(ny/norm);
parameters.push_back(data[0]->
x);
y);
}
使用最小二乘法,从输入点中拟合出确定直线模型的所需参量
leastSquaresEstimate(std:
meanX,
meanY,
nx,
ny,
norm;
covMat11,
covMat12,
covMat21,
covMat22;
The
entries
of
symmetric
covarinace
matrix
int
i,
dataSize
data.size();
meanX
meanY
0.0;
covMat11
covMat12
covMat21
covMat22
0;
for(i=0;
i<
dataSize;
i++)
+=data[i]->
data[i]->
meanX/=dataSize;
meanY/=dataSize;
-=
dataSize*meanX*meanX;
dataSize*meanX*meanY;
dataSize*meanY*meanY;
covMat12;
if(covMat11<
1e-12)
1.0;
else
//lamda1
is
largest
eigen-value
covariance
//and
used
to
compute
eigne-vector
corresponding
smallest
//eigenvalue,
which
isn'
t
computed
explicitly.
lamda1
(covMat11
sqrt((covMat11-covMat22)*(covMat11-covMat22)
4*covMat12*covMat12))
/
2.0;
-covMat12;
nx/=norm;
ny/=norm;
parameters.push_back(nx);
parameters.push_back(ny);
parameters.push_back(meanX);
parameters.push_back(meanY);
Given
check
if
[n_x,
n_y]
dot
[data.x-a_x,
data.y-a_y]
m_delta
通过与已知法线的点乘结果,确定待测点与已知直线的匹配程度;
结果越小则越符合,为
零则表明点在直线上
bool
agree(std:
parameters,
data)
signedDistance
parameters[0]*(data.x-parameters[2])
parameters[1]*(data.y-parameters[3]);
return
((signedDistance*signedDistance)
m_deltaSquared);
RANSAC寻找匹配的代码如下:
template<
class
T,
S>
Ransac<
T,S>
compute(std:
ParameterEsitmator<
*paramEstimator,
T>
numForEstimate)
T
leastSquaresEstimateData;
numDataObjects
numVotesForBest
-1;
*arr
new
int[numForEstimate];
numForEstimate表示拟合模型所需要的最少点数,对本例的直线来说,该值为2
short
*curVotes
short[numDataObjects];
//one
data[i]
agrees
with
current
model,
otherwise
zero
*bestVotes
best
//there
are
less
data
objects
than
minimum
required
for
an
exact
fit
if(numDataObjects
计算所有可能的直线,寻找其中误差最小的解。
对于100点的直线拟合来说,大约需要100*99*0.5=4950次运算,复杂度无疑是庞大的。
一般采用随机选取子集的方式。
computeAllChoices(paramEstimator,data,numForEstimate,
bestVotes,
curVotes,
numVotesForBest,
0,
data.size(),
numForEstimate,
arr);
//compute
least
squares
estimate
using
sub
set
for(int
j=0;
j<
numDataObjects;
j++)
if(bestVotes[j])
leastSquaresEstimateData.push_back(&
(data[j]));
对局内点再次用最小二乘法拟合出模型
paramEstimator->
leastSquaresEstimate(leastSquaresEstimateData,parameters);
delete
[]
arr;
bestVotes;
curVotes;
(double)leastSquaresEstimateData.size()/(double)numDataObjects;
在模型确定以及最大迭代次数允许的情况下,RANSAC总是能找到最优解。
经过我的实验,对于包含80%误差的数据集,RANSAC的效果远优于直接的最小二乘法。
RANSAC可以用于哪些场景呢?
最著名的莫过于图片的拼接技术。
优于镜头的限制,往往需要多张照片才能拍下那种巨幅的风景。
在多幅图像合成时,事先会在待合成的图片中提取一些关键的特征点。
计算机视觉的研究表明,不同视角下物体往往可以通过一个透视矩(3X3或2X2)阵的变换而得到。
RANSAC被用于拟合这个模型的参数(矩阵各行列的值),由此便可识别出不同照片中的同一物体。
可参考下图:
另外,RANSAC还可以用于图像搜索时的纠错与物体识别定位。
下图中,有几条直线是SIFT匹配算法的误判,RANSAC有效地将其识别,并将正确的模型(书本)用线框标注出来: