最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

OpenCV實(shí)現(xiàn)特征檢測(cè)和特征匹配方法匯總

 更新時(shí)間:2021年08月18日 15:34:01   作者:Madcola  
一幅圖像中總存在著其獨(dú)特的像素點(diǎn),這些點(diǎn)我們可以認(rèn)為就是這幅圖像的特征,成為特征點(diǎn),本文主要介紹了OpenCV實(shí)現(xiàn)特征檢測(cè)和特征匹配方法,感興趣的可以了解一下

一幅圖像中總存在著其獨(dú)特的像素點(diǎn),這些點(diǎn)我們可以認(rèn)為就是這幅圖像的特征,成為特征點(diǎn)。計(jì)算機(jī)視覺領(lǐng)域中的很重要的圖像特征匹配就是一特征點(diǎn)為基礎(chǔ)而進(jìn)行的,所以,如何定義和找出一幅圖像中的特征點(diǎn)就非常重要。這篇文章我總結(jié)了視覺領(lǐng)域最常用的幾種特征點(diǎn)以及特征匹配的方法。

在計(jì)算機(jī)視覺領(lǐng)域,興趣點(diǎn)(也稱關(guān)鍵點(diǎn)或特征點(diǎn))的概念已經(jīng)得到了廣泛的應(yīng)用, 包括目標(biāo)識(shí)別、 圖像配準(zhǔn)、 視覺跟蹤、 三維重建等。 這個(gè)概念的原理是, 從圖像中選取某些特征點(diǎn)并對(duì)圖像進(jìn)行局部分析,而非觀察整幅圖像。 只要圖像中有足夠多可檢測(cè)的興趣點(diǎn),并且這些興趣點(diǎn)各不相同且特征穩(wěn)定, 能被精確地定位,上述方法就十分有效。

以下是實(shí)驗(yàn)用的圖像:第一幅是手機(jī)抓拍的風(fēng)景圖,第二幅是遙感圖像。

1.SURF

特征檢測(cè)的視覺不變性是一個(gè)非常重要的概念。 但是要解決尺度不變性問題,難度相當(dāng)大。 為解決這一問題,計(jì)算機(jī)視覺界引入了尺度不變特征的概念。 它的理念是, 不僅在任何尺度下拍攝的物體都能檢測(cè)到一致的關(guān)鍵點(diǎn),而且每個(gè)被檢測(cè)的特征點(diǎn)都對(duì)應(yīng)一個(gè)尺度因子。 理想情況下,對(duì)于兩幅圖像中不同尺度的的同一個(gè)物體點(diǎn), 計(jì)算得到的兩個(gè)尺度因子之間的比率應(yīng)該等于圖像尺度的比率。近幾年, 人們提出了多種尺度不變特征,本節(jié)介紹其中的一種:SURF特征。 SURF全稱為“加速穩(wěn)健特征”(Speeded Up Robust Feature),我們將會(huì)看到,它們不僅是尺度不變特征,而且是具有較高計(jì)算效率的特征。

我們首先進(jìn)行常規(guī)的特征提取和特征點(diǎn)匹配,看看效果如何。

#include "highgui/highgui.hpp"    
#include "opencv2/nonfree/nonfree.hpp"    
#include "opencv2/legacy/legacy.hpp"   
#include <iostream>  

using namespace cv;
using namespace std;


