4. 关键点描述:在每个关键点周围的邻域内,在选定的尺度上测量图像局部的梯度。这些梯度被变换成一种表示,这种表示允许比较大的局部形状的变形和光照变化。
下面就来在Qt中调用Opencv来简单实现一下吧。
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转换成QImage cv::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 { //特征点检测 SiftFeatureDetector featureDetector; featureDetector.detect(image1, image1_kp); //画出特征点 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; //特征点提取 SiftDescriptorExtractor featureExtractor; featureExtractor.compute(image1, image1_kp, image1_desc); featureExtractor.compute(image2, image2_kp, image2_desc); //FLANN based descriptor matcher object FlannBasedMatcher 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 descriptor vector<vector<DMatch> > matches; matcher.knnMatch(image2_desc, matches, 2); //filter for good matches according to Lowe's algorithm vector<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(); }
最后效果如下:
这里两边选择了同一张照片,所以所有特征点都匹配了。可以换成相似的或者完全不同的照片看看结果。
值得一提的是
SiftFeatureDetector featureDetector;
可以换成
SurfFeatureDetector featureDetector;
<pre name="code" class="cpp">OrbFeatureDetector featureDetector;而
FlannBasedMatcher matcher;可以换成
BFMatcher matcher;//Brute Force based descriptor matcher object更多细节还得自己亲自去探索。