create_labelme_data.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. import base64
  2. import copy
  3. import json
  4. import random
  5. import cv2
  6. import numpy as np
  7. from PIL import Image, ImageFont, ImageDraw
  8. def create_table_image(if_add_seal=False):
  9. lines_of_table = []
  10. outline_of_table = []
  11. # 空图
  12. # weight = random.randint(512, 896)
  13. height = random.randint(512, 640)
  14. weight = random.randint(512, 768)
  15. weight_origion = weight
  16. height_origion = height
  17. img = np.zeros((weight, height), np.uint8)
  18. img.fill(255)
  19. # 画矩形表格轮廓
  20. num = random.choice([1, 1, 2])
  21. num = 1
  22. scale_x = random.randint(10, int(weight/5))
  23. # scale_y = random.randint(25, int(height/5))
  24. scale_y = random.randint(int(height/12), int(height/10))
  25. if num == 1:
  26. x1 = scale_x
  27. y1 = scale_y
  28. x2 = scale_x + (weight - 2 * scale_x)
  29. y2 = scale_y + (height - 2 * scale_y)
  30. img = cv2.rectangle(img, (y1, x1), (y2, x2), (0, 0, 0), 1)
  31. lines_of_table.extend([[(y1, x1), (y2, x1)], [(y2, x1), (y2, x2)],
  32. [(y2, x2), (y1, x2)], [(y1, x2), (y1, x1)]])
  33. if num == 2:
  34. scale_num = random.choice([0.4, 0.5, 0.6, 0.7])
  35. x1 = scale_x
  36. y1 = scale_y
  37. x2 = int((x1 + (weight - 2 * scale_x)) * scale_num)
  38. y2 = (y1 + (height - 2 * scale_y))
  39. # print(y1, x1, y2, x2)
  40. img = cv2.rectangle(img, (y1, x1), (y2, x2), (0, 0, 0), 1)
  41. lines_of_table.extend([[(y1, x1), (y2, x1)], [(y2, x1), (y2, x2)],
  42. [(y2, x2), (y1, x2)], [(y1, x2), (y1, x1)]])
  43. weight_origin = weight
  44. weight = weight-x2
  45. scale_x = random.randint(10, int(weight/5))
  46. scale_y = random.randint(25, int(height/5))
  47. x3 = scale_x + x2
  48. y3 = scale_y
  49. x4 = x3 + (weight - 2 * scale_x)
  50. y4 = y3 + (height - 2 * scale_y)
  51. # print(weight_origin)
  52. # print(y3, x3, y4, x4)
  53. if x2 + 10 <= x3 or y4 - y3 >= 20 or x4 - 10 <= weight_origin:
  54. img = cv2.rectangle(img, (y3, x3), (y4, x4), (0, 0, 0), 1)
  55. lines_of_table.extend([[(y3, x3), (y4, x3)], [(y4, x3), (y4, x4)],
  56. [(y4, x4), (y3, x4)], [(y3, x4), (y3, x3)]])
  57. # 画表格内单元格线
  58. # 第一个表格
  59. row_num = random.randint(23, 25)
  60. col_num = random.randint(3, 4)
  61. margin_x = int((x2 - x1)/row_num)
  62. margin_y = int((y2 - y1)/col_num)
  63. col_points = []
  64. row_points = []
  65. # for rn in range(0, row_num):
  66. # if y1+margin_y*rn < y2 - margin_y:
  67. # col_points.append(y1+margin_y*rn)
  68. # for cn in range(0, col_num):
  69. # if x1+margin_x*cn < x2 - margin_x:
  70. # row_points.append(x1+margin_x*cn)
  71. # 紧凑表格制作
  72. print("margin_y, margin_x", margin_y, margin_x)
  73. last_x = copy.copy(x1)
  74. row_points.append(last_x)
  75. for rn in range(0, row_num):
  76. last_x += margin_x
  77. if last_x < x2 - margin_x:
  78. row_points.append(last_x)
  79. print("row_points", row_points)
  80. last_y = copy.copy(y1)
  81. col_points.append(last_y)
  82. for cn in range(0, col_num):
  83. last_y += margin_y
  84. if last_y < y2 - margin_y:
  85. col_points.append(last_y)
  86. print("col_points", col_points)
  87. # 画线
  88. for col in col_points:
  89. # if random.choice([0, 1, 1, 1]):
  90. # 不跨行
  91. if random.choice([1, 1, 1, 1]):
  92. img = cv2.line(img, (col, x1), (col, x2), (0, 0, 0), 1)
  93. lines_of_table.append([(col, x1), (col, x2)])
  94. else:
  95. img = cv2.line(img, (col, x1+margin_x), (col, x2), (0, 0, 0), 1)
  96. lines_of_table.append([(col, x1+margin_x), (col, x2)])
  97. for row in row_points:
  98. # if random.choice([0, 1, 1, 1]):
  99. if random.choice([1, 1, 1, 1]):
  100. img = cv2.line(img, (y1, row), (y2, row), (0, 0, 0), 1)
  101. lines_of_table.append([(y1, row), (y2, row)])
  102. else:
  103. img = cv2.line(img, (y1+margin_y, row), (y2, row), (0, 0, 0), 1)
  104. lines_of_table.append([(y1+margin_y, row), (y2, row)])
  105. # 第二个表格
  106. if num == 2:
  107. row_num2 = random.randint(6, 7)
  108. col_num2 = random.randint(6, 7)
  109. margin_x2 = int((x4 - x3)/row_num2)
  110. margin_y2 = int((y4 - y3)/col_num2)
  111. col_points2 = []
  112. row_points2 = []
  113. for rn in range(0, row_num2):
  114. if y3+margin_y2*rn < y4 - margin_y2:
  115. col_points2.append(y3+margin_y2*rn)
  116. for cn in range(0, col_num2):
  117. if x3+margin_x2*cn < x4 - margin_x2:
  118. row_points2.append(x3+margin_x2*cn)
  119. # 画线
  120. for col in col_points2:
  121. if random.choice([0, 1, 1, 1]):
  122. img = cv2.line(img, (col, x3), (col, x4), (0, 0, 0), 1)
  123. lines_of_table.append([(col, x3), (col, x4)])
  124. else:
  125. img = cv2.line(img, (col, x3+margin_x2), (col, x4), (0, 0, 0), 1)
  126. lines_of_table.append([(col, x3+margin_x2), (col, x4)])
  127. for row in row_points2:
  128. if random.choice([0, 1, 1, 1]):
  129. img = cv2.line(img, (y3, row), (y4, row), (0, 0, 0), 1)
  130. lines_of_table.append([(y3, row), (y4, row)])
  131. else:
  132. img = cv2.line(img, (y3+margin_y2, row), (y4, row), (0, 0, 0), 1)
  133. lines_of_table.append([(y3+margin_y2, row), (y4, row)])
  134. # 画轮廓
  135. point1 = (y1 - 5, x1 - 5)
  136. point2 = (y2 + 5, x2 + 5)
  137. # img = cv2.rectangle(img, point1, point2, (0, 0, 255), 2)
  138. outline_of_table.append([point1, point2])
  139. if num == 2:
  140. point3 = (y3 - 5, x3 - 5)
  141. point4 = (y4 + 5, x4 + 5)
  142. # img = cv2.rectangle(img, point3, point4, (0, 0, 255), 2)
  143. outline_of_table.append([point3, point4])
  144. # 表格中填字
  145. font_list = ["卡", "啊", "的", "我", "你", "吧", "为", "看", "他", "个", "来", "哦", "啊"]
  146. font_num = random.randint(7, 10)
  147. text = "".join(random.sample(font_list, font_num))
  148. # print(text)
  149. # text_size = int(margin_y / 1.6) if margin_y < margin_x else int(margin_x) / 1.6
  150. # font_size = text_size / font_num
  151. font_size = 10
  152. text_point = []
  153. image_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
  154. for i in range(100):
  155. # text_x = random.choice(col_points) + int(margin_y/5)
  156. # text_y = random.choice(row_points) + int(margin_x/5)
  157. text_x = random.choice(col_points)
  158. text_y = random.choice(row_points)
  159. if (text_x, text_y) not in text_point:
  160. text_point.append((text_x, text_y))
  161. font = ImageFont.truetype("msyh.ttc", int(font_size))
  162. dr = ImageDraw.Draw(image_pil)
  163. bias_x = random.choice([0, 0, 0, 15, 30])
  164. dr.text((text_x+bias_x, text_y), text, font=font, fill="#000000")
  165. img = cv2.cvtColor(np.asarray(image_pil), cv2.COLOR_RGB2BGR)
  166. if num == 2:
  167. # text_size = int(margin_y2 / 1.6) if margin_y2 < margin_x2 else int(margin_x2) / 1.6
  168. # font_size = text_size / font_num
  169. font_size = 15
  170. text_point = []
  171. image_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
  172. for i in range(100):
  173. text_x = random.choice(col_points2) + int(margin_y2/5)
  174. text_y = random.choice(row_points2) + int(margin_x2/5)
  175. if (text_x, text_y) not in text_point:
  176. text_point.append((text_x, text_y))
  177. font = ImageFont.truetype("msyh.ttc", int(font_size))
  178. dr = ImageDraw.Draw(image_pil)
  179. dr.text((text_x, text_y), text, font=font, fill="#000000")
  180. img = cv2.cvtColor(np.asarray(image_pil), cv2.COLOR_RGB2BGR)
  181. # 加印章
  182. if if_add_seal:
  183. img = create_official_seal(img)
  184. # cv2.imshow("add_seal", img)
  185. # cv2.waitKey(0)
  186. # 获取图片的二进制格式数据
  187. image_bytes = np.array(cv2.imencode('.jpg', img)[1]).tobytes()
  188. # with open('temp.jpg', 'wb') as f:
  189. # f.write(image_bytes)
  190. # 显示
  191. # cv2.imshow("image", img)
  192. # cv2.waitKey(0)
  193. return lines_of_table, outline_of_table, image_bytes, weight_origion, height_origion
  194. def create_outline_labelme(outline_list, image_bytes):
  195. labelme_data = {}
  196. shapes_list = []
  197. for outline in outline_list:
  198. shape_dict = {"label": "table",
  199. "points": [[outline[0][0], outline[0][1]], [outline[1][0], outline[1][1]]],
  200. "shape_type": "rectangle"
  201. }
  202. shapes_list.append(shape_dict)
  203. labelme_data["shapes"] = shapes_list
  204. image_base64 = base64.b64encode(image_bytes)
  205. labelme_data["imageData"] = str(image_base64)
  206. return labelme_data
  207. def create_lines_labelme(line_list, image_bytes, weight, height):
  208. labelme_data = {}
  209. shapes_list = []
  210. for line in line_list:
  211. if abs(line[1][0] - line[0][0]) >= abs(line[1][1] - line[0][1]):
  212. shape_dict = {"label": "0",
  213. "points": [[line[0][0], line[0][1]], [line[1][0], line[1][1]]],
  214. "shape_type": "line"
  215. }
  216. else:
  217. shape_dict = {"label": "1",
  218. "points": [[line[0][0], line[0][1]], [line[1][0], line[1][1]]],
  219. "shape_type": "line"
  220. }
  221. shapes_list.append(shape_dict)
  222. labelme_data["shapes"] = shapes_list
  223. # image_str = str(image_bytes, encoding='utf-8')
  224. image_base64_bytes = base64.b64encode(image_bytes)
  225. image_base64_string = image_base64_bytes.decode('utf-8')
  226. labelme_data["imageData"] = image_base64_string
  227. labelme_data["imageHeight"] = height
  228. labelme_data["imageWidth"] = weight
  229. return labelme_data
  230. def create_official_seal(main_image_np):
  231. img1 = main_image_np
  232. # 随机选择公章
  233. seal_no = random.randint(0, 8)
  234. img2 = cv2.imread("../seal" + str(seal_no) + ".jpg")
  235. rows1, cols1, channels1 = img1.shape
  236. # 随机公章大小
  237. width = random.randint(int(cols1/6), int(cols1-cols1/6))
  238. # width = random.randint(150, 250)
  239. # width = 150
  240. height = width
  241. if width > rows1:
  242. width = rows1
  243. height = width
  244. img2 = cv2.resize(img2, (width, height))
  245. rows2, cols2, channels2 = img2.shape
  246. # 随机选择公章放置位置
  247. row_bias = random.randint(int(rows1/6), int(rows1-rows1/6))
  248. col_bias = random.randint(int(cols1/6), int(cols1-cols1/6))
  249. # I want to put logo on top-left corner, So I create a ROI
  250. # roi = img1[rows1-rows2-row_bias:rows1-row_bias, cols1-cols2-col_bias:cols1-col_bias]
  251. if rows1 >= rows2+row_bias and cols1 >= cols2+col_bias:
  252. roi_height = [row_bias, rows2+row_bias]
  253. roi_width = [col_bias, cols2+col_bias]
  254. elif rows1 < rows2+row_bias and cols1 < cols2+col_bias:
  255. roi_height = [rows1-width, rows1]
  256. roi_width = [cols1-width, cols1]
  257. elif cols1 < cols2+col_bias:
  258. roi_height = [row_bias, rows2+row_bias]
  259. roi_width = [cols1-width, cols1]
  260. else:
  261. roi_height = [rows1-width, rows1]
  262. roi_width = [col_bias, cols2+col_bias]
  263. roi = img1[roi_height[0]:roi_height[1], roi_width[0]:roi_width[1]]
  264. # Now create a mask of logo and create its inverse mask also
  265. img2gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
  266. ret, mask = cv2.threshold(img2gray, 200, 255, cv2.THRESH_BINARY)
  267. mask_inv = cv2.bitwise_not(mask)
  268. # Now black-out the area of logo in ROI
  269. print("row_bias, col_bias", row_bias, col_bias)
  270. print("img1.shape, img2.shape", img1.shape, img2.shape)
  271. print("roi.shape, mask.shape", roi.shape, mask.shape)
  272. img1_bg = cv2.bitwise_and(roi, roi, mask=mask)
  273. # Take only region of logo from logo image.
  274. img2_fg = cv2.bitwise_and(img2, img2, mask=mask_inv)
  275. # Put logo in ROI and modify the main image
  276. dst = cv2.add(img1_bg, img2_fg)
  277. img1[roi_height[0]:roi_height[1], roi_width[0]:roi_width[1]] = dst
  278. # cv2.imshow('res', img1)
  279. # cv2.waitKey(0)
  280. return img1
  281. if __name__ == '__main__':
  282. # 生成 单元格线 数据
  283. for i in range(2601, 2801):
  284. if i % 100 == 0:
  285. print(i)
  286. lines, outlines, image_data, weight, height = create_table_image(if_add_seal=True)
  287. labelme = create_lines_labelme(lines, image_data, weight, height)
  288. with open('../train/dataset-line/6/train_' + str(i) + '.json', 'w') as f:
  289. json.dump(labelme, f)
  290. # main_image = cv2.imread("../13.png")
  291. # create_official_seal(main_image)