在场景图片里提取二维码进行orb特征点匹配+opencv

在场景图片里提取二维码进行orb特征点匹配+opencv

1.代码


#include <opencv2/opencv.hpp>  
#include <iostream>  
#include<time.h>
#include<math.h>
#include <iostream>  
#include <set>
#include <opencv2/highgui/highgui.hpp>    
#include <opencv2/features2d/features2d.hpp>   
#include <opencv2/core/core.hpp> 
#include <opencv2/imgproc/imgproc.hpp> 
using namespace cv;
using namespace std;

RNG rng(12345);
//截取的四边形矩形图片名字
int cacORBFeatureAndCompare(Mat image1, Mat image2)
{
    
    
    {
    
    
       
        //cvtColor(image1,image1,COLOR_RGB2GRAY);
        //cvtColor(image2, image2,COLOR_RGB2GRAY);
        CV_Assert(image1.data != NULL && image2.data != NULL);//CV_Assert()若括号中的表达式值为false,则返回一个错误信息。
        vector<KeyPoint> keyPoint1, keyPoint2;
        Ptr<ORB> orb = ORB::create(100);
        Mat descriptors1, descriptors2;
        orb->detectAndCompute(image1, Mat(), keyPoint1, descriptors1);
        orb->detectAndCompute(image2, Mat(), keyPoint2, descriptors2);
        cout << "Key points of image" << keyPoint1.size() << endl;

        //可视化,显示关键点
        Mat ShowKeypoints1, ShowKeypoints2;
        drawKeypoints(image1, keyPoint1, ShowKeypoints1);
        drawKeypoints(image2, keyPoint2, ShowKeypoints2);
        imshow("Keypoints1", ShowKeypoints1);
        imshow("Keypoints2", ShowKeypoints2);
       // waitKey(0);

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

        //可视化
        Mat ShowMatches;
        drawMatches(image1, keyPoint1, image2, keyPoint2, matches, ShowMatches);
        imshow("matches", ShowMatches);
        waitKey(0);
        return 0;
    }
}

