辅助OpenCV识别倾斜的二维码

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

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

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

#include

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> contours;
	vector hierarchy;
	findContours(image1, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point());//RETR_EXTERNAL:只检测最外围轮廓/CHAIN_APPROX_NONE:保存物体边界上所有连续的轮廓点
	imshow("③边缘检测", image1);
	/*霍夫变换检测直线*/
	vectorlines;
	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];
	vectorcorners;
	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 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度的测试

辅助OpenCV识别倾斜的二维码_第1张图片

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

辅助OpenCV识别倾斜的二维码_第2张图片

辅助OpenCV识别倾斜的二维码_第3张图片

霍夫变换,不明觉厉

辅助OpenCV识别倾斜的二维码_第4张图片

辅助OpenCV识别倾斜的二维码_第5张图片

仿射变换,牛逼啊V

辅助OpenCV识别倾斜的二维码_第6张图片

OpenCV的detectAndDecode

辅助OpenCV识别倾斜的二维码_第7张图片

辅助OpenCV识别倾斜的二维码_第8张图片

再弄张10度的测一下

辅助OpenCV识别倾斜的二维码_第9张图片

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

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

你可能感兴趣的:(工业摄像机,机器式觉,计算机视觉,opencv,c++)