在场景图片里提取二维码进行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