目录
1、凸包检测
2、直线检测
3、点集拟合
4、二维码检测
1、凸包检测
//凸包检测
int test1()
{
Mat img = imread("F:/testMap/hand.png");
if (img.empty())
{
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
// 二值化
Mat gray, binary;
cvtColor(img, gray, COLOR_BGR2GRAY);
threshold(gray, binary, 105, 255, THRESH_BINARY);
//开运算消除细小区域
Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
morphologyEx(binary, binary, MORPH_OPEN, k);
imshow("binary", binary);
//轮廓发现
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(binary, contours, hierarchy, 0, 2, Point());
for (int n = 0; n < contours.size(); n++)
{
//计算凸包
vector<Point> hull;
convexHull(contours[n], hull);//绘制凸包
for (int i = 0; i < hull.size(); i++)
{
//绘制凸包顶点
circle(img, hull[i], 4, Scalar(255, 0, 0), 2, 8, 0);//连接凸包
if (i == hull.size() - 1)
{
line(img, hull[i], hull[0], Scalar(0, 0, 255), 2, 8, 0);
break;
}
line(img, hull[i], hull[i + 1], Scalar(0, 0, 255), 2, 8, 0);
}
}
imshow("hull", img);
waitKey(0);
return 0;
}
2、直线检测
//直线检测
void drawLine(Mat &img, //要标记直线的图像
vector<Vec2f> lines,//检测的直线数据
double rows, //原图像的行数(高)
double cols, //原图像的列数(宽)
Scalar scalar, //绘制直线的颜色
int n //绘制直线的线宽
)
{
Point pt1, pt2;
for (size_t i = 0; i < lines.size(); i++)
{
float rho = lines[i][0]; //直线距离坐标原点的距离
float theta = lines[i][1];//直线过坐标原点垂线与x轴夹角
double a = cos(theta); //夹角的余弦值
double b = sin(theta);//夹角的正弦值
double x0 = a*rho;
double y0 = b*rho;//直线与过坐标原点的垂线的交点
double length = max(rows, cols);//图像高宽的最大值
//计算直线上的一点
pt1.x = cvRound(x0 + length*(-b));
pt1.y = cvRound(y0 + length*(a));
//计算直线上另一点
pt2.x = cvRound(x0 - length * (-b));
pt2.y = cvRound(y0 - length * (a));
//两点绘制一条直线
line(img, pt1, pt2, scalar, n);
}
}
int test2()
{
Mat img = imread("F:/testMap/qier.png", IMREAD_GRAYSCALE);
if (img.empty())
{
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
Mat edge;
//检测边缘图像,并二值化
Canny(img, edge, 80, 180, 3, false);
//用不同的累加器进行检测直线
vector<Vec2f> lines1, lines2;
HoughLines(edge, lines1, 1, CV_PI / 180, 50, 0, 0);
HoughLines(edge, lines2, 1, CV_PI / 180, 150, 0, 0);
//在原图像中绘制直线
Mat img1, img2;
img.copyTo(img1);
img.copyTo(img2);
drawLine(img1, lines1, edge.rows, edge.cols, Scalar(255), 2);
drawLine(img2, lines2, edge.rows, edge.cols, Scalar(255), 2);
//显示图像
imshow("img ", img);
waitKey(0);
imshow("edge", edge);
waitKey(0);
imshow("img1", img1);
waitKey(0);
imshow("img2", img2);
waitKey(0);
return 0;
}
//渐进概率式霍夫变换
int test5()
{
Mat img = imread("F:/testMap/qier.png", IMREAD_GRAYSCALE);
if (img.empty())
{
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
Mat edge;
//检测边缘图像,并二值化
Canny(img, edge, 80, 180, 3, true);
threshold(edge, edge, 170, 255, THRESH_BINARY);
//利用渐进概率式霍夫变换提取直线
vector<Vec4i> linesP1, linesP2;
HoughLinesP(edge, linesP1, 1, CV_PI / 180, 150, 30, 10);//两个点连接最大距离10
HoughLinesP(edge, linesP2, 1, CV_PI / 180, 150, 30, 30);//两个点连接最大距离30
//绘制两个点连接最大距离10直线检测结果
Mat img1;
img.copyTo(img1);
for (size_t i = 0; i < linesP1.size(); i++)
{
line(img1, Point(linesP1[i][0], linesP1[i][1]), Point(linesP1[i][2], linesP1[i][3]), Scalar(255), 3);
}
//绘制两个点连接最大距离30直线检测结果
Mat img2;
img.copyTo(img);
for (size_t i = 0; i < linesP2.size(); i++)
{
line(img2, Point(linesP2[i][0], linesP2[i][1]), Point(linesP2[i][2], linesP2[i][3]), Scalar(255), 3);
}
//显示图像
imshow("img1", img1);
imshow("img2", img2);
waitKey(0);
return 0;
}
3、点集拟合
//点集拟合
int test3()
{
system("color 02");//更改输出界面颜色
Vec4f lines;//存放拟合后的直线
vector<Point2f> point;//待检测是否存在直线的所有点
const static float Points[20][2] = {
{ 0.0f, 0.0f }, { 10.0f, 11.0f }, { 21.0f, 20.0f }, { 30.0f, 30.0f },
{ 40.0f, 42.0f }, { 50.0f, 50.0f }, { 60.0f, 60.0f }, { 70.0f, 70.0f },
{ 80.0f, 80.0f }, { 90.0f, 92.0f }, { 100.0f, 100.0f }, { 110.0f, 110.0f },
{ 120.0f, 120.0f }, { 136.0f, 130.0f }, { 138.0f, 140.0f }, { 150.0f, 150.0f },
{ 160.0f, 163.0f }, { 175.0f, 170.0f }, { 181.0f, 180.0f }, { 200.0f, 190.0f } };
//将所有点存放在vector中,用于输入函数中
for (int i = 0; i < 20; i++)
{
point.push_back(Point2f(Points[i][0], Points[i][1]));
}
//参数设置
double param = 0;//距离模型中的数值参数C
double reps = 0.01;//坐标原点与直线之间的距离精度
double aeps = 0.01;//角度精度
fitLine(point, lines, DIST_L1, 0, 0.01, 0.01);
double k = lines[1] / lines[0];//直线斜率
cout << "直线斜率: " << k << endl;
cout << "直线上一点坐标x: " << lines[2] << ", y:" << lines[3] << endl;
cout << "直线解析式: y = " << k << "(x - " << lines[2] << ") + " << lines[3] << endl;
waitKey(0);
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<Point2f> triangle;
double area = minEnclosingTriangle(points, triangle);
//寻找包围点集的圆形
Point2f center;
float radius = 0;
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;
}
}
return 0;
}
4、二维码检测
//二维码检测
int test4()
{
Mat img = imread("F:/testMap/erweima.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);
//输出结果
namedWindow("result", WINDOW_NORMAL);
imshow("result", img);
namedWindow("qrcode_bin", WINDOW_NORMAL);
imshow("qrcode_bin", qrcode_bin);
waitKey(0);
return 0;
}