点集拟合
背景:当关注区域是面积较小、数目较多的像素点或者点集,且区域相对集中时,如果寻找每个轮廓的外接多边形,那么结果会有较多的多边形。为了避免该情况,我们将像素点或连通域看成一个大的区域,并寻找可以包围该区域的规则图形,如三角形、圆形等。
寻找包围三角形:
area = minEnclosingTriangle(points, triangle)
参数一:待寻找包围三角形的二维点集
参数二:三角形顶点坐标
返回:三角形面积
寻找包围圆:
minEnclosingCircle(points, center, radius)
参数一:待寻找包围圆形的二维点集
参数二、三:圆的圆心和半径
#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream>
#include<math.h>
#include <opencv2/imgproc.hpp>
#include<vector>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
//QuickDemo qd;
//qd.myFilter_demo(src);
//system("color F0");
Mat img(500, 500, CV_8UC3, Scalar::all(0));
RNG& rng = theRNG(); //生成随机点
while (true) {
int i, count = rng.uniform(1, 101);
vector<Point> points;
//生成随机点
for (i = 0; i < count; i++) {
Point pt;
pt.x = rng.uniform(img.cols / 4, img.cols * 3 / 4);
pt.y= rng.uniform(img.rows / 4, img.rows * 3 / 4);
points.push_back(pt);
}
//寻找包围点集的三角形
vector<Point> triangle;
double area = minEnclosingTriangle(points, triangle);
//寻找包围点集的圆形
float radius = 0;
Point2f center;
minEnclosingCircle(points, center, radius);
//创建两幅图片用于输出结果
img = Scalar::all(0);
Mat img2;
img.copyTo(img2);
//在图像中绘制坐标点
for (i = 0; i < count; i++) {
circle(img, points[i], 3, Scalar(255, 255, 255), FILLED, LINE_AA);
circle(img2, points[i], 3, Scalar(255, 255, 255), FILLED, LINE_AA);
}
for (i = 0; i < 3; i++) {
if (i == 2) {
line(img, triangle[i], triangle[0], Scalar(255, 255, 255), 1, 16);
break;
}
line(img, triangle[i], triangle[i+1], Scalar(255, 255, 255), 1, 16);
}
//绘制圆形
circle(img2, center, cvRound(radius), Scalar(255, 255, 255), 1, LINE_AA);
//输出结果
imshow("triangle", img);
imshow("circle", img2);
//按Q或者Esc退出程序
char key = (char)waitKey();
if (key == 27 || key == 'q' || key == 'Q') {
break;
}
}
//waitKey(0);
//destroyAllWindows();
return 0;
}
QR二维码检测
识别过程:
定位
isQRcode = qrcodedetector.detect(gray, points)
返回值:bool类型,图像是否含有二维码
参数一:待检测图像
参数二:二维码四个顶点坐标
解码
information = qrcodedetector.decode(gray, points, qrcode_bin);
返回值:string类型,解码结果
参数一:待检测图像
参数二:二维码四个顶点坐标
参数三:经过校正和二值化的二维码
定位+解码
information2 = qrcodedetector.detectAndDecode(gray, points2);
#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream>
#include<math.h>
#include <opencv2/imgproc.hpp>
#include<vector>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
//QuickDemo qd;
//qd.myFilter_demo(src);
//system("color F0");
Mat img = imread("D:/images/QR.png");
if (img.empty()) {
cout << "请输入正确的图像文件" << endl;
return -1;
}
Mat gray, qrcode_bin;
cvtColor(img, gray, COLOR_BGR2GRAY);
QRCodeDetector qrcodedetector;
vector<Point> points;
string information;
bool isQRcode;
isQRcode = qrcodedetector.detect(gray, points); //识别二维码
if (isQRcode) {
//解码
information = qrcodedetector.decode(gray, points, qrcode_bin);
cout << points << endl;
}
else {
cout << "无法识别二维码,请确认图像是否含有二维码" << endl;
return -1;
}
//绘制二维码的边框
for (int i = 0; i < points.size(); i++) {
if (i == points.size() - 1) {
line(img, points[i], points[0], Scalar(0, 0, 255), 2, 8);
break;
}
line(img, points[i], points[i+1], Scalar(0, 0, 255), 2, 8);
}
//将内容输出到图片上
putText(img, information.c_str(), Point(20, 30), 0, 1.0, Scalar(0, 0, 255), 2, 8);
//利用函数直接定位二维码,并解码
string information2;
vector<Point> points2;
information2 = qrcodedetector.detectAndDecode(gray, points2);
cout << points2 << endl;
putText(img, information2.c_str(), Point(20, 55), 0, 1.0, Scalar(0, 0, 0), 2, 8);
//输出结果
imshow("result", img);
namedWindow("qrcode_bin", WINDOW_NORMAL);
imshow("qrcode_bin", qrcode_bin);
waitKey(0);
//destroyAllWindows();
return 0;
}