相较于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. HTML网页/KRPano项目一键打包EXE工具(HTML网页打包成单个windows可执行文件exe)

    HTML一键打包EXE工具使用说明 工具简介 HTML一键打包EXE工具(HTML封装EXE,桌件)能把任意HTML项目(网址)一键打包为单个EXE文件,可以脱离浏览器和服务器,直接双击即可运行.支持 ...

  2. 全网最详细Java-JUC

    Java-JUC ⓪基础 ❶进程&线程 进程:指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间. 线程:比进程更小的执行单位,一个进程可以启动多个线程,每条线程并行执行不同的任务 ...

  3. Record - Nov. 28st, 2020 - Exam. REC

    Prob. 1 Desc. & Link. 暴力为 \(\Theta(NK)\). 正解(也许): 把每一个全为正整数的子段找出来. 然后判断一下中间连接的情况即可. 但是这样决策情况太多了. ...

  4. Arduino入门教程

        Arduino入门教程   Arduino是一款简单易学的开源电子原型平台,包含硬件(各种型号的Arduino板)和软件(Arduino IDE).它通过各种各样的传感器来感知环境,再通过控制 ...

  5. 校招零Offer要不要先找实习?

    国庆前后被问到最多的问题是:"磊哥,我现在还是 0 Offer,要不要先去找个实习?",给大家看看部分截图. 同学 A: 同学 B: 同学 C: 其他还有一些截图,我这里就不一一贴 ...

  6. Cython加密python代码防止反编译

    本方法适用于Linux环境下: 1.安装库Cython pip3 install Cython==3.0.0a10 2.编写待加密文件:hello.py import random def ac(): ...

  7. 一次考试的dp题

    很明显是dp 看题目的时候我们先进行初步的思考,发现一个性质 一个点时不可能被重复覆盖三次的很显然,如果一个点被覆盖了3次,这3个覆盖他的区间一定是有一个区间被完全包含的,因为有贡献的左右端点只有两个 ...

  8. 基于.Net 的 AvaloniUI 多媒体播放器方案汇总

    基于.Net 的 AvaloniUI 多媒体播放器方案汇总 摘要 随着国产化的推进,相信.Net的桌面端的小伙伴的可能已经有感受到了. 为了让.Net的桌面框架能够跨桌面平台,首选的就是Avalona ...

  9. salesforce零基础学习(一百三十三)ListView的button思考

    本篇参考: salesforce零基础学习(九十五)lightning out salesforce零基础学习(一百一十)list button实现的一些有趣事情 https://help.sales ...

  10. CF B. Gardener and the Array

    B. Gardener and the Array 思路:只要找到一个c他的每一位均在除了它的集合中出现过即可 这题T了2发,用来multiset,注意multiset大的时间复杂度是O(K + lo ...