int main()
{
    Mat image01 = imread("2.jpg", 1);    //右圖
    Mat image02 = imread("1.jpg", 1);    //左圖
    namedWindow("p2", 0);
    namedWindow("p1", 0);
    imshow("p2", image01);
    imshow("p1", image02);

    //灰度圖轉(zhuǎn)換  
    Mat image1, image2;
    cvtColor(image01, image1, CV_RGB2GRAY);
    cvtColor(image02, image2, CV_RGB2GRAY);


    //提取特征點(diǎn)    
    SurfFeatureDetector surfDetector(800);  // 海塞矩陣閾值,在這里調(diào)整精度,值越大點(diǎn)越少,越精準(zhǔn) 
    vector<KeyPoint> keyPoint1, keyPoint2;
    surfDetector.detect(image1, keyPoint1);
    surfDetector.detect(image2, keyPoint2);

    //特征點(diǎn)描述,為下邊的特征點(diǎn)匹配做準(zhǔn)備    
    SurfDescriptorExtractor SurfDescriptor;
    Mat imageDesc1, imageDesc2;
    SurfDescriptor.compute(image1, keyPoint1, imageDesc1);
    SurfDescriptor.compute(image2, keyPoint2, imageDesc2);

    //獲得匹配特征點(diǎn),并提取最優(yōu)配對(duì)     
    FlannBasedMatcher matcher;
    vector<DMatch> matchePoints;

    matcher.match(imageDesc1, imageDesc2, matchePoints, Mat());
    cout << "total match points: " << matchePoints.size() << endl;


    Mat img_match;
    drawMatches(image01, keyPoint1, image02, keyPoint2, matchePoints, img_match);
    namedWindow("match", 0);
    imshow("match",img_match);
    imwrite("match.jpg", img_match);

    waitKey();
    return 0;
}

由上面的特征點(diǎn)匹配的效果來看,匹配的效果還是相當(dāng)糟糕的,如果我們拿著這樣子的匹配結(jié)果去實(shí)現(xiàn)圖像拼接或者物體追蹤,效果肯定是極差的。所以我們需要進(jìn)一步篩選匹配點(diǎn),來獲取優(yōu)秀的匹配點(diǎn),這就是所謂的“去粗取精”。這里我們采用了Lowe's算法來進(jìn)一步獲取優(yōu)秀匹配點(diǎn)。

為了排除因?yàn)閳D像遮擋和背景混亂而產(chǎn)生的無匹配關(guān)系的關(guān)鍵點(diǎn),SIFT的作者Lowe提出了比較最近鄰距離與次近鄰距離的SIFT匹配方式:取一幅圖像中的一個(gè)SIFT關(guān)鍵點(diǎn),并找出其與另一幅圖像中歐式距離最近的前兩個(gè)關(guān)鍵點(diǎn),在這兩個(gè)關(guān)鍵點(diǎn)中,如果最近的距離除以次近的距離得到的比率ratio少于某個(gè)閾值T,則接受這一對(duì)匹配點(diǎn)。因?yàn)閷?duì)于錯(cuò)誤匹配,由于特征空間的高維性,相似的距離可能有大量其他的錯(cuò)誤匹配,從而它的ratio值比較高。顯然降低這個(gè)比例閾值T,SIFT匹配點(diǎn)數(shù)目會(huì)減少,但更加穩(wěn)定,反之亦然。

Lowe推薦ratio的閾值為0.8,但作者對(duì)大量任意存在尺度、旋轉(zhuǎn)和亮度變化的兩幅圖片進(jìn)行匹配,結(jié)果表明ratio取值在0. 4~0. 6 之間最佳,小于0. 4的很少有匹配點(diǎn),大于0. 6的則存在大量錯(cuò)誤匹配點(diǎn),所以建議ratio的取值原則如下:

ratio=0. 4:對(duì)于準(zhǔn)確度要求高的匹配;

ratio=0. 6:對(duì)于匹配點(diǎn)數(shù)目要求比較多的匹配;

ratio=0. 5:一般情況下。

#include "highgui/highgui.hpp"    
#include "opencv2/nonfree/nonfree.hpp"    
#include "opencv2/legacy/legacy.hpp"   
#include <iostream>  

using namespace cv;
using namespace std;


