【Python】【OpenCV】定位二维码
相较于BarCode,QRCode有明显的特征区域,也就是左上角、右上角、左下角三个”回“字区域,得益于hierarchy中,父子关系的轮廓是连续的(下标),所以这个时候我们就可以通过cv2.findContours()返回的hierarchy来进行定位。
我们直接上代码
1 import cv2
2 import numpy
3
4
5 def qrcode(image):
6 # 有些二维码和边缘紧贴,无法识别出整个矩形,所以我们先对图片大小进行扩展
7 expand_length = 10
8 edge = expand_length // 2
9 h, w = image.shape[:2]
10 image_extend = numpy.zeros((image.shape[0] + expand_length, image.shape[1] + expand_length, 3), numpy.uint8)
11 image_extend[:] = 255
12 image_extend[edge:edge + h, edge:edge + w] = image
13
14 # 转灰度、二值化、找轮廓
15 gray = cv2.cvtColor(image_extend, cv2.COLOR_BGR2GRAY)
16 # blur = cv2.GaussianBlur(gray, (5, 5), 0)
17 _, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
18 contours, hir = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
19
20 '''
21 2.4282182798755647
22 2.3203121154092337
23 2.3487607213520345
24 2.318010267306266
25 '''
26
27 # 三个“回”字特征轮廓存储
28 parent_hierarchy_list = []
29 parent_contours_list = []
30
31 # 通过层级信息去查找三个“回”字特征区域
32 for index, item in enumerate(hir[0][:-2]): # 查找最外层(A)轮廓
33 if item[2] != -1:
34 parent_index = item[2] - 1
35 if hir[0][index+1][3] == parent_index: # 查找次一层(B)轮廓
36 child_first = hir[0][index+1][2] - 1
37 if hir[0][index+2][3] == child_first: # 查找最里层(C)轮廓
38 # 计算A轮廓的周长和C轮廓周长的比值
39 error = cv2.arcLength(contours[parent_index], True) / cv2.arcLength(contours[parent_index + 2], True)
40 if 2 < error < 3:
41 parent_hierarchy_list.append(item)
42 parent_contours_list.append(contours[index])
43 # 绘制出三个“回”字特征区域的最外层轮廓
44 cv2.drawContours(image_extend, contours, index, (0, 255, 0), 3)
45
46 # 将整个二维码区域绘制出来
47 points_list = []
48 for index, box in enumerate(parent_contours_list):
49 x, y, w, h = cv2.boundingRect(box)
50 if index == 0:
51 points_list.append((x, y+h))
52 if index == 1:
53 points_list.append((x+w, y))
54 if index == 2:
55 points_list.append((x, y))
56 points_list = numpy.array(points_list)
57 rect = cv2.minAreaRect(points_list)
58 box = cv2.boxPoints(rect)
59 box = numpy.int0(box)
60 cv2.drawContours(image_extend, [box], 0, (255, 0, 0), 2)
61
62 cv2.imshow('', image_extend)
63
64
65 if __name__ == '__main__':
66 img = cv2.imread('../images/QRCode_3.png')
67 qrcode(img)
68 cv2.waitKey()
69 cv2.destroyAllWindows()
通常我们所见的二维码都是有留白边缘区域的,但是在随便找一些二维码图的过程中,有一些是没有留白边缘区域的:

上图是在IDE中打开的,原图是没有灰色边缘的,这个时候我们如果直接读取这张图片,得到的轮廓信息并不是我们期待的三个连续的父子关系的hierarchy,为了避免这种情况,这里就手动向外扩展十个像素,人为制造一个间隔。
通常来说,我们通过三层for循环来定位特征区域已经是足够的,但是如果二维码的其他区域也出现了三层轮廓,那么我们就需要进行筛选,所以代码通过计算最外层轮廓的长度和最内存轮廓长度的比值来进行筛选,每一个“回”的黑白框框的比例大概为1:1:3:1:1,也就是说他们的边长比为7:3,而这个比值在标准二维码中,只有三个特征区域才符合。
代码的21到24行中的数值,便是尝试过了四个不同的二维码得出的比值,都接近7:3。

最后我们绘制出四个边框,完成二维码的定位:

参考博客:opencv实现二维码检测_opencv识别二维码-CSDN博客
【Python】【OpenCV】定位二维码的更多相关文章
- 基于opencv 识别、定位二维码 (c++版)
前言 因工作需要,需要定位图片中的二维码:我遂查阅了相关资料,也学习了opencv开源库.通过一番努力,终于很好的实现了二维码定位.本文将讲解如何使用opencv定位二维码. 定位二维码不仅仅是为了识 ...
- [OpenCV实战]11 基于OpenCV的二维码扫描器
目录 1 二维码(QRCode)扫描 2 结果 3 参考 在这篇文章中,我们将看到如何使用OpenCV扫描二维码.您将需要OpenCV3.4.4或4.0.0及更高版本来运行代码. 1 二维码(QRCo ...
- Opencv+Zbar二维码识别(二维码校正)
二维码和车牌识别基本都会涉及到图像的校正,主要是形变和倾斜角度的校正,一种二维码的畸变如下图: 这个码用微信扫了一下,识别不出来,但是用Zbar还是可以准确识别的~~. 这里介绍一种二维码校正方法,通 ...
- Opencv+Zbar二维码识别(标准条形码/二维码识别)
使用Opencv+Zbar组合可以很容易的识别图片中的二维码,特别是标准的二维码,这里标准指的是二维码成像清晰,图片中二维码的空间占比在40%~100%之间,这样标准的图片,Zbar识别起来很容易,不 ...
- 使用python玩转二维码!速学速用!⛵
作者:韩信子@ShowMeAI Python3◉技能提升系列:https://www.showmeai.tech/tutorials/56 本文地址:https://showmeai.tech/art ...
- 一次使用Python连接数据库生成二维码并安装为windows服务的工作任务
最近有一个需求,在现有生产系统上的人员库中增加一个此人员关键信息的二维码,支持文字版和跳转版两种方式,与报表工具关联,可打印.以windows服务方式,定时检查,只要发现某人员没有此二维码信息,就生成 ...
- Python制作动态二维码只需要一行代码!炒鸡简单!
分享一个比较有意思的项目,只需要一行Python代码就可以快捷方便生成普通二维码.艺术二维码(黑白/彩色)和动态GIF二维码. 用法比较简单,直接通过pip安装即可. pip3 install myq ...
- 你只要5行代码,拥有你的个性二维码,用Python生成动态二维码
如果想了解更多关于python的应用,可以私信我,或者点击下方链接自行获取,里面到资料都是免费的(http://t.cn/A6Zvjdun) 二维码满天飞,但是有没有想过Python也能制作出专属于自 ...
- python生成个性二维码学习笔记
在linux环境下进行编码 1.先进家目录,自行创建Code文件夹 cd Code 2.下载MyQR库 sudo pip3 install MyQR 3.下载所需资源文件并解压 Code/ $ wge ...
- Python 生成个性二维码
1.1 实验内容 本课程通过调用MyQR接口来实现生成个人所需二维码,并可以设置二维码的大小.是否在现有图片的基础上生成.是否生成动态二维码. 本课程主要面向Python3初学者. 1.2 知识点 P ...
随机推荐
- [Servlet/Tomcat] HttpServletRequest#getHeader(headerNameWithIgnoreCase)(获取header时不区分大小写)
1 故事背景 最近项目上有个业务需求,翻译成技术需求,即:将request.headers中的几个header入参转换成request.body(pageRequest)中的内置参数. 为便于灵活配置 ...
- Note -「virtual tree」shorter vrt
Part. 1 Preface 没什么 preface. Part. 2 实现 具体来说就是把所有关键点按 \(\text{dfn}\) 排序,去重,然后求出相邻结点的 \(\text{LCA}\), ...
- Go 1.22 中的 For 循环
原文在这里. 由 David Chase and Russ Cox 发布于2023年9月19日 Go 1.21 版本包含了对 for 循环作用域的预览更改,我们计划在 Go 1.22 中发布此更改,以 ...
- Linux中python更换pip源
Linux中python更换pip源 执行以下命令,更换为阿里源: echo " [global] trusted-host = mirrors.aliyun.com index-url = ...
- NFC and Contactless Technologies
NFC and Contactless Technologies NFC与无接触技术 NFC technology enables simple and safe two-way interactio ...
- Asp-Net-Core开发笔记:EFCore统一实体和属性命名风格
前言 C# 编码规范中,类和属性都是大写驼峰命名风格(PascalCase / UpperCamelCase),而在数据库中我们往往使用小写蛇形命名(snake_case),在默认情况下,EFCore ...
- 全网最详细4W字Flink全面解析与实践(下)
本文已收录至GitHub,推荐阅读 Java随想录 微信公众号:Java随想录 原创不易,注重版权.转载请注明原作者和原文链接 承接上篇未完待续的话题,我们一起继续Flink的深入探讨 Flink S ...
- ASP.NET Core+Vue3 实现SignalR通讯
从ASP.NET Core 3.0版本开始,SignalR的Hub已经集成到了ASP.NET Core框架中.因此,在更高版本的ASP.NET Core中,不再需要单独引用Microsoft.AspN ...
- JavaScript高级程序设计笔记10 函数Function
函数 1.几种实例化函数对象的方式 以函数声明的方式定义 函数表达式 箭头函数(arrow function) 使用Function构造函数 接收任意多个字符串参数,最后一个参数始终会被当成函数体,而 ...
- 文心一言 VS 讯飞星火 VS chatgpt (141)-- 算法导论12.1 1题
一.用go语言,对于关键字集合(1,4,5,10,16,17,21),分别画出高度为 2.3.4.5和6的二又搜索树. 文心一言: 以下是用Go语言为给定的关键字集合(1, 4, 5, 10, 16, ...