pdf2text_evaluatePdfLayout.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import os
  2. import collections # 统计库
  3. import re # 正则
  4. from libs.commons import fitz # pyMuPDF库
  5. import json # json
  6. def calculate_overlapRatio_between_rect1_and_rect2(L1: float, U1: float, R1: float, D1: float, L2: float, U2: float, R2: float, D2: float) -> (float, float):
  7. # 计算两个rect,重叠面积各占2个rect面积的比例
  8. if min(R1, R2) < max(L1, L2) or min(D1, D2) < max(U1, U2):
  9. return 0, 0
  10. square_1 = (R1 - L1) * (D1 - U1)
  11. square_2 = (R2 - L2) * (D2 - U2)
  12. if square_1 == 0 or square_2 == 0:
  13. return 0, 0
  14. square_overlap = (min(R1, R2) - max(L1, L2)) * (min(D1, D2) - max(U1, U2))
  15. return square_overlap / square_1, square_overlap / square_2
  16. def evaluate_pdf_layout(page_ID: int, page: fitz.Page, json_from_DocXchain_obj: dict):
  17. """
  18. :param page_ID: int类型,当前page在当前pdf文档中是第page_D页。
  19. :param page :fitz读取的当前页的内容
  20. :param res_dir_path: str类型,是每一个pdf文档,在当前.py文件的目录下生成一个与pdf文档同名的文件夹,res_dir_path就是文件夹的dir
  21. :param json_from_DocXchain_obj: dict类型,把pdf文档送入DocXChain模型中后,提取bbox,结果保存到pdf文档同名文件夹下的 page_ID.json文件中了。json_from_DocXchain_obj就是打开后的dict
  22. """
  23. DPI = 72 # use this resolution
  24. pix = page.get_pixmap(dpi=DPI)
  25. pageL = 0
  26. pageR = int(pix.w)
  27. pageU = 0
  28. pageD = int(pix.h)
  29. #--------- 通过json_from_DocXchain来获取 title ---------#
  30. title_bbox_from_DocXChain = []
  31. xf_json = json_from_DocXchain_obj
  32. width_from_json = xf_json['page_info']['width']
  33. height_from_json = xf_json['page_info']['height']
  34. LR_scaleRatio = width_from_json / (pageR - pageL)
  35. UD_scaleRatio = height_from_json / (pageD - pageU)
  36. # {0: 'title', # 标题
  37. # 1: 'figure', # 图片
  38. # 2: 'plain text', # 文本
  39. # 3: 'header', # 页眉
  40. # 4: 'page number', # 页码
  41. # 5: 'footnote', # 脚注
  42. # 6: 'footer', # 页脚
  43. # 7: 'table', # 表格
  44. # 8: 'table caption', # 表格描述
  45. # 9: 'figure caption', # 图片描述
  46. # 10: 'equation', # 公式
  47. # 11: 'full column', # 单栏
  48. # 12: 'sub column', # 多栏
  49. # 13: 'embedding', # 嵌入公式
  50. # 14: 'isolated'} # 单行公式
  51. LOSS_THRESHOLD = 2000 # 经验值
  52. fullColumn_bboxs = []
  53. subColumn_bboxs = []
  54. plainText_bboxs = []
  55. #### read information of plain text
  56. for xf in xf_json['layout_dets']:
  57. L = xf['poly'][0] / LR_scaleRatio
  58. U = xf['poly'][1] / UD_scaleRatio
  59. R = xf['poly'][2] / LR_scaleRatio
  60. D = xf['poly'][5] / UD_scaleRatio
  61. L, R = min(L, R), max(L, R)
  62. U, D = min(U, D), max(U, D)
  63. if xf['category_id'] == 2:
  64. plainText_bboxs.append((L, U, R, D))
  65. #### read information of column
  66. for xf in xf_json['subfield_dets']:
  67. L = xf['poly'][0] / LR_scaleRatio
  68. U = xf['poly'][1] / UD_scaleRatio
  69. R = xf['poly'][2] / LR_scaleRatio
  70. D = xf['poly'][5] / UD_scaleRatio
  71. L, R = min(L, R), max(L, R)
  72. U, D = min(U, D), max(U, D)
  73. if xf['category_id'] == 11:
  74. fullColumn_bboxs.append((L, U, R, D))
  75. elif xf['category_id'] == 12:
  76. subColumn_bboxs.append((L, U, R, D))
  77. curPage_loss = 0 # 当前页的loss
  78. fail_cnt = 0 # Text文本块没被圈到的情形。
  79. for L, U, R, D in plainText_bboxs:
  80. find = False
  81. for L2, U2, R2, D2 in (fullColumn_bboxs + subColumn_bboxs):
  82. ratio_1, _ = calculate_overlapRatio_between_rect1_and_rect2(L, U, R, D, L2, U2, R2, D2)
  83. if ratio_1 >= 0.9:
  84. loss_1 = (L + R) / 2 - (L2 + R2) / 2
  85. loss_2 = L - L2
  86. cur_loss = min(abs(loss_1), abs(loss_2))
  87. curPage_loss += cur_loss
  88. find = True
  89. break
  90. if find == False:
  91. fail_cnt += 1
  92. isSimpleLayout_flag = False
  93. if fail_cnt == 0 and len(fullColumn_bboxs) <= 1 and len(subColumn_bboxs) <= 2:
  94. if curPage_loss <= LOSS_THRESHOLD:
  95. isSimpleLayout_flag = True
  96. return isSimpleLayout_flag, len(fullColumn_bboxs), len(subColumn_bboxs), curPage_loss