int main()
{

    Mat image01 = imread("g2.jpg", 1);    
    Mat image02 = imread("g4.jpg", 1);    
    imshow("p2", image01);
    imshow("p1", image02);

    //灰度圖轉(zhuǎn)換  
    Mat image1, image2;
    cvtColor(image01, image1, CV_RGB2GRAY);
    cvtColor(image02, image2, CV_RGB2GRAY);


    //提取特征點(diǎn)    
    SurfFeatureDetector surfDetector(2000);  // 海塞矩陣閾值,在這里調(diào)整精度,值越大點(diǎn)越少,越精準(zhǔn) 
    vector<KeyPoint> keyPoint1, keyPoint2;
    surfDetector.detect(image1, keyPoint1);
    surfDetector.detect(image2, keyPoint2);

    //特征點(diǎn)描述,為下邊的特征點(diǎn)匹配做準(zhǔn)備    
    SurfDescriptorExtractor SurfDescriptor;
    Mat imageDesc1, imageDesc2;
    SurfDescriptor.compute(image1, keyPoint1, imageDesc1);
    SurfDescriptor.compute(image2, keyPoint2, imageDesc2);

    FlannBasedMatcher matcher;
    vector<vector<DMatch> > matchePoints;
    vector<DMatch> GoodMatchePoints;

    vector<Mat> train_desc(1, imageDesc1);
    matcher.add(train_desc);
    matcher.train();

    matcher.knnMatch(imageDesc2, matchePoints, 2);
    cout << "total match points: " << matchePoints.size() << endl;

    // Lowe's algorithm,獲取優(yōu)秀匹配點(diǎn)
    for (int i = 0; i < matchePoints.size(); i++)
    {
        if (matchePoints[i][0].distance < 0.6 * matchePoints[i][1].distance)
        {
            GoodMatchePoints.push_back(matchePoints[i][0]);
        }
    }

    Mat first_match;
    drawMatches(image02, keyPoint2, image01, keyPoint1, GoodMatchePoints, first_match);
    imshow("first_match ", first_match);
    waitKey();
    return 0;
}

為了體現(xiàn)所謂的尺度不變形,我特意加入了額外一組圖片來測(cè)試

由特征點(diǎn)匹配的效果來看,現(xiàn)在的特征點(diǎn)匹配應(yīng)該是非常精準(zhǔn)了,因?yàn)槲覀円呀?jīng)把不合格的匹配點(diǎn)統(tǒng)統(tǒng)移除出去了。

2.SIFT

SURF算法是SIFT算法的加速版, 而SIFT(尺度不變特征轉(zhuǎn)換, ScaleInvariant Feature Transform) 是另一種著名的尺度不變特征檢測(cè)法。我們知道,SURF相對(duì)于SIFT而言,特征點(diǎn)檢測(cè)的速度有著極大的提升,所以在一些實(shí)時(shí)視頻流物體匹配上有著很強(qiáng)的應(yīng)用。而SIFT因?yàn)槠渚薮蟮奶卣饔?jì)算量而使得特征點(diǎn)提取的過程異常花費(fèi)時(shí)間,所以在一些注重速度的場(chǎng)合難有應(yīng)用場(chǎng)景。但是SIFT相對(duì)于SURF的優(yōu)點(diǎn)就是,由于SIFT基于浮點(diǎn)內(nèi)核計(jì)算特征點(diǎn),因此通常認(rèn)為, SIFT算法檢測(cè)的特征在空間和尺度上定位更加精確,所以在要求匹配極度精準(zhǔn)且不考慮匹配速度的場(chǎng)合可以考慮使用SIFT算法。

SIFT特征檢測(cè)的代碼我們僅需要對(duì)上面的SURF代碼作出一丁點(diǎn)修改即可。

#include "highgui/highgui.hpp"    
#include "opencv2/nonfree/nonfree.hpp"    
#include "opencv2/legacy/legacy.hpp"   
#include <iostream>  

using namespace cv;
using namespace std;


int main()
{
    Mat image01 = imread("1.jpg", 1);    //右圖
    Mat image02 = imread("2.jpg", 1);    //左圖
    namedWindow("p2", 0);
    namedWindow("p1", 0);
    imshow("p2", image01);
    imshow("p1", image02);

    //灰度圖轉(zhuǎn)換  
    Mat image1, image2;
    cvtColor(image01, image1, CV_RGB2GRAY);
    cvtColor(image02, image2, CV_RGB2GRAY);


    //提取特征點(diǎn)    
    SiftFeatureDetector siftDetector(2000);  // 海塞矩陣閾值,在這里調(diào)整精度,值越大點(diǎn)越少,越精準(zhǔn) 
    vector<KeyPoint> keyPoint1, keyPoint2;
    siftDetector.detect(image1, keyPoint1);
    siftDetector.detect(image2, keyPoint2);

    //特征點(diǎn)描述,為下邊的特征點(diǎn)匹配做準(zhǔn)備    
    SiftDescriptorExtractor SiftDescriptor;
    Mat imageDesc1, imageDesc2;
    SiftDescriptor.compute(image1, keyPoint1, imageDesc1);
    SiftDescriptor.compute(image2, keyPoint2, imageDesc2);

    //獲得匹配特征點(diǎn),并提取最優(yōu)配對(duì)     
    FlannBasedMatcher matcher;
    vector<DMatch> matchePoints;

    matcher.match(imageDesc1, imageDesc2, matchePoints, Mat());
    cout << "total match points: " << matchePoints.size() << endl;


    Mat img_match;
    drawMatches(image01, keyPoint1, image02, keyPoint2, matchePoints, img_match);

    imshow("match",img_match);
    imwrite("match.jpg", img_match);

    waitKey();
    return 0;
}

