辅助OpenCV识别倾斜的二维码

参考了:Opencv+Zbar二维码识别(二维码校正)

之前发现OpenCV不能识别倾斜有角度的二维码,找到了这个"仿射变换"听起来好厉害的东西,这就是图形学吗,怕了怕了

试了一下,效果还行吧,角度只要不是旋转的太离谱都能给掰正回来

#include<opencv.hpp>

using namespace std;
using namespace cv;

void main(int argc, char* argv[])
{
	/*读取图像*/
	cv::Mat imageSource = imread("test_x30.bmp");
	cv::Mat image;
	/*二值化*/
	imageSource.copyTo(image);
	GaussianBlur(image, image, Size(3, 3), 0);  //滤波,然后工科狗条件反射的想到稳压镇流
	threshold(image, image, 100, 255,THRESH_BINARY);//二值化
	imshow("①图像二值化", image);
	/*形态学变换*/
	cv::Mat element = getStructuringElement(2, Size(7, 7));
	morphologyEx(image,image,MORPH_OPEN,element);//开运算
	for (int i = 0; i < 10; i++)
	{
		erode(image, image, element);//腐蚀
		i++;
	}
	imshow("②形态学变换", image);
	/*边缘检测*/
	cv::Mat image1;
	Canny(image, image1, 100, 300, 3);
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	findContours(image1, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point());//RETR_EXTERNAL:只检测最外围轮廓/CHAIN_APPROX_NONE:保存物体边界上所有连续的轮廓点
	imshow("③边缘检测", image1);
	/*霍夫变换检测直线*/
	vector<Vec2f>lines;
	HoughLines(image1, lines, 1, CV_PI / 180, 100, 0, 0);
	cv::Mat DrawLine = Mat::zeros(image1.size(), CV_8UC1);
	imshow("④检测直线", DrawLine);
	/*交点检测*/
	for (int i = 0; i < lines.size(); i++)
	{
		float rho = lines[i][0];
		float theta = lines[i][1];
		Point pt1, pt2;
		double a = cos(theta), b = sin(theta);
		double x0 = a * rho, y0 = b * rho;
		pt1.x = cvRound(x0 + 1000 * (-b));
		pt1.y = cvRound(y0 + 1000 * a);
		pt2.x = cvRound(x0 - 1000 * (-b));
		pt2.y = cvRound(y0 - 1000 * a);
		line(DrawLine, pt1, pt2, Scalar(255), 1, 1);
	}
	Point2f P1[4];
	Point2f P2[4];
	vector<Point2f>corners;
	goodFeaturesToTrack(DrawLine, corners, 4, 0.1, 10, Mat());
	imshow("⑤交点定位", DrawLine);
	/*仿射变换*/
	for (int i = 0; i < corners.size(); i++)
	{
		circle(DrawLine, corners[i], 3, Scalar(255), 3);
		P1[i] = corners[i];
	}
	int width = P1[1].x - P1[0].x;
	int hight = P1[2].y - P1[0].y;
	P2[0] = P1[0];
	P2[1] = Point2f(P2[0].x + width, P2[0].y);
	P2[2] = Point2f(P2[0].x, P2[1].y + hight);
	P2[3] = Point2f(P2[1].x, P2[2].y);
	cv::Mat elementTransf;
	elementTransf = getAffineTransform(P1, P2);
	warpAffine(imageSource, imageSource, elementTransf, imageSource.size(), 1, 0, Scalar(255));
	imshow("⑥变换校正", imageSource);
	


	cv::QRCodeDetector QRdetecter;
	std::vector<cv::Point> list;
	cv::Mat  res;

	string txt = QRdetecter.detectAndDecode(imageSource, list, res);//res:提取出的二维码;返回解码后的字符串
	cout << txt << endl;
	for (int i = 0; i < list.size(); i++)
	{
		if (i == 3)
			line(imageSource, list[i], list[0], Scalar(0, 255, 0), 3);
		else
			line(imageSource, list[i], list[i + 1], Scalar(0, 255, 0), 3);
	}
	namedWindow("⑧提取二维码", 0);//可以拖动窗口大小
	resizeWindow("⑧提取二维码", 500, 500);//设置窗口大小
	moveWindow("⑧提取二维码", 1200, 500);//设置窗口位置

	imshow("⑦二维码检测定位", imageSource);
	imshow("⑧提取二维码", res);

	waitKey();
}

 先用一张歪了目测30度的测试

开运算应该是用来过滤去除背景的吧,不过测试图本就没有背景

霍夫变换,不明觉厉

仿射变换,牛逼啊V

OpenCV的detectAndDecode

再弄张10度的测一下

之前一张识别不出来的也能提取了

之前还想去看看C++下的什么zbar怎么用来着,结果这下只用OpneCV就实现了,啊这

  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: OpenCV是一个开源的计算机视觉库,可以用于图像处理和分析。要使用OpenCV识别彩色二维码,可以按照以下步骤进行: 1. 导入OpenCV库并加载图像: 要使用OpenCV,首先需要安装并导入相应的库。然后使用OpenCV的函数来加载要识别的彩色二维码图像。 2. 将图像转换为灰度图像: 使用OpenCV的函数将彩色图像转换为灰度图像。这是因为在处理二维码时,灰度图像有助于提取图像中的黑白信息。 3. 检测和解码二维码: 使用OpenCV的函数来检测图像中的二维码。对于彩色二维码,可以使用适当的函数参数来指定扫描彩色二维码。一旦检测到二维码,就可以使用OpenCV的函数来解码二维码中的信息。 4. 显示和输出解码信息: 将解码的信息显示在图像上,以便用户可以看到识别的结果。此外,可以将解码的信息输出到文件或其他系统中,以便进一步处理或存储。 需要注意的是,识别彩色二维码可能需要适当的图像处理和参数设置,以确保准确性和可靠性。此外,根据具体需求,还可以对识别到的二维码进行额外的处理或分析。 ### 回答2: OpenCV是一种开源的计算机视觉和机器学习软件库,它提供了许多功能强大的图像处理和分析工具。通过使用OpenCV,我们可以实现彩色二维码识别。 在进行彩色二维码识别之前,我们需要首先加载图像并对其进行预处理。首先,我们可以使用OpenCV的函数将图像转换为灰度图像,这将有助于提高识别的准确性。然后,我们可以使用OpenCV中的二维码检测函数来检测图像中的二维码。这些函数可以识别不同角度和尺寸的二维码。 在识别过程中,OpenCV会返回一个包含二维码信息的数据结构。我们可以从这个数据结构中提取二维码的内容并进行进一步处理,比如解码和解析其包含的信息。 在识别彩色二维码时,我们需要注意光照对识别的影响。光照强度和颜色可能会导致识别结果的误差或失败。为了解决这个问题,我们可以使用OpenCV的图像增强技术,如亮度调整和对比度增强,来改善图像的质量。 总结来说,通过使用OpenCV的图像处理和分析功能,我们可以实现彩色二维码识别。我们需要对图像进行预处理,使用二维码检测函数进行识别,并从识别结果中提取二维码的内容。并且需要注意光照对识别的影响,可以采用图像增强技术来改善识别结果。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值