首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >OpenCV 检测二维码并定位

OpenCV 检测二维码并定位

作者头像
chaibubble
发布于 2022-05-07 01:15:53
发布于 2022-05-07 01:15:53
56600
代码可运行
举报
运行总次数:0
代码可运行

注意:该程序功能是检测二维码,不是识别,只是在图中定出二维码的位置即可

原图是这样:如果出现这张图片时,程序需要找到二维码

其余图片是这样:

程序步骤: 1.图片缩小 2.灰度化,直方图均衡化,对比度增强,滤波 3.otsu阈值分割 4.五次膨胀 5.轮廓查找,如果轮廓满足一下条件,认为可能为二维码区域,像素面积大于60,长短轴之比小于1.3 6.对疑似区域做判断,因为本实验二维码贴在大概中心位置,找到疑似轮廓的质心,判断质心是不是在图片长宽的三分之一到三分之二之间,如果是认为是二维码区域 7.对二维码区域画成蓝色

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <stdio.h>  
#include <opencv/highgui.h>  
#include <time.h>  
#include <opencv2/opencv.hpp>  
#include <opencv/cv.h>  
#include <iostream> 

using namespace std;  
using namespace cv; 

int main(int argc,char *argv[])  
{
	
	Mat srcImage;
	Mat resizeImage;
	Mat grayImage;
	Mat equalizeHistImage;
	Mat contrastandbrightImage;
	Mat sobelImage;
	Mat thresholdImage;
	Mat dilateImage;
	Mat areaImage;
	Mat ellipseImage;
	srcImage = imread("3.jpg");
	Size dsize = Size(srcImage.cols*0.3,srcImage.rows*0.3);
	resize(srcImage, resizeImage,dsize);
	cvtColor(resizeImage,grayImage,CV_BGR2GRAY);
	equalizeHist(grayImage,equalizeHistImage);
	亮度、对比度增强
	contrastandbrightImage= Mat::zeros( equalizeHistImage.size(), equalizeHistImage.type() ); 
	for(int y = 0; y < equalizeHistImage.rows; y++ )  
	{  
		for(int x = 0; x <equalizeHistImage.cols; x++ )  
		{  
			contrastandbrightImage.at<uchar>(y,x)= saturate_cast<uchar>(6*(equalizeHistImage.at<uchar>(y,x) ));  	
		} 
	} 
	blur(contrastandbrightImage,contrastandbrightImage,Size(3,3));  
	//Sobel(contrastandbrightImage, sobelImage, CV_8U, 0,1 ,1, 1, 0, BORDER_DEFAULT);
	threshold(contrastandbrightImage,thresholdImage, 0, 255, CV_THRESH_OTSU+CV_THRESH_BINARY_INV);  
	Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));  
	//进行膨胀操作  
	dilate(thresholdImage, dilateImage, element);  
	dilate(dilateImage, dilateImage, element);
	dilate(dilateImage, dilateImage, element);  
	dilate(dilateImage, dilateImage, element);  
	dilate(dilateImage, dilateImage, element);  

	//dilateImage.copyTo(areaImage);
	//vector< vector< Point> > contours;  
	//findContours(areaImage,contours,CV_RETR_TREE,  CV_CHAIN_APPROX_NONE); 
	//vector<vector<Point> >::iterator itc= contours.begin();  
	//while (itc!=contours.end()) 
	//{  
	//	if( itc->size()<100)
	//	{  
	//		itc= contours.erase(itc);  
	//	}
	//   else
	//   {
	//	   ++itc;  
	//	}
	//}  
	//drawContours(areaImage, contours, -1, Scalar(255), CV_FILLED);

	//找轮廓 两步判断  一个是大小  一个是长短轴比比  认为面积比60大,长短轴比比1.3小的区域是二维码区域  再做下一步判断
	dilateImage.copyTo(ellipseImage);
	vector<vector<Point> > twocontours;
	vector<Vec4i>twohierarchy;
	findContours(ellipseImage,twocontours,twohierarchy,CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE);  
	vector<Moments> mu(twocontours.size() );      
    vector<Point2f> mc( twocontours.size() );
	for(int k = 0; k < (int)twocontours.size(); k++)    //查找轮廓
	{
		if (int(twocontours.at(k).size()) <=60)//轮廓面积小于60的不处理
		{
			drawContours(ellipseImage, twocontours, k, Scalar(0), CV_FILLED);
		}
		else
		{
			RotatedRect rRect = fitEllipse(twocontours.at(k)); 
			double majorAxis = rRect.size.height > rRect.size.width ? rRect.size.height : rRect.size.width;
			double minorAxis = rRect.size.height > rRect.size.width ? rRect.size.width : rRect.size.height;
			float rate = majorAxis/minorAxis;
			if (rate<1.3)   //长短轴之比小于1.4的轮廓
			{
				//可能为二维码的区域,判断是否为二维码区域
				printf("%f\n",rate);
				//求区域的质心
				mu[k] = moments( twocontours[k], false );   
				mc[k] = Point2d( mu[k].m10/mu[k].m00 , mu[k].m01/mu[k].m00 ); 
				//打印质心
				printf("x=%f,y=%f\n",mc[k].x,mc[k].y);
				//打印图像的长宽
				printf("图像的长%d,图像的宽%d\n",resizeImage.cols,resizeImage.rows);
				//画出质心
				Point center = Point(mc[k].x,mc[k].y);  
				int r = 10;    
				circle(resizeImage,center,r,Scalar(255,0,0));  
				//判断质心是不是在图像中间   三分之一 < 质心 < 三分之二
				if ((int)mc[k].x<(int)2*(resizeImage.cols/3)&&(int)mc[k].x>(int)(resizeImage.cols/3))
				{
					if ((int)mc[k].y<(int)2*(resizeImage.rows/3)&&(int)mc[k].y>(int)(resizeImage.rows/3))
					{
							drawContours(resizeImage, twocontours, k, Scalar(255,0,0), CV_FILLED);//把轮廓涂成蓝色
							printf("蓝色是二维码区域\n");
					}
				}
			}
			else  //长短轴之比大于1.4的轮廓  不是二维码区域
			{
				drawContours(resizeImage, twocontours, k, Scalar(0,0,255), CV_FILLED);//把轮廓涂成红色
			}
		}
	}		
	imshow("缩小图",resizeImage);
	imshow("灰度图",grayImage);
	imshow("对比度和亮度增强",contrastandbrightImage);
	//imshow("soble检测",sobelImage);
	imshow("二值化结果",thresholdImage);
	imshow("膨胀",dilateImage);
	//imshow("删除小面积",areaImage);
	imshow("长短轴",ellipseImage);
	waitKey(0);
}