沒有經(jīng)過點(diǎn)篩選的匹配效果同樣糟糕。下面繼續(xù)采用Lowe‘s的算法選出優(yōu)秀匹配點(diǎn)。

#include "highgui/highgui.hpp"    
#include "opencv2/nonfree/nonfree.hpp"    
#include "opencv2/legacy/legacy.hpp"   
#include <iostream>  

using namespace cv;
using namespace std;


int main()
{

    Mat image01 = imread("1.jpg", 1);
    Mat image02 = imread("2.jpg", 1);
    imshow("p2", image01);
    imshow("p1", image02);

    //灰度圖轉(zhuǎn)換  
    Mat image1, image2;
    cvtColor(image01, image1, CV_RGB2GRAY);
    cvtColor(image02, image2, CV_RGB2GRAY);


    //提取特征點(diǎn)    
    SiftFeatureDetector siftDetector(800);  // 海塞矩陣閾值,在這里調(diào)整精度,值越大點(diǎn)越少,越精準(zhǔn) 
    vector<KeyPoint> keyPoint1, keyPoint2;
    siftDetector.detect(image1, keyPoint1);
    siftDetector.detect(image2, keyPoint2);

    //特征點(diǎn)描述,為下邊的特征點(diǎn)匹配做準(zhǔn)備    
    SiftDescriptorExtractor SiftDescriptor;
    Mat imageDesc1, imageDesc2;
    SiftDescriptor.compute(image1, keyPoint1, imageDesc1);
    SiftDescriptor.compute(image2, keyPoint2, imageDesc2);

    FlannBasedMatcher matcher;
    vector<vector<DMatch> > matchePoints;
    vector<DMatch> GoodMatchePoints;

    vector<Mat> train_desc(1, imageDesc1);
    matcher.add(train_desc);
    matcher.train();

    matcher.knnMatch(imageDesc2, matchePoints, 2);
    cout << "total match points: " << matchePoints.size() << endl;

    // Lowe's algorithm,獲取優(yōu)秀匹配點(diǎn)
    for (int i = 0; i < matchePoints.size(); i++)
    {
        if (matchePoints[i][0].distance < 0.6 * matchePoints[i][1].distance)
        {
            GoodMatchePoints.push_back(matchePoints[i][0]);
        }
    }

    Mat first_match;
    drawMatches(image02, keyPoint2, image01, keyPoint1, GoodMatchePoints, first_match);
    imshow("first_match ", first_match);
    imwrite("first_match.jpg", first_match);
    waitKey();
    return 0;
}

3.ORB

ORB是ORiented Brief的簡(jiǎn)稱,是brief算法的改進(jìn)版。ORB算法比SIFT算法快100倍,比SURF算法快10倍。在計(jì)算機(jī)視覺領(lǐng)域有種說法,ORB算法的綜合性能在各種測(cè)評(píng)里較其他特征提取算法是最好的。

ORB算法是brief算法的改進(jìn),那么我們先說一下brief算法有什么去缺點(diǎn)。

BRIEF的優(yōu)點(diǎn)在于其速度,其缺點(diǎn)是:

  • 不具備旋轉(zhuǎn)不變性
  • 對(duì)噪聲敏感
  • 不具備尺度不變性

