Advertisement
Guest User

Untitled

a guest
Nov 21st, 2017
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.17 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3.  
  4. import numpy as np
  5. import cv2
  6. from shapely.geometry import Polygon
  7. from PIL import Image
  8. import random
  9. from os import listdir
  10. from os import path
  11. from os import makedirs
  12. from random import choice
  13. import argparse
  14.  
  15. max_w, max_h = 512, 512
  16. test_count, train_count = 10, 20
  17.  
  18.  
  19. def in_rectangle(width, height, x, y):
  20. if 0 < x < width and height > y > 0:
  21. return True
  22. return False
  23.  
  24.  
  25. def poly_in_rectangle(points, width, height):
  26. for p in points:
  27. if not in_rectangle(width, height, p[0], p[1]):
  28. return False
  29. return True
  30.  
  31.  
  32. def valid_intersection_polygons(i0, i1, i2, i3, max_x, max_y):
  33. inner_polygon = Polygon([(i0[0], i0[1]), (i1[0], i1[1]), (i2[0], i2[1]), (i3[0], i3[1])])
  34. outer_polygon = max_x * max_y
  35. p = inner_polygon.area / outer_polygon * 100
  36. if p > 0.5:
  37. return True
  38. return False
  39.  
  40.  
  41. def point_rotare(point, matrix):
  42. r = matrix.dot(np.float32([[point[0]], [point[1]], [1]]))
  43. return r[0][0], r[1][0]
  44.  
  45.  
  46. def find_centre(points):
  47. left_x, top_y, right_x, bottom_y = bounding_box(points)
  48. return (left_x + right_x) / 2, (top_y + bottom_y) / 2
  49.  
  50.  
  51. def rotate_and_scale_points(points, angle_min, angle_max,
  52. scale_min, scale_max,
  53. img_width, img_height):
  54. angle = random.uniform(angle_min, angle_max)
  55. while True:
  56. scale = random.uniform(scale_min, scale_max)
  57. centre = find_centre(points)
  58. M = cv2.getRotationMatrix2D(centre, angle, scale)
  59. # M = cv2.getRotationMatrix2D((img_width/2,img_height/2),90,1)
  60. new_points = list(map(lambda x: point_rotare(x, M), points))
  61. if poly_in_rectangle(new_points, img_width, img_height):
  62. return new_points
  63. scale_max -= 0.01 * abs(scale_max - scale_min) # Уменьшаем Scale пока не впишется
  64.  
  65.  
  66. def bounding_box(points):
  67. left_x = min(points, key=lambda p: p[0])[0]
  68. right_x = max(points, key=lambda p: p[0])[0]
  69. bottom_y = min(points, key=lambda p: p[1])[1]
  70. top_y = max(points, key=lambda p: p[1])[1]
  71. return (left_x, top_y, right_x, bottom_y)
  72.  
  73.  
  74. def move_poly(points, img_width, img_height):
  75. left_x, top_y, right_x, bottom_y = bounding_box(points)
  76. dx = random.uniform(-left_x, img_width - right_x)
  77. dy = random.uniform(-bottom_y, img_height - top_y)
  78. new_points = list(map(lambda p: [p[0] + dx, p[1] + dy], points))
  79. return new_points
  80.  
  81.  
  82. def random_shift_point(point, d, img_width, img_height):
  83. x = random.uniform(max(0, point[0] - d), min(img_width, point[0] + d))
  84. y = random.uniform(max(0, point[1] - d), min(img_height, point[1] + d))
  85. return [x, y]
  86.  
  87.  
  88. def random_perspective_points_transform(points, value, img_width, img_height):
  89. left_x, top_y, right_x, bottom_y = bounding_box(points)
  90. d = (right_x - left_x + top_y - bottom_y) / 2 * value
  91. new_points = list(
  92. map(lambda p: random_shift_point(p, d, img_width, img_height), points))
  93. return new_points
  94.  
  95.  
  96. def gen_points():
  97. x0, y0 = 0, 0
  98. x1, y1 = x0 + max_w, y0
  99. x2, y2 = x0 + max_w, y0 + max_h
  100. x3, y3 = x0, y0 + max_h
  101. return x0, y0, x1, y1, x2, y2, x3, y3
  102.  
  103.  
  104. def genM(img):
  105. x0, y0, x1, y1, x2, y2, x3, y3 = gen_points()
  106. rows, cols, ch = img.shape
  107. orig_points = np.float32(
  108. [[x0, y0],
  109. [x1, y1],
  110. [x2, y2],
  111. [x3, y3]])
  112. new_points = orig_points
  113. new_points = rotate_and_scale_points(new_points, 0, 360, 0.5, 2, cols, rows)
  114. new_points = move_poly(new_points, cols, rows)
  115. new_points = random_perspective_points_transform(new_points, 0.1, cols, rows)
  116. new_points = np.float32(new_points)
  117. M = cv2.getPerspectiveTransform(new_points, orig_points)
  118. return M, new_points
  119.  
  120.  
  121. def save_tile(img, M, save_img_path, color=True):
  122. if color:
  123. transformed_img = cv2.cvtColor(cv2.warpPerspective(img, M, (max_w, max_h)), cv2.COLOR_BGR2RGB)
  124. else:
  125. transformed_img = cv2.cvtColor(cv2.warpPerspective(img, M, (max_w, max_h)), cv2.COLOR_GRAY2RGB)
  126. im_pil = Image.fromarray(transformed_img)
  127. im_pil.save(save_img_path)
  128.  
  129.  
  130. def count_colours(img):
  131. unique, counts = np.unique(img, return_counts=True)
  132. return dict(zip(unique, counts))
  133.  
  134.  
  135. def threshold_black(img, threshold):
  136. result = count_colours(img)
  137. try:
  138. if result[255] < (result[0] + result[255]) * threshold:
  139. return True
  140. return False
  141. except:
  142. return False
  143.  
  144.  
  145. def crop(img_path, img_bg_path, img_mask_path, save_img_path, save_bg_path, threshold=0.5):
  146. img = cv2.imread(img_path)
  147. M, new_points = genM(img)
  148. if path.exists(img_mask_path):
  149. img_mask = cv2.imread(img_mask_path, cv2.IMREAD_UNCHANGED)[:, :, 3]
  150. transformed_img = cv2.cvtColor(cv2.warpPerspective(img_mask, M, (max_w, max_h)), cv2.COLOR_GRAY2RGB)
  151. # Тут проверка на точки через пороговое значение
  152. if threshold_black(transformed_img, threshold):
  153. return False
  154. img_bg = cv2.imread(img_bg_path, cv2.IMREAD_UNCHANGED)[:, :, 3]
  155.  
  156. save_tile(img, M, save_img_path, True)
  157. save_tile(img_bg, M, save_bg_path, False)
  158. return True
  159.  
  160.  
  161. def get_jpg_files_whithout_background(folder_path):
  162. files = []
  163. for file in listdir(folder_path):
  164. if file.endswith('.png') and '_bg' not in file and '_mask' not in file:
  165. files.append(path.join(folder_path, file))
  166. return files
  167.  
  168.  
  169. def cropping(root_folder, save_folder, max_files=100):
  170. if not path.exists(save_folder):
  171. makedirs(save_folder)
  172.  
  173. without_background = get_jpg_files_whithout_background(root_folder)
  174. count = 0
  175. while count < max_files:
  176. image = choice(without_background)
  177. base_name = path.basename(image)
  178.  
  179. mask_fat_name = base_name[:-4] + '_mask.png'
  180. mask_fat_name_full = path.join(image[:-len(base_name)], mask_fat_name)
  181.  
  182. bg_name = base_name[:-4] + '_bg.png'
  183. bg_name_full = path.join(image[:-len(base_name)], bg_name)
  184.  
  185. save_img_path = path.join(save_folder, str(count) + '_' + base_name)
  186. save_bg_path = path.join(save_folder, str(count) + '_' + bg_name)
  187.  
  188. print("Paths:", image, bg_name_full, mask_fat_name_full, save_img_path, save_bg_path)
  189. if crop(image, bg_name_full, mask_fat_name_full, save_img_path, save_bg_path, threshold=0.5):
  190. count += 1
  191.  
  192.  
  193. def smart_crop():
  194. parser = argparse.ArgumentParser()
  195. parser.add_argument('-i', '--input', help='Input folder name', required=True)
  196. args = parser.parse_args()
  197.  
  198. train_folder = path.join(args.input, 'train')
  199. if not path.exists(train_folder):
  200. makedirs(train_folder)
  201.  
  202. test_folder = path.join(args.input, 'test')
  203. if not path.exists(test_folder):
  204. makedirs(test_folder)
  205.  
  206. cropping('test_bad', path.join(test_folder, 'bad'), test_count)
  207. cropping('test_good', path.join(test_folder, 'good'), test_count)
  208.  
  209. cropping('train_bad', path.join(train_folder, 'bad'), train_count)
  210. cropping('train_good', path.join(train_folder, 'good'), train_count)
  211.  
  212.  
  213. if __name__ == '__main__':
  214. smart_crop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement