《Qt+Opencv入门(一)-- 基础算法 ORB SHIF SURF试验》

背景

1.Qt安装opencv网上教程很多,不在重复。贴个地址
2. 试验的方法都是网上找的一些算法进行测试。有用的请自取
3. 原本是想弄从判断某个游戏是否在某个界面上,奈何这些算法实现好像有点出入

进入正题

.pro 文件设置
OPENCV_SDK_DIR 为系统设置的安装完的opencv 路径
我的路径如下图,自己的路径自己修改
《Qt+Opencv入门(一)-- 基础算法 ORB SHIF SURF试验》_第1张图片

INCLUDEPATH += $$(OPENCV_SDK_DIR)/include

LIBS += -L$$(OPENCV_SDK_DIR)/x64/mingw/lib\
        -lopencv_core411        \
        -lopencv_highgui411     \
        -lopencv_imgcodecs411   \
        -lopencv_imgproc411     \
        -lopencv_features2d411  \
        -lopencv_calib3d411     \
        -lopencv_xfeatures2d411

mainwindow.cpp的 代码如下

#include "mainwindow.h"
#include "ui_mainwindow.h"



MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QString fileName,fileName2;

    fileName = QCoreApplication::applicationDirPath();
    fileName+="/images/";
    fileName+="1.jpg";

    fileName2 = QCoreApplication::applicationDirPath();
    fileName2+="/images/";
    fileName2+="2.jpg";

    Mat image = imread(fileName.toStdString());
    Mat image2 = imread(fileName2.toStdString());

    //新建一个窗口,显示该图片
    //imshow("My Image", image);

    //double ok =getPSNR(image,image2);
   // qDebug()<
//    if(ok){
//        qDebug()<<"一样";
//    }else{
//        qDebug()<<"不一样";
//    }


}

bool MainWindow::matIsEqual(const cv::Mat mat1, const cv::Mat mat2) {
    if (mat1.empty() && mat2.empty()) {
        return true;
    }
    if (mat1.cols != mat2.cols || mat1.rows != mat2.rows || mat1.dims != mat2.dims||
        mat1.channels()!=mat2.channels()) {
        return false;
    }
    if (mat1.size() != mat2.size() || mat1.channels() != mat2.channels() || mat1.type() != mat2.type()) {
        return false;
    }
    int nrOfElements1 = mat1.total()*mat1.elemSize();
    if (nrOfElements1 != mat2.total()*mat2.elemSize()) return false;
    bool lvRet = memcmp(mat1.data, mat2.data, nrOfElements1) == 0;
    return lvRet;
}


double MainWindow::getPSNR(Mat matSrc1,Mat matSrc2)
{
    Mat matDst1, matDst2;
        // 缩小尺寸:将图像缩小到8*8的尺寸,总共64个像素。这一步的作用是去除图像的细节,只保留结构/明暗等基本信息,摒弃不同尺寸/比例带来的图像差异;
        cv::resize(matSrc1, matDst1, Size(8, 8));
        cv::resize(matSrc2, matDst2, Size(8, 8));
        //灰度化
        //cvtColor(matSrc1, matDst1, CV_BGR2GRAY);
        //cvtColor(matSrc2, matDst2, CV_BGR2GRAY);
        cvtColor(matDst1, matDst1, CV_BGR2GRAY);
        cvtColor(matDst2, matDst2, CV_BGR2GRAY);

        //threshold(matDst1, matDst1, 100, 255, CV_THRESH_BINARY);
       // threshold(matDst2, matDst2, 100, 255, CV_THRESH_BINARY);

        imshow("Keypoints1", matDst1);
        imshow("Keypoints2", matDst2);

        int iAvg1 = 0, iAvg2 = 0;
        int arr1[64], arr2[64];
        for (int i = 0; i < 8; i++) {
            //位置是第i行的头指针
            uchar* data1 = matDst1.ptr<uchar>(i);
            uchar* data2 = matDst2.ptr<uchar>(i);
            int tmp = i * 8;
            for (int j = 0; j < 8; j++) {
                int tmp1 = tmp + j;
                arr1[tmp1] = data1[j] / 4 ;
                arr2[tmp1] = data2[j] / 4 ;
                iAvg1 += arr1[tmp1];
                iAvg2 += arr2[tmp1];
            }
        }
        iAvg1 /= 64;
        iAvg2 /= 64;
        for (int i = 0; i < 64; i++) {
            arr1[i] = (arr1[i] >= iAvg1) ? 1 : 0;
            arr2[i] = (arr2[i] >= iAvg2) ? 1 : 0;
        }
        int iDiffNum = 0;
        for (int i = 0; i < 64; i++)
            if (arr1[i] != arr2[i])
                ++iDiffNum;
        return iDiffNum;
}