而ORB算法就是試圖解決上述缺點(diǎn)中1和2提出的一種新概念。值得注意的是,ORB沒有解決尺度不變性。

#include "highgui/highgui.hpp"    
#include "opencv2/nonfree/nonfree.hpp"    
#include "opencv2/legacy/legacy.hpp"   
#include <iostream>  

using namespace cv;
using namespace std;


int main()
{

    Mat image01 = imread("g2.jpg", 1);
    Mat image02 = imread("g4.jpg", 1);
    imshow("p2", image01);
    imshow("p1", image02);

    //灰度圖轉(zhuǎn)換  
    Mat image1, image2;
    cvtColor(image01, image1, CV_RGB2GRAY);
    cvtColor(image02, image2, CV_RGB2GRAY);


    //提取特征點(diǎn)    
    OrbFeatureDetector OrbDetector(1000);  // 在這里調(diào)整精度,值越小點(diǎn)越少,越精準(zhǔn) 
    vector<KeyPoint> keyPoint1, keyPoint2;
    OrbDetector.detect(image1, keyPoint1);
    OrbDetector.detect(image2, keyPoint2);

    //特征點(diǎn)描述,為下邊的特征點(diǎn)匹配做準(zhǔn)備    
    OrbDescriptorExtractor OrbDescriptor;
    Mat imageDesc1, imageDesc2;
    OrbDescriptor.compute(image1, keyPoint1, imageDesc1);
    OrbDescriptor.compute(image2, keyPoint2, imageDesc2);

    flann::Index flannIndex(imageDesc1, flann::LshIndexParams(12, 20, 2), cvflann::FLANN_DIST_HAMMING);

    vector<DMatch> GoodMatchePoints;

    Mat macthIndex(imageDesc2.rows, 2, CV_32SC1), matchDistance(imageDesc2.rows, 2, CV_32FC1);
    flannIndex.knnSearch(imageDesc2, macthIndex, matchDistance, 2, flann::SearchParams());

    // Lowe's algorithm,獲取優(yōu)秀匹配點(diǎn)
    for (int i = 0; i < matchDistance.rows; i++)
    {
        if (matchDistance.at<float>(i,0) < 0.6 * matchDistance.at<float>(i, 1))
        {
            DMatch dmatches(i, macthIndex.at<int>(i, 0), matchDistance.at<float>(i, 0));
            GoodMatchePoints.push_back(dmatches);
        }
    }

    Mat first_match;
    drawMatches(image02, keyPoint2, image01, keyPoint1, GoodMatchePoints, first_match);
    imshow("first_match ", first_match);
    imwrite("first_match.jpg", first_match);
    waitKey();
    return 0;
}

4.FAST

FAST(加速分割測(cè)試獲得特征, Features from Accelerated Segment Test) 。 這種算子專門用來快速檢測(cè)興趣點(diǎn), 只需要對(duì)比幾個(gè)像素,就可以判斷是否為關(guān)鍵點(diǎn)。

跟Harris檢測(cè)器的情況一樣, FAST算法源于對(duì)構(gòu)成角點(diǎn)的定義。FAST對(duì)角點(diǎn)的定義基于候選特征點(diǎn)周圍的圖像強(qiáng)度值。 以某個(gè)點(diǎn)為中心作一個(gè)圓, 根據(jù)圓上的像素值判斷該點(diǎn)是否為關(guān)鍵點(diǎn)。 如果存在這樣一段圓弧, 它的連續(xù)長(zhǎng)度超過周長(zhǎng)的3/4, 并且它上面所有像素的強(qiáng)度值都與圓心的強(qiáng)度值明顯不同(全部更黑或更亮) , 那么就認(rèn)定這是一個(gè)關(guān)鍵點(diǎn)。

用這個(gè)算法檢測(cè)興趣點(diǎn)的速度非常快, 因此十分適合需要優(yōu)先考慮速度的應(yīng)用。 這些應(yīng)用包括實(shí)時(shí)視覺跟蹤、 目標(biāo)識(shí)別等, 它們需要在實(shí)
時(shí)視頻流中跟蹤或匹配多個(gè)點(diǎn)。

