相较于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. 300PLC转以太网作为RTU主站连接智能电表

    300PLC转以太网作为RTU主站连接智能电表 现场介绍: 西门子300PLC转以太网通过兴达易控MPI-ETH-XD1.0PLUS PLC转以太网模块把安科瑞的智能电表接入到300PLC里,读取电表 ...

  2. VMware Work Station使用ubuntu20.04挂载共享文件夹写入文件时出现输入/输出错误

    原因是默认的max_write为0x00020000即128k,超过此大小会报错,另外big_writes,umask等选项也要加上, sudo /usr/bin/vmhgfs-fuse .host: ...

  3. DB2复制表结构及数据

    在DB2数据库中,复制已经存在的表的结构及其数据.我们采用两步走方式:第一步先复制表结构,第二部拷贝数据. 第一步:复制表结构 方法一: Create table test_Rate as (sele ...

  4. 素数是个什么东西 prime number

    /**  * *********************************************************************  * 只有1和它本身两个正因数的自然数,叫质数 ...

  5. for遍历

    for遍历 一:常规方式 1.遍历数组 int arr[10] = {1,2,3,4,5,6,7,8,9,10}; for(int i = 0;i<10;i++) { cout<<a ...

  6. Chromium Mojo通信

    Mojo 是一个跨平台 IPC 框架,它诞生于 chromium ,用来实现 chromium 进程内/进程间的通信.目前,它也被用于 ChromeOS. 在我们代码应用中,如何使用Mojo来作进程间 ...

  7. 夯实JAVA基本之一——泛型详解(2):高级进阶(转)

    上一篇给大家初步讲解了泛型变量的各种应用环境,这篇将更深入的讲解一下有关类型绑定,通配符方面的知识. 一.类型绑定1.引入我们重新看上篇写的一个泛型:class Point<T> { pr ...

  8. pkg-config手册

    定义 pkg-config是一款用于返回已安装库元信息的工具: (语法)概要 pkg-config [--modversion] [--help] [--print-errors] [--silenc ...

  9. Util应用框架基础(四) - 验证

    本节介绍Util应用框架如何进行验证. 概述 验证是业务健壮性的基础. .Net 提供了一套称为 DataAnnotations 数据注解的方法,可以对属性进行一些基本验证,比如必填项验证,长度验证等 ...

  10. freeswitch的一个性能问题

    概述 freeswitch是一款简单好用的VOIP开源软交换平台. 在fs的使用过程中,会遇到各种各样的问题,各种问题中,性能问题是最头疼的. 最近在测试某些场景的时候,压测会造成fs的内存占用持续升 ...