image.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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, out_dir):
  35. self.path = path
  36. self.out_dir = out_dir
  37. def processor(params: ProcessorParams):
  38. file_path = params.path
  39. if os.path.exists(file_path) is not True:
  40. raise FileNotFoundError('Need to give the source path.')
  41. if not os.path.exists(params.out_dir):
  42. os.makedirs(params.out_dir)
  43. img = cv2.imread(file_path)
  44. if img is None:
  45. raise NotImageError()
  46. origin_h = img.shape[0]
  47. origin_w = img.shape[1]
  48. dst, r_w, r_h = crop(img, params.rect, origin_w, origin_h)
  49. width = to_size_int(params.width)
  50. height = to_size_int(params.height)
  51. change_size = True
  52. if width is None and height is None:
  53. change_size = False
  54. if change_size:
  55. if width is None:
  56. h = height
  57. w = round(h * origin_w / origin_h)
  58. elif height is None:
  59. w = width
  60. h = round(w * origin_h / origin_w)
  61. else:
  62. w = width
  63. h = height
  64. origin = img if dst is None else dst
  65. dst = cv2.resize(origin, (w, h))
  66. r_w = w
  67. r_h = h
  68. if r_w is None:
  69. r_w = origin_w
  70. if r_h is None:
  71. r_h = origin_h
  72. flip = params.flip
  73. if is_empty(flip) is not True:
  74. flip = to_int(flip)
  75. origin = img if dst is None else dst
  76. dst = cv2.flip(origin, flip)
  77. rotate = params.rotate
  78. if is_empty(rotate) is False and to_int(rotate) != 0:
  79. origin = img if dst is None else dst
  80. dst, new_w, new_h = rot_degree(origin, float(rotate), w=r_w, h=r_h)
  81. origin_filename = os.path.basename(file_path)
  82. out_file = os.path.join(params.out_dir, origin_filename)
  83. if dst is not None:
  84. cv2.imwrite(out_file, dst)
  85. return True
  86. return False
  87. def crop(img, rect: str, w, h):
  88. # 裁剪,
  89. # 如果没有改变,返回None
  90. if is_empty(rect):
  91. return None, None, None
  92. r = rect.split(',')
  93. if len(r) != 4:
  94. return None, None, None
  95. left = int(r[0])
  96. top = int(r[1])
  97. right = int(r[2])
  98. bottom = int(r[3])
  99. if left < 0:
  100. left = 0
  101. if right > w:
  102. right = w
  103. if top < 0:
  104. top = 0
  105. if bottom > h:
  106. bottom = h
  107. if left == 0 and top == 0 and right == w and bottom == h:
  108. return None, None, None
  109. return img[top:bottom, left:right], right - left, bottom - top
  110. def rot_degree(img, degree, w, h):
  111. center = (w / 2, h / 2)
  112. M = cv2.getRotationMatrix2D(center, degree, 1)
  113. top_right = np.array((w - 1, 0)) - np.array(center)
  114. bottom_right = np.array((w - 1, h - 1)) - np.array(center)
  115. top_right_after_rot = M[0:2, 0:2].dot(top_right)
  116. bottom_right_after_rot = M[0:2, 0:2].dot(bottom_right)
  117. new_width = max(int(abs(bottom_right_after_rot[0] * 2) + 0.5), int(abs(top_right_after_rot[0] * 2) + 0.5))
  118. new_height = max(int(abs(top_right_after_rot[1] * 2) + 0.5), int(abs(bottom_right_after_rot[1] * 2) + 0.5))
  119. offset_x = (new_width - w) / 2
  120. offset_y = (new_height - h) / 2
  121. M[0, 2] += offset_x
  122. M[1, 2] += offset_y
  123. dst = cv2.warpAffine(img, M, (new_width, new_height))
  124. return dst, new_width, new_height