4. Misc-图片隐写-二维码修复
任务目标
你拿到一张被破坏的二维码图片,图中二维码的定位角(三个回字形方块)被黑色色块覆盖,导致手机无法扫描。目标是通过图像处理修复定位角,使二维码能够被正常识别。
环境依赖
本案例使用 Python 3 + OpenCV 和 pyzbar 库。安装命令:
pip install opencv-python pyzbar
实现思路
二维码的定位角位于左上、右上、左下三个位置,每个定位角是一个 7×7 的黑色回字形模块。修复方法:将三个定位角区域整体替换为纯黑色正方形(尺寸为模块大小的 7 倍),因为定位角本身是黑色实心回字,直接涂黑即可被识别器正确识别为定位图案。
关键完整代码
import cv2
import numpy as np
from pyzbar.pyzbar import decode
def repair_qr(image_path, output_path):
# 读取图像
img = cv2.imread(image_path)
if img is None:
raise ValueError("无法读取图像,请检查路径")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
h, w = gray.shape
# 二值化
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# 寻找二维码区域的外轮廓
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if not contours:
raise ValueError("未找到二维码轮廓")
# 取最大轮廓作为二维码边界
qr_contour = max(contours, key=cv2.contourArea)
x, y, qr_w, qr_h = cv2.boundingRect(qr_contour)
# 二维码通常为正方形,取边长
size = max(qr_w, qr_h)
# 计算模块大小:二维码通常为25x25或29x29等版本,这里通过轮廓宽度估算
# 标准二维码版本1为21x21模块,版本2为25x25,此处按常见25x25处理
# 更精确方法:检测最外层黑白交替次数,此处简化为按25模块计算
module_size = size // 25
if module_size == 0:
module_size = 1
# 定位角尺寸:7个模块
finder_size = module_size * 7
# 三个定位角的中心位置(相对于二维码左上角)
# 左上角定位角中心:(3.5*module, 3.5*module)
# 右上角定位角中心:(size - 3.5*module, 3.5*module)
# 左下角定位角中心:(3.5*module, size - 3.5*module)
centers = [
(int(3.5 * module_size), int(3.5 * module_size)),
(int(size - 3.5 * module_size), int(3.5 * module_size)),
(int(3.5 * module_size), int(size - 3.5 * module_size))
]
# 在原始图像上绘制黑色正方形覆盖定位角区域
for cx, cy in centers:
x1 = x + cx - finder_size // 2
y1 = y + cy - finder_size // 2
x2 = x1 + finder_size
y2 = y1 + finder_size
# 确保不越界
x1 = max(0, x1); y1 = max(0, y1)
x2 = min(w, x2); y2 = min(h, y2)
cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 0), -1)
# 保存修复后的图像
cv2.imwrite(output_path, img)
# 验证:尝试解码
result = decode(cv2.imread(output_path))
if result:
return result[0].data.decode('utf-8')
else:
return None
if __name__ == "__main__":
# 使用示例
text = repair_qr("broken_qr.png", "fixed_qr.png")
if text:
print(f"修复成功,二维码内容: {text}")
else:
print("修复后仍无法识别,请检查图像质量或调整模块估算")
运行与验证
- 将损坏的二维码图片命名为
broken_qr.png放在脚本同目录下 - 运行脚本:
python repair_qr.py - 观察输出:若打印
修复成功及内容,说明修复完成 - 同时可用手机扫描生成的
fixed_qr.png验证
判定标准
- 脚本能输出二维码编码的原始文本内容
- 生成的
fixed_qr.png可被手机或扫码工具正常识别 - 若修复失败,检查原图二维码是否为标准版本(模块数 21/25/29 等),当前代码按 25×25 模块估算,若版本不同需调整
module_size计算方式
常见问题
模块大小估算不准: 若二维码版本不是 25×25,可改为检测最外层黑白环数量来确定模块数。简单替代方案:手动指定模块大小,例如 module_size = 8(像素),然后重新运行。