相较于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】定位二维码的更多相关文章

  1. 基于opencv 识别、定位二维码 (c++版)

    前言 因工作需要,需要定位图片中的二维码:我遂查阅了相关资料,也学习了opencv开源库.通过一番努力,终于很好的实现了二维码定位.本文将讲解如何使用opencv定位二维码. 定位二维码不仅仅是为了识 ...

  2. [OpenCV实战]11 基于OpenCV的二维码扫描器

    目录 1 二维码(QRCode)扫描 2 结果 3 参考 在这篇文章中,我们将看到如何使用OpenCV扫描二维码.您将需要OpenCV3.4.4或4.0.0及更高版本来运行代码. 1 二维码(QRCo ...

  3. Opencv+Zbar二维码识别(二维码校正)

    二维码和车牌识别基本都会涉及到图像的校正,主要是形变和倾斜角度的校正,一种二维码的畸变如下图: 这个码用微信扫了一下,识别不出来,但是用Zbar还是可以准确识别的~~. 这里介绍一种二维码校正方法,通 ...

  4. Opencv+Zbar二维码识别(标准条形码/二维码识别)

    使用Opencv+Zbar组合可以很容易的识别图片中的二维码,特别是标准的二维码,这里标准指的是二维码成像清晰,图片中二维码的空间占比在40%~100%之间,这样标准的图片,Zbar识别起来很容易,不 ...

  5. 使用python玩转二维码!速学速用!⛵

    作者:韩信子@ShowMeAI Python3◉技能提升系列:https://www.showmeai.tech/tutorials/56 本文地址:https://showmeai.tech/art ...

  6. 一次使用Python连接数据库生成二维码并安装为windows服务的工作任务

    最近有一个需求,在现有生产系统上的人员库中增加一个此人员关键信息的二维码,支持文字版和跳转版两种方式,与报表工具关联,可打印.以windows服务方式,定时检查,只要发现某人员没有此二维码信息,就生成 ...

  7. Python制作动态二维码只需要一行代码!炒鸡简单!

    分享一个比较有意思的项目,只需要一行Python代码就可以快捷方便生成普通二维码.艺术二维码(黑白/彩色)和动态GIF二维码. 用法比较简单,直接通过pip安装即可. pip3 install myq ...

  8. 你只要5行代码,拥有你的个性二维码,用Python生成动态二维码

    如果想了解更多关于python的应用,可以私信我,或者点击下方链接自行获取,里面到资料都是免费的(http://t.cn/A6Zvjdun) 二维码满天飞,但是有没有想过Python也能制作出专属于自 ...

  9. python生成个性二维码学习笔记

    在linux环境下进行编码 1.先进家目录,自行创建Code文件夹 cd Code 2.下载MyQR库 sudo pip3 install MyQR 3.下载所需资源文件并解压 Code/ $ wge ...

  10. Python 生成个性二维码

    1.1 实验内容 本课程通过调用MyQR接口来实现生成个人所需二维码,并可以设置二维码的大小.是否在现有图片的基础上生成.是否生成动态二维码. 本课程主要面向Python3初学者. 1.2 知识点 P ...

随机推荐

  1. js原生 toggle函数编写

    工作中遇到了需要动态切换slide下拉框展示与隐藏,同时需要切换元素上附加的样式,以下脚本为实现此功能的实践. //元素点击时切换隐藏与展示逻辑 var slidsDownShow = documen ...

  2. 2-MySQL基本语法

    上文说到,数据库的安装和连接,接下来将给大家讲解MySQL数据库的基本语法及数据的类型 1.基本语法 (1).查看当前所有数据库 : show databases; (2).创建数据库 create ...

  3. 5分钟入门 next13

    上半年vercel 推出了nextjs13 这个大版本,刚好最近有个c端的项目,所以就用了这个框架来写,技术体系基本也是文档提到的 tailwindcss + ts + swr + ssr ,总的来开 ...

  4. POI 操作sheet.shiftRows注意点

    sheet.shiftRows后使用getRow/getCell会导致NullPointException 正确使用应该是CreateRow CreateCell

  5. 文心一言 VS 讯飞星火 VS chatgpt (105)-- 算法导论10.1 3题

    三.用go语言,仿照图 10-2,画图表示依次执行操作 ENQUEUE(Q,4).ENQUEUE(Q,1).ENQUEUE(Q,3).DEQUEUE(Q).ENQUEUE(Q,8)和 DEQUEUE( ...

  6. Python基础合集

    入门介绍 01.python由来与发展介绍 02.WEB项目开发流程 第一篇 markdown编辑器 01.markdown基本语法 02.Typora简介与安装 03.Windows上gitee+T ...

  7. 【WPF】单例软件实现自重启

    原文地址 https://www.cnblogs.com/younShieh/p/17749694.html 如果本文对你有所帮助,不妨点个关注和推荐呀,这是对笔者最大的支持~   在WPF应用程序中 ...

  8. CF1746F Kazaee

    prologue 数组范围一定要看好了开,不然容易我一样,调试调了一页多. 还有就是不要傻乎乎地只跑一次和哈希,因为和哈希(从下面地佬的题解中才知道)它其实算作是一种 trick(类比SA(Stimu ...

  9. 实战0-1,Java开发者也能看懂的大模型应用开发实践!!!

    前言 在前几天的文章<续写AI技术新篇,融汇工程化实践>中,我分享说在RAG领域,很多都是工程上的实践,做AI大模型应用的开发其实Java也能写,那么本文就一个Java开发者的立场,构建实 ...

  10. unity利用Rigibody实现第一人称移动

    1. CameraRotation脚本,将它给MainCamera,实现上下视角旋转 using System.Collections; using System.Collections.Generi ...