python3 + opencv +pyzbar实时检测二维码 / 定位二维码,并绘制出二维码的框和提取二维码内容

·  阅读 1315

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

💐 兄dei点个赞呗! 💐

🍀 兄dei你的随手一赞,就是对我莫大的鼓励! 🍀

🌺 兄dei每日一赞,发大财行大运哦! 🌺

1 pyzbar二维码检测模块

1.1. pyzbar模块介绍

1、该模块是一个日本的author开源的一个二维码检测的项目,可以用来检测:

  • 二维码
  • 条形码

同时可以返回检测二维码和条形码的相关信息:

  • 二维码中包含的信息
  • 检测二维码的矩形框
  • 检测二维码的最小外接多边形框

2、pyzbar支持两种数据类型输入:

  • PIL读取的PIL.Image数据类型
  • opencv读取的ndarray数据类型

1.2 pyzbar模块的安装

1、Mac OS X:

brew install zbar

2、Linux:

sudo apt-get install libzbar0

3、直接使用pip安装

pip install pyzbar

1.3 pyzbar模块测试用例

1、pyzbar的decode接受测PIL.Image的实例

图片:

在这里插入图片描述

>>> from pyzbar.pyzbar import decode
>>> from PIL import Image
>>> decode(Image.open('pyzbar/tests/code128.png'))
[
    Decoded(
        data=b'Foramenifera', type='CODE128',
        rect=Rect(left=37, top=550, width=324, height=76),
        polygon=[
            Point(x=37, y=551), Point(x=37, y=625), Point(x=361, y=626),
            Point(x=361, y=550)
        ]
    )
    Decoded(
        data=b'Rana temporaria', type='CODE128',
        rect=Rect(left=4, top=0, width=390, height=76),
        polygon=[
            Point(x=4, y=1), Point(x=4, y=75), Point(x=394, y=76),
            Point(x=394, y=0)
        ]
    )
]
复制代码

从上面的内容可以看到,返回检测到两个条形二维码,每个条形二维码包含内容:

  • 条形码中存储的内容
  • 条形码的类型,例如这里的CODE128
  • 检测到条形码的矩形框,矩形框的左上角坐标和矩形框的宽与高
  • 检测到条形码的外接多边形框四个点坐标

2、检测二维码

测试图片(图片来源pyzbar的github项目):

在这里插入图片描述


from PIL import Image, ImageDraw

from pyzbar.pyzbar import decode


image = Image.open('./qrcode_rotated.png').convert('RGB')
draw = ImageDraw.Draw(image)
for barcode in decode(image):
    rect = barcode.rect
    draw.rectangle(
        (
            (rect.left, rect.top),
            (rect.left + rect.width, rect.top + rect.height)
        ),
        outline='#0080ff'
    )

    draw.polygon(barcode.polygon, outline='#e945ff')


image.save('bounding_box_and_polygon.png')
image.show()
复制代码

检测结果:

在这里插入图片描述

2 python3 + opencv +pyzbar实时检测二维码,并绘制二维码的矩形框

  • 连接摄像头,运行程序即可实时检测二维码
  • q键,退出显示和程序运行
__Author__ = "Shliang"
__Email__ = "shliang0603@gmail.com"

# coding:utf8

import cv2
import pyzbar.pyzbar as pyzbar
import numpy as np


def decodeDisplay(image):
    barcodes = pyzbar.decode(image)
    rects_list = []
    polygon_points_list = []
    QR_info = []

    # 这里循环,因为画面中可能有多个二维码
    for barcode in barcodes:
        # 提取条形码的边界框的位置
        # 画出图像中条形码的边界框
        (x, y, w, h) = barcode.rect
        rects_list.append((x, y, w, h))
        cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)
        polygon_points = barcode.polygon
        # print(f"polygon_points: {polygon_points}")  # polygon_points: [Point(x=217, y=174), Point(x=257, y=353), Point(x=433, y=316), Point(x=394, y=140)]
        # print(f"polygon_points: {polygon_points[0]}")  # polygon_points: Point(x=217, y=174)
        point_x, point_y = polygon_points[0]
        # print(f"point_x, point_y: {point_x, point_y}")  # point_x, point_y: (217, 174)

        extract_polygon_points = np.zeros((4, 2), dtype=np.int)
        for idx, points in enumerate(polygon_points):
            point_x, point_y = points  # 默认得到的point_x, point_y是float64类型
            extract_polygon_points[idx] = [point_x, point_y]

        print(extract_polygon_points.shape)  # (4, 2)

        # 不reshape成 (4,1 2)也是可以的
        extract_polygon_points = extract_polygon_points.reshape((-1, 1, 2))
        polygon_points_list.append(extract_polygon_points)

        # 要加上中括号,否则只会绘制四个点
        # cv2.polylines(image, extract_polygon_points, isClosed=True, color=(255, 0, 255), thickness=2)

        # 绘制多边形
        cv2.polylines(image, [extract_polygon_points], isClosed=True, color=(255, 0, 255), thickness=2,
                      lineType=cv2.LINE_AA)

        # 条形码数据为字节对象,所以如果我们想在输出图像上画出来,就需要先将它转换成字符串
        barcodeData = barcode.data.decode("utf-8")
        barcodeType = barcode.type

        # 绘出图像上条形码的数据和条形码类型
        text = "{} ({})".format(barcodeData, barcodeType)
        QR_info.append(text)
        cv2.putText(image, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX,
                    .5, (0, 0, 125), 2)

        # 向终端打印条形码数据和条形码类型
        print("[INFO] Found {} barcode: {}".format(barcodeType, barcodeData))
    return image, rects_list, polygon_points_list, QR_info


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

    while True:
        # 读取当前帧
        ret, frame = cap.read()
        # 转换为灰度图是为了检测到二维码,如果是BGR图很大概率是检测不到二维码
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        im, rects_list, polygon_points_list, QR_info = decodeDisplay(gray)

        # 把检测到二维码的信息再绘制到BGR彩色图像上
        for data in zip(rects_list, polygon_points_list, QR_info):
            print(f"data: {data}")
            x, y, w, h = data[0]
            polygon_points = data[1]
            text = data[2]
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
            cv2.polylines(frame, [polygon_points], isClosed=True, color=(255, 0, 255), thickness=2,
                          lineType=cv2.LINE_AA)
            cv2.putText(frame, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX,
                        .5, (0, 0, 125), 2)

        # 因为一个是单通道的灰度图,一个是BGR三通道的彩色图,因此不能够拼接在一起显示,这里就用两个窗口显示
        cv2.imshow("camera", im)
        cv2.imshow("frame", frame)

        # 按q键退出画面显示
        k = cv2.waitKey(1)
        if k == ord('q'):
            break


    cap.release()
    cv2.destroyAllWindows()



if __name__ == '__main__':
    detect()
复制代码

显示结果如下:

在这里插入图片描述

分类:
人工智能
标签:
收藏成功!
已添加到「」, 点击更改