凸包检测、直线检测、点集拟合、二维码检测

目录

1、凸包检测

2、直线检测

3、点集拟合

4、二维码检测


1、凸包检测

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

using namespace cv;
using namespace std;

//凸包检测
int test1()
{
	Mat img = imread("E:/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);//105 阈值   255 maxValue

	//开运算消除细小区域
	Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));//获取结构元素 MORPH_RECT 获取矩形卷积核 
	morphologyEx(binary, binary, MORPH_OPEN, k);//MORPH_OPEN 开运算
	imshow("binary", binary);

	//1、轮廓发现
	vector<vector<Point>> contours;//检测到的轮廓,每个轮廓里存放像素坐标
	vector<Vec4i> hierarchy;
	findContours(binary, contours, hierarchy, 0, 2, Point());//轮廓检测
	for (int n = 0; n < contours.size(); n++)//此处其实只存了一个轮廓
	{
		//2、计算凸包
		vector<Point> hull;
		convexHull(contours[n], hull);//凸包检测函数
		//3、绘制凸包
		for (int i = 0; i < hull.size(); i++)
		{
			//绘制凸包顶点
			circle(img, hull[i], 4, Scalar(255, 0, 0), 1, 8, 0);
			//连接凸包
			if (i == hull.size() - 1)//最后一个顶点与第一个顶点联接
			{
				line(img, hull[i], hull[0], Scalar(0, 0, 255), 1, 8, 0);
				break;
			}
			line(img, hull[i], hull[i + 1], Scalar(0, 0, 255), 1, 8, 0);
		}
	}
	imshow("hull", img);
	waitKey(0);
	return 0;
}

int main()
{
	test1();

	system("pause");
	return 0;
}

2、直线检测

 

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

using namespace cv;
using namespace std;

//直线检测 
//要标记直线的图像 检测的直线数据 原图像的行数(高) 原图像的列数(宽) 绘制直线的颜色 绘制直线的线宽
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("E:/testMap/qie.jpg", IMREAD_GRAYSCALE);
	if (img.empty())
	{
		cout << "请确认图像文件名称是否正确" << endl;
		return -1;
	}
	Mat edge;
	//检测边缘图像,并二值化
	Canny(img, edge, 80, 180, 3, false);
    threshold(edge, edge, 170, 255, THRESH_BINARY);

	//用不同的累加器进行检测直线
	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(100), 2);
	drawLine(img2, lines2, edge.rows, edge.cols, Scalar(200), 2);

	//显示图像
	imshow("img ", img);
	waitKey(0);
	imshow("edge", edge);
	waitKey(0);
	imshow("img1", img1);
	waitKey(0);
	imshow("img2", img2);
	waitKey(0);
	return 0;
}

int main()
{
	test2();

	system("pause");
	return 0;
}
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

//直线检测 
//渐进概率式霍夫变换
int test2()
{
	Mat img = imread("E:/testMap/qie.jpg", IMREAD_GRAYSCALE);
	if (img.empty())
	{
		cout << "请确认图像文件名称是否正确" << endl;
		return -1;
	}

	Mat edge;
	//检测边缘图像,并二值化
	Canny(img, edge, 80, 180, 3, false);
	threshold(edge, edge, 170, 255, THRESH_BINARY);

	//利用渐进概率式霍夫变换提取直线
	vector<Vec4i> linesP1, linesP2;//Vec4i 存放两个点
	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(img2);
	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);
	waitKey(0);
	imshow("img2", img2);
	waitKey(0);
	return 0;
}

int main()
{
	test2();

	system("pause");
	return 0;
}

3、点集拟合

 

 

 

 

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

using namespace cv;
using namespace std;

//点集拟合
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];//直线斜率y/x
	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;
}

int main()
{
	test3();

	system("pause");
	return 0;
}

4、二维码检测

 

 

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

using namespace cv;
using namespace std;

//二维码检测
int test4()
{
	Mat img = imread("E:/testMap/erweima.jpg");
	if (img.empty())
	{
		cout << "请确认图像文件名称是否正确" << endl;
		return -1;
	}

	Mat gray, qrcode_bin;//qrcode_bin 存放经过矫正和二值化的QR二维码
	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(5, 10), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 100, 255), 0.5, 8);

	//利用函数直接定位二维码并解码
	string information2;
	vector<Point> points2;
	information2 = qrcodedetector.detectAndDecode(gray, points2);
	cout << points2 << endl;
	putText(img, information2.c_str(), Point(5, 20), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 100, 0), 0.5, 8);

	//输出结果
	namedWindow("result", WINDOW_NORMAL);
	imshow("result", img);
	namedWindow("qrcode_bin", WINDOW_NORMAL);
	imshow("qrcode_bin", qrcode_bin);

	waitKey(0);
	return 0;
}

int main()
{
	test4();

	system("pause");
	return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zhang丶&|!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值