【计算机视觉】条形码与二维码识别
一、条形码简介
条形码是用可视化、机器可读的图像形式来表示信息。
一维条形码的条和空按照一定的编码规则平行排列,根据编码规则的不同,条形码分为不同类型,常见类型包括code39、code128、EAN-8、EAN-13、ISSN、ISBN、UPC等,以EAN-13类型条形码为例,它由左侧空白区、起始符、左侧数据符、前置码、底部供人识别的字符组成。
条形码每个数据字符由2个条和2个空构成,每一个条或者空由1~4个单位宽度组成,每个条形码数据字符的总宽度为7个单位。
二、OpenCV的条形码识别
条形码识别首先检测定位图像中的条形码,然后对检测出的条形码进行解码,得到条形码信息。
import cv2
from pyzbar.pyzbar import decode
# 加载图像
image_path = "barcode_image.jpg" # 替换为你的图像路径
image = cv2.imread(image_path)
# 转为灰度图像(可选)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 解码条形码
barcodes = decode(gray)
# 遍历检测到的条形码
for barcode in barcodes:
# 提取条形码的边界框坐标
(x, y, w, h) = barcode.rect
# 在图像上绘制矩形框
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 提取条形码数据
barcode_data = barcode.data.decode("utf-8")
barcode_type = barcode.type
# 在图像上显示条形码数据和类型
text = f"{barcode_data} ({barcode_type})"
cv2.putText(image, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
# 打印条形码数据
print(f"Found barcode: {barcode_data} (Type: {barcode_type})")
# 显示结果图像
cv2.imshow("Barcode Detection", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
这段代码是使用 OpenCV 和 Pyzbar 实现条形码识别的程序,下面对其进行逐行详细解释。
导入库
import cv2
from pyzbar.pyzbar import decode
- cv2:OpenCV 是一个用于计算机视觉的开源库,用于图像处理和显示。
- pyzbar.decode:
pyzbar
是一个专门用于解码条形码和二维码的 Python 库,decode
是其核心函数。
加载图像
image_path = "barcode_image.jpg" # 替换为你的图像路径
image = cv2.imread(image_path)
- image_path:指定条形码图片的路径。
- cv2.imread:加载图片并存储为一个 NumPy 数组。
image
是该图片的矩阵表示。
转为灰度图像(可选)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
- cv2.cvtColor:将图像从 BGR 色彩空间转换为灰度(单通道)。
- 灰度化的好处:条形码识别对色彩信息不敏感,灰度图像可减少计算复杂性,提高效率。
解码条形码
barcodes = decode(gray)
- decode(gray):对灰度图像进行条形码扫描。
- 返回值:
barcodes
是一个列表,每个元素代表一个检测到的条形码对象,包含以下信息:- data:条形码的内容。
- type:条形码的类型(如 Code128、EAN-13)。
- rect:条形码的位置和大小(矩形)。
遍历检测到的条形码
提取边界框坐标
(x, y, w, h) = barcode.rect
- barcode.rect:返回条形码的矩形边框,以
(x, y, w, h)
表示。x
和y
是左上角坐标。w
和h
是宽度和高度。
在图像上绘制矩形框
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
- cv2.rectangle:在图像上绘制矩形。
- 参数
(x, y)
和(x + w, y + h)
定义矩形的左上角和右下角。 (0, 255, 0)
定义矩形的颜色(绿色,BGR 格式)。2
指定矩形边框的粗细。
- 参数
提取条形码数据
barcode_data = barcode.data.decode("utf-8")
barcode_type = barcode.type
- barcode.data:返回条形码的原始字节数据。
- decode(“utf-8”):将字节数据解码为可读的字符串。
- barcode.type:条形码的格式类型,如
Code128
、EAN-13
等。
在图像上显示条形码数据和类型
text = f"{barcode_data} ({barcode_type})"
cv2.putText(image, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
- cv2.putText:在图像上绘制文本。
text
是显示的内容。(x, y - 10)
确定文本位置(在矩形框上方)。cv2.FONT_HERSHEY_SIMPLEX
是字体样式。0.5
是字体大小。(0, 255, 0)
是文本颜色(绿色)。2
是文本线条粗细。
打印条形码数据
print(f"Found barcode: {barcode_data} (Type: {barcode_type})")
- print:将条形码的内容和类型打印到终端。
显示结果图像
cv2.imshow("Barcode Detection", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
- cv2.imshow:显示图像。
"Barcode Detection"
是窗口标题。image
是带有条形码标注的图像。
- cv2.waitKey(0):等待按键事件,
0
表示无限等待。 - cv2.destroyAllWindows:关闭所有窗口。
三、二维码简介
二维码是一种高效的图形化编码技术,全称是“Quick Response Code”,简称“QR Code”。它最初由日本的公司 Denso Wave 在1994年发明,用于快速扫描和识别信息。二维码的主要特点是能以点阵方式存储大量数据,并可通过摄像头或专用扫描设备快速读取。
二维码的特点
- 高存储容量:
- 可存储多种类型的数据,包括文本、数字、URL、文件甚至多语言内容。
- 一个标准二维码的最大数据容量为:
- 数字:7089 个字符。
- 字母数字:4296 个字符。
- 二进制(8 位):2953 字节。
- 汉字:1817 个字符。
- 高效识别:
- 使用二维矩阵编码,支持从任意角度(360°)扫描,识别速度快。
- 容错能力强:
- 支持 4 级容错(L、M、Q、H),可修复最多 30% 的损坏或污损。
- 即使二维码部分损坏,仍能正确解码。
- 易生成、易读取:
- 使用免费工具即可生成二维码。
- 通过智能手机摄像头或专用扫码器即可解码。
二维码的结构
二维码由以下几个主要部分组成:
- 定位图形:
- 位于二维码的三个角落,用于快速确定二维码的位置和方向。
- 校正图形:
- 主要位于中间区域,确保二维码的精确解码。
- 数据区域:
- 用于存储实际的编码数据。
- 格式信息:
- 存储二维码的纠错级别和掩码模式。
- 版本信息:
- 标识二维码的大小和容量(版本1到40,对应不同尺寸)。
二维码的工作原理
- 数据编码: 数据被转化为点阵(黑白块)的形式,按特定规则排列。
- 图像扫描: 使用摄像头或扫码器拍摄二维码图像。
- 图像处理: 设备识别二维码中的定位点,确定数据区域,并校正角度。
- 数据解码: 通过算法解码点阵中的数据,恢复原始信息。
四、二维码识别
二维码识别算法代码
import cv2
from pyzbar.pyzbar import decode
def recognize_qr_code(image_path):
"""
识别图像中的二维码并返回解码信息。
:param image_path: 输入图像的路径
:return: 解码信息的列表,每个元素为一个字典,包含 'data' 和 'type'
"""
# 读取图像
image = cv2.imread(image_path)
# 转为灰度图像(可选,但能提高识别效果)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 解码二维码
qr_codes = decode(gray)
# 用于存储解码结果
decoded_info = []
# 遍历识别到的二维码
for qr_code in qr_codes:
# 提取二维码的数据和类型
qr_data = qr_code.data.decode('utf-8') # 解码数据为字符串
qr_type = qr_code.type # 二维码类型(如 QRCODE)
# 保存数据到结果列表
decoded_info.append({"data": qr_data, "type": qr_type})
# 在图像上绘制矩形框
(x, y, w, h) = qr_code.rect
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 显示解码信息
cv2.putText(image, qr_data, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
# 显示标注后的图像
cv2.imshow("QR Code Detection", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
return decoded_info
# 调用函数并打印结果
if __name__ == "__main__":
image_path = "qrcode_image.jpg" # 替换为你的二维码图片路径
results = recognize_qr_code(image_path)
if results:
for result in results:
print(f"Data: {result['data']}, Type: {result['type']}")
else:
print("No QR Code detected.")
代码解析
- 读取图像: 使用 OpenCV 的
cv2.imread
加载图像。 - 灰度处理: 将图像转为灰度以减少计算复杂性,使用
cv2.cvtColor
函数。 - 二维码解码: 使用
pyzbar.decode
函数检测图像中的二维码。- 返回一个列表,每个元素包含解码后的数据、类型和位置信息。
- 绘制矩形框和标注:
- 提取二维码的位置
rect
,并使用cv2.rectangle
绘制绿色框。 - 使用
cv2.putText
在图像上标注二维码的内容。
- 提取二维码的位置
- 显示结果: 使用
cv2.imshow
显示标注后的图像。 - 返回解码信息: 返回解码结果为一个字典列表,包含
data
和type
信息。