SIFT算法中所用的RANSAC算法源碼分析如下,算法的改進(jìn)(改進(jìn)是為適合我的應(yīng)用而修改)包括5個(gè)方面:
(1)去除圖像中某些噪聲的影響,如攝像機(jī)的編號(hào)等等,在特征點(diǎn)比較少的情況下對(duì)算法影響較大;
(2)去除代碼中對(duì)最小內(nèi)點(diǎn)數(shù)的限制;
(3)增加最小循環(huán)次數(shù)的限制(保證M矩陣的精度);
(4)增加最大循環(huán)次數(shù)的限制(保證循環(huán)可終結(jié));
(5)增加隨機(jī)循環(huán)過程中的M矩陣的正確性的判別(在M矩陣滿足某先驗(yàn)條件時(shí),才執(zhí)行后續(xù)操作);
CvMat* ransac_xform( struct feature* features, int n, int
mtype,
ransac_xform_fn
xform_fn, int m, double p_badxform,
ransac_err_fn
err_fn, double err_tol,
struct feature*** inliers, int* n_in )
{
struct feature** matched, ** sample, **
consensus, ** consensus_max = NULL;
struct ransac_data* rdata;
CvPoint2D64f* pts, * mpts;
CvMat* M = NULL;
gsl_rng* rng;
double p, in_frac = RANSAC_INLIER_FRAC_EST;
int i, nm, in, in_min, in_max = 0, k = 0;
const int MaxRunCount = 20000;
const int MinRunCount = 2000;
int runCount = 0;
int v;
//獲得所有的匹配點(diǎn)對(duì)的個(gè)數(shù)
nm = get_matched_features( features, n, mtype,
&matched );
if( nm < m )
{
fprintf( stderr, "Warning: not
enough matches to compute xform, %s" \
" line %d\n",
__FILE__, __LINE__ );
goto end;
}
rng = gsl_rng_alloc( gsl_rng_mt19937 );
gsl_rng_set( rng, time(NULL) );
//最小內(nèi)點(diǎn)的個(gè)數(shù)
in_min = calc_min_inliers( nm, m,
RANSAC_PROB_BAD_SUPP, p_badxform );
p = pow( 1.0 - pow( in_frac, m ), k );
i = 0;
while( p > p_badxform )
{
//隨機(jī)采樣m個(gè)樣本
sample = draw_ransac_sample(
matched, nm, m, rng );
//提取采樣中的對(duì)應(yīng)點(diǎn)對(duì)
extract_corresp_pts( sample, m,
mtype, &pts, &mpts );
//求取采樣點(diǎn)對(duì)的最小二乘解M矩陣
M = xform_fn( pts, mpts, m
);
if( ! M )
goto
iteration_end;
//尋找與隨機(jī)模型一致的采樣點(diǎn)對(duì),err_fn函數(shù)定義了一致性的判別條件
in = find_consensus( matched,
nm, mtype, M, err_fn, err_tol, &consensus);
//新增加的M矩陣的判別,由于我們應(yīng)用中不存在縮放變換,故我們可以判斷隨機(jī)估計(jì)矩陣是否正確
v = ValidateM(M);
//記錄滿足最大一致性相對(duì)應(yīng)的匹配點(diǎn)的數(shù)組和一致性個(gè)數(shù)
if( in > in_max
&& v)
{
if(
consensus_max )
free(
consensus_max );
consensus_max
= consensus;
in_max =
in;
in_frac =
(double)in_max / nm;
//p = pow(
1.0 - pow( in_frac, m ), ++k );
}
else
free(
consensus );
cvReleaseMat(
&M );
iteration_end:
release_mem( pts, mpts, sample
);
//增加最小迭代次數(shù)的限制
if(runCount >
MinRunCount)
{
//計(jì)算錯(cuò)誤率
p = pow( 1.0
- pow( in_frac, m ), ++k );
}
else
{
++k;
}
//增加最大迭代次數(shù)的限制
if(runCount >
MaxRunCount)
{
break;
}
runCount++;
//
}
printf("%d\n",runCount);
if( 1)
{
extract_corresp_pts(
consensus_max, in_max, mtype, &pts,
&mpts );
M = xform_fn( pts, mpts, in_max
);
in = find_consensus( matched,
nm, mtype, M, err_fn, err_tol, &consensus);
cvReleaseMat(
&M );
release_mem( pts, mpts,
consensus_max );
extract_corresp_pts( consensus,
in, mtype, &pts, &mpts );
M = xform_fn( pts, mpts, in
);
if( inliers )
{
*inliers =
consensus;
consensus =
NULL;
}
if( n_in )
*n_in =
in;
release_mem( pts, mpts,
consensus );
}
else if( consensus_max )
{
if( inliers )
*inliers =
NULL;
if( n_in )
*n_in =
0;
free( consensus_max );
}
gsl_rng_free( rng );
end:
for( i = 0; i < nm; i++ )
{
rdata = feat_ransac_data(
matched[i] );
matched[i]->feature_data
= rdata->orig_feat_data;
free( rdata );
}
free( matched );
return M;
}
|