BabelDOC 0.4.15__tar.gz → 0.4.17__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.15 → babeldoc-0.4.17}/.github/ISSUE_TEMPLATE/bug_report.yaml +5 -1
- {babeldoc-0.4.15 → babeldoc-0.4.17}/.github/workflows/docs.yml +1 -1
- {babeldoc-0.4.15 → babeldoc-0.4.17}/.github/workflows/publish-to-pypi.yml +1 -1
- {babeldoc-0.4.15 → babeldoc-0.4.17}/.github/workflows/test.yml +1 -1
- {babeldoc-0.4.15 → babeldoc-0.4.17}/PKG-INFO +1 -1
- babeldoc-0.4.17/babeldoc/__init__.py +1 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/const.py +1 -1
- babeldoc-0.4.17/babeldoc/docvision/rpc_doclayout2.py +336 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/docvision/rpc_doclayout3.py +2 -2
- babeldoc-0.4.15/babeldoc/docvision/rpc_doclayout2.py → babeldoc-0.4.17/babeldoc/docvision/rpc_doclayout4.py +27 -11
- babeldoc-0.4.17/babeldoc/format/pdf/babelpdf/base14.py +1970 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/frontend/il_creater.py +22 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/utils/layout_helper.py +4 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/high_level.py +17 -4
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/pdfinterp.py +4 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/main.py +9 -1
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/pdfpage.py +4 -1
- {babeldoc-0.4.15 → babeldoc-0.4.17}/pyproject.toml +2 -2
- babeldoc-0.4.15/babeldoc/__init__.py +0 -1
- {babeldoc-0.4.15 → babeldoc-0.4.17}/.cursorignore +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/.github/ISSUE_TEMPLATE/feature_request.yaml +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/.github/PULL_REQUEST_TEMPLATE/pr_form.yml +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/.github/dependabot.yml +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/.github/labels.yml +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/.github/release-drafter.yml +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/.github/workflows/codeql.yml +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/.github/workflows/labeler.yml +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/.github/workflows/lint.yml +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/.github/workflows/pr-lint.yml +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/.gitignore +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/.pre-commit-config.yaml +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/LICENSE +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/README.md +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/assets/assets.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/assets/embedding_assets_metadata.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/asynchronize/__init__.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/babeldoc_exception/BabelDOCException.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/babeldoc_exception/__init__.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/docvision/README.md +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/docvision/__init__.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/docvision/base_doclayout.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/docvision/doclayout.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/docvision/rpc_doclayout.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/docvision/table_detection/rapidocr.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/__init__.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/__init__.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/babelpdf/encoding.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/converter.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/__init__.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/backend/__init__.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/backend/pdf_creater.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/frontend/__init__.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/il_version_1.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/il_version_1.rnc +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/il_version_1.rng +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/il_version_1.xsd +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/midend/__init__.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/midend/add_debug_information.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/midend/automatic_term_extractor.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/midend/detect_scanned_file.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/midend/il_translator.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/midend/il_translator_llm_only.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/midend/layout_parser.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/midend/paragraph_finder.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/midend/remove_descent.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/midend/styles_and_formulas.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/midend/table_parser.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/midend/typesetting.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/utils/__init__.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/utils/fontmap.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/utils/formular_helper.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/utils/mupdf_helper.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/utils/paragraph_helper.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/utils/style_helper.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/utils/zstd_helper.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/document_il/xml_converter.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/result_merger.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/split_manager.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/format/pdf/translation_config.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/glossary.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/LICENSE +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/__init__.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/_saslprep.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/arcfour.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/ascii85.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/casting.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/ccitt.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/78-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/78-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/78-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/78-RKSJ-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/78-RKSJ-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/78-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/78ms-RKSJ-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/78ms-RKSJ-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/83pv-RKSJ-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/83pv-RKSJ-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/90ms-RKSJ-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/90ms-RKSJ-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/90msp-RKSJ-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/90msp-RKSJ-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/90pv-RKSJ-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/90pv-RKSJ-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/Add-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/Add-RKSJ-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/Add-RKSJ-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/Add-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/B5-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/B5-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/B5pc-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/B5pc-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/CNS-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/CNS-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/CNS1-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/CNS1-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/CNS2-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/CNS2-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/ETHK-B5-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/ETHK-B5-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/ETen-B5-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/ETen-B5-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/ETenms-B5-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/ETenms-B5-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/Ext-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/Ext-RKSJ-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/Ext-RKSJ-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/Ext-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/GB-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/GB-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/GB-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/GB-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/GBK-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/GBK-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/GBK2K-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/GBK2K-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/GBKp-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/GBKp-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/GBT-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/GBT-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/GBT-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/GBT-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/GBTpc-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/GBTpc-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/GBpc-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/GBpc-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/HKdla-B5-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/HKdla-B5-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/HKdlb-B5-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/HKdlb-B5-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/HKgccs-B5-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/HKgccs-B5-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/HKm314-B5-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/HKm314-B5-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/HKm471-B5-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/HKm471-B5-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/HKscs-B5-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/HKscs-B5-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/Hankaku-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/Hankaku-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/Hiragana-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/Hiragana-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/KSC-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/KSC-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/KSC-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/KSC-Johab-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/KSC-Johab-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/KSC-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/KSCms-UHC-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/KSCms-UHC-HW-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/KSCms-UHC-HW-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/KSCms-UHC-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/KSCpc-EUC-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/KSCpc-EUC-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/Katakana-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/Katakana-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/NWP-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/NWP-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/README.txt +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/RKSJ-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/RKSJ-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/Roman-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/Roman-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniCNS-UCS2-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniCNS-UCS2-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniCNS-UTF16-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniCNS-UTF16-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniCNS-UTF32-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniCNS-UTF32-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniCNS-UTF8-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniCNS-UTF8-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniGB-UCS2-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniGB-UCS2-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniGB-UTF16-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniGB-UTF16-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniGB-UTF32-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniGB-UTF32-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniGB-UTF8-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniGB-UTF8-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJIS-UCS2-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJIS-UCS2-HW-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJIS-UCS2-HW-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJIS-UCS2-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJIS-UTF16-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJIS-UTF16-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJIS-UTF32-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJIS-UTF32-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJIS-UTF8-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJIS-UTF8-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJIS2004-UTF16-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJIS2004-UTF16-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJIS2004-UTF32-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJIS2004-UTF32-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJIS2004-UTF8-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJIS2004-UTF8-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJISX0213-UTF32-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJISX0213-UTF32-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJISX02132004-UTF32-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniJISX02132004-UTF32-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniKS-UCS2-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniKS-UCS2-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniKS-UTF16-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniKS-UTF16-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniKS-UTF32-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniKS-UTF32-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniKS-UTF8-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/UniKS-UTF8-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/WP-Symbol-H.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/WP-Symbol-V.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/to-unicode-Adobe-CNS1.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/to-unicode-Adobe-GB1.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/to-unicode-Adobe-Japan1.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmap/to-unicode-Adobe-Korea1.pickle.gz +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/cmapdb.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/converter.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/data_structures.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/encodingdb.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/fontmetrics.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/glyphlist.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/high_level.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/image.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/jbig2.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/latin_enc.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/layout.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/lzw.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/pdfcolor.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/pdfdevice.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/pdfdocument.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/pdfexceptions.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/pdffont.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/pdfinterp.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/pdfparser.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/pdftypes.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/psexceptions.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/psparser.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/py.typed +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/runlength.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/settings.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/pdfminer/utils.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/progress_monitor.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/tools/generate_font_metadata.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/tools/italic_assistance.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/tools/italic_recognize_tool.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/translator/__init__.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/translator/cache.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/translator/translator.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/utils/__init__.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/utils/atomic_integer.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/babeldoc/utils/priority_thread_pool_executor.py +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/CODE_OF_CONDUCT.md +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/CONTRIBUTING.md +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/CONTRIBUTOR_REWARD.md +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/ImplementationDetails/AsyncTranslate/AsyncTranslate.md +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/ImplementationDetails/ILTranslator/ILTranslator.md +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/ImplementationDetails/PDFCreation/PDFCreation.md +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/ImplementationDetails/PDFParsing/PDFParsing.md +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/ImplementationDetails/ParagraphFinding/ParagraphFinding.md +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/ImplementationDetails/README.md +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/ImplementationDetails/StylesAndFormulas/StylesAndFormulas.md +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/ImplementationDetails/Typesetting/Typesetting.md +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/README.md +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/deploy.sh +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/example/demo_glossary.csv +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/images/babeldoc-banner.png +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/images/babeldoc-big-logo-darkmode-with-transparent-background.png +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/images/babeldoc-big-logo-darkmode-with-transparent-background.svg +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/images/babeldoc-big-logo-with-transparent-background.png +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/images/babeldoc-big-logo-with-transparent-background.svg +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/images/babeldoc-big-logo.png +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/images/babeldoc-contributor_reward_example.png +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/images/babeldoc-preview.gif +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/images/babeldoc-small-logo-with-transparent-background.png +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/images/babeldoc-small-logo-with-transparent-background.svg +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/images/babeldoc-small-logo.png +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/index.md +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/intro-to-pdf-object.md +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/requirements.txt +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/docs/supported_languages.md +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/mkdocs.yml +0 -0
- {babeldoc-0.4.15 → babeldoc-0.4.17}/tests/test_translation_config.py +0 -0
|
@@ -17,6 +17,10 @@ body:
|
|
|
17
17
|
required: true
|
|
18
18
|
- label: I am certain that this issue is with BabelDOC itself and can be reproduced through the BabelDOC cli
|
|
19
19
|
required: true
|
|
20
|
+
- label: I have uploaded the original file, or confirmed that this issue is unrelated to the original file
|
|
21
|
+
required: true
|
|
22
|
+
- label: I have uploaded the log.
|
|
23
|
+
required: true
|
|
20
24
|
|
|
21
25
|
- type: markdown
|
|
22
26
|
attributes:
|
|
@@ -77,7 +81,7 @@ body:
|
|
|
77
81
|
id: pdf
|
|
78
82
|
attributes:
|
|
79
83
|
label: Original PDF File
|
|
80
|
-
description: Upload the input PDF if applicable.
|
|
84
|
+
description: Upload the input PDF if applicable. (Issues related to specific PDFs but without uploaded files will be closed directly.)
|
|
81
85
|
validations:
|
|
82
86
|
required: false
|
|
83
87
|
|
|
@@ -17,7 +17,7 @@ jobs:
|
|
|
17
17
|
git config user.name github-actions[bot]
|
|
18
18
|
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
|
|
19
19
|
- name: Setup uv with Python 3.12
|
|
20
|
-
uses: astral-sh/setup-uv@
|
|
20
|
+
uses: astral-sh/setup-uv@7edac99f961f18b581bbd960d59d049f04c0002f # v6.4.1
|
|
21
21
|
with:
|
|
22
22
|
python-version: "3.12"
|
|
23
23
|
enable-cache: true
|
|
@@ -35,7 +35,7 @@ jobs:
|
|
|
35
35
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
36
36
|
|
|
37
37
|
- name: Setup uv with Python 3.12
|
|
38
|
-
uses: astral-sh/setup-uv@
|
|
38
|
+
uses: astral-sh/setup-uv@7edac99f961f18b581bbd960d59d049f04c0002f # v6.4.1
|
|
39
39
|
with:
|
|
40
40
|
python-version: "3.12"
|
|
41
41
|
enable-cache: true
|
|
@@ -28,7 +28,7 @@ jobs:
|
|
|
28
28
|
path: ~/.cache/babeldoc
|
|
29
29
|
key: babeldoc-assets-${{ hashFiles('babeldoc/assets/embedding_assets_metadata.py') }}
|
|
30
30
|
- name: Setup uv with Python ${{ matrix.python-version }}
|
|
31
|
-
uses: astral-sh/setup-uv@
|
|
31
|
+
uses: astral-sh/setup-uv@7edac99f961f18b581bbd960d59d049f04c0002f # v6.4.1
|
|
32
32
|
with:
|
|
33
33
|
python-version: ${{ matrix.python-version }}
|
|
34
34
|
enable-cache: true
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.4.17"
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import threading
|
|
3
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import cv2
|
|
7
|
+
import httpx
|
|
8
|
+
import msgpack
|
|
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
|
+
if not isinstance(image, list):
|
|
77
|
+
image = [image]
|
|
78
|
+
image_data = [encode_image(image) for image in image]
|
|
79
|
+
data = {
|
|
80
|
+
"image": image_data,
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# Pack data using msgpack
|
|
84
|
+
packed_data = msgpack.packb(data, use_bin_type=True)
|
|
85
|
+
# logger.debug(f"Packed data size: {len(packed_data)} bytes")
|
|
86
|
+
|
|
87
|
+
# Send request
|
|
88
|
+
# logger.debug(f"Sending request to {host}/inference")
|
|
89
|
+
response = httpx.post(
|
|
90
|
+
# f"{host}/analyze?min_sim=0.7&early_stop=0.99&timeout=480",
|
|
91
|
+
f"{host}/inference",
|
|
92
|
+
data=packed_data,
|
|
93
|
+
headers={
|
|
94
|
+
"Content-Type": "application/msgpack",
|
|
95
|
+
"Accept": "application/msgpack",
|
|
96
|
+
},
|
|
97
|
+
timeout=480,
|
|
98
|
+
follow_redirects=True,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# logger.debug(f"Response status: {response.status_code}")
|
|
102
|
+
# logger.debug(f"Response headers: {response.headers}")
|
|
103
|
+
idx = 0
|
|
104
|
+
id_lookup = {}
|
|
105
|
+
if response.status_code == 200:
|
|
106
|
+
try:
|
|
107
|
+
result = msgpack.unpackb(response.content, raw=False)
|
|
108
|
+
useful_result = []
|
|
109
|
+
if isinstance(result, dict):
|
|
110
|
+
names = {}
|
|
111
|
+
for box in result["boxes"]:
|
|
112
|
+
if box["score"] < 0.7:
|
|
113
|
+
continue
|
|
114
|
+
|
|
115
|
+
box["xyxy"] = box["coordinate"]
|
|
116
|
+
box["conf"] = box["score"]
|
|
117
|
+
if box["label"] not in names:
|
|
118
|
+
idx += 1
|
|
119
|
+
names[idx] = box["label"]
|
|
120
|
+
box["cls_id"] = idx
|
|
121
|
+
id_lookup[box["label"]] = idx
|
|
122
|
+
else:
|
|
123
|
+
box["cls_id"] = id_lookup[box["label"]]
|
|
124
|
+
names[box["cls_id"]] = box["label"]
|
|
125
|
+
box["cls"] = box["cls_id"]
|
|
126
|
+
useful_result.append(box)
|
|
127
|
+
if "names" not in result:
|
|
128
|
+
result["names"] = names
|
|
129
|
+
result["boxes"] = useful_result
|
|
130
|
+
result = [result]
|
|
131
|
+
return result
|
|
132
|
+
except Exception as e:
|
|
133
|
+
logger.exception(f"Failed to unpack response: {e!s}")
|
|
134
|
+
raise
|
|
135
|
+
else:
|
|
136
|
+
logger.error(f"Request failed with status {response.status_code}")
|
|
137
|
+
logger.error(f"Response content: {response.content}")
|
|
138
|
+
raise Exception(
|
|
139
|
+
f"Request failed with status {response.status_code}: {response.text}",
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class ResultContainer:
|
|
144
|
+
def __init__(self):
|
|
145
|
+
self.result = YoloResult(boxes_data=np.array([]), names=[])
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class RpcDocLayoutModel(DocLayoutModel):
|
|
149
|
+
"""DocLayoutModel implementation that uses RPC service."""
|
|
150
|
+
|
|
151
|
+
def __init__(self, host: str = "http://localhost:8000"):
|
|
152
|
+
"""Initialize RPC model with host address."""
|
|
153
|
+
self.host = host
|
|
154
|
+
self._stride = 32 # Default stride value
|
|
155
|
+
self._names = ["text", "title", "list", "table", "figure"]
|
|
156
|
+
self.lock = threading.Lock()
|
|
157
|
+
|
|
158
|
+
@property
|
|
159
|
+
def stride(self) -> int:
|
|
160
|
+
"""Stride of the model input."""
|
|
161
|
+
return self._stride
|
|
162
|
+
|
|
163
|
+
def resize_and_pad_image(self, image, new_shape):
|
|
164
|
+
"""
|
|
165
|
+
Resize and pad the image to the specified size,
|
|
166
|
+
ensuring dimensions are multiples of stride.
|
|
167
|
+
|
|
168
|
+
Parameters:
|
|
169
|
+
- image: Input image
|
|
170
|
+
- new_shape: Target size (integer or (height, width) tuple)
|
|
171
|
+
- stride: Padding alignment stride, default 32
|
|
172
|
+
|
|
173
|
+
Returns:
|
|
174
|
+
- Processed image
|
|
175
|
+
"""
|
|
176
|
+
if isinstance(new_shape, int):
|
|
177
|
+
new_shape = (new_shape, new_shape)
|
|
178
|
+
|
|
179
|
+
h, w = image.shape[:2]
|
|
180
|
+
new_h, new_w = new_shape
|
|
181
|
+
|
|
182
|
+
# Calculate scaling ratio
|
|
183
|
+
r = min(new_h / h, new_w / w)
|
|
184
|
+
resized_h, resized_w = int(round(h * r)), int(round(w * r))
|
|
185
|
+
|
|
186
|
+
# Resize image
|
|
187
|
+
image = cv2.resize(
|
|
188
|
+
image, (resized_w, resized_h), interpolation=cv2.INTER_LINEAR
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
# Calculate padding size
|
|
192
|
+
pad_h = new_h - resized_h
|
|
193
|
+
pad_w = new_w - resized_w
|
|
194
|
+
top, bottom = pad_h // 2, pad_h - pad_h // 2
|
|
195
|
+
left, right = pad_w // 2, pad_w - pad_w // 2
|
|
196
|
+
|
|
197
|
+
# Add padding
|
|
198
|
+
image = cv2.copyMakeBorder(
|
|
199
|
+
image, top, bottom, left, right, cv2.BORDER_CONSTANT, value=(114, 114, 114)
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
return image
|
|
203
|
+
|
|
204
|
+
def scale_boxes(self, img1_shape, boxes, img0_shape):
|
|
205
|
+
"""
|
|
206
|
+
Rescales bounding boxes (in the format of xyxy by default) from the shape of the image they were originally
|
|
207
|
+
specified in (img1_shape) to the shape of a different image (img0_shape).
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
img1_shape (tuple): The shape of the image that the bounding boxes are for,
|
|
211
|
+
in the format of (height, width).
|
|
212
|
+
boxes (torch.Tensor): the bounding boxes of the objects in the image, in the format of (x1, y1, x2, y2)
|
|
213
|
+
img0_shape (tuple): the shape of the target image, in the format of (height, width).
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
boxes (torch.Tensor): The scaled bounding boxes, in the format of (x1, y1, x2, y2)
|
|
217
|
+
"""
|
|
218
|
+
|
|
219
|
+
# Calculate scaling ratio
|
|
220
|
+
gain = min(img1_shape[0] / img0_shape[0], img1_shape[1] / img0_shape[1])
|
|
221
|
+
|
|
222
|
+
# Calculate padding size
|
|
223
|
+
pad_x = round((img1_shape[1] - img0_shape[1] * gain) / 2 - 0.1)
|
|
224
|
+
pad_y = round((img1_shape[0] - img0_shape[0] * gain) / 2 - 0.1)
|
|
225
|
+
|
|
226
|
+
# Remove padding and scale boxes
|
|
227
|
+
boxes = (boxes - [pad_x, pad_y, pad_x, pad_y]) / gain
|
|
228
|
+
return boxes
|
|
229
|
+
|
|
230
|
+
def predict_image(
|
|
231
|
+
self,
|
|
232
|
+
image,
|
|
233
|
+
host: str | None = None,
|
|
234
|
+
result_container: ResultContainer | None = None,
|
|
235
|
+
imgsz: int = 1024,
|
|
236
|
+
) -> ResultContainer:
|
|
237
|
+
"""Predict the layout of document pages using RPC service."""
|
|
238
|
+
if result_container is None:
|
|
239
|
+
result_container = ResultContainer()
|
|
240
|
+
target_imgsz = (800, 800)
|
|
241
|
+
orig_h, orig_w = image.shape[:2]
|
|
242
|
+
target_imgsz = (orig_h, orig_w)
|
|
243
|
+
if image.shape[0] != target_imgsz[0] or image.shape[1] != target_imgsz[1]:
|
|
244
|
+
image = self.resize_and_pad_image(image, new_shape=target_imgsz)
|
|
245
|
+
preds = predict_layout(image, host=self.host)
|
|
246
|
+
orig_h, orig_w = orig_h / DPI * 72, orig_w / DPI * 72
|
|
247
|
+
if len(preds) > 0:
|
|
248
|
+
for pred in preds:
|
|
249
|
+
boxes = [
|
|
250
|
+
YoloBox(
|
|
251
|
+
None,
|
|
252
|
+
self.scale_boxes(
|
|
253
|
+
target_imgsz, np.array(x["xyxy"]), (orig_h, orig_w)
|
|
254
|
+
),
|
|
255
|
+
np.array(x["conf"]),
|
|
256
|
+
x["cls"],
|
|
257
|
+
)
|
|
258
|
+
for x in pred["boxes"]
|
|
259
|
+
]
|
|
260
|
+
result_container.result = YoloResult(
|
|
261
|
+
boxes=boxes,
|
|
262
|
+
names={int(k): v for k, v in pred["names"].items()},
|
|
263
|
+
)
|
|
264
|
+
return result_container.result
|
|
265
|
+
|
|
266
|
+
def predict(self, image, imgsz=1024, **kwargs) -> list[YoloResult]:
|
|
267
|
+
"""Predict the layout of document pages using RPC service."""
|
|
268
|
+
# Handle single image input
|
|
269
|
+
if isinstance(image, np.ndarray) and len(image.shape) == 3:
|
|
270
|
+
image = [image]
|
|
271
|
+
|
|
272
|
+
result_containers = [ResultContainer() for _ in image]
|
|
273
|
+
predict_thread = ThreadPoolExecutor(max_workers=len(image))
|
|
274
|
+
for img, result_container in zip(image, result_containers, strict=True):
|
|
275
|
+
predict_thread.submit(
|
|
276
|
+
self.predict_image, img, self.host, result_container, 800
|
|
277
|
+
)
|
|
278
|
+
predict_thread.shutdown(wait=True)
|
|
279
|
+
result = [result_container.result for result_container in result_containers]
|
|
280
|
+
return result
|
|
281
|
+
|
|
282
|
+
def predict_page(
|
|
283
|
+
self, page, mupdf_doc: pymupdf.Document, translate_config, save_debug_image
|
|
284
|
+
):
|
|
285
|
+
translate_config.raise_if_cancelled()
|
|
286
|
+
with self.lock:
|
|
287
|
+
# pix = mupdf_doc[page.page_number].get_pixmap(dpi=72)
|
|
288
|
+
pix = get_no_rotation_img(mupdf_doc[page.page_number], dpi=DPI)
|
|
289
|
+
image = np.frombuffer(pix.samples, np.uint8).reshape(
|
|
290
|
+
pix.height,
|
|
291
|
+
pix.width,
|
|
292
|
+
3,
|
|
293
|
+
)[:, :, ::-1]
|
|
294
|
+
predict_result = self.predict_image(image, self.host, None, 800)
|
|
295
|
+
save_debug_image(image, predict_result, page.page_number + 1)
|
|
296
|
+
return page, predict_result
|
|
297
|
+
|
|
298
|
+
def handle_document(
|
|
299
|
+
self,
|
|
300
|
+
pages: list[babeldoc.format.pdf.document_il.il_version_1.Page],
|
|
301
|
+
mupdf_doc: pymupdf.Document,
|
|
302
|
+
translate_config,
|
|
303
|
+
save_debug_image,
|
|
304
|
+
):
|
|
305
|
+
with ThreadPoolExecutor(max_workers=16) as executor:
|
|
306
|
+
yield from executor.map(
|
|
307
|
+
self.predict_page,
|
|
308
|
+
pages,
|
|
309
|
+
(mupdf_doc for _ in range(len(pages))),
|
|
310
|
+
(translate_config for _ in range(len(pages))),
|
|
311
|
+
(save_debug_image for _ in range(len(pages))),
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
@staticmethod
|
|
315
|
+
def from_host(host: str) -> "RpcDocLayoutModel":
|
|
316
|
+
"""Create RpcDocLayoutModel from host address."""
|
|
317
|
+
return RpcDocLayoutModel(host=host)
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
if __name__ == "__main__":
|
|
321
|
+
logging.basicConfig(level=logging.DEBUG)
|
|
322
|
+
# Test the service
|
|
323
|
+
try:
|
|
324
|
+
# Use a default test image if example/1.png doesn't exist
|
|
325
|
+
image_path = "example/1.png"
|
|
326
|
+
if not Path(image_path).exists():
|
|
327
|
+
print(f"Warning: {image_path} not found.")
|
|
328
|
+
print("Please provide the path to a test image:")
|
|
329
|
+
image_path = input("> ")
|
|
330
|
+
|
|
331
|
+
logger.info(f"Processing image: {image_path}")
|
|
332
|
+
result = predict_layout(image_path)
|
|
333
|
+
print("Prediction results:")
|
|
334
|
+
print(result)
|
|
335
|
+
except Exception as e:
|
|
336
|
+
print(f"Error: {e!s}")
|
|
@@ -82,12 +82,12 @@ def predict_layout(
|
|
|
82
82
|
# Send request
|
|
83
83
|
# logger.debug(f"Sending request to {host}/inference")
|
|
84
84
|
response = httpx.post(
|
|
85
|
-
f"{host}/analyze?min_sim=0.7&early_stop=0.99&timeout=
|
|
85
|
+
f"{host}/analyze?min_sim=0.7&early_stop=0.99&timeout=1800",
|
|
86
86
|
files={"file": ("image.jpg", image_data, "image/jpeg")},
|
|
87
87
|
headers={
|
|
88
88
|
"Accept": "application/json",
|
|
89
89
|
},
|
|
90
|
-
timeout=
|
|
90
|
+
timeout=1800,
|
|
91
91
|
follow_redirects=True,
|
|
92
92
|
)
|
|
93
93
|
|
|
@@ -20,6 +20,7 @@ from babeldoc.docvision.base_doclayout import YoloResult
|
|
|
20
20
|
from babeldoc.format.pdf.document_il.utils.mupdf_helper import get_no_rotation_img
|
|
21
21
|
|
|
22
22
|
logger = logging.getLogger(__name__)
|
|
23
|
+
DPI = 150
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
def encode_image(image) -> bytes:
|
|
@@ -50,14 +51,14 @@ def encode_image(image) -> bytes:
|
|
|
50
51
|
), # 指数退避策略,初始 1 秒,最大 10 秒
|
|
51
52
|
retry=retry_if_exception_type((httpx.HTTPError, Exception)), # 针对哪些异常重试
|
|
52
53
|
before_sleep=lambda retry_state: logger.warning(
|
|
53
|
-
f"Request failed, retrying in {retry_state.next_action
|
|
54
|
+
f"Request failed, retrying in {getattr(retry_state.next_action, 'sleep', 'unknown')} seconds... "
|
|
54
55
|
f"(Attempt {retry_state.attempt_number}/3)"
|
|
55
56
|
),
|
|
56
57
|
)
|
|
57
58
|
def predict_layout(
|
|
58
59
|
image,
|
|
59
60
|
host: str = "http://localhost:8000",
|
|
60
|
-
|
|
61
|
+
_imgsz: int = 1024,
|
|
61
62
|
):
|
|
62
63
|
"""
|
|
63
64
|
Predict document layout using the MOSEC service
|
|
@@ -71,12 +72,12 @@ def predict_layout(
|
|
|
71
72
|
List of predictions containing bounding boxes and classes
|
|
72
73
|
"""
|
|
73
74
|
# Prepare request data
|
|
75
|
+
|
|
74
76
|
if not isinstance(image, list):
|
|
75
77
|
image = [image]
|
|
76
78
|
image_data = [encode_image(image) for image in image]
|
|
77
79
|
data = {
|
|
78
80
|
"image": image_data,
|
|
79
|
-
"imgsz": imgsz,
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
# Pack data using msgpack
|
|
@@ -86,31 +87,46 @@ def predict_layout(
|
|
|
86
87
|
# Send request
|
|
87
88
|
# logger.debug(f"Sending request to {host}/inference")
|
|
88
89
|
response = httpx.post(
|
|
90
|
+
# f"{host}/analyze?min_sim=0.7&early_stop=0.99&timeout=480",
|
|
89
91
|
f"{host}/inference",
|
|
90
92
|
data=packed_data,
|
|
91
93
|
headers={
|
|
92
94
|
"Content-Type": "application/msgpack",
|
|
93
95
|
"Accept": "application/msgpack",
|
|
94
96
|
},
|
|
95
|
-
timeout=
|
|
97
|
+
timeout=480,
|
|
96
98
|
follow_redirects=True,
|
|
97
99
|
)
|
|
98
100
|
|
|
99
101
|
# logger.debug(f"Response status: {response.status_code}")
|
|
100
102
|
# logger.debug(f"Response headers: {response.headers}")
|
|
101
|
-
|
|
103
|
+
idx = 0
|
|
104
|
+
id_lookup = {}
|
|
102
105
|
if response.status_code == 200:
|
|
103
106
|
try:
|
|
104
107
|
result = msgpack.unpackb(response.content, raw=False)
|
|
108
|
+
useful_result = []
|
|
105
109
|
if isinstance(result, dict):
|
|
106
110
|
names = {}
|
|
107
111
|
for box in result["boxes"]:
|
|
112
|
+
if box["score"] < 0.7:
|
|
113
|
+
continue
|
|
114
|
+
|
|
108
115
|
box["xyxy"] = box["coordinate"]
|
|
109
116
|
box["conf"] = box["score"]
|
|
110
|
-
box["
|
|
117
|
+
if box["label"] not in names:
|
|
118
|
+
idx += 1
|
|
119
|
+
names[idx] = box["label"]
|
|
120
|
+
box["cls_id"] = idx
|
|
121
|
+
id_lookup[box["label"]] = idx
|
|
122
|
+
else:
|
|
123
|
+
box["cls_id"] = id_lookup[box["label"]]
|
|
111
124
|
names[box["cls_id"]] = box["label"]
|
|
125
|
+
box["cls"] = box["cls_id"]
|
|
126
|
+
useful_result.append(box)
|
|
112
127
|
if "names" not in result:
|
|
113
128
|
result["names"] = names
|
|
129
|
+
result["boxes"] = useful_result
|
|
114
130
|
result = [result]
|
|
115
131
|
return result
|
|
116
132
|
except Exception as e:
|
|
@@ -214,7 +230,7 @@ class RpcDocLayoutModel(DocLayoutModel):
|
|
|
214
230
|
def predict_image(
|
|
215
231
|
self,
|
|
216
232
|
image,
|
|
217
|
-
host: str = None,
|
|
233
|
+
host: str | None = None,
|
|
218
234
|
result_container: ResultContainer | None = None,
|
|
219
235
|
imgsz: int = 1024,
|
|
220
236
|
) -> ResultContainer:
|
|
@@ -226,8 +242,8 @@ class RpcDocLayoutModel(DocLayoutModel):
|
|
|
226
242
|
target_imgsz = (orig_h, orig_w)
|
|
227
243
|
if image.shape[0] != target_imgsz[0] or image.shape[1] != target_imgsz[1]:
|
|
228
244
|
image = self.resize_and_pad_image(image, new_shape=target_imgsz)
|
|
229
|
-
preds = predict_layout(
|
|
230
|
-
|
|
245
|
+
preds = predict_layout(image, host=self.host)
|
|
246
|
+
orig_h, orig_w = orig_h / DPI * 72, orig_w / DPI * 72
|
|
231
247
|
if len(preds) > 0:
|
|
232
248
|
for pred in preds:
|
|
233
249
|
boxes = [
|
|
@@ -269,7 +285,7 @@ class RpcDocLayoutModel(DocLayoutModel):
|
|
|
269
285
|
translate_config.raise_if_cancelled()
|
|
270
286
|
with self.lock:
|
|
271
287
|
# pix = mupdf_doc[page.page_number].get_pixmap(dpi=72)
|
|
272
|
-
pix = get_no_rotation_img(mupdf_doc[page.page_number])
|
|
288
|
+
pix = get_no_rotation_img(mupdf_doc[page.page_number], dpi=DPI)
|
|
273
289
|
image = np.frombuffer(pix.samples, np.uint8).reshape(
|
|
274
290
|
pix.height,
|
|
275
291
|
pix.width,
|
|
@@ -286,7 +302,7 @@ class RpcDocLayoutModel(DocLayoutModel):
|
|
|
286
302
|
translate_config,
|
|
287
303
|
save_debug_image,
|
|
288
304
|
):
|
|
289
|
-
with ThreadPoolExecutor(max_workers=
|
|
305
|
+
with ThreadPoolExecutor(max_workers=1) as executor:
|
|
290
306
|
yield from executor.map(
|
|
291
307
|
self.predict_page,
|
|
292
308
|
pages,
|