int MainWindow::getORB(Mat rgbd1,Mat rgbd2){


//   Mat rgbd1 = imread("自己的图片Path");
//   Mat rgbd2 = imread("自己的图片Path");

//   Mat rgbd1 = imread(imagePatha);
//   Mat rgbd2 = imread(imagePathb);
   if (!rgbd1.data || !rgbd2.data)
   {
      cout << "error reading images " << endl;      return -1;
   }
   Ptr<ORB> orb = ORB::create();
   vector<KeyPoint> Keypoints1,Keypoints2;
   Mat descriptors1,descriptors2;

   orb->detectAndCompute(rgbd1, Mat(), Keypoints1, descriptors1);
   orb->detectAndCompute(rgbd2, Mat(), Keypoints2, descriptors2);

   //cout << "Key points of image" << Keypoints.size() << endl;

   //可视化,显示关键点
   Mat ShowKeypoints1, ShowKeypoints2;
   drawKeypoints(rgbd1,Keypoints1,ShowKeypoints1);
   drawKeypoints(rgbd2, Keypoints2, ShowKeypoints2);
   imshow("Keypoints1", ShowKeypoints1);
   imshow("Keypoints2", ShowKeypoints2);
   waitKey(0);

   //Matching
   vector<DMatch> matches;
   Ptr<DescriptorMatcher> matcher =DescriptorMatcher::create("BruteForce");
   matcher->match(descriptors1, descriptors2, matches);
   qDebug() << "find out total " << matches.size() << " matches" << endl;

   //可视化
   Mat ShowMatches;
   drawMatches(rgbd1,Keypoints1,rgbd2,Keypoints2,matches,ShowMatches);
   imshow("matches", ShowMatches);
   waitKey(0);

       return 0;
}



void MainWindow::imgSIFT(Mat img_1,Mat img_2)//SIFT算法
{
    //sift算法不是开源的所以很多内容用起来很不方便
    //Create SIFT class pointer
    Ptr<Feature2D> f2d = xfeatures2d::SIFT::create();
    //1、读入图片
//    Mat img_1 = imread("D:/ImageTest/source.png");//模板图片
//    Mat img_2 = imread("D:/ImageTest/222.JPG");//检测图片
    //2、声明检测点;Detect the keypoints
    vector<KeyPoint> keypoints_1, keypoints_2;
    f2d->detect(img_1, keypoints_1);
    f2d->detect(img_2, keypoints_2);
    //3、计算描述符(特征向量);Calculate descriptors (feature vectors)
    Mat descriptors_1, descriptors_2;
    f2d->compute(img_1, keypoints_1, descriptors_1);
    f2d->compute(img_2, keypoints_2, descriptors_2);
    //4、使用BFMatcher匹配描述符向量;Matching descriptor vector using BFMatcher
    BFMatcher matcher;
    vector<DMatch> matches;
    matcher.match(descriptors_1, descriptors_2, matches);
    //5、绘制匹配出的关键点
    Mat img_matches;
    drawMatches(img_1, keypoints_1, img_2, keypoints_2, matches, img_matches);
    imshow("match",img_matches);
    //6、匹配结果筛选
    nth_element(matches.begin(), matches.begin()+30, matches.end());   //提取出前最佳匹配结果
    matches.erase(matches.begin()+30, matches.end());    //剔除掉其余的匹配结果
    Mat img_matches2;
    drawMatches(img_1, keypoints_1, img_2, keypoints_2, matches, img_matches2);
    imshow("match2",img_matches2);
    waitKey(0);
}

