生活随笔
收集整理的這篇文章主要介紹了
利用RANSAC算法筛选SIFT特征匹配
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
關于RANSAC算法的基本思想,可從網上搜索找到,這里只是RANSAC用于SIFT特征匹配篩選時的一些說明。
RANSAC算法在SIFT特征篩選中的主要流程是:
(1) 從樣本集中隨機抽選一個RANSAC樣本,即4個匹配點對
(2) 根據這4個匹配點對計算變換矩陣M
(3) 根據樣本集,變換矩陣M,和誤差度量函數計算滿足當前變換矩陣的一致集consensus,并返回一致集中元素個數
(4) 根據當前一致集中元素個數判斷是否最優(最大)一致集,若是則更新當前最優一致集
(5) 更新當前錯誤概率p,若p大于允許的最小錯誤概率則重復(1)至(4)繼續迭代,直到當前錯誤概率p小于最小錯誤概率
下面結合RobHess的源碼說明一下RANSAC算法在SIFT特征匹配篩選中的實現,
具體的源碼分析見此系列文章:RobHess的SIFT源碼分析:綜述
在RobHess的源碼中,RANSAC算法的聲明和實現在xform.h和xform.c文件中
實現RANSAC算法的主函數是ransac_xform,如下:
[cpp]?view plain
?copy ? 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?)??
函數說明:利用RANSAC算法進行特征點篩選,計算出最佳匹配的變換矩陣
參數:
features:特征點數組,只有當mtype類型的匹配點存在時才被用來進行單應性計算
n:特征點個數
mtype:決定使用每個特征點的哪個匹配域進行變換矩陣的計算,應該是FEATURE_MDL_MATCH,
? ? FEATURE_BCK_MATCH,FEATURE_MDL_MATCH中的一個。若是FEATURE_MDL_MATCH,
? ? 對應的匹配點對坐標是每個特征點的img_pt域和其匹配點的mdl_pt域,
? ? 否則,對應的匹配點對是每個特征點的img_pt域和其匹配點的img_pt域。
xform_fn:函數指針,指向根據輸入的點對進行變換矩陣計算的函數,一般傳入lsq_homog()函數
m:在函數xform_fn中計算變換矩陣需要的最小特征點對個數
p_badxform:允許的錯誤概率,即允許RANSAC算法計算出的變換矩陣錯誤的概率,當前計算出的模型的錯誤概率小于p_badxform時迭代停止
err_fn:函數指針,對于給定的變換矩陣,計算推定的匹配點對之間的變換誤差,一般傳入homog_xfer_err()函數
err_tol:容錯度,對于給定的變換矩陣,在此范圍內的點對被認為是內點
inliers:輸出參數,指針數組,指向計算出的最終的內點集合,若為空,表示沒計算出符合要求的一致集
? ? ? ? ? ? ? ?此數組的內存將在本函數中被分配,使用完后必須在調用出釋放:free(*inliers)
n_in:輸出參數,最終計算出的內點的數目
返回值:RANSAC算法計算出的變換矩陣,若為空,表示出錯或無法計算出可接受矩陣
注釋如下:
[cpp]?view plain
?copy ? 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;?? ?????? ?????? ????double?p,?in_frac?=?RANSAC_INLIER_FRAC_EST;?? ?????? ?????? ?????? ?????? ?????? ????int?i,?nm,?in,?in_min,?in_max?=?0,?k?=?0;?? ?? ?????? ????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;?? ????}?? ?? ?????? ????srand(?time(NULL)?);?? ?? ?????? ????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?)?? ????{?? ?????????? ????????sample?=?draw_ransac_sample(?matched,?nm,?m?);?? ?????????? ????????extract_corresp_pts(?sample,?m,?mtype,?&pts,?&mpts?);?? ?????????? ????????M?=?xform_fn(?pts,?mpts,?m?);?? ????????if(?!?M?)?? ????????????goto?iteration_end;?? ?????????? ????????in?=?find_consensus(?matched,?nm,?mtype,?M,?err_fn,?err_tol,?&consensus);?? ?? ?????????? ????????if(?in?>?in_max?)?? ????????{?? ????????????if(?consensus_max?)?? ????????????????free(?consensus_max?);?? ????????????consensus_max?=?consensus;?? ????????????in_max?=?in;?? ????????????in_frac?=?(double)in_max?/?nm;?? ????????}?? ????????else?? ????????????free(?consensus?);?? ????????cvReleaseMat(?&M?);?? ?? iteration_end:?? ????????release_mem(?pts,?mpts,?sample?);?? ????????p?=?pow(?1.0?-?pow(?in_frac,?m?),?++k?);?? ????}?? ?? ?????? ?????? ?????? ????if(?in_max?>=?in_min?)?? ????{?? ?????????? ????????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?);?? ????}?? ?? ?????? 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;?? }??
實驗測試:
[cpp]?view plain
?copy ? ?? void?match(IplImage?*img1,IplImage?*img2)?? {?? ????IplImage?*img1_Feat?=?cvCloneImage(img1);?? ????IplImage?*img2_Feat?=?cvCloneImage(img2);?? ?????? ????struct?feature?*feat1,?*feat2;?? ????int?n1,?n2;?? ????struct?feature?*feat;?? ????struct?kd_node?*kd_root;?? ????struct?feature?**nbrs;?? ????int?matchNum;?? ????struct?feature?**inliers;?? ????int?n_inliers;?? ?????? ?????? ?????? ????n1?=?sift_features(?img1,?&feat1?);?? ????export_features("feature1.txt",feat1,n1);?? ????draw_features(?img1_Feat,?feat1,?n1?);?? ????cvShowImage("img1_Feat",img1_Feat);?? ?? ?????? ????n2?=?sift_features(?img2,?&feat2?);?? ????export_features("feature2.txt",feat2,n2);?? ????draw_features(?img2_Feat,?feat2,?n2?);?? ????cvShowImage("img2_Feat",img2_Feat);?? ?????? ????Point?pt1,pt2;?? ????double?d0,d1;?? ????matchNum?=?0;?? ?? ?????? ????stacked?=?stack_imgs(?img1,?img2?);?? ????stacked_ransac?=?stack_imgs(?img1,?img2?);?? ?? ?????? ????kd_root?=?kdtree_build(?feat2,?n2?);?? ?? ?????? ????for(int?i?=?0;?i?<?n1;?i++?)?? ????{?? ????????feat?=?feat1+i;?? ?????????? ????????int?k?=?kdtree_bbf_knn(?kd_root,?feat,?2,?&nbrs,?KDTREE_BBF_MAX_NN_CHKS?);?? ????????if(?k?==?2?)?? ????????{?? ????????????d0?=?descr_dist_sq(?feat,?nbrs[0]?);?? ????????????d1?=?descr_dist_sq(?feat,?nbrs[1]?);?? ?????????????? ????????????if(?d0?<?d1?*?NN_SQ_DIST_RATIO_THR?)?? ????????????{????? ????????????????pt1?=?Point(?cvRound(?feat->x?),?cvRound(?feat->y?)?);?? ????????????????pt2?=?Point(?cvRound(?nbrs[0]->x?),?cvRound(?nbrs[0]->y?)?);?? ????????????????pt2.y?+=?img1->height;?? ????????????????cvLine(?stacked,?pt1,?pt2,?CV_RGB(255,0,255),?1,?8,?0?);?? ????????????????matchNum++;?? ????????????????feat1[i].fwd_match?=?nbrs[0];?? ????????????}?? ????????}?? ????????free(?nbrs?);?? ????}?? ????qDebug()<<tr("經距離比值法篩選后的匹配點對個數:")<<matchNum<<endl;?? ?????? ????cvNamedWindow(IMG_MATCH1);?? ????cvShowImage(IMG_MATCH1,stacked);?? ?? ?????? ????CvMat?*?H?=?ransac_xform(feat1,n1,FEATURE_FWD_MATCH,lsq_homog,4,0.01,homog_xfer_err,3.0,&inliers,&n_inliers);?? ????qDebug()<<tr("經RANSAC算法篩選后的匹配點對個數:")<<n_inliers<<endl;?? ?????? ????for(int?i=0;?i<n_inliers;?i++)?? ????{?? ????????feat?=?inliers[i];?? ????????pt1?=?Point(cvRound(feat->x),?cvRound(feat->y));?? ????????pt2?=?Point(cvRound(feat->fwd_match->x),?cvRound(feat->fwd_match->y));?? ????????qDebug()<<"("<<pt1.x<<","<<pt1.y<<")--->("<<pt2.x<<","<<pt2.y<<")"<<endl;?? ????????pt2.y?+=?img1->height;?? ????????cvLine(stacked_ransac,pt1,pt2,CV_RGB(255,0,255),1,8,0);?? ????}?? ????cvNamedWindow(IMG_MATCH2);?? ????cvShowImage(IMG_MATCH2,stacked_ransac);?? }??
結果:
RANSAC篩選前
RANSAC篩選后
? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?RANSAC篩選前 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?RANSAC篩選后
RANSAC篩選前
RANSAC篩選后
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??RANSAC篩選前 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??RANSAC篩選后
RANSAC篩選前
RANSAC篩選后
RANSAC篩選前
RANSAC篩選后
? ? ? ? ? ? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?RANSAC篩選前 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?RANSAC篩選后? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??RANSAC篩選前 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??RANSAC篩選后
? ? ? ? ? ? ??? ? ? ? ? ? ? ?? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? RANSAC篩選前 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? RANSAC篩選后? ? ? ? ??
RANSAC篩選前
RANSAC篩選后
RANSAC篩選前
RANSAC篩選后
RANSAC篩選前
RANSAC篩選后
from:?http://blog.csdn.net/masibuaa/article/details/9145441
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的利用RANSAC算法筛选SIFT特征匹配的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。