gen_qrcodes.py 3.9 KB

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