// Surf 特征检测与匹配:
int MainWindow::Surf(Mat img_1,Mat img_2)
{

    //1、加载图片
//    Mat img_1 = imread( "D:/ImageTest/source.png", IMREAD_GRAYSCALE );//模板图片
//    Mat img_2 = imread("D:/ImageTest/222.JPG", IMREAD_GRAYSCALE );//被查找图片
    //2、使用SURF检测器检测关键点,计算描述符;Detect the keypoints using SURF Detector, compute the descriptors
    int minHessian = 400;

    Ptr<Feature2D> detector = xfeatures2d::SURF::create();
//    detector.setHessianThreshold(minHessian);
//    detector.reset(minHessian);
    std::vector<KeyPoint> keypoints_1, keypoints_2;
    Mat descriptors_1, descriptors_2;
    detector->detectAndCompute( img_1, Mat(), keypoints_1, descriptors_1 );
    detector->detectAndCompute( img_2, Mat(), keypoints_2, descriptors_2 );
    //3、匹配描述符向量与一个蛮力匹配;Matching descriptor vectors with a brute force matcher
    BFMatcher matcher(NORM_L2);
    std::vector< DMatch > matches;
    matcher.match( descriptors_1, descriptors_2, matches );
    //4、绘制匹配结果;Draw matches
    Mat img_matches;
    drawMatches( img_1, keypoints_1, img_2, keypoints_2, matches, img_matches );
    //5、显示检测到匹配; Show detected matches
    imshow("SURF_Matches", img_matches );
    //6、匹配结果筛选
    nth_element(matches.begin(), matches.begin()+50, matches.end());   //提取出前最佳匹配结果
    matches.erase(matches.begin()+50, matches.end());    //剔除掉其余的匹配结果
    Mat img_matches2;
    drawMatches(img_1, keypoints_1, img_2, keypoints_2, matches, img_matches2);
    imshow("SURF_Matches2",img_matches2);
    waitKey(0);
}

//滑动条回调函数
void MatchingMethod( int, void* )
{
  // 将被显示的原图像
#if 0
  Mat img_display;
  img.copyTo( img_display );
  //cvtColor(img_display,img_display,CV_GRAY2BGR);

  // 创建输出结果的矩阵
  int result_cols =  img.cols - templ.cols + 1;
  int result_rows = img.rows - templ.rows + 1;

  result.create( result_cols, result_rows, CV_32FC1 );

  // 进行匹配和标准化
  matchTemplate( img, templ, result, match_method );
  normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );

  // 通过函数 minMaxLoc 定位最匹配的位置
  double minVal; double maxVal; Point minLoc; Point maxLoc;
  Point matchLoc;

  minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );

  // 对于方法 SQDIFF 和 SQDIFF_NORMED, 越小的数值代表更高的匹配结果. 而对于其他方法, 数值越大匹配越好
  if( match_method  == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED )
    { matchLoc = minLoc; }
  else
    { matchLoc = maxLoc; }

  //cvtColor(result,result,CV_GRAY2BGR);
  // 绘制匹配结果
  rectangle( img_display, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
  rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );

  imshow( image_window, img_display );
  imshow( result_window, result );
#endif
}


MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked(bool checked)
{
    QString filename = QFileDialog::getOpenFileName(this,
            tr("选择图片"),
            "",
            tr("Images(*.png *.bmp *.jpg *.tif *.GIF)"));
        if (filename.isEmpty())
        {
            return;
        }
        else
        {
            string str = filename.toStdString();  // 将filename转变为string类型;
            image_1 = imread(str);
            cvtColor(image_1, image_1, CV_BGR2RGB);
            cv::resize(image_1, image_1, Size(300, 200));
            QImage img_1 = QImage((const unsigned char*)(image_1.data), image_1.cols, image_1.rows, QImage::Format_RGB888);
            label_1 = new QLabel();
            label_1->setPixmap(QPixmap::fromImage(img_1));
            label_1->resize(QSize(img_1.width(), img_1.height()));
            ui->Picture1->setWidget(label_1);
            //ui->Picture1->setWidget(label_1);
            //ui->tableWidget.setWidget(label_1);
        }

}

void MainWindow::on_pushButton_2_clicked()
{
    QString filename = QFileDialog::getOpenFileName(this,
            tr("选择图片"),
            "",
            tr("Images(*.png *.bmp *.jpg *.tif *.GIF)"));
        if (filename.isEmpty())
        {
            return;
        }
        else
        {
            string str = filename.toStdString();  // 将filename转变为string类型;
            image_2 = imread(str);
            //image=imread(fileName.toLatin1().data);
            cvtColor(image_2, image_2, CV_BGR2RGB);
            cv::resize(image_2, image_2, Size(300, 200));
            QImage img_1 = QImage((const unsigned char*)(image_2.data), image_2.cols, image_2.rows, QImage::Format_RGB888);
            label_1 = new QLabel();
            label_1->setPixmap(QPixmap::fromImage(img_1));
            label_1->resize(QSize(img_1.width(), img_1.height()));
            ui->Picture2->setWidget(label_1);
        }
}

