vis_utils.py 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. from magic_pdf.libs.commons import fitz
  2. import os
  3. from magic_pdf.libs.coordinate_transform import get_scale_ratio
  4. def draw_model_output(
  5. raw_pdf_doc: fitz.Document, paras_dict_arr: list[dict], save_path: str
  6. ):
  7. """
  8. 在page上画出bbox,保存到save_path
  9. """
  10. """
  11. # {0: 'title', # 标题
  12. # 1: 'figure', # 图片
  13. # 2: 'plain text', # 文本
  14. # 3: 'header', # 页眉
  15. # 4: 'page number', # 页码
  16. # 5: 'footnote', # 脚注
  17. # 6: 'footer', # 页脚
  18. # 7: 'table', # 表格
  19. # 8: 'table caption', # 表格描述
  20. # 9: 'figure caption', # 图片描述
  21. # 10: 'equation', # 公式
  22. # 11: 'full column', # 单栏
  23. # 12: 'sub column', # 多栏
  24. # 13: 'embedding', # 嵌入公式
  25. # 14: 'isolated'} # 单行公式
  26. """
  27. color_map = {
  28. "body": fitz.pdfcolor["green"],
  29. "non_body": fitz.pdfcolor["red"],
  30. }
  31. """
  32. {"layout_dets": [], "subfield_dets": [], "page_info": {"page_no": 22, "height": 1650, "width": 1275}}
  33. """
  34. for i, page in enumerate(raw_pdf_doc):
  35. v = paras_dict_arr[i]
  36. page_idx = v["page_info"]["page_no"]
  37. width = v["page_info"]["width"]
  38. height = v["page_info"]["height"]
  39. horizontal_scale_ratio, vertical_scale_ratio = get_scale_ratio(
  40. paras_dict_arr[i], page
  41. )
  42. for order, block in enumerate(v["layout_dets"]):
  43. L = block["poly"][0] / horizontal_scale_ratio
  44. U = block["poly"][1] / vertical_scale_ratio
  45. R = block["poly"][2] / horizontal_scale_ratio
  46. D = block["poly"][5] / vertical_scale_ratio
  47. # L += pageL # 有的页面,artBox偏移了。不在(0,0)
  48. # R += pageL
  49. # U += pageU
  50. # D += pageU
  51. L, R = min(L, R), max(L, R)
  52. U, D = min(U, D), max(U, D)
  53. bbox = [L, U, R, D]
  54. color = color_map["body"]
  55. if block["category_id"] in (3, 4, 5, 6, 0):
  56. color = color_map["non_body"]
  57. rect = fitz.Rect(bbox)
  58. page.draw_rect(rect, fill=None, width=0.5, overlay=True, color=color)
  59. parent_dir = os.path.dirname(save_path)
  60. if not os.path.exists(parent_dir):
  61. os.makedirs(parent_dir)
  62. raw_pdf_doc.save(save_path)
  63. def debug_show_bbox(
  64. raw_pdf_doc: fitz.Document,
  65. page_idx: int,
  66. bboxes: list,
  67. droped_bboxes: list,
  68. expect_drop_bboxes: list,
  69. save_path: str,
  70. expected_page_id: int,
  71. ):
  72. """
  73. 以覆盖的方式写个临时的pdf,用于debug
  74. """
  75. if page_idx != expected_page_id:
  76. return
  77. if os.path.exists(save_path):
  78. # 删除已经存在的文件
  79. os.remove(save_path)
  80. # 创建一个新的空白 PDF 文件
  81. doc = fitz.open("")
  82. width = raw_pdf_doc[page_idx].rect.width
  83. height = raw_pdf_doc[page_idx].rect.height
  84. new_page = doc.new_page(width=width, height=height)
  85. shape = new_page.new_shape()
  86. for bbox in bboxes:
  87. # 原始box画上去
  88. rect = fitz.Rect(*bbox[0:4])
  89. shape = new_page.new_shape()
  90. shape.draw_rect(rect)
  91. shape.finish(
  92. color=fitz.pdfcolor["red"], fill=fitz.pdfcolor["blue"], fill_opacity=0.2
  93. )
  94. shape.finish()
  95. shape.commit()
  96. for bbox in droped_bboxes:
  97. # 原始box画上去
  98. rect = fitz.Rect(*bbox[0:4])
  99. shape = new_page.new_shape()
  100. shape.draw_rect(rect)
  101. shape.finish(color=None, fill=fitz.pdfcolor["yellow"], fill_opacity=0.2)
  102. shape.finish()
  103. shape.commit()
  104. for bbox in expect_drop_bboxes:
  105. # 原始box画上去
  106. rect = fitz.Rect(*bbox[0:4])
  107. shape = new_page.new_shape()
  108. shape.draw_rect(rect)
  109. shape.finish(color=fitz.pdfcolor["red"], fill=None)
  110. shape.finish()
  111. shape.commit()
  112. # shape.insert_textbox(fitz.Rect(200, 0, 600, 20), f"total bboxes: {len(bboxes)}", fontname="helv", fontsize=12,
  113. # color=(0, 0, 0))
  114. # shape.finish(color=fitz.pdfcolor['black'])
  115. # shape.commit()
  116. parent_dir = os.path.dirname(save_path)
  117. if not os.path.exists(parent_dir):
  118. os.makedirs(parent_dir)
  119. doc.save(save_path)
  120. doc.close()
  121. def debug_show_page(
  122. page,
  123. bboxes1: list,
  124. bboxes2: list,
  125. bboxes3: list,
  126. ):
  127. save_path = "./tmp/debug.pdf"
  128. if os.path.exists(save_path):
  129. # 删除已经存在的文件
  130. os.remove(save_path)
  131. # 创建一个新的空白 PDF 文件
  132. doc = fitz.open("")
  133. width = page.rect.width
  134. height = page.rect.height
  135. new_page = doc.new_page(width=width, height=height)
  136. shape = new_page.new_shape()
  137. for bbox in bboxes1:
  138. # 原始box画上去
  139. rect = fitz.Rect(*bbox[0:4])
  140. shape = new_page.new_shape()
  141. shape.draw_rect(rect)
  142. shape.finish(
  143. color=fitz.pdfcolor["red"], fill=fitz.pdfcolor["blue"], fill_opacity=0.2
  144. )
  145. shape.finish()
  146. shape.commit()
  147. for bbox in bboxes2:
  148. # 原始box画上去
  149. rect = fitz.Rect(*bbox[0:4])
  150. shape = new_page.new_shape()
  151. shape.draw_rect(rect)
  152. shape.finish(color=None, fill=fitz.pdfcolor["yellow"], fill_opacity=0.2)
  153. shape.finish()
  154. shape.commit()
  155. for bbox in bboxes3:
  156. # 原始box画上去
  157. rect = fitz.Rect(*bbox[0:4])
  158. shape = new_page.new_shape()
  159. shape.draw_rect(rect)
  160. shape.finish(color=fitz.pdfcolor["red"], fill=None)
  161. shape.finish()
  162. shape.commit()
  163. parent_dir = os.path.dirname(save_path)
  164. if not os.path.exists(parent_dir):
  165. os.makedirs(parent_dir)
  166. doc.save(save_path)
  167. doc.close()
  168. def draw_layout_bbox_on_page(
  169. raw_pdf_doc: fitz.Document, paras_dict: dict, header, footer, pdf_path: str
  170. ):
  171. """
  172. 在page上画出bbox,保存到save_path
  173. """
  174. # 检查文件是否存在
  175. is_new_pdf = False
  176. if os.path.exists(pdf_path):
  177. # 打开现有的 PDF 文件
  178. doc = fitz.open(pdf_path)
  179. else:
  180. # 创建一个新的空白 PDF 文件
  181. is_new_pdf = True
  182. doc = fitz.open("")
  183. for k, v in paras_dict.items():
  184. page_idx = v["page_idx"]
  185. layouts = v["layout_bboxes"]
  186. page = doc[page_idx]
  187. shape = page.new_shape()
  188. for order, layout in enumerate(layouts):
  189. border_offset = 1
  190. rect_box = layout["layout_bbox"]
  191. layout_label = layout["layout_label"]
  192. fill_color = fitz.pdfcolor["pink"] if layout_label == "U" else None
  193. rect_box = [
  194. rect_box[0] + 1,
  195. rect_box[1] - border_offset,
  196. rect_box[2] - 1,
  197. rect_box[3] + border_offset,
  198. ]
  199. rect = fitz.Rect(*rect_box)
  200. shape.draw_rect(rect)
  201. shape.finish(color=fitz.pdfcolor["red"], fill=fill_color, fill_opacity=0.4)
  202. """
  203. draw order text on layout box
  204. """
  205. font_size = 10
  206. shape.insert_text(
  207. (rect_box[0] + 1, rect_box[1] + font_size),
  208. f"{order}",
  209. fontsize=font_size,
  210. color=(0, 0, 0),
  211. )
  212. """画上footer header"""
  213. if header:
  214. shape.draw_rect(fitz.Rect(header))
  215. shape.finish(color=None, fill=fitz.pdfcolor["black"], fill_opacity=0.2)
  216. if footer:
  217. shape.draw_rect(fitz.Rect(footer))
  218. shape.finish(color=None, fill=fitz.pdfcolor["black"], fill_opacity=0.2)
  219. shape.commit()
  220. if is_new_pdf:
  221. doc.save(pdf_path)
  222. else:
  223. doc.saveIncr()
  224. doc.close()
  225. @DeprecationWarning
  226. def draw_layout_on_page(
  227. raw_pdf_doc: fitz.Document, page_idx: int, page_layout: list, pdf_path: str
  228. ):
  229. """
  230. 把layout的box用红色边框花在pdf_path的page_idx上
  231. """
  232. def draw(shape, layout, fill_color=fitz.pdfcolor["pink"]):
  233. border_offset = 1
  234. rect_box = layout["layout_bbox"]
  235. layout_label = layout["layout_label"]
  236. sub_layout = layout["sub_layout"]
  237. if len(sub_layout) == 0:
  238. fill_color = fill_color if layout_label == "U" else None
  239. rect_box = [
  240. rect_box[0] + 1,
  241. rect_box[1] - border_offset,
  242. rect_box[2] - 1,
  243. rect_box[3] + border_offset,
  244. ]
  245. rect = fitz.Rect(*rect_box)
  246. shape.draw_rect(rect)
  247. shape.finish(color=fitz.pdfcolor["red"], fill=fill_color, fill_opacity=0.2)
  248. # if layout_label=='U':
  249. # bad_boxes = layout.get("bad_boxes", [])
  250. # for bad_box in bad_boxes:
  251. # rect = fitz.Rect(*bad_box)
  252. # shape.draw_rect(rect)
  253. # shape.finish(color=fitz.pdfcolor['red'], fill=fitz.pdfcolor['red'], fill_opacity=0.2)
  254. # else:
  255. # rect = fitz.Rect(*rect_box)
  256. # shape.draw_rect(rect)
  257. # shape.finish(color=fitz.pdfcolor['blue'])
  258. for sub_layout in sub_layout:
  259. draw(shape, sub_layout)
  260. shape.commit()
  261. # 检查文件是否存在
  262. is_new_pdf = False
  263. if os.path.exists(pdf_path):
  264. # 打开现有的 PDF 文件
  265. doc = fitz.open(pdf_path)
  266. else:
  267. # 创建一个新的空白 PDF 文件
  268. is_new_pdf = True
  269. doc = fitz.open("")
  270. page = doc[page_idx]
  271. shape = page.new_shape()
  272. for order, layout in enumerate(page_layout):
  273. draw(shape, layout, fitz.pdfcolor["yellow"])
  274. # shape.insert_textbox(fitz.Rect(200, 0, 600, 20), f"total bboxes: {len(layout)}", fontname="helv", fontsize=12,
  275. # color=(0, 0, 0))
  276. # shape.finish(color=fitz.pdfcolor['black'])
  277. # shape.commit()
  278. parent_dir = os.path.dirname(pdf_path)
  279. if not os.path.exists(parent_dir):
  280. os.makedirs(parent_dir)
  281. if is_new_pdf:
  282. doc.save(pdf_path)
  283. else:
  284. doc.saveIncr()
  285. doc.close()