部分结果图:

无二维码图片的结果图:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-02-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
OpenCV 对轮廓的绘图与筛选操作总结
OpenCV利用findContours找到图像中的轮廓,根据这些轮廓的特征进行筛选有利于进一步逼近最终的兴趣区域,减少其他算法的时间,提高代码的运行效率,而对轮廓的绘图则可以直观的看到筛选结果。 其
chaibubble
2018/01/02
4.8K0
OpenCV  对轮廓的绘图与筛选操作总结
OpenCV二维码检测与定位
在如今流行扫描的年代,应用程序实现二维码扫描检测与识别已经是应用程序的标配、特别是在移动端、如果你的应用程序不能自动发现检测二维码,自动定位二维码你都不好意思跟别人打招呼,二维码识别与解析基于ZXin
OpenCV学堂
2018/04/04
4.8K0
OpenCV二维码检测与定位
OpenCV 闭合轮廓检测
这个好像是骨头什么的,但是要求轮廓闭合,于是对图片进行一下膨胀操作,再次检测轮廓就好了。
流川疯
2022/11/29
1K0
OpenCV 闭合轮廓检测
OpenCV 应用边缘检测与霍夫线变换实现旋转角度检测
使用opencv的图片旋转功能,把它旋转一个角度,旋转方法参考: http://blog.csdn.net/chaipp0607/article/details/63263347
chaibubble
2022/05/07
1.1K0
OpenCV 应用边缘检测与霍夫线变换实现旋转角度检测
OpenCV findContours函数边缘近似方法
在使用OpenCV的过程中,findcontours是相对使用比较多的,在之前的博客中,介绍了vector<vector<Point> > contours容器: http://blog.csdn.net/chaipp0607/article/details/52858661 查找轮廓时内轮廓与外轮廓: http://blog.csdn.net/chaipp0607/article/details/53765440
chaibubble
2022/05/07
6470
OpenCV findContours函数边缘近似方法
OpenCV 应用fitEllipse函数一种异常问题分析
说明fitEllipse函数要求轮廓的像素点个数大于等于5个,可以将代码修改为:
chaibubble
2022/05/07
6440
OpenCV 应用fitEllipse函数一种异常问题分析
OpenCV 轮廓检测
http://blog.sina.com.cn/s/blog_8fc98fe501017ypb.html
流川疯
2022/11/29
1.1K0
OpenCV 轮廓检测
OpenCV 删除轮廓的方法(二)
利用vector迭代器(iterator)遍历内容,利用erase()函数删除轮廓,实验设计为小于20的轮廓被删除,为了效果更明显,在阈值分割前不做平滑和滤波的处理,代码如下:
chaibubble
2022/05/07
1.1K0
OpenCV 删除轮廓的方法(二)
使用 OpenCV + 微信二维码引擎实现二维码识别
点击上方蓝字关注我们 微信公众号:OpenCV学堂 关注获取更多计算机视觉与深度学习知识 作者:Tony沈哲 链接:https://juejin.cn/post/7079313321446506532 来源:稀土掘金 背景 今年自疫情以来,我都没有写过文章。一方面是疫情导致居家办公比较烦躁,另一方面最近有点懒了。但是工作还是要继续,趁这几天优化了一下最近的项目,我整理了一下如何使用 OpenCV 和微信二维码引擎来实现二维码的识别。 微信开源了其二维码的解码功能,并贡献给 OpenCV 社区。其开源的
OpenCV学堂
2022/03/28
5.5K0
【OpenCV入门之九】轮廓查找和多边形包围轮廓
学习计算机视觉最重要的能力应该就是编程了,为了帮助小伙伴尽快入门计算机视觉,小白准备了【OpenCV入门】系列。新的一年文章的内容进行了很大的完善,主要是借鉴了更多大神的文章,希望让小伙伴更加容易理解。如果小伙伴觉得有帮助,请点击一下文末的“好看”鼓励一下小白。
小白学视觉
2019/06/02
2.1K0
OpenCV轮廓检测,计算物体旋转角度
http://blog.csdn.net/wangyaninglm/article/details/41864251
流川疯
2019/01/18
4.6K0
终于可以摆脱OpenCV中Hough圆调参的烦恼了
OpenCV图像项目中,圆的检测很常见。 例如:检测烂苹果的个数,寻找目标靶心,人眼,嘴巴识别等。 其中用到的关键技术是OpenCV中集成的霍夫圆检测函数。 HoughCircles( InputArray image, // 输入图像 ,必须是8位的单通道灰度图像 OutputArray circles, // 输出结果,发现的圆信息 Int method, // 方法 - HOUGH_GRADIENT Double dp,
用户9831583
2022/06/16
3.2K0
终于可以摆脱OpenCV中Hough圆调参的烦恼了
[C++]使用OpenCV去除面积较小的连通域
云未归来
2025/07/20
1560
[C++]使用OpenCV去除面积较小的连通域
VC++中使用OpenCV进行形状和轮廓检测
在VC++中使用OpenCV进行形状和轮廓检测,轮廓是形状分析以及物体检测和识别的有用工具。如下面的图像中Shapes.png中有三角形、矩形、正方形、圆形等,我们如何去区分不同的形状,并且根据轮廓进行检测呢?
ccf19881030
2024/05/24
1.1K0
VC++中使用OpenCV进行形状和轮廓检测
图像分割之分水岭算法[通俗易懂]
分水岭概念是以对图像进行三维可视化处理为基础的:其中两个是坐标,另一个是灰度级。基于“地形学”的这种解释,我们考虑三类点:
全栈程序员站长
2022/07/05
2.9K0
图像分割之分水岭算法[通俗易懂]
图像中二维码的检测和定位
所谓开操作是指先腐蚀后膨胀的操作。在之前的文章二值图像分析:案例实战(文本分离+硬币计数)曾经介绍过开操作的用途。
fengzhizi715
2018/08/24
3.8K0
图像中二维码的检测和定位
opencv 视觉项目学习笔记(二): 基于 svm 和 knn 车牌识别
    训练数据: 所有训练数据存储再一个 N x M 的矩阵中, 其中 N 为样本数, M 为特征数(每个样本是该训练矩阵中的一行)。这些数据  所有数据存在  xml 文件中, 
用户2434869
2018/10/11
3.2K0
OpenCV 删除轮廓的方法(一)
一种比较方便的删除轮廓的处理方式,是我刚刚学习到的一个方法,在这之前,如果我想删除一个不需要的轮廓,用的方法是将该轮廓填充为背景色,之前的博客提到过,在countours容器中,如果把轮廓填充为背景色,那么只是视觉上看不到该轮廓,但是实际上还存在在容器中。所以之前总是要填充之后从新copyto一下,然后重新找一遍轮廓,达到删除轮廓的效果。这种方式实在是low。 [见之前的博客http://blog.csdn.net/chaipp0607/article/details/52858661 代码如下:
chaibubble
2022/05/07
5510
OpenCV 删除轮廓的方法(一)
C++ OpenCV透视变换综合练习
以前的文章《C++ OpenCV之透视变换》介绍过透视变换,当时主要是自己固定的变换坐标点,所以在想可不可以做一个通过轮廓检测后自适应的透视变换,实现的思路通过检测主体的轮廓,使用外接矩形和多边形拟合的四个最边的点进行透视变换。
Vaccae
2021/01/18
1.2K0
PaddleOCR C++(三)---动态库返回识别结果及矩形位置
《PaddleOCR C++学习笔记(二)》尝试做图像的分割,结果都效果不明显,所以这篇我们从OCR识别这里来处理,将返回的识别字符和对应的识别矩形框都显示出来,用于区分识别的效果。
Vaccae
2021/07/30
2.5K1
PaddleOCR C++(三)---动态库返回识别结果及矩形位置
相关推荐
OpenCV 对轮廓的绘图与筛选操作总结
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验