在这篇文章中,我们将使用名为pystrich的库实现标准条形码的生成,使用ZBar 和 OpenCV 的库实现条形码和二维码的识别。
1.条形码与二维码的生成
1.1 ean13标准条形码
from pystrich.ean13 import EAN13Encoder
# pip install pystrich
encode = EAN13Encoder('123202123123')
encode.save('pystrich.png')
# pip install python-barcode
from barcode.writer import ImageWriter
from barcode.ean import EuropeanArticleNumber13
ean = EuropeanArticleNumber13("123202123123", writer=ImageWriter())
ean.save("barcode")
条形码最常用的ean13,前三位是国家代码,接着4位是企业代码,接着5位是企业自定义,最后一位是校验码(自动生成)
参数是一个12位的值,会生成13位的条形码
校验码的计算方法是 10 -(偶数位之和*3 + 奇数位之和) % 10
123202123123X 10 - ((2+2+2+2+1+3)*3 +(1+3+0+1+3+2)) % 10 -->4
1232021231234
1.2简单二维码生成
#!/usr/bin/python3
# -*- encoding: utf-8 -*-
"""
@File : generateQRCode.py
@Time : 2021/10/12 14:13
"""
# 方法一
# 生成二维码
import qrcode
# 二维码包含的示例数据
data = "https://blog.csdn.net/weixin_43229348"
# 生成的二维码图片名称
filename = "CSDNBlog.png"
# 生成二维码
img = qrcode.make(data)
# 保存成图片输出
img.save(filename)
# 方法二
# 手机扫描效果如下,如果是网址,会直接跳转到对应网页,如果是文字,则解析出对应内容。
import qrcode
def makeQrCode(data):
# 设置二维码属性
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4,
)
# 添加文本(文本或者网址等)
qr.add_data(data)
# 生成二维码
qr.make(fit=True)
img = qr.make_image()
# img = qr.make_image(fill_color="pink", back_color="green")
# 保存二维码
img.save("CSDNBlog.png")
if __name__ == "__main__":
makeQrCode("https://blog.csdn.net/weixin_43229348")
1.3二维码中加入图片
# 导入图像处理库PIL的image方法
from PIL import Image
# qrcode是第三方库,需要pip install qrcode安装
import qrcode
# 初步生成二维码图像
qr = qrcode.QRCode(version=None,error_correction=qrcode.constants.ERROR_CORRECT_H,box_size=8,border=4)
# 添加二维码信息,可以是文字、数字、url
qr.add_data("https://blog.csdn.net/weixin_43229348")
# 生成二维码实例
qr.make(fit=True)
# 把实例转换成图片
img = qr.make_image()
# 把颜色模式转换为RGBA
img = img.convert("RGBA")
# 打开logo文件,二维码中心logo图片
icon = Image.open("favicon.jpg")
# 先得出二维码的宽和高
img_w,img_h = img.size
factor = 4
# 通过二维码宽高计算出logo图片宽和高的最大限度
size_w = int(img_w / factor)
size_h = int(img_h / factor)
# 获取logo的宽和高
icon_w,icon_h = icon.size
#比较logo宽高和最大限度宽高,如果超过最大限度就将logo尺寸调整到最大限度
if icon_w >size_w:
icon_w = size_w
if icon_h > size_h:
icon_h = size_h
# 重新调整logo的尺寸 Image.NEAREST :低质量 Image.BILINEAR:双线性
# Image.BICUBIC :三次样条插值 Image.ANTIALIAS:高质量
icon = icon.resize((icon_w,icon_h),Image.ANTIALIAS)
# 根据logo和图片的长宽确定logo的位置
w = int((img_w - icon_w)/2)
h = int((img_h - icon_h)/2)
# 将logo颜色模式转换为RGBA
icon = icon.convert("RGBA")
# 将logo图片粘贴到二维码的指定位置
img.paste(icon,(w,h))
# 保存二维码到指定位置,设置二维码格式
img.save('CSDNWithLOGO.png')
参数含义:
version:值为1~40的整数,控制二维码的大小(最小值是1,是个12×12的矩阵)。 如果想让程序自动确定,将值设置为 None 并使用 fit 参数即可。
error_correction:控制二维码的错误纠正功能。可取值下列4个常量。
ERROR_CORRECT_L:大约7%或更少的错误能被纠正。
ERROR_CORRECT_M(默认):大约15%或更少的错误能被纠正。
ROR_CORRECT_H:大约30%或更少的错误能被纠正。
box_size:控制二维码中每个小格子包含的像素数。
border:控制边框(二维码与图片边界的距离)包含的格子数(默认为4,是相关标准规定的最小值)
2.条形码与二维码的识别
2.1第 1 步:安装 ZBar
检测和解码不同类型条码和二维码的最佳库称为 ZBar。在我们开始之前,您需要按照此处的说明下载并安装 ZBar。
Ubuntu 用户可以使用安装:
sudo apt-get install libzbar-dev libzbar0
2.2第 2 步:安装 pyzbar(仅适用于 Python 用户)
ZBar 正式版不支持 Python 3,所以我们推荐使用 pyzbar,它同时支持 ython 2 和 Python 3。如果你只是想使用 python 2,你可以安装 zbar,跳过安装 pyzbar。
安装ZBar
# 注意:官方 zbar 版本不支持 Python 3
pip install zbar
安装pyzbar
pip install pyzbar
2.3了解条码/二维码的结构
ZBar 返回的一个条码/二维码对象有三个字段
- 1.Type:如果 ZBar 检测到的符号是二维码,则类型为 QR-Code。如果是条码,则类型是ZBar能够读取的几种条码之一。在我们的示例中,我们使用了 CODE-128 类型的条形码。
- 2.Data:这是嵌入在条形码/二维码中的数据。此数据通常是字母数字,但其他类型(数字、字节/二进制等)也有效。
- 3.Location:这是定位代码的点的集合。对于 QR 码,它是与 QR 码四边形的四个角对应的四个点的列表。对于条码,位置是标记条码中字边界开始和结束的点的集合。下面为几种不同类型的符号绘制了位置点。
使用红点绘制的 ZBar 位置点。对于 QR 码,它是符号的 4 个角的向量。对于条形码,它是沿字边界形成线条的点的集合。
2.4使用 ZBar + OpenCV 扫描条码和二维码的 C++ 代码
我们首先定义一个结构来保存有关在图像中检测到的条形码或二维码的信息。
typedef struct
{
string type;
string data;
vector <Point> location;
} decodedObject;
类型、数据和位置字段在上一节中进行了说明。
让我们看看 decode 函数,它接收图像并返回找到的所有条形码和二维码。
// 查找和解码条形码和二维码
void decode(Mat &im, vector<decodedObject>&decodedObjects)
{
// Create zbar scanner
ImageScanner scanner;
// 创建 zbar 扫描仪
scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);
// 将图像转换为灰度
Mat imGray;
cvtColor(im, imGray,CV_BGR2GRAY);
// 将图像数据包装在 zbar 图像中
Image image(im.cols, im.rows, "Y800", (uchar *)imGray.data, im.cols * im.rows);
// 扫描条形码和二维码的图像
int n = scanner.scan(image);
// 打印结果
for(Image::SymbolIterator symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol)
{
decodedObject obj;
obj.type = symbol->get_type_name();
obj.data = symbol->get_data();
// 打印 type 和 data
cout << "Type : " << obj.type << endl;
cout << "Data : " << obj.data << endl << endl;
// 获取位置
for(int i = 0; i< symbol->get_location_size(); i++)
{
obj.location.push_back(Point(symbol->get_location_x(i),symbol->get_location_y(i)));
}
decodedObjects.push_back(obj);
}
}
首先,我们创建了一个ZBar ImageScanner的实例,并将其配置为检测所有类型的条形码和QR码。如果希望只检测特定类型的符号,则需要将ZBAR_NONE更改为这里列出的另一种类型。然后我们将图像转换为灰度。然后在第16行将灰度图像转换为ZBar兼容的格式。最后,我们扫描图像中的符号。最后,我们遍历符号并提取类型、数据和位置信息,并将其推入检测对象的向量中。
接下来,我们将解释显示所有符号的代码。下面的代码接收输入图像和前一步解码后的符号向量。如果这些点形成了一个四边形(例如QR码),我们只需画出这个四边形。如果位置不是一个四边形,我们画出所有点的外边界(也称为凸包)。这是使用OpenCV函数convexHull完成的。
// 显示条码和二维码位置
void display(Mat &im, vector<decodedObject>&decodedObjects)
{
// 遍历所有解码对象
for(int i = 0; i < decodedObjects.size(); i++)
{
vector<Point> points = decodedObjects[i].location;
vector<Point> hull;
// 如果点不形成四边形,请找到凸包
if(points.size() > 4)
convexHull(points, hull);
else
hull = points;
// 凸包中的点数
int n = hull.size();
for(int j = 0; j < n; j++)
{
line(im, hull[j], hull[ (j+1) % n], Scalar(255,0,0), 3);
}
}
// 显示结果
imshow("Results", im);
waitKey(0);
}
最后,我们有下面共享的主要函数,它只是读取图像,使用上述 decode 函数解码符号并使用上述 display 函数显示位置。
2.5使用 ZBar + OpenCV 扫描条码和二维码的 Python 代码
对于 Python,我们使用 pyzbar,它有一个简单的解码功能来定位和解码图像中的所有符号。decode 函数简单地封装了 pyzbar 的 decode 函数,并在定位的条形码和二维码上循环并打印数据。
来自上一步的解码符号被传递到显示函数。如果这些点形成一个四边形(例如在二维码中),我们只需绘制四边形。如果位置不是四边形,我们绘制所有点(也称为凸包)的外边界。这是使用 OpenCV 函数 cv2.convexHull 完成的。
最后,主函数简单地读取图像、解码并显示结果。
from __future__ import print_function
import pyzbar.pyzbar as pyzbar
import numpy as np
import cv2
def decode(im):
# 查找条形码和二维码
decodedObjects = pyzbar.decode(im)
# 打印结果
for obj in decodedObjects:
print('Type : ', obj.type)
print('Data : ', obj.data, '\n')
return decodedObjects
# 显示条码和二维码位置
def display(im, decodedObjects):
# 遍历所有解码对象
for decodedObject in decodedObjects:
points = decodedObject.polygon
# 如果点不形成四边形,请找到凸包
if len(points) > 4:
hull = cv2.convexHull(np.array([point for point in points], dtype=np.float32))
hull = list(map(tuple, np.squeeze(hull)))
else:
hull = points
# 凸包中的点数
n = len(hull)
hull = [(int(x), int(y)) for x, y in hull]
# 绘制凸包
for j in range(0, n):
cv2.line(im, hull[j], hull[(j + 1) % n], (255, 0, 0), 3)
# 显示结果
cv2.imshow("Results", im)
cv2.waitKey(0)
# 主函数
if __name__ == '__main__':
# 读取图片
im = cv2.imread('barcode.png')
decodedObjects = decode(im)
display(im, decodedObjects)
参考目录
https://www.cnblogs.com/liqinsan/p/11490955.html
https://blog.csdn.net/qq_34802511/article/details/86699027
https://learnopencv.com/barcode-and-qr-code-scanner-using-zbar-and-opencv/