BabelDOC 0.4.12__tar.gz → 0.4.13__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {babeldoc-0.4.12 → babeldoc-0.4.13}/.gitignore +6 -1
- {babeldoc-0.4.12 → babeldoc-0.4.13}/PKG-INFO +3 -1
- babeldoc-0.4.13/babeldoc/__init__.py +1 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/assets/embedding_assets_metadata.py +2 -1
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/const.py +1 -1
- babeldoc-0.4.13/babeldoc/docvision/rpc_doclayout3.py +329 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/il_version_1.py +6 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/il_version_1.rnc +1 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/il_version_1.rng +6 -1
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/il_version_1.xsd +2 -1
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/midend/typesetting.py +514 -222
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/utils/layout_helper.py +51 -17
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/utils/mupdf_helper.py +2 -2
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/high_level.py +1 -1
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/main.py +40 -1
- {babeldoc-0.4.12 → babeldoc-0.4.13}/pyproject.toml +5 -2
- babeldoc-0.4.12/babeldoc/__init__.py +0 -1
- babeldoc-0.4.12/uv.lock +0 -3284
- {babeldoc-0.4.12 → babeldoc-0.4.13}/.cursorignore +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/.github/ISSUE_TEMPLATE/bug_report.yaml +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/.github/ISSUE_TEMPLATE/feature_request.yaml +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/.github/PULL_REQUEST_TEMPLATE/pr_form.yml +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/.github/dependabot.yml +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/.github/labels.yml +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/.github/release-drafter.yml +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/.github/workflows/codeql.yml +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/.github/workflows/docs.yml +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/.github/workflows/labeler.yml +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/.github/workflows/lint.yml +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/.github/workflows/pr-lint.yml +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/.github/workflows/publish-to-pypi.yml +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/.github/workflows/test.yml +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/.pre-commit-config.yaml +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/LICENSE +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/README.md +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/assets/assets.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/asynchronize/__init__.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/babeldoc_exception/BabelDOCException.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/babeldoc_exception/__init__.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/docvision/README.md +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/docvision/__init__.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/docvision/base_doclayout.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/docvision/doclayout.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/docvision/rpc_doclayout.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/docvision/rpc_doclayout2.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/docvision/table_detection/rapidocr.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/__init__.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/__init__.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/converter.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/__init__.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/backend/__init__.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/backend/pdf_creater.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/frontend/__init__.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/frontend/il_creater.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/midend/__init__.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/midend/add_debug_information.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/midend/automatic_term_extractor.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/midend/detect_scanned_file.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/midend/il_translator.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/midend/il_translator_llm_only.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/midend/layout_parser.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/midend/paragraph_finder.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/midend/remove_descent.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/midend/styles_and_formulas.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/midend/table_parser.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/utils/__init__.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/utils/fontmap.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/utils/formular_helper.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/utils/paragraph_helper.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/utils/style_helper.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/utils/zstd_helper.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/document_il/xml_converter.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/pdfinterp.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/result_merger.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/split_manager.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/format/pdf/translation_config.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/glossary.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/LICENSE +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/__init__.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/_saslprep.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/arcfour.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/ascii85.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/casting.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/ccitt.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/78-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/78-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/78-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/78-RKSJ-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/78-RKSJ-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/78-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/78ms-RKSJ-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/78ms-RKSJ-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/83pv-RKSJ-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/83pv-RKSJ-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/90ms-RKSJ-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/90ms-RKSJ-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/90msp-RKSJ-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/90msp-RKSJ-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/90pv-RKSJ-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/90pv-RKSJ-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/Add-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/Add-RKSJ-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/Add-RKSJ-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/Add-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/B5-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/B5-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/B5pc-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/B5pc-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/CNS-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/CNS-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/CNS1-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/CNS1-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/CNS2-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/CNS2-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/ETHK-B5-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/ETHK-B5-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/ETen-B5-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/ETen-B5-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/ETenms-B5-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/ETenms-B5-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/Ext-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/Ext-RKSJ-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/Ext-RKSJ-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/Ext-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/GB-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/GB-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/GB-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/GB-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/GBK-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/GBK-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/GBK2K-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/GBK2K-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/GBKp-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/GBKp-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/GBT-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/GBT-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/GBT-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/GBT-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/GBTpc-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/GBTpc-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/GBpc-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/GBpc-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/HKdla-B5-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/HKdla-B5-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/HKdlb-B5-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/HKdlb-B5-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/HKgccs-B5-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/HKgccs-B5-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/HKm314-B5-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/HKm314-B5-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/HKm471-B5-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/HKm471-B5-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/HKscs-B5-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/HKscs-B5-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/Hankaku-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/Hankaku-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/Hiragana-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/Hiragana-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/KSC-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/KSC-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/KSC-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/KSC-Johab-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/KSC-Johab-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/KSC-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/KSCms-UHC-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/KSCms-UHC-HW-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/KSCms-UHC-HW-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/KSCms-UHC-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/KSCpc-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/KSCpc-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/Katakana-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/Katakana-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/NWP-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/NWP-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/README.txt +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/RKSJ-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/RKSJ-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/Roman-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/Roman-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniCNS-UCS2-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniCNS-UCS2-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniCNS-UTF16-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniCNS-UTF16-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniCNS-UTF32-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniCNS-UTF32-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniCNS-UTF8-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniCNS-UTF8-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniGB-UCS2-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniGB-UCS2-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniGB-UTF16-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniGB-UTF16-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniGB-UTF32-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniGB-UTF32-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniGB-UTF8-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniGB-UTF8-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJIS-UCS2-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJIS-UCS2-HW-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJIS-UCS2-HW-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJIS-UCS2-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJIS-UTF16-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJIS-UTF16-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJIS-UTF32-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJIS-UTF32-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJIS-UTF8-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJIS-UTF8-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJIS2004-UTF16-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJIS2004-UTF16-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJIS2004-UTF32-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJIS2004-UTF32-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJIS2004-UTF8-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJIS2004-UTF8-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJISX0213-UTF32-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJISX0213-UTF32-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJISX02132004-UTF32-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniJISX02132004-UTF32-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniKS-UCS2-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniKS-UCS2-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniKS-UTF16-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniKS-UTF16-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniKS-UTF32-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniKS-UTF32-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniKS-UTF8-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/UniKS-UTF8-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/WP-Symbol-H.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/WP-Symbol-V.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/to-unicode-Adobe-CNS1.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/to-unicode-Adobe-GB1.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/to-unicode-Adobe-Japan1.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmap/to-unicode-Adobe-Korea1.pickle.gz +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/cmapdb.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/converter.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/data_structures.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/encodingdb.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/fontmetrics.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/glyphlist.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/high_level.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/image.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/jbig2.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/latin_enc.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/layout.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/lzw.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/pdfcolor.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/pdfdevice.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/pdfdocument.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/pdfexceptions.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/pdffont.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/pdfinterp.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/pdfpage.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/pdfparser.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/pdftypes.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/psexceptions.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/psparser.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/py.typed +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/runlength.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/settings.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/pdfminer/utils.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/progress_monitor.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/tools/generate_font_metadata.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/tools/italic_assistance.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/tools/italic_recognize_tool.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/translator/__init__.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/translator/cache.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/translator/translator.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/utils/__init__.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/utils/atomic_integer.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/babeldoc/utils/priority_thread_pool_executor.py +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/CODE_OF_CONDUCT.md +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/CONTRIBUTING.md +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/CONTRIBUTOR_REWARD.md +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/ImplementationDetails/AsyncTranslate/AsyncTranslate.md +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/ImplementationDetails/ILTranslator/ILTranslator.md +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/ImplementationDetails/PDFCreation/PDFCreation.md +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/ImplementationDetails/PDFParsing/PDFParsing.md +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/ImplementationDetails/ParagraphFinding/ParagraphFinding.md +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/ImplementationDetails/README.md +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/ImplementationDetails/StylesAndFormulas/StylesAndFormulas.md +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/ImplementationDetails/Typesetting/Typesetting.md +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/README.md +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/deploy.sh +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/example/demo_glossary.csv +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/images/babeldoc-banner.png +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/images/babeldoc-big-logo-darkmode-with-transparent-background.png +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/images/babeldoc-big-logo-darkmode-with-transparent-background.svg +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/images/babeldoc-big-logo-with-transparent-background.png +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/images/babeldoc-big-logo-with-transparent-background.svg +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/images/babeldoc-big-logo.png +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/images/babeldoc-contributor_reward_example.png +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/images/babeldoc-preview.gif +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/images/babeldoc-small-logo-with-transparent-background.png +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/images/babeldoc-small-logo-with-transparent-background.svg +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/images/babeldoc-small-logo.png +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/index.md +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/intro-to-pdf-object.md +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/requirements.txt +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/docs/supported_languages.md +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/mkdocs.yml +0 -0
- {babeldoc-0.4.12 → babeldoc-0.4.13}/tests/test_translation_config.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: BabelDOC
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.13
|
|
4
4
|
Summary: Yet Another Document Translator
|
|
5
5
|
Project-URL: Homepage, https://github.com/funstory-ai/BabelDOC
|
|
6
6
|
Project-URL: Issues, https://github.com/funstory-ai/BabelDOC/issues
|
|
@@ -38,10 +38,12 @@ Requires-Dist: rapidocr-onnxruntime>=1.4.4
|
|
|
38
38
|
Requires-Dist: rich>=13.9.4
|
|
39
39
|
Requires-Dist: rtree>=1.4.0
|
|
40
40
|
Requires-Dist: scikit-image>=0.25.2
|
|
41
|
+
Requires-Dist: scipy>=1.15.3
|
|
41
42
|
Requires-Dist: tenacity>=9.0.0
|
|
42
43
|
Requires-Dist: tiktoken>=0.9.0
|
|
43
44
|
Requires-Dist: toml>=0.10.2
|
|
44
45
|
Requires-Dist: tqdm>=4.67.1
|
|
46
|
+
Requires-Dist: uharfbuzz>=0.50.2
|
|
45
47
|
Requires-Dist: xsdata[cli,lxml,soap]>=24.12
|
|
46
48
|
Provides-Extra: cuda
|
|
47
49
|
Requires-Dist: onnxruntime-gpu>=1.16.1; extra == 'cuda'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.4.13"
|
|
@@ -608,6 +608,7 @@ ALL_FONT_FAMILY = {
|
|
|
608
608
|
"KR": KR_FONT_FAMILY,
|
|
609
609
|
"JP": JP_FONT_FAMILY,
|
|
610
610
|
"EN": EN_FONT_FAMILY,
|
|
611
|
+
"JA": JP_FONT_FAMILY,
|
|
611
612
|
}
|
|
612
613
|
|
|
613
614
|
|
|
@@ -633,7 +634,7 @@ def get_font_family(lang_code: str):
|
|
|
633
634
|
lang_code = lang_code.upper()
|
|
634
635
|
if "KR" in lang_code:
|
|
635
636
|
font_family = KR_FONT_FAMILY
|
|
636
|
-
elif "JP" in lang_code:
|
|
637
|
+
elif "JP" in lang_code or "JA" in lang_code:
|
|
637
638
|
font_family = JP_FONT_FAMILY
|
|
638
639
|
elif "HK" in lang_code:
|
|
639
640
|
font_family = HK_FONT_FAMILY
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
import threading
|
|
4
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import cv2
|
|
8
|
+
import httpx
|
|
9
|
+
import numpy as np
|
|
10
|
+
import pymupdf
|
|
11
|
+
from tenacity import retry
|
|
12
|
+
from tenacity import retry_if_exception_type
|
|
13
|
+
from tenacity import stop_after_attempt
|
|
14
|
+
from tenacity import wait_exponential
|
|
15
|
+
|
|
16
|
+
import babeldoc
|
|
17
|
+
from babeldoc.docvision.base_doclayout import DocLayoutModel
|
|
18
|
+
from babeldoc.docvision.base_doclayout import YoloBox
|
|
19
|
+
from babeldoc.docvision.base_doclayout import YoloResult
|
|
20
|
+
from babeldoc.format.pdf.document_il.utils.mupdf_helper import get_no_rotation_img
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
DPI = 150
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def encode_image(image) -> bytes:
|
|
27
|
+
"""Read and encode image to bytes
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
image: Can be either a file path (str) or numpy array
|
|
31
|
+
"""
|
|
32
|
+
if isinstance(image, str):
|
|
33
|
+
if not Path(image).exists():
|
|
34
|
+
raise FileNotFoundError(f"Image file not found: {image}")
|
|
35
|
+
img = cv2.imread(image)
|
|
36
|
+
if img is None:
|
|
37
|
+
raise ValueError(f"Failed to read image: {image}")
|
|
38
|
+
else:
|
|
39
|
+
img = image
|
|
40
|
+
|
|
41
|
+
# logger.debug(f"Image shape: {img.shape}")
|
|
42
|
+
encoded = cv2.imencode(".jpg", img)[1].tobytes()
|
|
43
|
+
# logger.debug(f"Encoded image size: {len(encoded)} bytes")
|
|
44
|
+
return encoded
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@retry(
|
|
48
|
+
stop=stop_after_attempt(3), # 最多重试 3 次
|
|
49
|
+
wait=wait_exponential(
|
|
50
|
+
multiplier=1, min=1, max=10
|
|
51
|
+
), # 指数退避策略,初始 1 秒,最大 10 秒
|
|
52
|
+
retry=retry_if_exception_type((httpx.HTTPError, Exception)), # 针对哪些异常重试
|
|
53
|
+
before_sleep=lambda retry_state: logger.warning(
|
|
54
|
+
f"Request failed, retrying in {getattr(retry_state.next_action, 'sleep', 'unknown')} seconds... "
|
|
55
|
+
f"(Attempt {retry_state.attempt_number}/3)"
|
|
56
|
+
),
|
|
57
|
+
)
|
|
58
|
+
def predict_layout(
|
|
59
|
+
image,
|
|
60
|
+
host: str = "http://localhost:8000",
|
|
61
|
+
_imgsz: int = 1024,
|
|
62
|
+
):
|
|
63
|
+
"""
|
|
64
|
+
Predict document layout using the MOSEC service
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
image: Can be either a file path (str) or numpy array
|
|
68
|
+
host: Service host URL
|
|
69
|
+
imgsz: Image size for model input
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
List of predictions containing bounding boxes and classes
|
|
73
|
+
"""
|
|
74
|
+
# Prepare request data
|
|
75
|
+
|
|
76
|
+
image_data = encode_image(image)
|
|
77
|
+
|
|
78
|
+
# Pack data using msgpack
|
|
79
|
+
# packed_data = msgpack.packb(data, use_bin_type=True)
|
|
80
|
+
# logger.debug(f"Packed data size: {len(packed_data)} bytes")
|
|
81
|
+
|
|
82
|
+
# Send request
|
|
83
|
+
# logger.debug(f"Sending request to {host}/inference")
|
|
84
|
+
response = httpx.post(
|
|
85
|
+
f"{host}/analyze?min_sim=0.7&early_stop=0.99&timeout=240",
|
|
86
|
+
files={"file": ("image.jpg", image_data, "image/jpeg")},
|
|
87
|
+
headers={
|
|
88
|
+
"Accept": "application/json",
|
|
89
|
+
},
|
|
90
|
+
timeout=300,
|
|
91
|
+
follow_redirects=True,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# logger.debug(f"Response status: {response.status_code}")
|
|
95
|
+
# logger.debug(f"Response headers: {response.headers}")
|
|
96
|
+
idx = 0
|
|
97
|
+
id_lookup = {}
|
|
98
|
+
if response.status_code == 200:
|
|
99
|
+
try:
|
|
100
|
+
result = json.loads(response.text)
|
|
101
|
+
useful_result = []
|
|
102
|
+
if isinstance(result, dict):
|
|
103
|
+
names = {}
|
|
104
|
+
for box in result["boxes"]:
|
|
105
|
+
if box["ocr_match_score"] < 0.7:
|
|
106
|
+
continue
|
|
107
|
+
|
|
108
|
+
box["xyxy"] = box["coords"]
|
|
109
|
+
box["conf"] = box["ocr_match_score"]
|
|
110
|
+
if box["label"] not in names:
|
|
111
|
+
idx += 1
|
|
112
|
+
names[idx] = box["label"]
|
|
113
|
+
box["cls_id"] = idx
|
|
114
|
+
id_lookup[box["label"]] = idx
|
|
115
|
+
else:
|
|
116
|
+
box["cls_id"] = id_lookup[box["label"]]
|
|
117
|
+
names[box["cls_id"]] = box["label"]
|
|
118
|
+
box["cls"] = box["cls_id"]
|
|
119
|
+
useful_result.append(box)
|
|
120
|
+
if "names" not in result:
|
|
121
|
+
result["names"] = names
|
|
122
|
+
result["boxes"] = useful_result
|
|
123
|
+
result = [result]
|
|
124
|
+
return result
|
|
125
|
+
except Exception as e:
|
|
126
|
+
logger.exception(f"Failed to unpack response: {e!s}")
|
|
127
|
+
raise
|
|
128
|
+
else:
|
|
129
|
+
logger.error(f"Request failed with status {response.status_code}")
|
|
130
|
+
logger.error(f"Response content: {response.content}")
|
|
131
|
+
raise Exception(
|
|
132
|
+
f"Request failed with status {response.status_code}: {response.text}",
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class ResultContainer:
|
|
137
|
+
def __init__(self):
|
|
138
|
+
self.result = YoloResult(boxes_data=np.array([]), names=[])
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class RpcDocLayoutModel(DocLayoutModel):
|
|
142
|
+
"""DocLayoutModel implementation that uses RPC service."""
|
|
143
|
+
|
|
144
|
+
def __init__(self, host: str = "http://localhost:8000"):
|
|
145
|
+
"""Initialize RPC model with host address."""
|
|
146
|
+
self.host = host
|
|
147
|
+
self._stride = 32 # Default stride value
|
|
148
|
+
self._names = ["text", "title", "list", "table", "figure"]
|
|
149
|
+
self.lock = threading.Lock()
|
|
150
|
+
|
|
151
|
+
@property
|
|
152
|
+
def stride(self) -> int:
|
|
153
|
+
"""Stride of the model input."""
|
|
154
|
+
return self._stride
|
|
155
|
+
|
|
156
|
+
def resize_and_pad_image(self, image, new_shape):
|
|
157
|
+
"""
|
|
158
|
+
Resize and pad the image to the specified size,
|
|
159
|
+
ensuring dimensions are multiples of stride.
|
|
160
|
+
|
|
161
|
+
Parameters:
|
|
162
|
+
- image: Input image
|
|
163
|
+
- new_shape: Target size (integer or (height, width) tuple)
|
|
164
|
+
- stride: Padding alignment stride, default 32
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
- Processed image
|
|
168
|
+
"""
|
|
169
|
+
if isinstance(new_shape, int):
|
|
170
|
+
new_shape = (new_shape, new_shape)
|
|
171
|
+
|
|
172
|
+
h, w = image.shape[:2]
|
|
173
|
+
new_h, new_w = new_shape
|
|
174
|
+
|
|
175
|
+
# Calculate scaling ratio
|
|
176
|
+
r = min(new_h / h, new_w / w)
|
|
177
|
+
resized_h, resized_w = int(round(h * r)), int(round(w * r))
|
|
178
|
+
|
|
179
|
+
# Resize image
|
|
180
|
+
image = cv2.resize(
|
|
181
|
+
image, (resized_w, resized_h), interpolation=cv2.INTER_LINEAR
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
# Calculate padding size
|
|
185
|
+
pad_h = new_h - resized_h
|
|
186
|
+
pad_w = new_w - resized_w
|
|
187
|
+
top, bottom = pad_h // 2, pad_h - pad_h // 2
|
|
188
|
+
left, right = pad_w // 2, pad_w - pad_w // 2
|
|
189
|
+
|
|
190
|
+
# Add padding
|
|
191
|
+
image = cv2.copyMakeBorder(
|
|
192
|
+
image, top, bottom, left, right, cv2.BORDER_CONSTANT, value=(114, 114, 114)
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
return image
|
|
196
|
+
|
|
197
|
+
def scale_boxes(self, img1_shape, boxes, img0_shape):
|
|
198
|
+
"""
|
|
199
|
+
Rescales bounding boxes (in the format of xyxy by default) from the shape of the image they were originally
|
|
200
|
+
specified in (img1_shape) to the shape of a different image (img0_shape).
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
img1_shape (tuple): The shape of the image that the bounding boxes are for,
|
|
204
|
+
in the format of (height, width).
|
|
205
|
+
boxes (torch.Tensor): the bounding boxes of the objects in the image, in the format of (x1, y1, x2, y2)
|
|
206
|
+
img0_shape (tuple): the shape of the target image, in the format of (height, width).
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
boxes (torch.Tensor): The scaled bounding boxes, in the format of (x1, y1, x2, y2)
|
|
210
|
+
"""
|
|
211
|
+
|
|
212
|
+
# Calculate scaling ratio
|
|
213
|
+
gain = min(img1_shape[0] / img0_shape[0], img1_shape[1] / img0_shape[1])
|
|
214
|
+
|
|
215
|
+
# Calculate padding size
|
|
216
|
+
pad_x = round((img1_shape[1] - img0_shape[1] * gain) / 2 - 0.1)
|
|
217
|
+
pad_y = round((img1_shape[0] - img0_shape[0] * gain) / 2 - 0.1)
|
|
218
|
+
|
|
219
|
+
# Remove padding and scale boxes
|
|
220
|
+
boxes = (boxes - [pad_x, pad_y, pad_x, pad_y]) / gain
|
|
221
|
+
return boxes
|
|
222
|
+
|
|
223
|
+
def predict_image(
|
|
224
|
+
self,
|
|
225
|
+
image,
|
|
226
|
+
host: str | None = None,
|
|
227
|
+
result_container: ResultContainer | None = None,
|
|
228
|
+
imgsz: int = 1024,
|
|
229
|
+
) -> ResultContainer:
|
|
230
|
+
"""Predict the layout of document pages using RPC service."""
|
|
231
|
+
if result_container is None:
|
|
232
|
+
result_container = ResultContainer()
|
|
233
|
+
target_imgsz = (800, 800)
|
|
234
|
+
orig_h, orig_w = image.shape[:2]
|
|
235
|
+
target_imgsz = (orig_h, orig_w)
|
|
236
|
+
if image.shape[0] != target_imgsz[0] or image.shape[1] != target_imgsz[1]:
|
|
237
|
+
image = self.resize_and_pad_image(image, new_shape=target_imgsz)
|
|
238
|
+
preds = predict_layout(image, host=self.host, imgsz=800)
|
|
239
|
+
orig_h, orig_w = orig_h / DPI * 72, orig_w / DPI * 72
|
|
240
|
+
if len(preds) > 0:
|
|
241
|
+
for pred in preds:
|
|
242
|
+
boxes = [
|
|
243
|
+
YoloBox(
|
|
244
|
+
None,
|
|
245
|
+
self.scale_boxes(
|
|
246
|
+
target_imgsz, np.array(x["xyxy"]), (orig_h, orig_w)
|
|
247
|
+
),
|
|
248
|
+
np.array(x["conf"]),
|
|
249
|
+
x["cls"],
|
|
250
|
+
)
|
|
251
|
+
for x in pred["boxes"]
|
|
252
|
+
]
|
|
253
|
+
result_container.result = YoloResult(
|
|
254
|
+
boxes=boxes,
|
|
255
|
+
names={int(k): v for k, v in pred["names"].items()},
|
|
256
|
+
)
|
|
257
|
+
return result_container.result
|
|
258
|
+
|
|
259
|
+
def predict(self, image, imgsz=1024, **kwargs) -> list[YoloResult]:
|
|
260
|
+
"""Predict the layout of document pages using RPC service."""
|
|
261
|
+
# Handle single image input
|
|
262
|
+
if isinstance(image, np.ndarray) and len(image.shape) == 3:
|
|
263
|
+
image = [image]
|
|
264
|
+
|
|
265
|
+
result_containers = [ResultContainer() for _ in image]
|
|
266
|
+
predict_thread = ThreadPoolExecutor(max_workers=len(image))
|
|
267
|
+
for img, result_container in zip(image, result_containers, strict=True):
|
|
268
|
+
predict_thread.submit(
|
|
269
|
+
self.predict_image, img, self.host, result_container, 800
|
|
270
|
+
)
|
|
271
|
+
predict_thread.shutdown(wait=True)
|
|
272
|
+
result = [result_container.result for result_container in result_containers]
|
|
273
|
+
return result
|
|
274
|
+
|
|
275
|
+
def predict_page(
|
|
276
|
+
self, page, mupdf_doc: pymupdf.Document, translate_config, save_debug_image
|
|
277
|
+
):
|
|
278
|
+
translate_config.raise_if_cancelled()
|
|
279
|
+
with self.lock:
|
|
280
|
+
# pix = mupdf_doc[page.page_number].get_pixmap(dpi=72)
|
|
281
|
+
pix = get_no_rotation_img(mupdf_doc[page.page_number], dpi=DPI)
|
|
282
|
+
image = np.frombuffer(pix.samples, np.uint8).reshape(
|
|
283
|
+
pix.height,
|
|
284
|
+
pix.width,
|
|
285
|
+
3,
|
|
286
|
+
)[:, :, ::-1]
|
|
287
|
+
predict_result = self.predict_image(image, self.host, None, 800)
|
|
288
|
+
save_debug_image(image, predict_result, page.page_number + 1)
|
|
289
|
+
return page, predict_result
|
|
290
|
+
|
|
291
|
+
def handle_document(
|
|
292
|
+
self,
|
|
293
|
+
pages: list[babeldoc.format.pdf.document_il.il_version_1.Page],
|
|
294
|
+
mupdf_doc: pymupdf.Document,
|
|
295
|
+
translate_config,
|
|
296
|
+
save_debug_image,
|
|
297
|
+
):
|
|
298
|
+
with ThreadPoolExecutor(max_workers=4) as executor:
|
|
299
|
+
yield from executor.map(
|
|
300
|
+
self.predict_page,
|
|
301
|
+
pages,
|
|
302
|
+
(mupdf_doc for _ in range(len(pages))),
|
|
303
|
+
(translate_config for _ in range(len(pages))),
|
|
304
|
+
(save_debug_image for _ in range(len(pages))),
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
@staticmethod
|
|
308
|
+
def from_host(host: str) -> "RpcDocLayoutModel":
|
|
309
|
+
"""Create RpcDocLayoutModel from host address."""
|
|
310
|
+
return RpcDocLayoutModel(host=host)
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
if __name__ == "__main__":
|
|
314
|
+
logging.basicConfig(level=logging.DEBUG)
|
|
315
|
+
# Test the service
|
|
316
|
+
try:
|
|
317
|
+
# Use a default test image if example/1.png doesn't exist
|
|
318
|
+
image_path = "example/1.png"
|
|
319
|
+
if not Path(image_path).exists():
|
|
320
|
+
print(f"Warning: {image_path} not found.")
|
|
321
|
+
print("Please provide the path to a test image:")
|
|
322
|
+
image_path = input("> ")
|
|
323
|
+
|
|
324
|
+
logger.info(f"Processing image: {image_path}")
|
|
325
|
+
result = predict_layout(image_path)
|
|
326
|
+
print("Prediction results:")
|
|
327
|
+
print(result)
|
|
328
|
+
except Exception as e:
|
|
329
|
+
print(f"Error: {e!s}")
|
|
@@ -112,6 +112,7 @@ PDFParagraph =
|
|
|
112
112
|
attribute xobjId { xsd:int }?,
|
|
113
113
|
attribute unicode { xsd:string },
|
|
114
114
|
attribute scale { xsd:float }?,
|
|
115
|
+
attribute optimal_scale { xsd:float }?,
|
|
115
116
|
attribute vertical { xsd:boolean }?,
|
|
116
117
|
attribute FirstLineIndent { xsd:boolean }?,
|
|
117
118
|
attribute debug_id { xsd:string }?,
|
|
@@ -196,7 +196,7 @@
|
|
|
196
196
|
</optional>
|
|
197
197
|
<optional>
|
|
198
198
|
<attribute name="formula_layout_id">
|
|
199
|
-
<data type="
|
|
199
|
+
<data type="int"/>
|
|
200
200
|
</attribute>
|
|
201
201
|
</optional>
|
|
202
202
|
<ref name="PDFStyle"/>
|
|
@@ -324,6 +324,11 @@
|
|
|
324
324
|
<data type="float"/>
|
|
325
325
|
</attribute>
|
|
326
326
|
</optional>
|
|
327
|
+
<optional>
|
|
328
|
+
<attribute name="optimal_scale">
|
|
329
|
+
<data type="float"/>
|
|
330
|
+
</attribute>
|
|
331
|
+
</optional>
|
|
327
332
|
<optional>
|
|
328
333
|
<attribute name="vertical">
|
|
329
334
|
<data type="boolean"/>
|
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
<xs:attribute name="advance" type="xs:float"/>
|
|
104
104
|
<xs:attribute name="xobjId" type="xs:int"/>
|
|
105
105
|
<xs:attribute name="debug_info" type="xs:boolean"/>
|
|
106
|
-
<xs:attribute name="formula_layout_id" type="xs:
|
|
106
|
+
<xs:attribute name="formula_layout_id" type="xs:int"/>
|
|
107
107
|
</xs:complexType>
|
|
108
108
|
</xs:element>
|
|
109
109
|
<xs:element name="visual_bbox">
|
|
@@ -185,6 +185,7 @@
|
|
|
185
185
|
<xs:attribute name="xobjId" type="xs:int"/>
|
|
186
186
|
<xs:attribute name="unicode" use="required" type="xs:string"/>
|
|
187
187
|
<xs:attribute name="scale" type="xs:float"/>
|
|
188
|
+
<xs:attribute name="optimal_scale" type="xs:float"/>
|
|
188
189
|
<xs:attribute name="vertical" type="xs:boolean"/>
|
|
189
190
|
<xs:attribute name="FirstLineIndent" type="xs:boolean"/>
|
|
190
191
|
<xs:attribute name="debug_id" type="xs:string"/>
|