create_labelme_data.py 16 KB

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