1. 程式人生 > >Opencv實現:SIFT特徵提取+RANSAC剔除誤匹配點

Opencv實現:SIFT特徵提取+RANSAC剔除誤匹配點

最近整理一下利用SIFT特徵提取方法和RANSAC(隨機抽樣一致性方法)進行剔除無匹配點的內容,將實現過程進行記錄。
程式註釋的非常清楚了,新手也能很快看懂。

    //讀取影象
    Mat img01=imread("3.png");
    Mat img02=imread("4.png");
    imshow("original image1",img01);
    imshow("original image2",img02);

    //SIFT特徵檢測
    SiftFeatureDetector detector;        //定義特點點檢測器
    vector<KeyPoint>
keypoint01,keypoint02;//定義兩個容器存放特徵點 detector.detect(img01,keypoint01); detector.detect(img02,keypoint02); //在兩幅圖中畫出檢測到的特徵點 Mat out_img01; Mat out_img02; drawKeypoints(img01,keypoint01,out_img01); drawKeypoints(img02,keypoint02,out_img02); imshow("特徵點圖01",out_img01); imshow("特徵點圖02",out_img02); //提取特徵點的特徵向量(128維)
SiftDescriptorExtractor extractor; Mat descriptor01,descriptor02; extractor.compute(img01,keypoint01,descriptor01); extractor.compute(img02,keypoint02,descriptor02); //匹配特徵點,主要計算兩個特徵點特徵向量的歐式距離,距離小於某個閾值則認為匹配 BruteForceMatcher<L2<float>> matcher; vector<DMatch> matches; Mat img_matches; matcher.match(descriptor01,descriptor02,matches); drawMatches(img01,keypoint01,img02,keypoint02,matches,img_matches); imshow("誤匹配消除前"
,img_matches);

下面是利用RANSAC進行消除無匹配點:

    //RANSAC 消除誤匹配特徵點 主要分為三個部分:
    //1)根據matches將特徵點對齊,將座標轉換為float型別
    //2)使用求基礎矩陣方法 findFundamentalMat,得到RansacStatus
    //3)根據RansacStatus來將誤匹配的點也即RansacStatus[i]=0的點刪除

    //根據matches將特徵點對齊,將座標轉換為float型別
    vector<KeyPoint> R_keypoint01,R_keypoint02;
    for (size_t i=0;i<matches.size();i++)   
    {
        R_keypoint01.push_back(keypoint01[matches[i].queryIdx]);
        R_keypoint02.push_back(keypoint02[matches[i].trainIdx]);
        //這兩句話的理解:R_keypoint1是要儲存img01中能與img02匹配的特徵點,
        //matches中儲存了這些匹配點對的img01和img02的索引值
    }

    //座標轉換
    vector<Point2f>p01,p02;
    for (size_t i=0;i<matches.size();i++)
    {
        p01.push_back(R_keypoint01[i].pt);
        p02.push_back(R_keypoint02[i].pt);
    }

    //利用基礎矩陣剔除誤匹配點
    vector<uchar> RansacStatus;
    Mat Fundamental= findFundamentalMat(p01,p02,RansacStatus,FM_RANSAC);


    vector<KeyPoint> RR_keypoint01,RR_keypoint02;
    vector<DMatch> RR_matches;            //重新定義RR_keypoint 和RR_matches來儲存新的關鍵點和匹配矩陣
    int index=0;
    for (size_t i=0;i<matches.size();i++)
    {
        if (RansacStatus[i]!=0)
        {
            RR_keypoint01.push_back(R_keypoint01[i]);
            RR_keypoint02.push_back(R_keypoint02[i]);
            matches[i].queryIdx=index;
            matches[i].trainIdx=index;
            RR_matches.push_back(matches[i]);
            index++;
        }
    }
    Mat img_RR_matches;
    drawMatches(img01,RR_keypoint01,img02,RR_keypoint02,RR_matches,img_RR_matches);
    imshow("消除誤匹配點後",img_RR_matches);

實現效果如圖:
這裡寫圖片描述