Feature descriptors and matching of opencv (violence matching and FLANN matching)

What is feature descriptors / matching

What is feature descriptors
Pictures have their own characteristics
matching
Extract the features of an image, search for the training set image library and find the fitting area

Some API introduction

Function api

void cv::drawMatches(
                    InputArray  img1,
                    const std::vector< KeyPoint > &keypoints1,
                    InputArray  img2,
                    const std::vector< KeyPoint > &keypoints2,
                    const std::vector< DMatch > &matches1to2,
                    InputOutputArray    outImg,
                    const Scalar &  matchColor = Scalar::all(-1),
                    const Scalar &  singlePointColor = Scalar::all(-1),
                    const std::vector< char > &matchesMask = std::vector< char >(), 
                    int flags = DrawMatchesFlags::DEFAULT
                    )
void cv::drawMatches(
                    InputArray  img1,
                    const std::vector< KeyPoint > &keypoints1,
                    InputArray  img2,
                    const std::vector< KeyPoint > &keypoints2,
                    const std::vector< std::vector< DMatch > > &matches1to2,
                    InputOutputArray    outImg,
                    const Scalar &  matchColor = Scalar::all(-1),
                    const Scalar &  singlePointColor = Scalar::all(-1),
                    const std::vector< std::vector< char > > &matchesMask = std::vector< std::vector< char > >(), 
                    int flags = DrawMatchesFlags::DEFAULT
                    )   

Parameter introduction
The only difference between the two functions is that DMatch data receives different data types

  • img1: first source image received
  • keypoints1:KeyPoint type key point (feature point), detected by the first image
  • img2: second image received
  • keypoints2:KeyPoint type key point (feature point), detected by the second image
  • Matchsto2: dmatch type vector, representing the matching points from the first image to the second image, indicating that each feature point bean in Figure 1 has one-to-one corresponding points in Figure 2
  • outImg: output image after matching, whose content depends on flag of output image
  • matchColor: the color of two matching points for drawing matching, that is, the color of lines and points. A default value indicates that the color is randomly generated
  • singlePointColor: paint color for feature points without matching
  • Matchsmask: determine which masks will be drawn. If the mask is empty, all matching will be drawn
  • flags: draw matching flag bits, with the default value drawmatchsflags:: default. The options are as follows:
enum  { 
          DEFAULT = 0,  //The output image matrix is created, and only the middle part of each feature point is drawn.
          DRAW_OVER_OUTIMG = 1,     //Instead of creating an output image matrix, draw a match pair on the output image
          NOT_DRAW_SINGLE_POINTS = 2,   //Single point feature points are not drawn
          DRAW_RICH_KEYPOINTS = 4       //For each feature point, draw a key image with size and direction
      }

Violent match

Line by line, column by column to match
For example, the following example: use SURF feature extraction BF matching method to match (violent matching)

#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <iostream>

using namespace std;
using namespace cv;
using namespace cv::xfeatures2d;

#define PIC_PATH "/work/opencv_pic/"
#define PIC_NAME "opencv.jpg"

#define PIC_PATH1 "/work/opencv_pic/"
#define PIC_NAME1 "opencvbkp.jpg"

int main(void)
{
    Mat src,src1;

    //Get the complete picture path and name
    string pic = string(PIC_PATH1)+string(PIC_NAME1);
    string pic1 = string(PIC_PATH)+string(PIC_NAME);

    //Print picture path
    cout << "pic path is :"<<pic<<endl;
    cout << "pic1 path is :"<<pic1<<endl;
    //Read pictures
    src = imread(pic,IMREAD_GRAYSCALE);
    src1 = imread(pic1,IMREAD_GRAYSCALE);
    //Judge whether the picture exists
    if(src.empty() || src1.empty())
    {
        cout<<"pic is not exist!!!!"<<endl;
        return -1;
    }

    //display picture
    namedWindow("src pic",WINDOW_AUTOSIZE);
    imshow("src pic",src);
    namedWindow("src1 pic",WINDOW_AUTOSIZE);
    imshow("src1 pic",src1);


    int minHessian = 400;
    vector<KeyPoint> keypoint1,keypoint2;   //descriptor
    Mat descriptor1,descriptor2;            //Describing images

    Ptr<SURF> detector = SURF::create(minHessian);   //Create SURF object

    //Calculate eigenvalues
    detector->detectAndCompute(src,Mat(),keypoint1,descriptor1);
    detector->detectAndCompute(src1,Mat(),keypoint2,descriptor2);


    BFMatcher matcher;
    vector<DMatch> matches;
    matcher.match(descriptor1,descriptor2,matches);

    Mat matchimages;
    drawMatches(src,keypoint1,src1,keypoint2,matches,matchimages);
    imshow("matchImages",matchimages);

    waitKey(0);
    destroyAllWindows();
    return 0;
}

