Python二维码解析案例实现?

wen python案例 3

本文目录导读:

  1. 环境准备
  2. 基础二维码解析示例
  3. 完整示例:GUI二维码扫描器
  4. 常见问题及解决方案

我来为您提供一个完整的Python二维码解析案例,这个案例将展示如何使用Python读取和解析二维码中的信息。

环境准备

首先安装必要的库:

pip install opencv-python pillow pyzbar

基础二维码解析示例

从图片文件解析二维码

import cv2
from pyzbar.pyzbar import decode
from PIL import Image
def decode_qr_code_from_image(image_path):
    """
    从图片文件中解析二维码
    Args:
        image_path: 二维码图片路径
    Returns:
        解码后的数据列表
    """
    try:
        # 使用OpenCV读取图片
        image = cv2.imread(image_path)
        if image is None:
            raise ValueError("无法读取图片文件")
        # 使用pyzbar解码二维码
        decoded_objects = decode(image)
        results = []
        for obj in decoded_objects:
            data = {
                'data': obj.data.decode('utf-8'),  # 解码数据
                'type': obj.type,                   # 二维码类型
                'rect': obj.rect,                   # 二维码位置
                'polygon': obj.polygon              # 二维码多边形
            }
            results.append(data)
        return results
    except Exception as e:
        print(f"解码失败: {str(e)}")
        return []
# 使用示例
if __name__ == "__main__":
    # 替换为您的二维码图片路径
    results = decode_qr_code_from_image("qrcode.png")
    if results:
        for i, result in enumerate(results, 1):
            print(f"二维码 {i}:")
            print(f"  内容: {result['data']}")
            print(f"  类型: {result['type']}")
            print(f"  位置: {result['rect']}")
    else:
        print("未检测到二维码")

从摄像头实时解析二维码