我們使用FastFeatureDetector 進(jìn)行特征點(diǎn)提取,因?yàn)閛pencv沒有提供fast專用的描述子提取器,所以我們借用SiftDescriptorExtractor 來實(shí)現(xiàn)描述子的提取。

#include "highgui/highgui.hpp"    
#include "opencv2/nonfree/nonfree.hpp"    
#include "opencv2/legacy/legacy.hpp"   
#include <iostream>  

using namespace cv;
using namespace std;


int main()
{

    Mat image01 = imread("1.jpg", 1);
    Mat image02 = imread("2.jpg", 1);
    imshow("p2", image01);
    imshow("p1", image02);

    //灰度圖轉(zhuǎn)換  
    Mat image1, image2;
    cvtColor(image01, image1, CV_RGB2GRAY);
    cvtColor(image02, image2, CV_RGB2GRAY);


    //提取特征點(diǎn)    
    FastFeatureDetector Detector(50);  //閾值 
    vector<KeyPoint> keyPoint1, keyPoint2;
    Detector.detect(image1, keyPoint1);
    Detector.detect(image2, keyPoint2);

    //特征點(diǎn)描述,為下邊的特征點(diǎn)匹配做準(zhǔn)備    
    SiftDescriptorExtractor   Descriptor;
    Mat imageDesc1, imageDesc2;
    Descriptor.compute(image1, keyPoint1, imageDesc1);
    Descriptor.compute(image2, keyPoint2, imageDesc2);

    BruteForceMatcher< L2<float> > matcher;   
    vector<vector<DMatch> > matchePoints;
    vector<DMatch> GoodMatchePoints;

    vector<Mat> train_desc(1, imageDesc1);
    matcher.add(train_desc);
    matcher.train();

    matcher.knnMatch(imageDesc2, matchePoints, 2);
    cout << "total match points: " << matchePoints.size() << endl;

    // Lowe's algorithm,獲取優(yōu)秀匹配點(diǎn)
    for (int i = 0; i < matchePoints.size(); i++)
    {
        if (matchePoints[i][0].distance < 0.6 * matchePoints[i][1].distance)
        {
            GoodMatchePoints.push_back(matchePoints[i][0]);
        }
    }

    Mat first_match;
    drawMatches(image02, keyPoint2, image01, keyPoint1, GoodMatchePoints, first_match);
    imshow("first_match ", first_match);
    imwrite("first_match.jpg", first_match);
    waitKey();
    return 0;
}

如果我們把描述子換成SurfDescriptorExtractor,即FastFeatureDetector + SurfDescriptorExtractor的組合,看看效果

可以看出,這種組合下的特征點(diǎn)匹配并不精確。

如果我們把描述子換成SurfDescriptorExtractor,即FastFeatureDetector + BriefDescriptorExtractor 的組合,看看效果

速度雖快,但是精度卻差強(qiáng)人意。

看到這里可能很多人會(huì)有疑惑:為什么FAST特征點(diǎn)可以用所以我們借用SiftDescriptorExtractor或者其他描述子提取器進(jìn)行提???

在這里我說一下自己的理解。要完成特征點(diǎn)的匹配第一個(gè)步驟就是找出每幅圖像的特征點(diǎn),這叫做特征檢測(cè),比如我們使用FastFeatureDetector、SiftFeatureDetector都是特征檢測(cè)的模塊。我們得到這些圖像的特征點(diǎn)后,我們就對(duì)這些特征點(diǎn)進(jìn)行進(jìn)一步的分析,用一些數(shù)學(xué)上的特征對(duì)其進(jìn)行描述,如梯度直方圖,局部隨機(jī)二值特征等。所以在這一步我們可以選擇其他描述子提取器對(duì)這些點(diǎn)進(jìn)行特征描述,進(jìn)而完成特征點(diǎn)的精確匹配。

在opencv中,SURF,ORB,SIFT既包含F(xiàn)eatureDetector,又包含 DescriptorExtractor,所以我們使用上述三種算法做特征匹配時(shí),都用其自帶的方法配套使用。

