create_labelme_data.py 15 KB

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