You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将拍摄的QR Code图片转换为视觉一致的规整标准QR Code?

问题原因

你当前代码的逻辑是先解析二维码存储的原始数据,再调用qrcode库默认参数重新生成二维码。qrcode默认会自动匹配适配的QR版本、纠错等级、掩码模式等参数,这些参数和你拍摄的原始二维码参数不一致,因此会出现数据完全相同但视觉模块排布不同的问题。

解决方案

有两种可行方案,第二种通用适配性更强:

方案1:指定匹配原始二维码的参数重新生成

你需要先获取原始二维码的版本、纠错等级、掩码模式等参数,生成时完全对应指定,同时设置fit=False禁止自动调整参数。你提供的示例原始二维码对应参数为版本3、纠错等级M、掩码模式4,修改后代码如下:

from PIL import Image
from pyzbar import pyzbar
import qrcode

img1 = Image.open('in.png')
out1 = pyzbar.decode(img1)[0]

# 完全指定原始二维码参数,禁止自动适配
qr = qrcode.QRCode(
    version=3,
    error_correction=qrcode.constants.ERROR_CORRECT_M,
    box_size=10,
    border=4,
    mask_pattern=4
)
qr.add_data(out1.data)
qr.make(fit=False)  # 关键参数:关闭自动适配,强制使用指定参数

output = qr.make_image(fill_color="black", back_color="white")
output.save("out.png", "PNG")

方案2:采样原始二维码模块重绘(通用方案)

不需要提前知道二维码参数,通过透视变换转正拍摄的斜二维码,采样每个模块的颜色后重绘为标准直角模块,100%还原原始视觉排布,需要额外安装opencv-python依赖:

import cv2
import numpy as np
from PIL import Image
from pyzbar import pyzbar

# 读取输入图像
img = cv2.imread('in.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
decoded_qr = pyzbar.decode(gray)[0]

# 获取二维码四个角的坐标
src_points = np.array([(p.x, p.y) for p in decoded_qr.polygon], dtype=np.float32)
# 可自定义输出大小:比如每个模块占10像素,29模块对应290像素,可按需调整
target_pixel = 290
dst_points = np.array([
    [0, 0],
    [target_pixel, 0],
    [target_pixel, target_pixel],
    [0, target_pixel]
], dtype=np.float32)

# 透视变换把斜的二维码转正
trans_matrix = cv2.getPerspectiveTransform(src_points, dst_points)
warped_qr = cv2.warpPerspective(gray, trans_matrix, (target_pixel, target_pixel))
# 二值化转纯黑纯白
_, binary_qr = cv2.threshold(warped_qr, 127, 255, cv2.THRESH_BINARY)

# 按模块采样重绘,去除噪点
module_size = 10
module_count = target_pixel // module_size
output_img = np.full((target_pixel, target_pixel), 255, dtype=np.uint8)

for row in range(module_count):
    for col in range(module_count):
        # 取每个模块中心位置的像素值作为模块颜色
        center_y = row * module_size + module_size // 2
        center_x = col * module_size + module_size // 2
        if binary_qr[center_y, center_x] < 127:
            # 把整个模块涂成黑色
            cv2.rectangle(output_img, 
                         (col * module_size, row * module_size),
                         ((col+1)*module_size - 1, (row+1)*module_size -1),
                         0, -1)

# 保存结果
Image.fromarray(output_img).save('out.png')

注意点

  • 方案1只适用于你当前提供的这个二维码,如果要处理其他二维码,需要重新匹配对应参数
  • 方案2的target_pixel和module_size可以按需调整,只要保持target_pixel = module_size * 原始QR模块数即可,你也可以通过识别原始QR版本自动计算模块数

内容的提问来源于stack exchange,提问作者EllipticalInitial

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 00:36:05