image.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import os
  2. from flask import request, logging, send_file, jsonify
  3. from werkzeug.datastructures import CombinedMultiDict
  4. from app import app
  5. from .resp import success_resp, error_resp
  6. import numpy as np
  7. from .req import ReplaceForm, is_empty
  8. import tools
  9. import cv2
  10. from .file import get_upload_file_path, get_output_dir, file_url, get_output_file_path
  11. log = logging.create_logger(app)
  12. @app.route("/image/seg", methods=['POST'])
  13. def seg():
  14. if 'fileId' not in request.values:
  15. return "请先上传图片!", 500
  16. file_id = request.values.get('fileId')
  17. file_path = get_upload_file_path(file_id)
  18. _, fg, _, path = tools.seg(file_path, get_output_dir())
  19. # filename = os.path.relpath(path, OUTPUT_DIR)
  20. return jsonify(success_resp({
  21. "fileId": file_id,
  22. "url": file_url(path, True)
  23. }))
  24. @app.route("/image/replace", methods=["POST"])
  25. def replace():
  26. form_data = request.form
  27. form = ReplaceForm(form_data)
  28. if form.validate() is False:
  29. return jsonify(error_resp("参数错误!"))
  30. if is_empty(form.bg_file_id.data) and is_empty(form.background.data):
  31. return jsonify(error_resp("请选择需要替换的背景!"))
  32. img_path = get_upload_file_path(form.file_id.data)
  33. bg_path = get_upload_file_path(form.bg_file_id.data)
  34. if os.path.exists(bg_path) is False:
  35. bg_path = form.background.data
  36. result = tools.replace(img_path=img_path, background=bg_path, save_dir=get_output_dir())
  37. return jsonify({
  38. "fileId": form.file_id.data,
  39. "url": file_url(result, True)
  40. })
  41. @app.route("/image/resize", methods=["POST", 'GET'])
  42. def resize():
  43. # flip: 翻转, 0 为沿X轴翻转,正数为沿Y轴翻转,负数为同时沿X轴和Y轴翻转
  44. # reset: 是否重头开始,否则从上一次的处理开始,默认为重头开始
  45. # resize: 重新设定尺寸
  46. # rect: 裁剪,left,top,right,bottom 四个参数
  47. reset = request.values.get("reset")
  48. file_id = request.values.get("fileId")
  49. width = request.values.get("width")
  50. height = request.values.get("height")
  51. rotate = request.values.get("rotate")
  52. flip = request.values.get("flip")
  53. rect = request.values.get('rect')
  54. if is_empty(reset):
  55. reset = True
  56. else:
  57. reset = False
  58. file_path = get_upload_file_path(file_id)
  59. if os.path.exists(file_path) is not True:
  60. return "文件上传失败,请重新上传!", 400
  61. out_file = get_output_file_path(file_id, "resize")
  62. if reset is False and os.path.exists(out_file):
  63. img = cv2.imread(out_file)
  64. else:
  65. img = cv2.imread(file_path)
  66. origin_h = img.shape[0]
  67. origin_w = img.shape[1]
  68. img = crop(img, rect, origin_w, origin_h)
  69. change_size = True
  70. if is_empty(width) and is_empty(height):
  71. change_size = False
  72. w = origin_w
  73. h = origin_h
  74. elif is_empty(width):
  75. h = int(height)
  76. w = round(h * origin_w / origin_h)
  77. elif is_empty(height):
  78. w = int(width)
  79. h = round(w * origin_h / origin_w)
  80. else:
  81. w = int(width)
  82. h = int(height)
  83. dst = img
  84. if change_size:
  85. dst = cv2.resize(img, (w, h))
  86. if is_empty(flip) is not True:
  87. flip = int(flip)
  88. dst = cv2.flip(dst, flip)
  89. if is_empty(rotate) is False:
  90. dst = rot_degree(dst, float(rotate), w=w, h=h)
  91. if dst is not None:
  92. cv2.imwrite(out_file, dst)
  93. return send_file(out_file, mimetype="image/png")
  94. return send_file(file_path, mimetype="image/png")
  95. def crop(img, rect: str, w, h):
  96. # 裁剪
  97. if is_empty(rect):
  98. return img
  99. r = rect.split(',')
  100. if len(r) != 4:
  101. return img
  102. left = int(r[0])
  103. top = int(r[1])
  104. right = int(r[2])
  105. bottom = int(r[3])
  106. if left < 0:
  107. left = 0
  108. if right > w:
  109. right = w
  110. if top < 0:
  111. top = 0
  112. if bottom > h:
  113. bottom = h
  114. if left == 0 and top == 0 and right == w and bottom == h:
  115. return img
  116. return img[top:bottom, left:right]
  117. def rot_degree(img, degree, w, h):
  118. center = (w / 2, h / 2)
  119. M = cv2.getRotationMatrix2D(center, degree, 1)
  120. top_right = np.array((w - 1, 0)) - np.array(center)
  121. bottom_right = np.array((w - 1, h - 1)) - np.array(center)
  122. top_right_after_rot = M[0:2, 0:2].dot(top_right)
  123. bottom_right_after_rot = M[0:2, 0:2].dot(bottom_right)
  124. new_width = max(int(abs(bottom_right_after_rot[0] * 2) + 0.5), int(abs(top_right_after_rot[0] * 2) + 0.5))
  125. new_height = max(int(abs(top_right_after_rot[1] * 2) + 0.5), int(abs(bottom_right_after_rot[1] * 2) + 0.5))
  126. offset_x = (new_width - w) / 2
  127. offset_y = (new_height - h) / 2
  128. M[0, 2] += offset_x
  129. M[1, 2] += offset_y
  130. dst = cv2.warpAffine(img, M, (new_width, new_height))
  131. return dst