dataset_controller.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. """
  2. 数据集图片处理http接口
  3. """
  4. import os.path
  5. from flask import Blueprint, request, send_file
  6. from watermark_generate.domain import *
  7. from watermark_generate.domain.dataset_domain import ExtractLabelRespSchema, ExtractLabelResp
  8. from watermark_generate.tools import logger_tool
  9. from watermark_generate.tools.picture_watermark import PictureWatermarkEmbeder, extract
  10. from PIL import Image, ImageDraw
  11. import random
  12. dataset = Blueprint('dataset', __name__)
  13. logger = logger_tool.logger
  14. # 允许的扩展名
  15. ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg'}
  16. # 判断文件扩展名是否合法
  17. def allowed_file(filename):
  18. return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
  19. # 获取文件扩展名
  20. def get_file_extension(filename):
  21. return filename.rsplit('.', 1)[1].lower()
  22. @dataset.route('/znwr/jit/ai/v1/picture_embed', methods=['POST'])
  23. def picture_embed_label():
  24. """
  25. 上传图片,嵌入密码标签,进行处理、
  26. label: 密码标签
  27. file: 上传的图像
  28. :return: 成功:处理完成的图像二进制流 失败:{code: -1, msg:'错误信息'}
  29. """
  30. label = request.form.get('label')
  31. if 'file' not in request.files:
  32. return VerifyLabelRespSchema().dump(VerifyLabelResp(code=-1, msg='没有上传文件'))
  33. file = request.files['file']
  34. file_name = file.filename
  35. logger.debug(f'label: {label},upload_file_name: {file_name}')
  36. if file_name == '':
  37. return VerifyLabelRespSchema().dump(VerifyLabelResp(code=-1, msg='上传文件名为空'))
  38. if file and allowed_file(file_name):
  39. file_extension = get_file_extension(file_name)
  40. save_file_name = f'uploaded_image.{file_extension}'
  41. embed_file_name = f'embed_image.{file_extension}'
  42. file.save(save_file_name) # 保存图片到服务器
  43. # 嵌入水印
  44. embeder = PictureWatermarkEmbeder(label)
  45. try:
  46. embeder.embed(save_file_name, embed_file_name)
  47. except Exception as e:
  48. logger.error(f'嵌入水印失败{e}')
  49. return VerifyLabelRespSchema().dump(VerifyLabelResp(code=-1, msg=f'图片水印嵌入失败:{e}'))
  50. if not embeder.verify():
  51. return VerifyLabelRespSchema().dump(VerifyLabelResp(code=-1, msg=f'水印嵌入验证失败,请更换图片'))
  52. # 在图片的任意位置添加随机数量和大小的噪声块
  53. img = Image.open(embed_file_name)
  54. draw = ImageDraw.Draw(img)
  55. num_noise_patches = random.randint(5, 10)
  56. for _ in range(num_noise_patches):
  57. # 添加 10x10 大小的噪声块
  58. patch_size = 10
  59. x = random.randint(0, img.width - patch_size)
  60. y = random.randint(0, img.height - patch_size)
  61. draw.rectangle([x, y, x + patch_size, y + patch_size], fill=(128, 0, 128))
  62. # 保存修改后的图片
  63. img.save(embed_file_name)
  64. # 确定文件的MIME类型
  65. if file_extension == 'jpg' or file_extension == 'jpeg':
  66. mimetype = 'image/jpeg'
  67. elif file_extension == 'png':
  68. mimetype = 'image/png'
  69. else:
  70. # 如果无法确定文件类型,默认使用二进制流
  71. mimetype = 'application/octet-stream'
  72. return send_file(open(embed_file_name, 'rb'), mimetype=mimetype, download_name=embed_file_name)
  73. else:
  74. return VerifyLabelRespSchema().dump(VerifyLabelResp(code=-1, msg='文件类型不允许,只允许jpg,jpeg,png文件类型'))
  75. @dataset.route('/znwr/jit/ai/v1/picture_check', methods=['POST'])
  76. def picture_embed_check():
  77. """
  78. 图片嵌入水印功能自检
  79. :return: 自检结果
  80. """
  81. save_file_name = './resource/test.jpg'
  82. embed_file_name = './resource/test_embed.jpg'
  83. if not os.path.exists(save_file_name):
  84. return VerifyLabelRespSchema().dump(VerifyLabelResp(code=-1, msg='水印测试图片装载失败'))
  85. embeder = PictureWatermarkEmbeder('012ABCDEF')
  86. try:
  87. embeder.embed(save_file_name, embed_file_name)
  88. except Exception as e:
  89. logger.error(f'嵌入水印失败{e}')
  90. return VerifyLabelRespSchema().dump(VerifyLabelRespSchema(code=-1, msg=f'水印嵌入图片失败:{e}'))
  91. if not embeder.verify():
  92. return VerifyLabelRespSchema().dump(VerifyLabelRespSchema(code=-1, msg=f'水印嵌入验证失败'))
  93. return VerifyLabelRespSchema().dump(VerifyLabelResp(code=0, msg='ok'))
  94. @dataset.route('/znwr/jit/ai/v1/picture_extract', methods=['POST'])
  95. def picture_embed_extract():
  96. """
  97. 图片水印提取
  98. :return: 提取结果
  99. """
  100. if 'file' not in request.files:
  101. return VerifyLabelRespSchema().dump(VerifyLabelResp(code=-1, msg='没有上传文件'))
  102. file = request.files['file']
  103. file_name = file.filename
  104. logger.debug(f'上传文件名称:{file_name}')
  105. if file_name == '':
  106. return VerifyLabelRespSchema().dump(VerifyLabelResp(code=-1, msg='上传文件名为空'))
  107. if file and allowed_file(file_name):
  108. file_extension = get_file_extension(file_name)
  109. save_file_name = f'extract_image.{file_extension}'
  110. file.save(save_file_name) # 保存图片到服务器
  111. secret = extract(save_file_name)
  112. logger.debug(f'label:{secret}')
  113. return ExtractLabelRespSchema().dump(
  114. ExtractLabelResp(code=0, msg='ok', label=secret)
  115. )
  116. return VerifyLabelRespSchema().dump(VerifyLabelRespSchema(code=-1, msg=f'文件格式不支持,仅支持jpg,jpeg,png格式'))