model_init.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. import os
  2. import torch
  3. from loguru import logger
  4. from .model_list import AtomicModel
  5. from ...model.layout.doclayoutyolo import DocLayoutYOLOModel
  6. from ...model.mfd.yolo_v8 import YOLOv8MFDModel
  7. from ...model.mfr.unimernet.Unimernet import UnimernetModel
  8. from ...model.mfr.pp_formulanet_plus_m.predict_formula import FormulaRecognizer
  9. from mineru.model.ocr.pytorch_paddle import PytorchPaddleOCR
  10. from ...model.ori_cls.paddle_ori_cls import PaddleOrientationClsModel
  11. from ...model.table.cls.paddle_table_cls import PaddleTableClsModel
  12. # from ...model.table.rec.RapidTable import RapidTableModel
  13. from ...model.table.rec.slanet_plus.main import RapidTableModel
  14. from ...model.table.rec.unet_table.main import UnetTableModel
  15. from ...utils.enum_class import ModelPath
  16. from ...utils.models_download_utils import auto_download_and_get_model_root_path
  17. MFR_MODEL = os.getenv('MINERU_FORMULA_CH_SUPPORT', 'False')
  18. if MFR_MODEL.lower() in ['true', '1', 'yes']:
  19. MFR_MODEL = "pp_formulanet_plus_m"
  20. elif MFR_MODEL.lower() in ['false', '0', 'no']:
  21. MFR_MODEL = "unimernet_small"
  22. else:
  23. logger.warning(f"Invalid MINERU_FORMULA_CH_SUPPORT value: {MFR_MODEL}, set to default 'False'")
  24. MFR_MODEL = "unimernet_small"
  25. def img_orientation_cls_model_init():
  26. atom_model_manager = AtomModelSingleton()
  27. ocr_engine = atom_model_manager.get_atom_model(
  28. atom_model_name=AtomicModel.OCR,
  29. det_db_box_thresh=0.5,
  30. det_db_unclip_ratio=1.6,
  31. lang="ch_lite",
  32. enable_merge_det_boxes=False
  33. )
  34. cls_model = PaddleOrientationClsModel(ocr_engine)
  35. return cls_model
  36. def table_cls_model_init():
  37. return PaddleTableClsModel()
  38. def wired_table_model_init(lang=None):
  39. atom_model_manager = AtomModelSingleton()
  40. ocr_engine = atom_model_manager.get_atom_model(
  41. atom_model_name=AtomicModel.OCR,
  42. det_db_box_thresh=0.5,
  43. det_db_unclip_ratio=1.6,
  44. lang=lang,
  45. enable_merge_det_boxes=False
  46. )
  47. table_model = UnetTableModel(ocr_engine)
  48. return table_model
  49. def wireless_table_model_init(lang=None):
  50. atom_model_manager = AtomModelSingleton()
  51. ocr_engine = atom_model_manager.get_atom_model(
  52. atom_model_name=AtomicModel.OCR,
  53. det_db_box_thresh=0.5,
  54. det_db_unclip_ratio=1.6,
  55. lang=lang,
  56. enable_merge_det_boxes=False
  57. )
  58. table_model = RapidTableModel(ocr_engine)
  59. return table_model
  60. def mfd_model_init(weight, device='cpu'):
  61. if str(device).startswith('npu'):
  62. device = torch.device(device)
  63. mfd_model = YOLOv8MFDModel(weight, device)
  64. return mfd_model
  65. def mfr_model_init(weight_dir, device='cpu'):
  66. if MFR_MODEL == "unimernet_small":
  67. mfr_model = UnimernetModel(weight_dir, device)
  68. elif MFR_MODEL == "pp_formulanet_plus_m":
  69. mfr_model = FormulaRecognizer(weight_dir, device)
  70. else:
  71. logger.error('MFR model name not allow')
  72. exit(1)
  73. return mfr_model
  74. def doclayout_yolo_model_init(weight, device='cpu'):
  75. if str(device).startswith('npu'):
  76. device = torch.device(device)
  77. model = DocLayoutYOLOModel(weight, device)
  78. return model
  79. def ocr_model_init(det_db_box_thresh=0.3,
  80. lang=None,
  81. det_db_unclip_ratio=1.8,
  82. enable_merge_det_boxes=True
  83. ):
  84. if lang is not None and lang != '':
  85. model = PytorchPaddleOCR(
  86. det_db_box_thresh=det_db_box_thresh,
  87. lang=lang,
  88. use_dilation=True,
  89. det_db_unclip_ratio=det_db_unclip_ratio,
  90. enable_merge_det_boxes=enable_merge_det_boxes,
  91. )
  92. else:
  93. model = PytorchPaddleOCR(
  94. det_db_box_thresh=det_db_box_thresh,
  95. use_dilation=True,
  96. det_db_unclip_ratio=det_db_unclip_ratio,
  97. enable_merge_det_boxes=enable_merge_det_boxes,
  98. )
  99. return model
  100. class AtomModelSingleton:
  101. _instance = None
  102. _models = {}
  103. def __new__(cls, *args, **kwargs):
  104. if cls._instance is None:
  105. cls._instance = super().__new__(cls)
  106. return cls._instance
  107. def get_atom_model(self, atom_model_name: str, **kwargs):
  108. lang = kwargs.get('lang', None)
  109. if atom_model_name in [AtomicModel.WiredTable, AtomicModel.WirelessTable]:
  110. key = (
  111. atom_model_name,
  112. lang
  113. )
  114. elif atom_model_name in [AtomicModel.OCR]:
  115. key = (
  116. atom_model_name,
  117. kwargs.get('det_db_box_thresh', 0.3),
  118. lang,
  119. kwargs.get('det_db_unclip_ratio', 1.8),
  120. kwargs.get('enable_merge_det_boxes', True)
  121. )
  122. else:
  123. key = atom_model_name
  124. if key not in self._models:
  125. self._models[key] = atom_model_init(model_name=atom_model_name, **kwargs)
  126. return self._models[key]
  127. def atom_model_init(model_name: str, **kwargs):
  128. atom_model = None
  129. if model_name == AtomicModel.Layout:
  130. atom_model = doclayout_yolo_model_init(
  131. kwargs.get('doclayout_yolo_weights'),
  132. kwargs.get('device')
  133. )
  134. elif model_name == AtomicModel.MFD:
  135. atom_model = mfd_model_init(
  136. kwargs.get('mfd_weights'),
  137. kwargs.get('device')
  138. )
  139. elif model_name == AtomicModel.MFR:
  140. atom_model = mfr_model_init(
  141. kwargs.get('mfr_weight_dir'),
  142. kwargs.get('device')
  143. )
  144. elif model_name == AtomicModel.OCR:
  145. atom_model = ocr_model_init(
  146. kwargs.get('det_db_box_thresh', 0.3),
  147. kwargs.get('lang'),
  148. kwargs.get('det_db_unclip_ratio', 1.8),
  149. kwargs.get('enable_merge_det_boxes', True)
  150. )
  151. elif model_name == AtomicModel.WirelessTable:
  152. atom_model = wireless_table_model_init(
  153. kwargs.get('lang'),
  154. )
  155. elif model_name == AtomicModel.WiredTable:
  156. atom_model = wired_table_model_init(
  157. kwargs.get('lang'),
  158. )
  159. elif model_name == AtomicModel.TableCls:
  160. atom_model = table_cls_model_init()
  161. elif model_name == AtomicModel.ImgOrientationCls:
  162. atom_model = img_orientation_cls_model_init()
  163. else:
  164. logger.error('model name not allow')
  165. exit(1)
  166. if atom_model is None:
  167. logger.error('model init failed')
  168. exit(1)
  169. else:
  170. return atom_model
  171. class MineruPipelineModel:
  172. def __init__(self, **kwargs):
  173. self.formula_config = kwargs.get('formula_config')
  174. self.apply_formula = self.formula_config.get('enable', True)
  175. self.table_config = kwargs.get('table_config')
  176. self.apply_table = self.table_config.get('enable', True)
  177. self.lang = kwargs.get('lang', None)
  178. self.device = kwargs.get('device', 'cpu')
  179. logger.info(
  180. 'DocAnalysis init, this may take some times......'
  181. )
  182. atom_model_manager = AtomModelSingleton()
  183. if self.apply_formula:
  184. # 初始化公式检测模型
  185. self.mfd_model = atom_model_manager.get_atom_model(
  186. atom_model_name=AtomicModel.MFD,
  187. mfd_weights=str(
  188. os.path.join(auto_download_and_get_model_root_path(ModelPath.yolo_v8_mfd), ModelPath.yolo_v8_mfd)
  189. ),
  190. device=self.device,
  191. )
  192. # 初始化公式解析模型
  193. if MFR_MODEL == "unimernet_small":
  194. mfr_model_path = ModelPath.unimernet_small
  195. elif MFR_MODEL == "pp_formulanet_plus_m":
  196. mfr_model_path = ModelPath.pp_formulanet_plus_m
  197. else:
  198. logger.error('MFR model name not allow')
  199. exit(1)
  200. self.mfr_model = atom_model_manager.get_atom_model(
  201. atom_model_name=AtomicModel.MFR,
  202. mfr_weight_dir=str(os.path.join(auto_download_and_get_model_root_path(mfr_model_path), mfr_model_path)),
  203. device=self.device,
  204. )
  205. # 初始化layout模型
  206. self.layout_model = atom_model_manager.get_atom_model(
  207. atom_model_name=AtomicModel.Layout,
  208. doclayout_yolo_weights=str(
  209. os.path.join(auto_download_and_get_model_root_path(ModelPath.doclayout_yolo), ModelPath.doclayout_yolo)
  210. ),
  211. device=self.device,
  212. )
  213. # 初始化ocr
  214. self.ocr_model = atom_model_manager.get_atom_model(
  215. atom_model_name=AtomicModel.OCR,
  216. det_db_box_thresh=0.3,
  217. lang=self.lang
  218. )
  219. # init table model
  220. if self.apply_table:
  221. self.wired_table_model = atom_model_manager.get_atom_model(
  222. atom_model_name=AtomicModel.WiredTable,
  223. lang=self.lang,
  224. )
  225. self.wireless_table_model = atom_model_manager.get_atom_model(
  226. atom_model_name=AtomicModel.WirelessTable,
  227. lang=self.lang,
  228. )
  229. self.table_cls_model = atom_model_manager.get_atom_model(
  230. atom_model_name=AtomicModel.TableCls,
  231. )
  232. self.img_orientation_cls_model = atom_model_manager.get_atom_model(
  233. atom_model_name=AtomicModel.ImgOrientationCls,
  234. lang=self.lang,
  235. )
  236. logger.info('DocAnalysis init done!')