image.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. import os
  2. import numpy as np
  3. import cv2
  4. def is_empty(s: str):
  5. return s is None or len(str(s)) == 0
  6. def to_int(s: str):
  7. if isinstance(s, (int, float)):
  8. return s
  9. if is_empty(s):
  10. return None
  11. return int(str(s))
  12. def to_size_int(s: str):
  13. v = to_int(s)
  14. if v is None:
  15. return v
  16. if v < 1:
  17. return None
  18. return v
  19. class NotImageError(Exception):
  20. def __init__(self):
  21. super().__init__("File Is Not Image")
  22. class ProcessorParams:
  23. def __init__(self, width, height, rotate, flip, rect, out_dir, path):
  24. self.width = width
  25. self.height = height
  26. self.rotate = rotate
  27. # 翻转, 0 为沿X轴翻转,正数为沿Y轴翻转,负数为同时沿X轴和Y轴翻转
  28. self.flip = flip
  29. # 裁剪,left,top,right,bottom 四个参数
  30. self.rect = rect
  31. # 保存的文件夹
  32. self.out_dir = out_dir
  33. self.path = path
  34. def set_path(self, path):
  35. self.path = path
  36. def processor(params: ProcessorParams):
  37. file_path = params.path
  38. if os.path.exists(file_path) is not True:
  39. raise FileNotFoundError('Need to give the source path.')
  40. if not os.path.exists(params.out_dir):
  41. os.makedirs(params.out_dir)
  42. img = cv2.imread(file_path)
  43. if img is None:
  44. raise NotImageError()
  45. origin_h = img.shape[0]
  46. origin_w = img.shape[1]
  47. dst, r_w, r_h = crop(img, params.rect, origin_w, origin_h)
  48. width = to_size_int(params.width)
  49. height = to_size_int(params.height)
  50. change_size = True
  51. if width is None and height is None:
  52. change_size = False
  53. if change_size:
  54. if width is None:
  55. h = height
  56. w = round(h * origin_w / origin_h)
  57. elif height is None:
  58. w = width
  59. h = round(w * origin_h / origin_w)
  60. else:
  61. w = width
  62. h = height
  63. origin = img if dst is None else dst
  64. dst = cv2.resize(origin, (w, h))
  65. r_w = w
  66. r_h = h
  67. if r_w is None:
  68. r_w = origin_w
  69. if r_h is None:
  70. r_h = origin_h
  71. flip = params.flip
  72. if is_empty(flip) is not True:
  73. flip = to_int(flip)
  74. origin = img if dst is None else dst
  75. dst = cv2.flip(origin, flip)
  76. rotate = params.rotate
  77. if is_empty(rotate) is False and to_int(rotate) != 0:
  78. origin = img if dst is None else dst
  79. dst, new_w, new_h = rot_degree(origin, float(rotate), w=r_w, h=r_h)
  80. origin_filename = os.path.basename(file_path)
  81. out_file = os.path.join(params.out_dir, origin_filename)
  82. if dst is not None:
  83. cv2.imwrite(out_file, dst)
  84. return True
  85. return False
  86. def crop(img, rect: str, w, h):
  87. # 裁剪,
  88. # 如果没有改变,返回None
  89. if is_empty(rect):
  90. return None, None, None
  91. r = rect.split(',')
  92. if len(r) != 4:
  93. return None, None, None
  94. left = int(r[0])
  95. top = int(r[1])
  96. right = int(r[2])
  97. bottom = int(r[3])
  98. if left < 0:
  99. left = 0
  100. if right > w:
  101. right = w
  102. if top < 0:
  103. top = 0
  104. if bottom > h:
  105. bottom = h
  106. if left == 0 and top == 0 and right == w and bottom == h:
  107. return None, None, None
  108. return img[top:bottom, left:right], right - left, bottom - top
  109. def rot_degree(img, degree, w, h):
  110. center = (w / 2, h / 2)
  111. M = cv2.getRotationMatrix2D(center, degree, 1)
  112. top_right = np.array((w - 1, 0)) - np.array(center)
  113. bottom_right = np.array((w - 1, h - 1)) - np.array(center)
  114. top_right_after_rot = M[0:2, 0:2].dot(top_right)
  115. bottom_right_after_rot = M[0:2, 0:2].dot(bottom_right)
  116. new_width = max(int(abs(bottom_right_after_rot[0] * 2) + 0.5), int(abs(top_right_after_rot[0] * 2) + 0.5))
  117. new_height = max(int(abs(top_right_after_rot[1] * 2) + 0.5), int(abs(bottom_right_after_rot[1] * 2) + 0.5))
  118. offset_x = (new_width - w) / 2
  119. offset_y = (new_height - h) / 2
  120. M[0, 2] += offset_x
  121. M[1, 2] += offset_y
  122. dst = cv2.warpAffine(img, M, (new_width, new_height))
  123. return dst, new_width, new_height