OpenCV实践之路——Qt中用opencv提取和匹配SIFT特征点
本文由@星沉閣冰不語(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)都匹配了。可以換成相似的或者完全不同的照片看看結(jié)果。
值得一提的是
SiftFeatureDetector featureDetector;可以換成
本文由@星沉閣冰不語(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)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从用户场景来看,什么是推荐系统
- 下一篇: 初中女生学计算机好还是学医好,最好就业的