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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

OpenCV实践之路——Qt中用opencv提取和匹配SIFT特征点

發(fā)布時(shí)間:2024/1/18 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCV实践之路——Qt中用opencv提取和匹配SIFT特征点 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文由@星沉閣冰不語(yǔ)出品,轉(zhuǎn)載請(qǐng)注明作者和出處。

文章鏈接:http://blog.csdn.net/xingchenbingbuyu/article/details/50695399

微博:http://weibo.com/xingchenbing?


SIFT是我本科畢業(yè)設(shè)計(jì)就開始研究的一個(gè)算法,也是視覺領(lǐng)域極為經(jīng)典的一個(gè)算法。SIFT算法的實(shí)質(zhì)是在不同的尺度空間上查找關(guān)鍵點(diǎn)(特征點(diǎn)),并計(jì)算出關(guān)鍵點(diǎn)的方向。SIFT所查找到的關(guān)鍵點(diǎn)是一些十分突出,不會(huì)因光照,仿射變換和噪音等因素而變化的點(diǎn),如角點(diǎn)、邊緣點(diǎn)、暗區(qū)的亮點(diǎn)及亮區(qū)的暗點(diǎn)等。?

Lowe將SIFT算法分解為如下四步:
1. 尺度空間極值檢測(cè):搜索所有尺度上的圖像位置。通過高斯微分函數(shù)來識(shí)別潛在的對(duì)于尺度和旋轉(zhuǎn)不變的興趣點(diǎn)。
2. 關(guān)鍵點(diǎn)定位:在每個(gè)候選的位置上,通過一個(gè)擬合精細(xì)的模型來確定位置和尺度。關(guān)鍵點(diǎn)的選擇依據(jù)于它們的穩(wěn)定程度。
3. 方向確定:基于圖像局部的梯度方向,分配給每個(gè)關(guān)鍵點(diǎn)位置一個(gè)或多個(gè)方向。所有后面的對(duì)圖像數(shù)據(jù)的操作都相對(duì)于關(guān)鍵點(diǎn)的方向、尺度和位置進(jìn)行變換,從而提供對(duì)于這些變換的不變性。

4. 關(guān)鍵點(diǎn)描述:在每個(gè)關(guān)鍵點(diǎn)周圍的鄰域內(nèi),在選定的尺度上測(cè)量圖像局部的梯度。這些梯度被變換成一種表示,這種表示允許比較大的局部形狀的變形和光照變化。

下面就來在Qt中調(diào)用Opencv來簡(jiǎn)單實(shí)現(xiàn)一下吧。

mainwindow.cpp如下:

#include "mainwindow.h" #include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow) {ui->setupUi(this);}MainWindow::~MainWindow() {delete ui; }void MainWindow::on_pushButton_clicked() { //打開一張圖片QString fileName = QFileDialog::getOpenFileName(this,tr("Open Image"),".",tr("Image File(*.png *.jpg *.jpeg *.bmp)"));image1 = cv::imread(fileName.toLatin1().data());if(image1.empty()){cout<<"Please open an image!" <<endl;}else{//把Mat轉(zhuǎn)換成QImagecv::cvtColor(image1,image1,CV_BGR2RGB);QImage img = QImage((const unsigned char*)(image1.data),image1.cols,image1.rows,QImage::Format_RGB888);//在QLabel中顯示圖片ui->label->setPixmap(QPixmap::fromImage(img));ui->label->resize(ui->label->pixmap()->size());} }void MainWindow::on_pushButton_2_clicked() {QString fileName = QFileDialog::getOpenFileName(this,tr("Open Image"),".",tr("Image File(*.png *.jpg *.jpeg *.bmp)"));image2 = cv::imread(fileName.toLatin1().data());if(image1.empty()){cout<<"Please open an image!" <<endl;}else{cv::cvtColor(image2,image2,CV_BGR2RGB);QImage img2 = QImage((const unsigned char*)(image2.data),image2.cols,image2.rows,QImage::Format_RGB888);ui->label_2->setPixmap(QPixmap::fromImage(img2));ui->label_2->resize(ui->label_2->pixmap()->size());} }void MainWindow::on_pushButton_3_clicked() {if(image1.empty()){cout<<"Please open an image!" <<endl;}else{ //特征點(diǎn)檢測(cè)SiftFeatureDetector featureDetector;featureDetector.detect(image1, image1_kp);//畫出特征點(diǎn)drawKeypoints(image1,image1_kp,image1,Scalar(0,255,0),DrawMatchesFlags::DRAW_RICH_KEYPOINTS);QImage img1 = QImage((const unsigned char*)(image1.data),image1.cols,image1.rows,QImage::Format_RGB888);ui->label->setPixmap(QPixmap::fromImage(img1));ui->label->resize(QSize(img1.width(),img1.height()));}if(image2.empty()){cout<<"Please open an image!" <<endl;}else{SiftFeatureDetector featureDetector;featureDetector.detect(image2, image2_kp);drawKeypoints(image2,image2_kp,image2,Scalar(0,255,0),DrawMatchesFlags::DRAW_RICH_KEYPOINTS);QImage img2 = QImage((const unsigned char*)(image2.data),image2.cols,image2.rows,QImage::Format_RGB888);ui->label_2->setPixmap(QPixmap::fromImage(img2));ui->label_2->resize(QSize(img2.width(),img2.height()));}}void MainWindow::on_pushButton_4_clicked() {Mat image1_desc,image2_desc;//特征點(diǎn)提取SiftDescriptorExtractor featureExtractor;featureExtractor.compute(image1, image1_kp, image1_desc);featureExtractor.compute(image2, image2_kp, image2_desc);//FLANN based descriptor matcher objectFlannBasedMatcher matcher;vector<Mat> image1_desc_collection(1, image1_desc);matcher.add(image1_desc_collection);matcher.train();//match image1 and image2 descriptor,getting 2 nearest neighbors for all test descriptorvector<vector<DMatch> > matches;matcher.knnMatch(image2_desc, matches, 2);//filter for good matches according to Lowe's algorithmvector<DMatch> good_matches;for (unsigned int i = 0; i < matches.size(); i++){if (matches[i][0].distance < 0.6*matches[i][1].distance)good_matches.push_back(matches[i][0]);}Mat img_show;drawMatches(image2, image2_kp, image1, image1_kp, good_matches, img_show);QImage img3 = QImage((const unsigned char*)(img_show.data),img_show.cols,img_show.rows,QImage::Format_RGB888);ui->label->setPixmap(QPixmap::fromImage(img3));ui->label->resize(QSize(img3.width(),img3.height()));ui->label_2->hide(); }


這里需要注意的一點(diǎn)是由于圖片在打開的時(shí)候已經(jīng)從BGR轉(zhuǎn)換到RGB了,最后提取和匹配特征點(diǎn)之后就不需要再轉(zhuǎn)換了,不然圖片發(fā)藍(lán)。

最后效果如下:

這里兩邊選擇了同一張照片,所以所有特征點(diǎn)都匹配了。可以換成相似的或者完全不同的照片看看結(jié)果。

值得一提的是

SiftFeatureDetector featureDetector;

可以換成

SurfFeatureDetector featureDetector; <pre name="code" class="cpp">OrbFeatureDetector featureDetector;

FlannBasedMatcher matcher;可以換成

BFMatcher matcher;//Brute Force based descriptor matcher object更多細(xì)節(jié)還得自己親自去探索。


本文由@星沉閣冰不語(yǔ)出品,轉(zhuǎn)載請(qǐng)注明作者和出處。

文章鏈接:http://blog.csdn.net/xingchenbingbuyu/article/details/51375078

微博:http://weibo.com/xingchenbing?


總結(jié)

以上是生活随笔為你收集整理的OpenCV实践之路——Qt中用opencv提取和匹配SIFT特征点的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。