void MainWindow::on_pushButton_3_clicked()
{
        //progress *pro;
        QString panduan;
        int den=((getPSNR(image_1, image_2)));
        if (den <= 5)
        {
            panduan = "They are too similar!";
        }
        else if (den > 10)
        {
            panduan = "They are two different pictures!";
        }
        else
        {
            panduan = "They are a litter similar.";
        }
        den = 100 - den;
        QString str = QString::number(den);
        QString buf = "相似度为: " + str +"%  我的判断为: " + panduan;

        ui->Similar_text->setText(buf);

}

void MainWindow::on_pushButton_4_clicked()
{
    QString panduan;
    int den=((getORB(image_1, image_2)));
    if (den <= 5)
    {
        panduan = "They are too similar!";
    }
    else if (den > 10)
    {
        panduan = "They are two different pictures!";
    }
    else
    {
        panduan = "They are a litter similar.";
    }
    den = 100 - den;
    QString str = QString::number(den);
    QString buf = "相似度为: " + str +"%  我的判断为: " + panduan;

    ui->Similar_text->setText(buf);
}


void MainWindow::on_pushButton_5_clicked()
{

    imgSIFT(image_1, image_2);
}

#if 0
/*Method
0: SQDIFF           平方差匹配
1: SQDIFF NORMED    标准平方差匹配
2: TM CCORR         相关匹配
3: TM CCORR NORMED  标准相关匹配
4: TM COEFF         相关匹配
5: TM COEFF NORMED" 标准相关匹配
*/

//滑动条回调函数
void MainWindow::MatchingMethod( int, void* )
{
  // 将被显示的原图像
  Mat img_display;
  image_1.copyTo( img_display );
  //cvtColor(img_display,img_display,CV_GRAY2BGR);

  // 创建输出结果的矩阵
  int result_cols =  image_1.cols - templ.cols + 1;
  int result_rows = image_1.rows - templ.rows + 1;

  result.create( result_cols, result_rows, CV_32FC1 );

  // 进行匹配和标准化
  matchTemplate( image_1, templ, result, match_method );
  normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );

  // 通过函数 minMaxLoc 定位最匹配的位置
  double minVal; double maxVal; Point minLoc; Point maxLoc;
  Point matchLoc;

  minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );

  // 对于方法 SQDIFF 和 SQDIFF_NORMED, 越小的数值代表更高的匹配结果. 而对于其他方法, 数值越大匹配越好
  if( match_method  == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED )
    { matchLoc = minLoc; }
  else
    { matchLoc = maxLoc; }

  //cvtColor(result,result,CV_GRAY2BGR);
  // 绘制匹配结果
  rectangle( img_display, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
  rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );

  imshow( image_window, img_display );
  imshow( result_window, result );

}
#endif

void MainWindow::on_pushButton_6_clicked()
{
    Surf(image_1, image_2);
}

mainwindow.h 的代码如下

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
#include 
#include 
#include                    //graphicsview类
#include 
#include       // Basic OpenCV structures
#include // Image processing methods for the CPU
#include // Read images
#include 
#include 
#include 


#include 
#include 
#include 

using namespace  cv;
using namespace std;

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    bool   matIsEqual(const cv::Mat mat1, const cv::Mat mat2);
    double getPSNR(Mat matSrc1,Mat matSrc2);
    int    getORB(Mat rgbd1,Mat rgbd2);
    void   imgSIFT(Mat img_1,Mat img_2);//SIFT算法
    int     Surf(Mat img_1,Mat img_2);
    void MatchingMethod( int, void* );
private slots:
    void on_pushButton_clicked(bool checked);

    void on_pushButton_2_clicked();

    void on_pushButton_3_clicked();

    void on_pushButton_4_clicked();

    void on_pushButton_5_clicked();

    void on_pushButton_6_clicked();

private:
    Ui::MainWindow *ui;
    cv::Mat image_1,image_2,image1_kp,image2_kp;						//图像
    QLabel *label_1;
    QLabel *label_2;

};

#endif // MAINWINDOW_H

ui的一些变量名
《Qt+Opencv入门(一)-- 基础算法 ORB SHIF SURF试验》_第2张图片

《Qt+Opencv入门(一)-- 基础算法 ORB SHIF SURF试验》_第3张图片

预留贴个7积分的工程下载目录:-https://download.csdn.net/download/wangsenye/12537449

你可能感兴趣的:(opencv,opencv)