Python二维码应用(一)QRcode二维码生成&识别

  • A+
所属分类:Python

一、机器视觉之QRcode

问:什么是QRcode呢?
答:二维码(2-dimensional bar code),是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的。它能将数字、英文字母、汉字、日文字母、特殊符号(如空格,%,/ 等)、二进制等信息记录到一个正方形的图片中。
因此,在转换的过程中,离不开编码压缩方式。在许多种类的二维条码中,常用的码制有:Data Matrix,Maxi Code,Aztec,QR Code,Vericode,PDF417,Ultracode,Code 49,Code 16K等。
二维码在现实生活中的应用越来与普遍,归功于 QR code 码制的流行。我们常说的二维码就是它,所以,二维码又被称为 QR code。
QR code 是一种矩阵式二维条码(又称棋盘式二维条码)。它是在一个矩形空间通过黑、白像素在矩阵中的不同分布进行编码。在矩阵相应元素位置上,用点(方点、圆点或其他形状)的出现表示二进制“1”,点的不出现表示二进制的“0”,点的排列组合确定了矩阵式二维条码所代表的意义。
我们的目的是要使用 Python 生成 QR 码,那我们需要先了解二维码(QR 码)的结构。根据标准(ISO/IEC 18004),我们可以了解到 QR 码结构如下:
Python二维码应用(一)QRcode二维码生成&识别
二维码的绘制大概过程如下:
在二维码的左上角、左下角、右上角绘制位置探测图形,位置探测图形一定是一个 7x7 的矩阵;
(1)绘制校正图形,校正图形一定是一个 5x5 的矩阵;
(2)绘制两条连接三个位置探测图形的定位图形;
(3)在上述图片的基础上,继续绘制格式信息;
(4)接着绘制版本信息;
(5)填充数据码和纠错码到二维码图中;
(6)最后绘制蒙版图案。因为按照上述方式填充内容,可能会出现大面积空白或黑块的情况,导致扫描识别十分困难。所以需要对整个图像与蒙版进行蒙版操作(Masking),蒙版操作即为异或 XOR 操作。在这一步,我们可以将数据排列成各种图片。

问:主要运用qrcode库文件、这是个什么东东呢?
答: 这里给一篇博客有详细叙述:Python生成二维码

开源库import qrcode具体使用方法:
编码:


import qrcode
img = qrcode.make('helloworld')

qr = qrcode.QRCode(
    version=5,
    error_correction=qrcode.constants.ERROR_CORRECT_H,
    box_size=8,
    border=4)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

解码:


def decode_qr_code(code_img_path):
    if not os.path.exists(code_img_path):
        raise FileExistsError(code_img_path)
    
    return pyzbar.decode(Image.open(code_img_path), symbols=[pyzbar.ZBarSymbol.QRCODE])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

二、基于Python的QRcodetest

环境:python3.7+zbar+qrcode

(一)配置环境

打开cmd、pip分别安装以下库文件:(zxing也是一个强大的二维码开源库文件,建议安装)

pip install opencv-python
pip install numpy
pip install pillow
pip install myqr
pip install qrcode
pip install zxing
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

tips:记得安装完成后,如果是eclipse要重新启动一次才能加载进来

(二)生成自己的二维码

1 MyQr制作gif二维码:

同目录下放置一张gif格式图片
Python二维码应用(一)QRcode二维码生成&识别

Python二维码应用(一)QRcode二维码生成&识别 Python二维码应用(一)QRcode二维码生成&识别

源码:



from MyQR import myqr
myqr.run(
    
    words='helloworld',
    version=1,  
    level='H',  
    picture='test.gif',  
    colorized=True,  
    contrast=1.0,  
    brightness=1.0,  
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2 qrcode制作带图片的二维码:
新建工程QRcodeTest;新建PyDev包,命名为MakeMyQRcode:
Python二维码应用(一)QRcode二维码生成&识别

因为我想做出一个漂亮简单一点的code,所以首先在目录文件下贴入一张图片,命名为QRcodeCenter,like this(左:成果图,右:准备中心图片):
Python二维码应用(一)QRcode二维码生成&识别 Python二维码应用(一)QRcode二维码生成&识别

源码:

'''
==============================
test1:生成二维码及查看
==============================
'''
from PIL import Image
import qrcode

qr = qrcode.QRCode(
    version=5, error_correction=qrcode.constants.ERROR_CORRECT_H, box_size=8, border=4)
qr.add_data("这里是二维码信息!")
qr.make(fit=True)

img = qr.make_image()
img = img.convert("RGBA")

icon = Image.open("QRcodeCenter.jpg")  

img_w, img_h = img.size
factor = 4
size_w = int(img_w / factor)
size_h = int(img_h / factor)

icon_w, icon_h = icon.size
if icon_w > size_w:
    icon_w = size_w
if icon_h > size_h:
    icon_h = size_h
icon = icon.resize((icon_w, icon_h), Image.ANTIALIAS)

w = int((img_w - icon_w) / 2)
h = int((img_h - icon_h) / 2)
icon = icon.convert("RGBA")
img.paste(icon, (w, h), icon)
img.show()   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

(三)识别二维码

在工程QRcodeTest;新建PyDev包,命名为ScanQRcode:
Python二维码应用(一)QRcode二维码生成&识别
运行结果:
Python二维码应用(一)QRcode二维码生成&识别 Python二维码应用(一)QRcode二维码生成&识别
源码:



'''
====================================
test2:生成二维码保存及对二维码解码输出
====================================
'''
import os
import qrcode
from PIL import Image
from pyzbar import pyzbar


def make_qr_code(content, save_path=None):
    qr_code_maker = qrcode.QRCode(version=5,
                                  error_correction=qrcode.constants.ERROR_CORRECT_M,
                                  box_size=8,
                                  border=4,
                                  )
    qr_code_maker.add_data(data=content)
    qr_code_maker.make(fit=True)
    img = qr_code_maker.make_image(fill_color="black", back_color="white")
    if save_path:
        img.save(save_path)
    else:
        img.show()  


def make_qr_code_with_icon(content, icon_path, save_path=None):
    if not os.path.exists(icon_path):
        raise FileExistsError(icon_path)

    
    qr_code_maker = qrcode.QRCode(version=5,
                                  error_correction=qrcode.constants.ERROR_CORRECT_H,
                                  box_size=8,
                                  border=4,
                                  )
    qr_code_maker.add_data(data=content)
    qr_code_maker.make(fit=True)
    qr_code_img = qr_code_maker.make_image(
        fill_color="black", back_color="white").convert('RGBA')

    
    icon_img = Image.open(icon_path)
    code_width, code_height = qr_code_img.size
    icon_img = icon_img.resize(
        (code_width // 4, code_height // 4), Image.ANTIALIAS)

    
    qr_code_img.paste(icon_img, (code_width * 3 // 8, code_width * 3 // 8))

    if save_path:
        qr_code_img.save(save_path)  
        qr_code_img.show()  
    else:
        print("save error!")


def decode_qr_code(code_img_path):
    if not os.path.exists(code_img_path):
        raise FileExistsError(code_img_path)

    
    return pyzbar.decode(Image.open(code_img_path), symbols=[pyzbar.ZBarSymbol.QRCODE])


if __name__ == "__main__":
    print("============QRcodetest===============")
    print("         1、Make a QRcode            ")
    print("         2、Scan a QRcode            ")
    print("=====================================")
    print("1、请输入编码信息:")
    code_Data = input('>>:').strip()
    print("正在编码:")
    
    make_qr_code_with_icon(
        code_Data, "QRcodeCenter.jpg", "qrcode.png")  
    print("图片已保存,名称为:qrcode.png")
    results = decode_qr_code("qrcode.png")
    print("2、正在解码:")
    if len(results):
        print("解码结果是:")
        print(results[0].data.decode("utf-8"))
    else:
        print("Can not recognize.")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86

三、调用opencv库摄像头识别图像

(一)用opencv找出(条形码&二维码)位置

opencv抠图教程
按照教程一步步调试运行(这里用一张条形码和一张二维码进行测试):

  • QRcodetest项目下新建ScanQRcode.py
    Python二维码应用(一)QRcode二维码生成&识别
  • 并保存两张图片在项目目录下:分别为qrcode.pngtest2.jpg
    Python二维码应用(一)QRcode二维码生成&识别
    运行测试:(不支持二维码)
    qrcode.png:
    Python二维码应用(一)QRcode二维码生成&识别
    test2.jpg:
    Python二维码应用(一)QRcode二维码生成&识别
    遇到问题:
    都只识别了部分条码,抠图也不是很成功!而且不能识别二维码!
    Python二维码应用(一)QRcode二维码生成&识别

源码:


'''
==============================
test3:找出图片中的条形码或二维码
(ps.仅识别条形码成功)
==============================
'''
import numpy as np
import argparse
import cv2

print("请输入解码图片完整名称:")
code_name = input('>>:').strip()
print("正在识别:")

image = cv2.imread(code_name)

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)


gradX = cv2.Sobel(gray, ddepth=cv2.cv2.CV_32F, dx=1, dy=0, ksize=-1)
gradY = cv2.Sobel(gray, ddepth=cv2.cv2.CV_32F, dx=0, dy=1, ksize=-1)


gradient = cv2.subtract(gradX, gradY)

gradient = cv2.convertScaleAbs(gradient)

blurred = cv2.blur(gradient, (9, 9))
(_, thresh) = cv2.threshold(blurred, 225, 255, cv2.THRESH_BINARY)


kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7))
closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
closed = cv2.erode(closed, None, iterations=4)
closed = cv2.dilate(closed, None, iterations=4)


(_, cnts, _) = cv2.findContours(closed.copy(),
                                cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]
rect = cv2.minAreaRect(c)
box = np.int0(cv2.boxPoints(rect))


cv2.drawContours(image, [box], -1, (0, 255, 0), 3)
cv2.imshow("ScanQRcodeTest", image)
cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

(二)调用解码函数进行解码

  • QRcodetest项目下新建ScanInvedio.py
    Python二维码应用(一)QRcode二维码生成&识别
    运行测试:(不支持条形码)

因为我自身电脑摄像头设置,颜色有点问题,请忽略

Python二维码应用(一)QRcode二维码生成&识别 Python二维码应用(一)QRcode二维码生成&识别

源码:

'''
================================
test4:识别摄像头中的条形码或二维码
(ps.仅识别二维码码成功)
================================
'''
import cv2
import pyzbar.pyzbar as pyzbar

def decodeDisplay(image):
    barcodes = pyzbar.decode(image)
    for barcode in barcodes:
        
        
        (x, y, w, h) = barcode.rect
        cv2.rectangle(image, (x, y), (x + w, y + h), (225, 225, 225), 2)

        
        
        barcodeData = barcode.data.decode("utf-8")
        barcodeType = barcode.type

        
        text = "{} ({})".format(barcodeData, barcodeType)
        cv2.putText(image, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX,
                    .5, (225, 225, 225), 2)

        
        print("[INFO] Found {} barcode: {}".format(barcodeType, barcodeData))
    return image


def detect():
    camera = cv2.VideoCapture(0)

    while True:
        
        ret, frame = camera.read()
        
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        im = decodeDisplay(gray)

        cv2.waitKey(5)
        cv2.imshow("camera", im)
        
        if cv2.waitKey(10) & 0xFF == ord('q'):
            break
    camera.release()
    cv2.destroyAllWindows()
    
if __name__ == '__main__':
    detect()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

大功告成!

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin