日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

利用RANSAC算法筛选SIFT特征匹配

發布時間:2025/3/21 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 利用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?)??
  • {??
  • ????//matched:所有具有mtype類型匹配點的特征點的數組,也就是樣本集??
  • ????//sample:單個樣本,即4個特征點的數組??
  • ????//consensus:當前一致集;??
  • ????//consensus_max:當前最大一致集(即當前的最好結果的一致集)??
  • ????struct?feature**?matched,?**?sample,?**?consensus,?**?consensus_max?=?NULL;??
  • ????struct?ransac_data*?rdata;//每個特征點的feature_data域的ransac數據指針??
  • ????CvPoint2D64f*?pts,?*?mpts;//每個樣本對應的兩個坐標數組:特征點坐標數組pts和匹配點坐標數組mpts??
  • ????CvMat*?M?=?NULL;//當前變換矩陣??
  • ????//p:當前計算出的模型的錯誤概率,當p小于p_badxform時迭代停止??
  • ????//in_frac:內點數目占樣本總數目的百分比??
  • ????double?p,?in_frac?=?RANSAC_INLIER_FRAC_EST;??
  • ????//nm:輸入的特征點數組中具有mtype類型匹配點的特征點個數??
  • ????//in:當前一致集中元素個數??
  • ????//in_min:一致集中元素個數允許的最小值,保證RANSAC最終計算出的轉換矩陣錯誤的概率小于p_badxform所需的最小內點數目??
  • ????//in_max:當前最優一致集(最大一致集)中元素的個數??
  • ????//k:迭代次數,與計算當前模型的錯誤概率有關??
  • ????int?i,?nm,?in,?in_min,?in_max?=?0,?k?=?0;??
  • ??
  • ????//找到特征點數組features中所有具有mtype類型匹配點的特征點,放到matched數組(樣本集)中,返回值nm是matched數組的元素個數??
  • ????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;??
  • ????}??
  • ??
  • ????/*?initialize?random?number?generator?*/??
  • ????srand(?time(NULL)?);//初始化隨機數生成器??
  • ??
  • ????//計算保證RANSAC最終計算出的轉換矩陣錯誤的概率小于p_badxform所需的最小內點數目??
  • ????in_min?=?calc_min_inliers(?nm,?m,?RANSAC_PROB_BAD_SUPP,?p_badxform?);??
  • ????//當前計算出的模型的錯誤概率,內點所占比例in_frac越大,錯誤概率越小;迭代次數k越大,錯誤概率越小??
  • ????p?=?pow(?1.0?-?pow(?in_frac,?m?),?k?);??
  • ????i?=?0;??
  • ??
  • ????//當前錯誤概率大于輸入的允許錯誤概率p_badxform,繼續迭代??
  • ????while(?p?>?p_badxform?)??
  • ????{??
  • ????????//從樣本集matched中隨機抽選一個RANSAC樣本(即一個4個特征點的數組),放到樣本變量sample中??
  • ????????sample?=?draw_ransac_sample(?matched,?nm,?m?);??
  • ????????//從樣本中獲取特征點和其對應匹配點的二維坐標,分別放到輸出參數pts和mpts中??
  • ????????extract_corresp_pts(?sample,?m,?mtype,?&pts,?&mpts?);??
  • ????????//調用參數中傳入的函數xform_fn,計算將m個點的數組pts變換為mpts的矩陣,返回變換矩陣給M??
  • ????????M?=?xform_fn(?pts,?mpts,?m?);//一般傳入lsq_homog()函數??
  • ????????if(?!?M?)//出錯判斷??
  • ????????????goto?iteration_end;??
  • ????????//給定特征點集,變換矩陣,誤差函數,計算出當前一致集consensus,返回一致集中元素個數給in??
  • ????????in?=?find_consensus(?matched,?nm,?mtype,?M,?err_fn,?err_tol,?&consensus);??
  • ??
  • ????????//若當前一致集大于歷史最優一致集,即當前一致集為最優,則更新最優一致集consensus_max??
  • ????????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?);??
  • ????}??
  • ??
  • ????//根據最優一致集計算最終的變換矩陣??
  • ????/*?calculate?final?transform?based?on?best?consensus?set?*/??
  • ????//若最優一致集中元素個數大于最低標準,即符合要求??
  • ????if(?in_max?>=?in_min?)??
  • ????{??
  • ????????//從最優一致集中獲取特征點和其對應匹配點的二維坐標,分別放到輸出參數pts和mpts中??
  • ????????extract_corresp_pts(?consensus_max,?in_max,?mtype,?&pts,?&mpts?);??
  • ????????//調用參數中傳入的函數xform_fn,計算將in_max個點的數組pts變換為mpts的矩陣,返回變換矩陣給M??
  • ????????M?=?xform_fn(?pts,?mpts,?in_max?);??
  • ????????/***********下面會再進行一次迭代**********/??
  • ????????//根據變換矩陣M從樣本集matched中計算出一致集consensus,返回一致集中元素個數給in??
  • ????????in?=?find_consensus(?matched,?nm,?mtype,?M,?err_fn,?err_tol,?&consensus);??
  • ????????cvReleaseMat(?&M?);??
  • ????????release_mem(?pts,?mpts,?consensus_max?);??
  • ????????//從一致集中獲取特征點和其對應匹配點的二維坐標,分別放到輸出參數pts和mpts中??
  • ????????extract_corresp_pts(?consensus,?in,?mtype,?&pts,?&mpts?);??
  • ????????//調用參數中傳入的函數xform_fn,計算將in個點的數組pts變換為mpts的矩陣,返回變換矩陣給M??
  • ????????M?=?xform_fn(?pts,?mpts,?in?);??
  • ????????if(?inliers?)??
  • ????????{??
  • ????????????*inliers?=?consensus;//將最優一致集賦值給輸出參數:inliers,即內點集合??
  • ????????????consensus?=?NULL;??
  • ????????}??
  • ????????if(?n_in?)??
  • ????????????*n_in?=?in;//將最優一致集中元素個數賦值給輸出參數:n_in,即內點個數??
  • ????????release_mem(?pts,?mpts,?consensus?);??
  • ????}??
  • ????else?if(?consensus_max?)??
  • ????{???//沒有計算出符合要求的一致集??
  • ????????if(?inliers?)??
  • ????????????*inliers?=?NULL;??
  • ????????if(?n_in?)??
  • ????????????*n_in?=?0;??
  • ????????free(?consensus_max?);??
  • ????}??
  • ??
  • ????//RANSAC算法結束:恢復特征點中被更改的數據域feature_data,并返回變換矩陣M??
  • end:??
  • ????for(?i?=?0;?i?<?nm;?i++?)??
  • ????{??
  • ????????//利用宏feat_ransac_data來提取matched[i]中的feature_data成員并轉換為ransac_data格式的指針??
  • ????????rdata?=?feat_ransac_data(?matched[i]?);??
  • ????????//恢復feature_data成員的以前的值??
  • ????????matched[i]->feature_data?=?rdata->orig_feat_data;??
  • ????????free(?rdata?);//釋放內存??
  • ????}??
  • ????free(?matched?);??
  • ??
  • ????return?M;//返回求出的變換矩陣M??
  • }??

  • 實驗測試:

    [cpp]?view plain?copy ?
  • //特征提取和匹配??
  • void?match(IplImage?*img1,IplImage?*img2)??
  • {??
  • ????IplImage?*img1_Feat?=?cvCloneImage(img1);//復制圖1,深拷貝,用來畫特征點??
  • ????IplImage?*img2_Feat?=?cvCloneImage(img2);//復制圖2,深拷貝,用來畫特征點??
  • ??????
  • ????struct?feature?*feat1,?*feat2;//feat1:圖1的特征點數組,feat2:圖2的特征點數組??
  • ????int?n1,?n2;//n1:圖1中的特征點個數,n2:圖2中的特征點個數??
  • ????struct?feature?*feat;//每個特征點??
  • ????struct?kd_node?*kd_root;//k-d樹的樹根??
  • ????struct?feature?**nbrs;//當前特征點的最近鄰點數組??
  • ????int?matchNum;//經距離比值法篩選后的匹配點對的個數??
  • ????struct?feature?**inliers;//精RANSAC篩選后的內點數組??
  • ????int?n_inliers;//經RANSAC算法篩選后的內點個數,即feat1中具有符合要求的特征點的個數??
  • ??????
  • ????//默認提取的是LOWE格式的SIFT特征點??
  • ????//提取并顯示第1幅圖片上的特征點??
  • ????n1?=?sift_features(?img1,?&feat1?);//檢測圖1中的SIFT特征點,n1是圖1的特征點個數??
  • ????export_features("feature1.txt",feat1,n1);//將特征向量數據寫入到文件??
  • ????draw_features(?img1_Feat,?feat1,?n1?);//畫出特征點??
  • ????cvShowImage("img1_Feat",img1_Feat);//顯示??
  • ??
  • ????//提取并顯示第2幅圖片上的特征點??
  • ????n2?=?sift_features(?img2,?&feat2?);//檢測圖2中的SIFT特征點,n2是圖2的特征點個數??
  • ????export_features("feature2.txt",feat2,n2);//將特征向量數據寫入到文件??
  • ????draw_features(?img2_Feat,?feat2,?n2?);//畫出特征點??
  • ????cvShowImage("img2_Feat",img2_Feat);//顯示??
  • ??????
  • ????Point?pt1,pt2;//連線的兩個端點??
  • ????double?d0,d1;//feat1中每個特征點到最近鄰和次近鄰的距離??
  • ????matchNum?=?0;//經距離比值法篩選后的匹配點對的個數??
  • ??
  • ????//將2幅圖片合成1幅圖片,上下排列??
  • ????stacked?=?stack_imgs(?img1,?img2?);//合成圖像,顯示經距離比值法篩選后的匹配結果??
  • ????stacked_ransac?=?stack_imgs(?img1,?img2?);//合成圖像,顯示經RANSAC算法篩選后的匹配結果??
  • ??
  • ????//根據圖2的特征點集feat2建立k-d樹,返回k-d樹根給kd_root??
  • ????kd_root?=?kdtree_build(?feat2,?n2?);??
  • ??
  • ????//遍歷特征點集feat1,針對feat1中每個特征點feat,選取符合距離比值條件的匹配點,放到feat的fwd_match域中??
  • ????for(int?i?=?0;?i?<?n1;?i++?)??
  • ????{??
  • ????????feat?=?feat1+i;//第i個特征點的指針??
  • ????????//在kd_root中搜索目標點feat的2個最近鄰點,存放在nbrs中,返回實際找到的近鄰點個數??
  • ????????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]?);//feat與最近鄰點的距離的平方??
  • ????????????d1?=?descr_dist_sq(?feat,?nbrs[1]?);//feat與次近鄰點的距離的平方??
  • ????????????//若d0和d1的比值小于閾值NN_SQ_DIST_RATIO_THR,則接受此匹配,否則剔除??
  • ????????????if(?d0?<?d1?*?NN_SQ_DIST_RATIO_THR?)??
  • ????????????{???//將目標點feat和最近鄰點作為匹配點對??
  • ????????????????pt1?=?Point(?cvRound(?feat->x?),?cvRound(?feat->y?)?);//圖1中點的坐標??
  • ????????????????pt2?=?Point(?cvRound(?nbrs[0]->x?),?cvRound(?nbrs[0]->y?)?);//圖2中點的坐標(feat的最近鄰點)??
  • ????????????????pt2.y?+=?img1->height;//由于兩幅圖是上下排列的,pt2的縱坐標加上圖1的高度,作為連線的終點??
  • ????????????????cvLine(?stacked,?pt1,?pt2,?CV_RGB(255,0,255),?1,?8,?0?);//畫出連線??
  • ????????????????matchNum++;//統計匹配點對的個數??
  • ????????????????feat1[i].fwd_match?=?nbrs[0];//使點feat的fwd_match域指向其對應的匹配點??
  • ????????????}??
  • ????????}??
  • ????????free(?nbrs?);//釋放近鄰數組??
  • ????}??
  • ????qDebug()<<tr("經距離比值法篩選后的匹配點對個數:")<<matchNum<<endl;??
  • ????//顯示并保存經距離比值法篩選后的匹配圖??
  • ????cvNamedWindow(IMG_MATCH1);//創建窗口??
  • ????cvShowImage(IMG_MATCH1,stacked);//顯示??
  • ??
  • ????//利用RANSAC算法篩選匹配點,計算變換矩陣H??
  • ????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;??
  • ????//遍歷經RANSAC算法篩選后的特征點集合inliers,找到每個特征點的匹配點,畫出連線??
  • ????for(int?i=0;?i<n_inliers;?i++)??
  • ????{??
  • ????????feat?=?inliers[i];//第i個特征點??
  • ????????pt1?=?Point(cvRound(feat->x),?cvRound(feat->y));//圖1中點的坐標??
  • ????????pt2?=?Point(cvRound(feat->fwd_match->x),?cvRound(feat->fwd_match->y));//圖2中點的坐標(feat的匹配點)??
  • ????????qDebug()<<"("<<pt1.x<<","<<pt1.y<<")--->("<<pt2.x<<","<<pt2.y<<")"<<endl;??
  • ????????pt2.y?+=?img1->height;//由于兩幅圖是上下排列的,pt2的縱坐標加上圖1的高度,作為連線的終點??
  • ????????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特征匹配的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。