import cv2
from pyzbar.pyzbar import decode
def real_time_qr_decode():
    """
    实时从摄像头读取并解析二维码
    """
    # 打开摄像头
    cap = cv2.VideoCapture(0)
    if not cap.isOpened():
        print("无法打开摄像头")
        return
    print("按 'q' 键退出程序")
    while True:
        # 读取摄像头帧
        ret, frame = cap.read()
        if not ret:
            print("无法获取视频帧")
            break
        # 解码二维码
        decoded_objects = decode(frame)
        # 在图像上绘制结果
        for obj in decoded_objects:
            # 绘制二维码边框
            points = obj.polygon
            if len(points) > 4:
                hull = cv2.convexHull(points)
                points = hull
            n = len(points)
            for j in range(n):
                cv2.line(frame, points[j], points[(j+1) % n], (0, 255, 0), 3)
            # 提取数据
            data = obj.data.decode('utf-8')
            rect = obj.rect
            # 显示数据
            cv2.putText(frame, data, (rect.left, rect.top - 10),
                       cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
            print(f"检测到二维码: {data}")
        # 显示视频帧
        cv2.imshow('QR Code Scanner', frame)
        # 按 'q' 键退出
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    # 释放资源
    cap.release()
    cv2.destroyAllWindows()
# 运行实时扫描
if __name__ == "__main__":
    real_time_qr_decode()

高级功能:创建和保存二维码

import qrcode
from PIL import Image
import cv2
from pyzbar.pyzbar import decode
import numpy as np
class QRCodeManager:
    def __init__(self):
        pass
    def create_qr_code(self, data, output_path="qrcode.png", 
                       fill_color="black", back_color="white", 
                       box_size=10, border=4):
        """
        创建二维码并保存
        Args:
            data: 要编码的数据
            output_path: 输出文件路径
            fill_color: 二维码颜色
            back_color: 背景颜色
            box_size: 每个小方块的大小
            border: 边框大小
        """
        qr = qrcode.QRCode(
            version=1,
            error_correction=qrcode.constants.ERROR_CORRECT_L,
            box_size=box_size,
            border=border,
        )
        qr.add_data(data)
        qr.make(fit=True)
        # 创建二维码图像
        img = qr.make_image(fill_color=fill_color, back_color=back_color)
        img.save(output_path)
        print(f"二维码已保存到: {output_path}")
        return img
    def decode_and_verify(self, image_path):
        """
        解码并验证二维码内容
        """
        results = decode_qr_code_from_image(image_path)
        return results
    def qr_code_info(self, image_path):
        """
        获取二维码的详细信息
        """
        image = cv2.imread(image_path)
        if image is None:
            return None
        decoded = decode(image)
        info = []
        for obj in decoded:
            # 获取二维码的详细信息
            data = {
                'content': obj.data.decode('utf-8'),
                'type': obj.type,
                'position': {
                    'x': obj.rect.left,
                    'y': obj.rect.top,
                    'width': obj.rect.width,
                    'height': obj.rect.height
                },
                'orientation': self._get_orientation(obj.polygon),
                'quality': self._calculate_quality(image, obj.rect)
            }
            info.append(data)
        return info
    def _get_orientation(self, polygon):
        """
        计算二维码的旋转角度
        """
        if len(polygon) < 4:
            return 0
        points = np.array(polygon, dtype=np.float32)
        rect = cv2.minAreaRect(points)
        angle = rect[2]
        # 调整角度范围
        if angle < -45:
            angle += 90
        return angle
    def _calculate_quality(self, image, rect):
        """
        评估二维码图像质量
        """
        x, y, w, h = rect.x, rect.y, rect.width, rect.height
        # 确保坐标在图像范围内
        if x < 0 or y < 0 or x + w > image.shape[1] or y + h > image.shape[0]:
            return 0
        # 提取二维码区域
        qr_region = image[y:y+h, x:x+w]
        # 计算对比度
        gray = cv2.cvtColor(qr_region, cv2.COLOR_BGR2GRAY)
        contrast = gray.std()
        # 返回质量评分(0-100)
        quality = min(100, max(0, contrast * 2))
        return quality
# 使用示例
if __name__ == "__main__":
    manager = QRCodeManager()
    # 1. 创建二维码
    print("=== 创建二维码 ===")
    data = "https://www.example.com"
    manager.create_qr_code(data, "my_qrcode.png")
    # 2. 解析二维码
    print("\n=== 解析二维码 ===")
    results = manager.decode_and_verify("my_qrcode.png")
    print(f"解码结果: {results}")
    # 3. 获取二维码信息
    print("\n=== 二维码信息 ===")
    info = manager.qr_code_info("my_qrcode.png")
    for item in info:
        print(f"内容: {item['content']}")
        print(f"类型: {item['type']}")
        print(f"位置: {item['position']}")
        print(f"旋转角度: {item['orientation']:.2f}°")
        print(f"质量评分: {item['quality']:.2f}")

批量处理二维码

import os
import cv2
from pyzbar.pyzbar import decode
from concurrent.futures import ThreadPoolExecutor
def batch_decode_qr_codes(directory_path):
    """
    批量处理目录中的二维码图片
    Args:
        directory_path: 图片目录路径
    Returns:
        处理结果字典
    """
    results = {}
    # 获取所有图片文件
    image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.gif']
    image_files = []
    for file in os.listdir(directory_path):
        if any(file.lower().endswith(ext) for ext in image_extensions):
            image_files.append(os.path.join(directory_path, file))
    def process_image(image_path):
        """处理单个图片"""
        try:
            image = cv2.imread(image_path)
            if image is None:
                return image_path, None, "无法读取图片"
            decoded_objects = decode(image)
            if decoded_objects:
                data = [obj.data.decode('utf-8') for obj in decoded_objects]
                return image_path, data, "成功"
            else:
                return image_path, None, "未检测到二维码"
        except Exception as e:
            return image_path, None, str(e)
    # 使用线程池并行处理
    with ThreadPoolExecutor(max_workers=4) as executor:
        futures = [executor.submit(process_image, img_path) 
                  for img_path in image_files]
        for future in futures:
            path, data, status = future.result()
            results[path] = {
                'data': data,
                'status': status
            }
    return results
# 使用示例
if __name__ == "__main__":
    # 替换为您的图片目录路径
    results = batch_decode_qr_codes("./qr_images/")
    for file_path, info in results.items():
        print(f"\n文件: {file_path}")
        print(f"状态: {info['status']}")
        if info['data']:
            print(f"内容: {info['data']}")

完整示例:GUI二维码扫描器

import tkinter as tk
from tkinter import filedialog, messagebox
import cv2
from PIL import Image, ImageTk
from pyzbar.pyzbar import decode
import threading
class QRCodeScannerGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("二维码扫描器")
        self.root.geometry("800x600")
        # 初始化变量
        self.cap = None
        self.is_scanning = False
        self.current_frame = None
        # 创建GUI组件
        self.create_widgets()
    def create_widgets(self):
        # 顶部控制栏
        control_frame = tk.Frame(self.root)
        control_frame.pack(pady=10)
        tk.Button(control_frame, text="选择图片", 
                 command=self.select_image, width=15).pack(side=tk.LEFT, padx=5)
        tk.Button(control_frame, text="开始扫描", 
                 command=self.start_scanning, width=15).pack(side=tk.LEFT, padx=5)
        tk.Button(control_frame, text="停止扫描", 
                 command=self.stop_scanning, width=15).pack(side=tk.LEFT, padx=5)
        # 图像显示区域
        self.image_label = tk.Label(self.root)
        self.image_label.pack(expand=True, fill=tk.BOTH, padx=10, pady=10)
        # 结果显示区域
        result_frame = tk.Frame(self.root)
        result_frame.pack(pady=10)
        tk.Label(result_frame, text="扫描结果:").pack(side=tk.LEFT)
        self.result_text = tk.Text(result_frame, height=3, width=60)
        self.result_text.pack(side=tk.LEFT, padx=5)
        # 状态栏
        self.status_label = tk.Label(self.root, text="就绪", bd=1, 
                                    relief=tk.SUNKEN, anchor=tk.W)
        self.status_label.pack(side=tk.BOTTOM, fill=tk.X)
    def select_image(self):
        """选择图片文件"""
        file_path = filedialog.askopenfilename(
            title="选择二维码图片",
            filetypes=[("图片文件", "*.png *.jpg *.jpeg *.bmp *.gif")]
        )
        if file_path:
            self.stop_scanning()
            self.process_image(file_path)
    def process_image(self, image_path):
        """处理选择的图片"""
        try:
            # 读取并显示图片
            image = cv2.imread(image_path)
            if image is None:
                raise ValueError("无法读取图片")
            # 解码二维码
            decoded_objects = decode(image)
            # 绘制检测结果
            for obj in decoded_objects:
                points = obj.polygon
                if len(points) > 4:
                    hull = cv2.convexHull(points)
                    points = hull
                n = len(points)
                for j in range(n):
                    cv2.line(image, points[j], points[(j+1) % n], (0, 255, 0), 3)
                # 显示解码结果
                data = obj.data.decode('utf-8')
                self.result_text.insert(tk.END, f"检测到二维码: {data}\n")
            if not decoded_objects:
                self.result_text.insert(tk.END, "未检测到二维码\n")
            # 显示图片
            self.display_image(image)
            self.status_label.config(text=f"处理完成: {image_path}")
        except Exception as e:
            messagebox.showerror("错误", f"处理图片时出错: {str(e)}")
    def start_scanning(self):
        """开始实时扫描"""
        if self.is_scanning:
            return
        self.cap = cv2.VideoCapture(0)
        if not self.cap.isOpened():
            messagebox.showerror("错误", "无法打开摄像头")
            return
        self.is_scanning = True
        self.status_label.config(text="正在扫描...")
        # 在新线程中运行扫描
        self.scan_thread = threading.Thread(target=self.scan_loop)
        self.scan_thread.daemon = True
        self.scan_thread.start()
    def scan_loop(self):
        """扫描循环"""
        while self.is_scanning and self.cap.isOpened():
            ret, frame = self.cap.read()
            if not ret:
                break
            # 解码二维码
            decoded_objects = decode(frame)
            # 绘制检测框
            for obj in decoded_objects:
                points = obj.polygon
                if len(points) > 4:
                    hull = cv2.convexHull(points)
                    points = hull
                n = len(points)
                for j in range(n):
                    cv2.line(frame, points[j], points[(j+1) % n], (0, 255, 0), 3)
                # 显示解码结果
                data = obj.data.decode('utf-8')
                self.root.after(0, self.update_result, f"检测到二维码: {data}\n")
            # 显示帧
            self.display_image(frame)
        # 清理
        if self.cap:
            self.cap.release()
    def stop_scanning(self):
        """停止扫描"""
        self.is_scanning = False
        if self.cap:
            self.cap.release()
        self.cap = None
        self.status_label.config(text="扫描已停止")
    def display_image(self, image):
        """显示图像"""
        # 转换颜色空间
        image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        # 调整大小以适应窗口
        height, width = image_rgb.shape[:2]
        max_height = 400
        max_width = 700
        if height > max_height or width > max_width:
            scale = min(max_height/height, max_width/width)
            new_width = int(width * scale)
            new_height = int(height * scale)
            image_rgb = cv2.resize(image_rgb, (new_width, new_height))
        # 转换为PIL图像
        image_pil = Image.fromarray(image_rgb)
        image_tk = ImageTk.PhotoImage(image_pil)
        # 更新显示
        self.image_label.config(image=image_tk)
        self.image_label.image = image_tk
    def update_result(self, text):
        """更新结果显示"""
        self.result_text.insert(tk.END, text)
        self.result_text.see(tk.END)
# 运行GUI应用
if __name__ == "__main__":
    root = tk.Tk()
    app = QRCodeScannerGUI(root)
    root.mainloop()

常见问题及解决方案

安装问题

# Windows系统
pip install opencv-python pillow pyzbar
# 如果pyzbar安装失败,需要先安装Visual C++ Redistributable
# 下载地址: https://aka.ms/vs/16/release/vc_redist.x64.exe
# macOS系统
brew install zbar
pip install pyzbar
# Linux系统
sudo apt-get install libzbar0
pip install pyzbar

解码注意事项

# 图像预处理提高解码成功率
def preprocess_for_qr_decode(image):
    """
    图像预处理,提高二维码解码成功率
    """
    # 转换为灰度图
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    # 应用高斯模糊去噪
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    # 自适应阈值处理
    thresh = cv2.adaptiveThreshold(blurred, 255, 
                                  cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                  cv2.THRESH_BINARY, 11, 2)
    # 形态学操作
    kernel = np.ones((3, 3), np.uint8)
    morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
    return morph
# 使用预处理后的图像进行解码
def decode_with_preprocessing(image_path):
    image = cv2.imread(image_path)
    processed = preprocess_for_qr_decode(image)
    # 尝试在预处理后的图像上解码
    results = decode(processed)
    if not results:
        # 如果失败,尝试原始图像
        results = decode(image)
    return results

这个案例涵盖了Python二维码解析的主要功能,包括:

  • 从图片文件解析
  • 实时摄像头扫描
  • 批量处理
  • GUI界面
  • 图像预处理提高识别率

您可以根据具体需求选择合适的实现方式。

标签: 二维码解析

抱歉,评论功能暂时关闭!