除此之外,如果我們相用FAST角點(diǎn)檢測(cè)并作特征點(diǎn)匹配該怎么辦?此時(shí)可以使用上述的FastFeatureDetector + BriefDescriptorExtractor 的方式,這種組合方式其實(shí)就是著名的ORB算法。所以特征點(diǎn)檢測(cè)和特征點(diǎn)匹配是兩種不同的步驟,我們只需根據(jù)自己項(xiàng)目的需求對(duì)這兩個(gè)步驟的方法隨意組合就好。

5.Harris角點(diǎn)

在圖像中搜索有價(jià)值的特征點(diǎn)時(shí),使用角點(diǎn)是一種不錯(cuò)的方法。 角點(diǎn)是很容易在圖像中定位的局部特征, 并且大量存在于人造物體中(例如墻壁、 門、 窗戶、 桌子等產(chǎn)生的角點(diǎn))。 角點(diǎn)的價(jià)值在于它是兩條邊緣線的接合點(diǎn), 是一種二維特征,可以被精確地定位(即使是子像素級(jí)精度)。 與此相反的是位于均勻區(qū)域或物體輪廓上的點(diǎn)以及在同一物體的不同圖像上很難重復(fù)精確定位的點(diǎn)。 Harris特征檢測(cè)是檢測(cè)角點(diǎn)的經(jīng)典方法。

這里僅展示GoodFeaturesToTrackDetector + SiftDescriptorExtractor的組合方式的代碼,其他組合不再演示。

#include "highgui/highgui.hpp"    
#include "opencv2/nonfree/nonfree.hpp"    
#include "opencv2/legacy/legacy.hpp"   
#include <iostream>  

using namespace cv;
using namespace std;


int main()
{

    Mat image01 = imread("1.jpg", 1);
    Mat image02 = imread("2.jpg", 1);
    imshow("p2", image01);
    imshow("p1", image02);

    //灰度圖轉(zhuǎn)換  
    Mat image1, image2;
    cvtColor(image01, image1, CV_RGB2GRAY);
    cvtColor(image02, image2, CV_RGB2GRAY);


    //提取特征點(diǎn)    
    GoodFeaturesToTrackDetector Detector(500);  //最大點(diǎn)數(shù),值越大,點(diǎn)越多
    vector<KeyPoint> keyPoint1, keyPoint2;
    Detector.detect(image1, keyPoint1);
    Detector.detect(image2, keyPoint2);

    //特征點(diǎn)描述,為下邊的特征點(diǎn)匹配做準(zhǔn)備    
    SiftDescriptorExtractor  Descriptor;
    Mat imageDesc1, imageDesc2;
    Descriptor.compute(image1, keyPoint1, imageDesc1);
    Descriptor.compute(image2, keyPoint2, imageDesc2);

    BruteForceMatcher< L2<float> > matcher;   
    vector<vector<DMatch> > matchePoints;
    vector<DMatch> GoodMatchePoints;

    vector<Mat> train_desc(1, imageDesc1);
    matcher.add(train_desc);
    matcher.train();

    matcher.knnMatch(imageDesc2, matchePoints, 2);
    cout << "total match points: " << matchePoints.size() << endl;

    // Lowe's algorithm,獲取優(yōu)秀匹配點(diǎn)
    for (int i = 0; i < matchePoints.size(); i++)
    {
        if (matchePoints[i][0].distance < 0.6 * matchePoints[i][1].distance)
        {
            GoodMatchePoints.push_back(matchePoints[i][0]);
        }
    }

    Mat first_match;
    drawMatches(image02, keyPoint2, image01, keyPoint1, GoodMatchePoints, first_match);
    imshow("first_match ", first_match);
    imwrite("first_match.jpg", first_match);
    waitKey();
    return 0;
}

匹配相當(dāng)精準(zhǔn)

計(jì)算機(jī)視覺領(lǐng)域其實(shí)還有了很多特征檢測(cè)的方法,比如HOG、Harr、LBP等,這里就不再敘述了,因?yàn)榉椒ǘ际穷愃?,我們根?jù)自己的需求挑選相應(yīng)的方法就好了。

到此這篇關(guān)于OpenCV實(shí)現(xiàn)特征檢測(cè)和特征匹配方法匯總的文章就介紹到這了,更多相關(guān)OpenCV 特征檢測(cè)和特征匹配內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++指針 詳細(xì)介紹及總結(jié)

    C++指針 詳細(xì)介紹及總結(jié)

    這篇文章主要介紹了C++指針 詳細(xì)介紹及總結(jié)的相關(guān)資料,需要的朋友可以參考下
    2016-09-09
  • 淺談C++左值引用和右值引用

    淺談C++左值引用和右值引用

    這篇文章主要介紹了C++左值引用和右值引用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 淺談C語言編程中的布爾bool數(shù)據(jù)類型

    淺談C語言編程中的布爾bool數(shù)據(jù)類型

    這篇文章主要介紹了C語言編程中的布爾bool數(shù)據(jù)類型,bool并不是需要通過C++才能使用的,需要的朋友可以參考下
    2015-11-11
  • C++?LeetCode542矩陣示例詳解

    C++?LeetCode542矩陣示例詳解

    這篇文章主要為大家介紹了C++?LeetCode542矩陣示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • 關(guān)于C++的重載運(yùn)算符和重載函數(shù)

    關(guān)于C++的重載運(yùn)算符和重載函數(shù)

    一般來說,重載運(yùn)算符在實(shí)際的項(xiàng)目開發(fā)中會(huì)經(jīng)常的用到,但如果某些自定義類型通過簡(jiǎn)短幾行代碼重載一些常用的運(yùn)算符(如:+-*/),就能讓編程工作帶來方便,需要的朋友可以參考下本文
    2023-05-05
  • c++并查集優(yōu)化(基于size和rank)

    c++并查集優(yōu)化(基于size和rank)

    這篇文章主要介紹了c++并查集優(yōu)化(基于size和rank),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • C++中inline函數(shù)詳解

    C++中inline函數(shù)詳解

    inline函數(shù)的定義:在函數(shù)聲明或定義中函數(shù)返回類型前加上關(guān)鍵字inline,即可以把函數(shù)指定為內(nèi)聯(lián)函數(shù)。inline函數(shù)對(duì)編譯器而言必須是可見的,以便它能夠在調(diào)用點(diǎn)展開該函數(shù)。
    2015-07-07
  • C++表達(dá)式求值詳解

    C++表達(dá)式求值詳解

    下面小編就為大家?guī)硪黄獪\談C++ 語言中的表達(dá)式求值。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2021-10-10
  • C++深入探索類和對(duì)象之封裝及class與struct的區(qū)別

    C++深入探索類和對(duì)象之封裝及class與struct的區(qū)別

    C++?類與對(duì)象涉及的知識(shí)點(diǎn)非常廣泛,所以我準(zhǔn)備寫成幾個(gè)特定的部分來作為博文分享,這次的blog將詳細(xì)講解類的屬性、行為、訪問權(quán)限,class與struct的區(qū)別以及具體案例,希望能夠?qū)δ銈冇袔椭?,解決入門小白或者對(duì)這方面了解不多的朋友們,那么接下來開始今天的內(nèi)容
    2022-05-05
  • C語言示例代碼講解棧與隊(duì)列

    C語言示例代碼講解棧與隊(duì)列

    棧和隊(duì)列,嚴(yán)格意義上來說,也屬于線性表,因?yàn)樗鼈円捕加糜诖鎯?chǔ)邏輯關(guān)系為?"一對(duì)一"?的數(shù)據(jù),但由于它們比較特殊,本章講解分別用隊(duì)列實(shí)現(xiàn)棧與用棧實(shí)現(xiàn)隊(duì)列
    2022-05-05

最新評(píng)論

永登县| 长兴县| 黄大仙区| 惠安县| 合水县| 绵竹市| 清新县| 黄大仙区| 伊川县| 楚雄市| 阿克苏市| 齐河县| 阿坝县| 大关县| 广州市| 吉首市| 吴忠市| 兴和县| 神农架林区| 子洲县| 沾益县| 施甸县| 云林县| 安康市| 临清市| 黔南| 古浪县| 岐山县| 闽侯县| 新巴尔虎左旗| 靖州| 祁阳县| 宁河县| 遵义市| 望奎县| 轮台县| 新乡市| 上思县| 峨边| 军事| 禹州市|