Mat QRtrack(Mat srcImageCopy)
{
    
    
    Mat srcImageCopy1;
    srcImageCopy.copyTo(srcImageCopy1);
    Mat srcImage0;
    srcImageCopy.copyTo(srcImage0);
    cvtColor(srcImage0, srcImage0, COLOR_RGB2GRAY);
   
    Mat srcImage = Mat::zeros(srcImage0.rows, srcImage0.cols, CV_8UC3);
    resize(srcImage0, srcImage, srcImage.size());
    threshold(srcImage, srcImage, 150, 255, THRESH_BINARY);
    //imshow("二值化", srcImage);
    //getStructuringElement函数会返回指定形状和尺寸的结构元素
    Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
    //morphologyEx(srcImage, srcImage, MORPH_CLOSE, element);//闭运算滤波
    vector<vector<Point>> contours, RectContours, contoursMax;//轮廓,为点向量,
    findContours(srcImage, contours, RETR_LIST, CHAIN_APPROX_NONE);//找轮廓
    vector<vector<Point>> hull(contours.size());//用于存放凸包
    Mat drawing(srcImage.size(), CV_8UC3, cv::Scalar(0));
    int i = 0;
    int num[100];
    int sum = 0;
    double Length = 0;
    vector<float> length(contours.size());//用于保存每个轮廓的长度
    vector<float> Area_contours(contours.size()), Area_hull(contours.size()), Rectangularity(contours.size()), circularity(contours.size());
    for (i = 0; i < contours.size(); i++)
    {
    
    //把所有的轮廓画出来
        Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
        length[i] = arcLength(contours[i], true);//轮廓的长度   
        if (length[i] > 200)
        {
    
    //通过长度匹配滤除小轮廓
            if (length[i] >= Length)
            {
    
    
                convexHull(Mat(contours[i]), hull[i], false);//把凸包找出来,寻找凸包函数
                Area_contours[i] = contourArea(contours[i]);   //轮廓面积
                Area_hull[i] = contourArea(hull[i]);           //凸包面积
                Rectangularity[i] = Area_contours[i] / Area_hull[i]; //矩形度
                if (Rectangularity[i] > 0.85)
                {
    
    
                    //通过矩形度和圆形度滤除数字 
                    //Length = arcLength(contours[i], true);
                    num[sum] = i;
                    if (sum > 0)
                    {
    
    
                        if (arcLength(contours[num[sum]], true) > arcLength(contours[num[sum - 1]], true))
                        {
    
    
                            Length = arcLength(contours[i], true);
                            sum++;
                        }
                    }
                    else
                    {
    
    
                        Length = arcLength(contours[i], true);
                        sum++;
                    }
                    drawContours(drawing, hull, i, color, 1);
                    drawContours(srcImageCopy, hull, i, color, 1); //得到四边形
                }
            }
        }
    }
    if ((sum - 1) >= 0)
    {
    
    
        RectContours.push_back(hull[num[sum - 1]]);//把提取出来的方框导入到新的轮廓组
        vector<vector<Point> > contours_poly(RectContours.size());
        vector<Rect> boundRect(RectContours.size()); //最小矩形

        //一个循环,遍历所有部分,进行本程序最核心的操作
        for (unsigned int i = 0; i < RectContours.size(); i++)
        {
    
    
            approxPolyDP(RectContours[i], contours_poly[i], 3, true);//用指定精度逼近多边形曲线 
            boundRect[i] = boundingRect(Mat(contours_poly[i]));//计算点集的最外面(up-right)矩形边界
        }
        // 绘制多边形轮廓 + 包围的矩形框 
        Mat drawing1 = Mat::zeros(srcImage.size(), CV_8UC3);
        Mat image_cut[100];      //从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy  
        Mat image_copy[100];   //clone函数创建新的图片 
        for (int unsigned i = 0; i < RectContours.size(); i++)
        {
    
    
            Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));//随机设置颜色
            Point text_lb;//中点
            rectangle(drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);//绘制矩形
            text_lb = Point((boundRect[i].tl().x + boundRect[i].br().x) * 0.5, (boundRect[i].tl().y + boundRect[i].br().y) * 0.5);
            //putTextZH(drawing, "中点", center[i], Scalar(0, 0, 255), 10, "Arial");
            int width = abs(boundRect[i].tl().x - boundRect[i].br().x);
            int height = abs(boundRect[i].tl().y - boundRect[i].br().y);
            Rect rect(boundRect[i].tl().x , boundRect[i].tl().y , width , height );   //创建一个Rect框,属于cv中的类,四个参数代表x,y,width,height  

            image_cut[i] = Mat(srcImageCopy1, rect);      //从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy  
            image_copy[i] = image_cut[i].clone();   //clone函数创建新的图片 
          
            return  image_copy[i];
        }
    }
    else
    {
    
    
        cout << "无匹配";
        

    }
}


int main()
{
    
    
    char strangerName[2000];
    char strangerName1[2000];
    Mat model, m001;
    sprintf_s(strangerName, "model");
    sprintf_s(strangerName1,"pipei");
    Mat srcImageCopy1= imread("G:\\22\\00009.jpg", 2|4);

    Mat srcImageCopy2 = imread("G:\\44\\00014.jpg", 2|4);

    namedWindow(strangerName, WINDOW_AUTOSIZE);
    namedWindow(strangerName1, WINDOW_AUTOSIZE);
    imshow(strangerName,QRtrack(srcImageCopy1));
    imshow(strangerName1, QRtrack(srcImageCopy2));
    QRtrack(srcImageCopy1).copyTo(model);
    QRtrack(srcImageCopy2).copyTo(m001);
    
    
    cacORBFeatureAndCompare(m001,model);
    waitKey(0);
    return 0;
}


2.效果

在这里插入图片描述

3.注意点

opencv4.1.1不允许使用抽象类类型“cv::FastFeatureDetector”的对象.
为什么会报错?
角点检测的几个方法(SURF,SIFT,ORB)都被转移opencv_contrib中了。所以版本之间有差异。
转自:https://blog.csdn.net/weixin_43860261/article/details/88672429
转载完整工程项目代码:https://download.csdn.net/download/m0_45866718/12819697

猜你喜欢

转载自blog.csdn.net/m0_45866718/article/details/108164244