gen_qrcodes.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. # watermarking_data_process.py
  2. # 本py文件主要用于数据隐私保护以及watermarking_trigger的插入。
  3. import os
  4. import random
  5. import cv2
  6. import qrcode
  7. from qrcode.main import QRCode
  8. from PIL import Image
  9. from watermark_generate.tools import logger_tool
  10. logger = logger_tool.logger
  11. def random_partition(key, parts):
  12. """
  13. 随机分割给定的字符串为指定数量的部分。
  14. :param key: 密码标签
  15. :param parts: 切割份数
  16. """
  17. n = len(key)
  18. points = sorted(random.sample(range(1, n), parts - 1))
  19. return [key[i:j] for i, j in zip([0] + points, points + [n])]
  20. def generate_qrcodes(key: str, watermarking_dir='./dataset/watermarking', partition=True, variants=4):
  21. """
  22. 根据传入的密码标签,并将其分成variants个部分,每部分生成一个二维码保存到指定目录,并将十六进制密钥存储到文件中。
  23. :param key: 密码标签
  24. :param watermarking_dir: 生成密码标签二维码存放位置
  25. :param partition: 是否对密码标签随机切割,默认为是
  26. :param variants: 开启对密码标签随机切割后,密码标签切割份数,默认为4。当random_partition为False时,该参数无效
  27. """
  28. # 开启对密码标签随机切割后分割密钥,否则不进行切割
  29. parts = random_partition(key, variants) if partition else [key]
  30. # 创建存储密钥和QR码的目录
  31. os.makedirs(watermarking_dir, exist_ok=True)
  32. # 保存十六进制密钥到文件,并为每个部分生成QR码
  33. for i, part in enumerate(parts, 1):
  34. part_file = os.path.join(watermarking_dir, f"key_part_{i}.txt")
  35. with open(part_file, 'w') as file:
  36. file.write(part)
  37. logger.info(f"Saved part {i} to {part_file}, len = {len(part)}")
  38. # 生成每个部分的QR码
  39. qr = QRCode(
  40. version=1,
  41. error_correction=qrcode.constants.ERROR_CORRECT_L,
  42. box_size=2,
  43. border=1
  44. )
  45. qr.add_data(part)
  46. qr.make(fit=True)
  47. qr_img = qr.make_image(fill_color="black", back_color="white")
  48. qr_img_path = os.path.join(watermarking_dir, f"QR_{i}.png")
  49. qr_img.save(qr_img_path)
  50. logger.info(f"Saved QR code for part {i} to {qr_img_path}")
  51. # 新增检测流程,防止生成的二维码无法识别
  52. reconstructed_key = ''
  53. qr_files = [f for f in os.listdir(watermarking_dir) if f.startswith('QR_') and f.endswith('.png')]
  54. for f in qr_files:
  55. qr_path = os.path.join(watermarking_dir, f)
  56. img = Image.open(qr_path)
  57. decode = detect_qrcode_in_bbox(qr_path,[0,0,img.width, img.height])
  58. if decode is None:
  59. return False
  60. reconstructed_key = reconstructed_key + decode
  61. return reconstructed_key == key
  62. def detect_qrcode_in_bbox(image_path, bbox):
  63. """
  64. 在指定的bounding box中检测和解码QR码。
  65. 参数:
  66. image_path (str): 图片路径。
  67. bbox (list): bounding box,格式为[x_min, y_min, x_max, y_max]。
  68. 返回:
  69. str: QR码解码后的信息,如果未找到QR码则返回 None。
  70. """
  71. # 读取图片
  72. img = cv2.imread(image_path)
  73. if img is None:
  74. raise FileNotFoundError(f"Image not found or unable to load: {image_path}")
  75. # 将浮点数的bounding box坐标转换为整数
  76. x_min, y_min, x_max, y_max = map(int, bbox)
  77. # 裁剪出bounding box中的区域
  78. qr_region = img[y_min:y_max, x_min:x_max]
  79. # 初始化QRCodeDetector
  80. qr_decoder = cv2.QRCodeDetector()
  81. # 检测并解码QR码
  82. data, _, _ = qr_decoder.detectAndDecode(qr_region)
  83. return data if data else None
  84. def extract_qrcode_from_image(pic_path):
  85. # 读取图片
  86. img = cv2.imread(pic_path)
  87. if img is None:
  88. raise FileNotFoundError(f"Image not found or unable to load: {pic_path}")
  89. # 初始化QRCodeDetector
  90. qr_decoder = cv2.QRCodeDetector()
  91. # 检测并解码QR码
  92. data, _, _ = qr_decoder.detectAndDecode(img)
  93. return data