Code running effect

FLANN feature matching

The problem of nearest neighbor search is a major problem in image recognition, data compression, pattern recognition and classification, machine learning, document retrieval system, statistics and data analysis. It seems to be a very difficult task to solve this problem in high-dimensional space. No algorithm is obviously superior to standard brute force search, so more and more people turn their interest to execution A class of algorithms for nearest neighbor search.
FLANN (Fast Library for Approximate Nearest Neighbors) is the most complete near neighbor open source library at present. It not only implements a series of search algorithms, but also includes a mechanism of automatically selecting the fastest algorithm.
The function FlannBasedMatcher() is provided in opencv

Code demo

#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <iostream>

using namespace std;
using namespace cv;
using namespace cv::xfeatures2d;

#define PIC_PATH "/work/opencv_pic/"
#define PIC_NAME "opencv.jpg"

#define PIC_PATH1 "/work/opencv_pic/"
#define PIC_NAME1 "opencvbkp.jpg"

int main(void)
{
    Mat src,src1;

    //Get the complete picture path and name
    string pic = string(PIC_PATH1)+string(PIC_NAME1);
    string pic1 = string(PIC_PATH)+string(PIC_NAME);

    //Print picture path
    cout << "pic path is :"<<pic<<endl;
    cout << "pic1 path is :"<<pic1<<endl;
    //Read pictures
    src = imread(pic,IMREAD_GRAYSCALE);
    src1 = imread(pic1,IMREAD_GRAYSCALE);
    //Judge whether the picture exists
    if(src.empty() || src1.empty())
    {
        cout<<"pic is not exist!!!!"<<endl;
        return -1;
    }

    //display picture
    namedWindow("src pic",WINDOW_AUTOSIZE);
    imshow("src pic",src);
    namedWindow("src1 pic",WINDOW_AUTOSIZE);
    imshow("src1 pic",src1);


    int minHessian = 400;
    vector<KeyPoint> keypoint1,keypoint2;   //descriptor
    Mat descriptor1,descriptor2;            //Describing images

    Ptr<SURF> detector = SURF::create(minHessian);   //Create SURF object

    //Calculate eigenvalues
    detector->detectAndCompute(src,Mat(),keypoint1,descriptor1);
    detector->detectAndCompute(src1,Mat(),keypoint2,descriptor2);

    //BFMatcher matcher;
    FlannBasedMatcher matcher;   //Flann matcher
    vector<DMatch> matches;      //Matching data
    matcher.match(descriptor1,descriptor2,matches);   //Describe matching store matching results in matches
    
    //flann matching based on distance matching to find the best distance
    float maxdist = 3;
    float mindist = 100;

    //Find the maximum value and the minimum value by gradual convergence
    for(int i=0;i<descriptor1.rows;i++)
    {
        float distance = matches[i].distance;
        distance*=100;
         cout<<"distance: "<<distance<<endl;
        if(distance>maxdist)
            maxdist = distance;
        if(distance<mindist)
            mindist = distance;
    }

    //Print out the maximum value and the minimum value
    cout<<"maxdist: "<<maxdist<<endl;
    cout<<"mindist: "<<mindist<<endl;

    vector<DMatch> goodmatches;   //Define the optimal set of distance points
    for(int i=0;i<descriptor1.rows;i++)
    {
        float distance = matches[i].distance;
        if(distance*100<=2*mindist)
        {
            //Add the minimum distance found to goodmatches
            goodmatches.push_back(matches[i]);
        }
    }
    Mat matchimages;
    //Drawing matching points greatly reduced
    drawMatches(src,keypoint1,src1,keypoint2,goodmatches,matchimages);
    imshow("matchImages",matchimages);
    
    waitKey(0);
    destroyAllWindows();
    return 0;
}

Code running effect

101 original articles published, 41 praised, 50000 visitors+
Private letter follow

Tags: OpenCV

Posted on Sat, 01 Feb 2020 03:32:22 -0500 by xubi