yomitoku 0.9.1__tar.gz → 0.9.2__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.
- {yomitoku-0.9.1 → yomitoku-0.9.2}/PKG-INFO +5 -2
- {yomitoku-0.9.1 → yomitoku-0.9.2}/README.md +2 -1
- {yomitoku-0.9.1 → yomitoku-0.9.2}/README_EN.md +1 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/docs/cli.en.md +9 -1
- {yomitoku-0.9.1 → yomitoku-0.9.2}/docs/cli.ja.md +6 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/docs/index.en.md +1 -1
- {yomitoku-0.9.1 → yomitoku-0.9.2}/docs/index.ja.md +1 -1
- {yomitoku-0.9.1 → yomitoku-0.9.2}/docs/mcp.en.md +16 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/docs/mcp.ja.md +14 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/pyproject.toml +3 -1
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/cli/main.py +22 -5
- yomitoku-0.9.1/src/yomitoku/cli/mcp.py → yomitoku-0.9.2/src/yomitoku/cli/mcp_server.py +37 -6
- yomitoku-0.9.2/src/yomitoku/utils/searchable_pdf.py +116 -0
- yomitoku-0.9.2/uv.lock +1898 -0
- yomitoku-0.9.1/uv.lock +0 -1815
- {yomitoku-0.9.1 → yomitoku-0.9.2}/.github/FUNDING.yml +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/.github/release-drafter.yml +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/.github/workflows/build-and-publish-docs.yaml +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/.github/workflows/build-and-publish.yml +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/.github/workflows/create-release.yml +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/.github/workflows/lint-and-test.yml +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/.gitignore +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/.pre-commit-config.yaml +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/.python-version +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/configs/yomitoku-layout-parser-rtdtrv2-open-beta.yaml +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/configs/yomitoku-table-structure-recognizer-rtdtrv2-open-beta.yaml +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/configs/yomitoku-text-detector-dbnet-open-beta.yaml +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/configs/yomitoku-text-recognizer-parseq-open-beta.yaml +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/configs/yomitoku-text-recognizer-parseq-small-open-beta.yaml +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/demo/sample.pdf +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/demo/setting_document_anaysis.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/demo/simple_document_analysis.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/demo/simple_layout.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/demo/simple_ocr.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/demo/text_detector.yaml +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/dockerfile +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/docs/assets/logo.svg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/docs/configuration.en.md +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/docs/configuration.ja.md +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/docs/installation.en.md +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/docs/installation.ja.md +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/docs/module.en.md +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/docs/module.ja.md +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/gallery.md +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/mkdocs.yml +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/pytest.ini +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/scripts/register_hugging_face_hub.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/__init__.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/base.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/cli/__init__.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/configs/__init__.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/configs/cfg_layout_parser_rtdtrv2.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/configs/cfg_layout_parser_rtdtrv2_v2.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/configs/cfg_table_structure_recognizer_rtdtrv2.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/configs/cfg_text_detector_dbnet.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/configs/cfg_text_detector_dbnet_v2.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/configs/cfg_text_recognizer_parseq.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/configs/cfg_text_recognizer_parseq_small.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/configs/cfg_text_recognizer_parseq_v2.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/constants.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/data/__init__.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/data/dataset.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/data/functions.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/document_analyzer.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/export/__init__.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/export/export_csv.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/export/export_html.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/export/export_json.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/export/export_markdown.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/layout_analyzer.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/layout_parser.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/models/__init__.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/models/dbnet_plus.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/models/layers/__init__.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/models/layers/activate.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/models/layers/dbnet_feature_attention.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/models/layers/parseq_transformer.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/models/layers/rtdetr_backbone.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/models/layers/rtdetr_hybrid_encoder.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/models/layers/rtdetrv2_decoder.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/models/parseq.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/models/rtdetr.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/ocr.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/onnx/.gitkeep +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/postprocessor/__init__.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/postprocessor/dbnet_postporcessor.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/postprocessor/parseq_tokenizer.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/postprocessor/rtdetr_postprocessor.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/reading_order.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/resource/MPLUS1p-Medium.ttf +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/resource/charset.txt +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/table_structure_recognizer.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/text_detector.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/text_recognizer.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/utils/__init__.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/utils/graph.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/utils/logger.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/utils/misc.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/src/yomitoku/utils/visualizer.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/in/demo.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/in/gallery1.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/in/gallery2.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/in/gallery3.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/in/gallery4.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/in/gallery5.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/in/gallery6.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/in/gallery7.jpeg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/logo/horizontal.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/demo_html.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/figures/in_demo_p1_figure_0.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/figures/in_gallery1_p1_figure_0.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/figures/in_gallery1_p1_figure_1.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/figures/in_gallery1_p1_figure_10.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/figures/in_gallery1_p1_figure_2.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/figures/in_gallery1_p1_figure_3.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/figures/in_gallery1_p1_figure_4.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/figures/in_gallery1_p1_figure_5.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/figures/in_gallery1_p1_figure_6.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/figures/in_gallery1_p1_figure_7.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/figures/in_gallery1_p1_figure_8.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/figures/in_gallery1_p1_figure_9.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/figures/in_gallery3_p1_figure_0.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/figures/in_gallery3_p1_figure_1.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/figures/in_gallery5_p1_figure_0.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/figures/in_gallery5_p1_figure_1.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/figures/in_gallery6_p1_figure_0.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/figures/in_gallery6_p1_figure_1.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/figures/in_gallery7_p1_figure_0.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_demo_p1.html +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_demo_p1.md +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_demo_p1_layout.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_demo_p1_ocr.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery1_p1.html +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery1_p1.md +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery1_p1_layout.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery1_p1_ocr.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery2_p1.html +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery2_p1.md +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery2_p1_layout.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery2_p1_ocr.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery3_p1.html +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery3_p1.md +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery3_p1_layout.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery3_p1_ocr.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery4_p1.html +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery4_p1.md +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery4_p1_layout.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery4_p1_ocr.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery5_p1.html +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery5_p1.md +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery5_p1_layout.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery5_p1_ocr.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery6_p1.html +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery6_p1.md +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery6_p1_layout.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery6_p1_ocr.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery7_p1.html +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery7_p1.md +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery7_p1_layout.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/static/out/in_gallery7_p1_ocr.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/data/invalid.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/data/invalid.pdf +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/data/rgba.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/data/sampldoc.tif +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/data/small.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/data/subdir/test.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/data/test.bmp +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/data/test.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/data/test.pdf +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/data/test.png +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/data/test.tiff +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/data/test.txt +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/data/test_gray.jpg +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/test_base.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/test_cli.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/test_data.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/test_document_analyzer.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/test_export.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/test_layout_analyzer.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/test_ocr.py +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/yaml/layout_parser.yaml +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/yaml/table_structure_recognizer.yaml +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/yaml/text_detector.yaml +0 -0
- {yomitoku-0.9.1 → yomitoku-0.9.2}/tests/yaml/text_recognizer.yaml +0 -0
@@ -1,12 +1,13 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: yomitoku
|
3
|
-
Version: 0.9.
|
3
|
+
Version: 0.9.2
|
4
4
|
Summary: Yomitoku is an AI-powered document image analysis package designed specifically for the Japanese language.
|
5
5
|
Author-email: Kotaro Kinoshita <kotaro.kinoshita@mlism.com>
|
6
6
|
License: CC BY-NC-SA 4.0
|
7
7
|
Keywords: Deep Learning,Japanese,OCR
|
8
8
|
Requires-Python: <3.13,>=3.10
|
9
9
|
Requires-Dist: huggingface-hub>=0.26.1
|
10
|
+
Requires-Dist: jaconv>=0.4.0
|
10
11
|
Requires-Dist: lxml>=5.3.0
|
11
12
|
Requires-Dist: omegaconf>=2.3.0
|
12
13
|
Requires-Dist: onnx>=1.17.0
|
@@ -15,6 +16,7 @@ Requires-Dist: opencv-python>=4.10.0.84
|
|
15
16
|
Requires-Dist: pyclipper>=1.3.0.post6
|
16
17
|
Requires-Dist: pydantic>=2.9.2
|
17
18
|
Requires-Dist: pypdfium2>=4.30.0
|
19
|
+
Requires-Dist: reportlab>=4.4.1
|
18
20
|
Requires-Dist: shapely>=2.0.6
|
19
21
|
Requires-Dist: timm>=1.0.11
|
20
22
|
Requires-Dist: torch>=2.5.0
|
@@ -41,7 +43,7 @@ YomiToku は日本語に特化した AI 文章画像解析エンジン(Document
|
|
41
43
|
- 🤖 日本語データセットで学習した 4 種類(文字位置の検知、文字列認識、レイアウト解析、表の構造認識)の AI モデルを搭載しています。4 種類のモデルはすべて独自に学習されたモデルで日本語文書に対して、高精度に推論可能です。
|
42
44
|
- 🇯🇵 各モデルは日本語の文書画像に特化して学習されており、7000 文字を超える日本語文字の認識をサーポート、手書き文字、縦書きなど日本語特有のレイアウト構造の文書画像の解析も可能です。(日本語以外にも英語の文書に対しても対応しています)。
|
43
45
|
- 📈 レイアウト解析、表の構造解析, 読み順推定機能により、文書画像のレイアウトの意味的構造を壊さずに情報を抽出することが可能です。
|
44
|
-
- 📄 多様な出力形式をサポートしています。html やマークダウン、json、csv
|
46
|
+
- 📄 多様な出力形式をサポートしています。html やマークダウン、json、csv のいずれかのフォーマットに変換可能です。また、文書内に含まれる図表、画像の抽出の出力も可能です。文書画像をサーチャブルPDFに変換する処理もサポートしています。
|
45
47
|
- ⚡ GPU 環境で高速に動作し、効率的に文書の文字起こし解析が可能です。また、VRAM も 8GB 以内で動作し、ハイエンドな GPU を用意する必要はありません。
|
46
48
|
|
47
49
|
## 🖼️ デモ
|
@@ -96,6 +98,7 @@ yomitoku ${path_data} -f md -o results -v --figure --lite
|
|
96
98
|
- `--encoding` エクスポートする出力ファイルの文字エンコーディングを指定します。サポートされていない文字コードが含まれる場合は、その文字を無視します。(utf-8, utf-8-sig, shift-jis, enc-jp, cp932)
|
97
99
|
- `--combine` PDFを入力に与えたときに、複数ページが含まれる場合に、それらの予測結果を一つのファイルに統合してエクスポートします。
|
98
100
|
- `--ignore_meta` 文章のheater, fotterなどの文字情報を出力ファイルに含めません。
|
101
|
+
- `--searchable_pdf` 読み取った文字情報をPDFに埋め込み全文検索可能なPDFを出力します。
|
99
102
|
|
100
103
|
その他のオプションに関しては、ヘルプを参照
|
101
104
|
|
@@ -16,7 +16,7 @@ YomiToku は日本語に特化した AI 文章画像解析エンジン(Document
|
|
16
16
|
- 🤖 日本語データセットで学習した 4 種類(文字位置の検知、文字列認識、レイアウト解析、表の構造認識)の AI モデルを搭載しています。4 種類のモデルはすべて独自に学習されたモデルで日本語文書に対して、高精度に推論可能です。
|
17
17
|
- 🇯🇵 各モデルは日本語の文書画像に特化して学習されており、7000 文字を超える日本語文字の認識をサーポート、手書き文字、縦書きなど日本語特有のレイアウト構造の文書画像の解析も可能です。(日本語以外にも英語の文書に対しても対応しています)。
|
18
18
|
- 📈 レイアウト解析、表の構造解析, 読み順推定機能により、文書画像のレイアウトの意味的構造を壊さずに情報を抽出することが可能です。
|
19
|
-
- 📄 多様な出力形式をサポートしています。html やマークダウン、json、csv
|
19
|
+
- 📄 多様な出力形式をサポートしています。html やマークダウン、json、csv のいずれかのフォーマットに変換可能です。また、文書内に含まれる図表、画像の抽出の出力も可能です。文書画像をサーチャブルPDFに変換する処理もサポートしています。
|
20
20
|
- ⚡ GPU 環境で高速に動作し、効率的に文書の文字起こし解析が可能です。また、VRAM も 8GB 以内で動作し、ハイエンドな GPU を用意する必要はありません。
|
21
21
|
|
22
22
|
## 🖼️ デモ
|
@@ -71,6 +71,7 @@ yomitoku ${path_data} -f md -o results -v --figure --lite
|
|
71
71
|
- `--encoding` エクスポートする出力ファイルの文字エンコーディングを指定します。サポートされていない文字コードが含まれる場合は、その文字を無視します。(utf-8, utf-8-sig, shift-jis, enc-jp, cp932)
|
72
72
|
- `--combine` PDFを入力に与えたときに、複数ページが含まれる場合に、それらの予測結果を一つのファイルに統合してエクスポートします。
|
73
73
|
- `--ignore_meta` 文章のheater, fotterなどの文字情報を出力ファイルに含めません。
|
74
|
+
- `--searchable_pdf` 読み取った文字情報をPDFに埋め込み全文検索可能なPDFを出力します。
|
74
75
|
|
75
76
|
その他のオプションに関しては、ヘルプを参照
|
76
77
|
|
@@ -70,6 +70,7 @@ yomitoku ${path_data} -f md -o results -v --figure --lite
|
|
70
70
|
- `--encoding` Specifies the character encoding for the output file to be exported. If unsupported characters are included, they will be ignored. (utf-8, utf-8-sig, shift-jis, enc-jp, cp932)
|
71
71
|
- `--combine` When a PDF is provided as input and contains multiple pages, this option combines their prediction results into a single file for export.
|
72
72
|
- `--ignore_meta` Excludes text information such as headers and footers from the output file.
|
73
|
+
- `--searchable_pdf` Embeds the recognized text into the PDF and outputs a fully searchable PDF.
|
73
74
|
|
74
75
|
For other options, please refer to the help documentation.
|
75
76
|
|
@@ -121,4 +121,12 @@ yomitoku ${path_data} --reading_order left2right
|
|
121
121
|
|
122
122
|
* `left2right`: Prioritizes reading from left to right. Suitable for layouts like receipts or health insurance cards, where key-value text pairs are arranged in columns.
|
123
123
|
|
124
|
-
* `right2left`: Prioritizes reading from right to left. Effective for vertically written documents.
|
124
|
+
* `right2left`: Prioritizes reading from right to left. Effective for vertically written documents.
|
125
|
+
|
126
|
+
## Create a searchable PDF
|
127
|
+
|
128
|
+
Detect the text in the image and embed it into the PDF as invisible text, converting the file into a searchable PDF.
|
129
|
+
|
130
|
+
```
|
131
|
+
yomitoku ${path_data} --searchable_pdf
|
132
|
+
```
|
@@ -119,3 +119,9 @@ yomitoku ${path_data} --reading_order left2right
|
|
119
119
|
|
120
120
|
- `right2left:` 右から左方向に優先的に読み取り順を推定します。縦書きのドキュメントに対して有効です。
|
121
121
|
|
122
|
+
## 検索可能なPDFを作成する
|
123
|
+
画像内の文字情報を認識し、文字情報を透明テキストとして、PDFに埋め込むことで、サーチャブルPDFに変換します。
|
124
|
+
|
125
|
+
```
|
126
|
+
yomitoku ${path_data} --searchable_pdf
|
127
|
+
```
|
@@ -5,7 +5,7 @@ YomiToku is a Document AI engine specialized in Japanese document image analysis
|
|
5
5
|
- 🤖 Equipped with four AI models trained on Japanese datasets: text detection, text recognition, layout analysis, and table structure recognition. All models are independently trained and optimized for Japanese documents, delivering high-precision inference.
|
6
6
|
- 🇯🇵 Each model is specifically trained for Japanese document images, supporting the recognition of over 7,000 Japanese characters, including vertical text and other layout structures unique to Japanese documents. (It also supports English documents.)
|
7
7
|
- 📈 By leveraging layout analysis, table structure parsing, and reading order estimation, it extracts information while preserving the semantic structure of the document layout.
|
8
|
-
- 📄 Supports a variety of output formats, including HTML, Markdown, JSON, and CSV. It also allows for the extraction of diagrams and images contained within the documents.
|
8
|
+
- 📄 Supports a variety of output formats, including HTML, Markdown, JSON, and CSV. It also allows for the extraction of diagrams and images contained within the documents.It also supports converting document images into fully text-searchable PDFs.
|
9
9
|
- ⚡ Operates efficiently in GPU environments, enabling fast document transcription and analysis. It requires less than 8GB of VRAM, eliminating the need for high-end GPUs.。
|
10
10
|
|
11
11
|
## 🙋 FAQ
|
@@ -5,7 +5,7 @@ YomiToku は日本語に特化した AI 文章画像解析エンジン(Document
|
|
5
5
|
- 🤖 日本語データセットで学習した 4 種類(文字位置の検知、文字列認識、レイアウト解析、表の構造認識)の AI モデルを搭載しています。4 種類のモデルはすべて独自に学習されたモデルで日本語文書に対して、高精度に推論可能です。
|
6
6
|
- 🇯🇵 各モデルは日本語の文書画像に特化して学習されており、7000 文字を超える日本語文字の認識をサーポート、手書き文字、縦書きなど日本語特有のレイアウト構造の文書画像の解析も可能です。(日本語以外にも英語の文書に対しても対応しています)。
|
7
7
|
- 📈 レイアウト解析、表の構造解析, 読み順推定機能により、文書画像のレイアウトの意味的構造を壊さずに情報を抽出することが可能です。
|
8
|
-
- 📄 多様な出力形式をサポートしています。html やマークダウン、json、csv
|
8
|
+
- 📄 多様な出力形式をサポートしています。html やマークダウン、json、csv のいずれかのフォーマットに変換可能です。また、文書内に含まれる図表、画像の抽出の出力も可能です。文書画像を全文検索可能なサーチャブルPDFに変換する処理もサポートしています。
|
9
9
|
- ⚡ GPU 環境で高速に動作し、効率的に文書の文字起こし解析が可能です。また、VRAM も 8GB 以内で動作し、ハイエンドな GPU を用意する必要はありません。
|
10
10
|
|
11
11
|
## 🙋 FAQ
|
@@ -46,3 +46,19 @@ For example, if you use `yomitoku/demo/sample.pdf` as a sample, instruct as foll
|
|
46
46
|
```txt
|
47
47
|
Analyze sample.pdf using OCR and translate it into English.
|
48
48
|
```
|
49
|
+
|
50
|
+
## Starting the SSE Server
|
51
|
+
|
52
|
+
Set the path to the folder containing the images to be processed by OCR in the resource directory.
|
53
|
+
|
54
|
+
```
|
55
|
+
export RESOURCE_DIR="path of dataset"
|
56
|
+
```
|
57
|
+
|
58
|
+
Start the SSE server using the following command:
|
59
|
+
|
60
|
+
```
|
61
|
+
uv run yomitoku_mcp -t sse
|
62
|
+
```
|
63
|
+
|
64
|
+
The SSE server endpoint will be available at `http://127.0.0.1:8000/sse`.
|
@@ -13,6 +13,7 @@
|
|
13
13
|
uv sync --extra mcp
|
14
14
|
```
|
15
15
|
|
16
|
+
|
16
17
|
## Claude Desktopの設定
|
17
18
|
|
18
19
|
次にClaude Desktopの設定ファイルの`mcpServers`に以下ように設定を追加します。(設定ファイルの開き方は[こちら](https://modelcontextprotocol.io/quickstart/user)を参照してください)
|
@@ -48,3 +49,16 @@ uv sync --extra mcp
|
|
48
49
|
```txt
|
49
50
|
sample.pdfをOCRで解析して要約してください。
|
50
51
|
```
|
52
|
+
|
53
|
+
## SSEサーバーの起動
|
54
|
+
環境変数の`RESOURCE_DIR`にOCRの対象画像が含まれたフォルダのパスを設定してください。
|
55
|
+
```
|
56
|
+
export RESOURCE_DIR="path of dataset"
|
57
|
+
```
|
58
|
+
|
59
|
+
以下のコマンドでSSEサーバーを起動します。
|
60
|
+
```
|
61
|
+
uv run yomitoku_mcp -t sse
|
62
|
+
```
|
63
|
+
|
64
|
+
` http://127.0.0.1:8000/sse`がSSEサーバーのエンドポイントになります。
|
@@ -30,6 +30,8 @@ dependencies = [
|
|
30
30
|
"torch>=2.5.0",
|
31
31
|
"torchvision>=0.20.0",
|
32
32
|
"onnxruntime>=1.20.1",
|
33
|
+
"reportlab>=4.4.1",
|
34
|
+
"jaconv>=0.4.0",
|
33
35
|
]
|
34
36
|
|
35
37
|
[tool.uv-dynamic-versioning]
|
@@ -70,7 +72,7 @@ explicit = true
|
|
70
72
|
|
71
73
|
[project.scripts]
|
72
74
|
yomitoku = "yomitoku.cli.main:main"
|
73
|
-
yomitoku_mcp = "yomitoku.cli.
|
75
|
+
yomitoku_mcp = "yomitoku.cli.mcp_server:main"
|
74
76
|
|
75
77
|
[project.optional-dependencies]
|
76
78
|
mcp = [
|
@@ -9,6 +9,7 @@ from ..constants import SUPPORT_OUTPUT_FORMAT
|
|
9
9
|
from ..data.functions import load_image, load_pdf
|
10
10
|
from ..document_analyzer import DocumentAnalyzer
|
11
11
|
from ..utils.logger import set_logger
|
12
|
+
from ..utils.searchable_pdf import create_searchable_pdf
|
12
13
|
|
13
14
|
from ..export import save_csv, save_html, save_json, save_markdown
|
14
15
|
from ..export import convert_json, convert_csv, convert_html, convert_markdown
|
@@ -80,11 +81,13 @@ def process_single_file(args, analyzer, path, format):
|
|
80
81
|
else:
|
81
82
|
imgs = load_image(path)
|
82
83
|
|
84
|
+
format_results = []
|
83
85
|
results = []
|
84
86
|
for page, img in enumerate(imgs):
|
85
87
|
result, ocr, layout = analyzer(img)
|
86
88
|
dirname = path.parent.name
|
87
89
|
filename = path.stem
|
90
|
+
results.append(result)
|
88
91
|
|
89
92
|
# cv2.imwrite(
|
90
93
|
# os.path.join(args.outdir, f"{dirname}_{filename}_p{page+1}.jpg"), img
|
@@ -130,7 +133,7 @@ def process_single_file(args, analyzer, path, format):
|
|
130
133
|
figure_dir=args.figure_dir,
|
131
134
|
)
|
132
135
|
|
133
|
-
|
136
|
+
format_results.append(
|
134
137
|
{
|
135
138
|
"format": format,
|
136
139
|
"data": json.model_dump(),
|
@@ -157,7 +160,7 @@ def process_single_file(args, analyzer, path, format):
|
|
157
160
|
figure_dir=args.figure_dir,
|
158
161
|
)
|
159
162
|
|
160
|
-
|
163
|
+
format_results.append(
|
161
164
|
{
|
162
165
|
"format": format,
|
163
166
|
"data": csv,
|
@@ -188,7 +191,7 @@ def process_single_file(args, analyzer, path, format):
|
|
188
191
|
encoding=args.encoding,
|
189
192
|
)
|
190
193
|
|
191
|
-
|
194
|
+
format_results.append(
|
192
195
|
{
|
193
196
|
"format": format,
|
194
197
|
"data": html,
|
@@ -219,14 +222,14 @@ def process_single_file(args, analyzer, path, format):
|
|
219
222
|
encoding=args.encoding,
|
220
223
|
)
|
221
224
|
|
222
|
-
|
225
|
+
format_results.append(
|
223
226
|
{
|
224
227
|
"format": format,
|
225
228
|
"data": md,
|
226
229
|
}
|
227
230
|
)
|
228
231
|
|
229
|
-
out = merge_all_pages(
|
232
|
+
out = merge_all_pages(format_results)
|
230
233
|
if args.combine:
|
231
234
|
out_path = os.path.join(args.outdir, f"{dirname}_{filename}.{format}")
|
232
235
|
save_merged_file(
|
@@ -235,6 +238,15 @@ def process_single_file(args, analyzer, path, format):
|
|
235
238
|
out,
|
236
239
|
)
|
237
240
|
|
241
|
+
if args.searchable_pdf:
|
242
|
+
pdf_path = os.path.join(args.outdir, f"{filename}.pdf")
|
243
|
+
create_searchable_pdf(
|
244
|
+
imgs,
|
245
|
+
results,
|
246
|
+
output_path=pdf_path,
|
247
|
+
)
|
248
|
+
logger.info(f"Output SearchablePDF: {pdf_path}")
|
249
|
+
|
238
250
|
|
239
251
|
def main():
|
240
252
|
parser = argparse.ArgumentParser()
|
@@ -349,6 +361,11 @@ def main():
|
|
349
361
|
type=str,
|
350
362
|
choices=["auto", "left2right", "top2bottom", "right2left"],
|
351
363
|
)
|
364
|
+
parser.add_argument(
|
365
|
+
"--searchable_pdf",
|
366
|
+
action="store_true",
|
367
|
+
help="if set, create searchable PDF",
|
368
|
+
)
|
352
369
|
|
353
370
|
args = parser.parse_args()
|
354
371
|
|
@@ -1,14 +1,20 @@
|
|
1
|
-
import json
|
2
|
-
import io
|
3
1
|
import csv
|
2
|
+
import io
|
3
|
+
import json
|
4
4
|
import os
|
5
|
+
from argparse import ArgumentParser
|
5
6
|
from pathlib import Path
|
6
7
|
|
7
8
|
from mcp.server.fastmcp import Context, FastMCP
|
8
9
|
|
9
10
|
from yomitoku import DocumentAnalyzer
|
10
11
|
from yomitoku.data.functions import load_image, load_pdf
|
11
|
-
from yomitoku.export import
|
12
|
+
from yomitoku.export import (
|
13
|
+
convert_csv,
|
14
|
+
convert_html,
|
15
|
+
convert_json,
|
16
|
+
convert_markdown,
|
17
|
+
)
|
12
18
|
|
13
19
|
try:
|
14
20
|
RESOURCE_DIR = os.environ["RESOURCE_DIR"]
|
@@ -154,12 +160,37 @@ async def get_file_list() -> list[str]:
|
|
154
160
|
return os.listdir(RESOURCE_DIR)
|
155
161
|
|
156
162
|
|
157
|
-
def run_mcp_server():
|
163
|
+
def run_mcp_server(transport="stdio", mount_path=None):
|
158
164
|
"""
|
159
165
|
Run the MCP server.
|
160
166
|
"""
|
161
|
-
|
167
|
+
|
168
|
+
if transport == "stdio":
|
169
|
+
mcp.run()
|
170
|
+
elif transport == "sse":
|
171
|
+
mcp.run(transport=transport, mount_path=mount_path)
|
172
|
+
|
173
|
+
|
174
|
+
def main():
|
175
|
+
parser = ArgumentParser(description="Run the MCP server.")
|
176
|
+
parser.add_argument(
|
177
|
+
"--transport",
|
178
|
+
"-t",
|
179
|
+
type=str,
|
180
|
+
default="stdio",
|
181
|
+
choices=["stdio", "sse"],
|
182
|
+
help="Transport method for the MCP server.",
|
183
|
+
)
|
184
|
+
parser.add_argument(
|
185
|
+
"--mount_path",
|
186
|
+
"-m",
|
187
|
+
type=str,
|
188
|
+
default=None,
|
189
|
+
help="Mount path for the MCP server (only used with SSE transport).",
|
190
|
+
)
|
191
|
+
args = parser.parse_args()
|
192
|
+
run_mcp_server(transport=args.transport, mount_path=args.mount_path)
|
162
193
|
|
163
194
|
|
164
195
|
if __name__ == "__main__":
|
165
|
-
|
196
|
+
main()
|
@@ -0,0 +1,116 @@
|
|
1
|
+
import os
|
2
|
+
|
3
|
+
from PIL import Image
|
4
|
+
from io import BytesIO
|
5
|
+
|
6
|
+
from reportlab.pdfgen import canvas
|
7
|
+
from reportlab.pdfbase.ttfonts import TTFont
|
8
|
+
from reportlab.pdfbase import pdfmetrics
|
9
|
+
from reportlab.pdfbase.pdfmetrics import stringWidth
|
10
|
+
|
11
|
+
import numpy as np
|
12
|
+
import jaconv
|
13
|
+
|
14
|
+
from ..constants import ROOT_DIR
|
15
|
+
|
16
|
+
FONT_PATH = ROOT_DIR + "/resource/MPLUS1p-Medium.ttf"
|
17
|
+
pdfmetrics.registerFont(TTFont("MPLUS1p-Medium", FONT_PATH))
|
18
|
+
|
19
|
+
|
20
|
+
def _poly2rect(points):
|
21
|
+
"""
|
22
|
+
Convert a polygon defined by its corner points to a rectangle.
|
23
|
+
The points should be in the format [[x1, y1], [x2, y2], [x3, y3], [x4, y4]].
|
24
|
+
"""
|
25
|
+
points = np.array(points, dtype=int)
|
26
|
+
x_min = points[:, 0].min()
|
27
|
+
x_max = points[:, 0].max()
|
28
|
+
y_min = points[:, 1].min()
|
29
|
+
y_max = points[:, 1].max()
|
30
|
+
|
31
|
+
return [x_min, y_min, x_max, y_max]
|
32
|
+
|
33
|
+
|
34
|
+
def _calc_font_size(content, bbox_height, bbox_width):
|
35
|
+
rates = np.arange(0.5, 1.0, 0.01)
|
36
|
+
|
37
|
+
min_diff = np.inf
|
38
|
+
best_font_size = None
|
39
|
+
for rate in rates:
|
40
|
+
font_size = bbox_height * rate
|
41
|
+
text_w = stringWidth(content, "MPLUS1p-Medium", font_size)
|
42
|
+
diff = abs(text_w - bbox_width)
|
43
|
+
if diff < min_diff:
|
44
|
+
min_diff = diff
|
45
|
+
best_font_size = font_size
|
46
|
+
|
47
|
+
return best_font_size
|
48
|
+
|
49
|
+
|
50
|
+
def to_full_width(text):
|
51
|
+
fw_map = {
|
52
|
+
"\u00a5": "\uffe5", # ¥ → ¥
|
53
|
+
"\u00b7": "\u30fb", # · → ・
|
54
|
+
" ": "\u3000", # 半角スペース→全角スペース
|
55
|
+
}
|
56
|
+
|
57
|
+
TO_FULLWIDTH = str.maketrans(fw_map)
|
58
|
+
|
59
|
+
jaconv_text = jaconv.h2z(text, kana=True, ascii=True, digit=True)
|
60
|
+
jaconv_text = jaconv_text.translate(TO_FULLWIDTH)
|
61
|
+
|
62
|
+
return jaconv_text
|
63
|
+
|
64
|
+
|
65
|
+
def create_searchable_pdf(images, ocr_results, output_path):
|
66
|
+
packet = BytesIO()
|
67
|
+
c = canvas.Canvas(packet)
|
68
|
+
|
69
|
+
for i, (image, ocr_result) in enumerate(zip(images, ocr_results)):
|
70
|
+
image = Image.fromarray(image[:, :, ::-1]) # Convert BGR to RGB
|
71
|
+
pdfmetrics.registerFont(TTFont("MPLUS1p-Medium", FONT_PATH))
|
72
|
+
|
73
|
+
image_path = f"tmp_{i}.png"
|
74
|
+
image.save(image_path)
|
75
|
+
w, h = image.size
|
76
|
+
|
77
|
+
c.setPageSize((w, h))
|
78
|
+
c.drawImage(image_path, 0, 0, width=w, height=h)
|
79
|
+
os.remove(image_path) # Clean up temporary image file
|
80
|
+
|
81
|
+
for word in ocr_result.words:
|
82
|
+
text = word.content
|
83
|
+
bbox = _poly2rect(word.points)
|
84
|
+
direction = word.direction
|
85
|
+
|
86
|
+
x1, y1, x2, y2 = bbox
|
87
|
+
bbox_height = y2 - y1
|
88
|
+
bbox_width = x2 - x1
|
89
|
+
|
90
|
+
if direction == "vertical":
|
91
|
+
text = to_full_width(text)
|
92
|
+
|
93
|
+
if direction == "horizontal":
|
94
|
+
font_size = _calc_font_size(text, bbox_height, bbox_width)
|
95
|
+
else:
|
96
|
+
font_size = _calc_font_size(text, bbox_width, bbox_height)
|
97
|
+
|
98
|
+
c.setFont("MPLUS1p-Medium", font_size)
|
99
|
+
c.setFillColorRGB(1, 1, 1, alpha=0) # 透明
|
100
|
+
# c.setFillColorRGB(0, 0, 0)
|
101
|
+
if direction == "vertical":
|
102
|
+
base_y = h - y2 + (bbox_height - font_size)
|
103
|
+
for j, ch in enumerate(text):
|
104
|
+
c.saveState()
|
105
|
+
c.translate(x1 + font_size * 0.5, base_y - (j - 1) * font_size)
|
106
|
+
c.rotate(-90)
|
107
|
+
c.drawString(0, 0, ch)
|
108
|
+
c.restoreState()
|
109
|
+
else:
|
110
|
+
base_y = h - y2 + (bbox_height - font_size) * 0.5
|
111
|
+
c.drawString(x1, base_y, text)
|
112
|
+
c.showPage()
|
113
|
+
c.save()
|
114
|
+
|
115
|
+
with open(output_path, "wb") as f:
|
116
|
+
f.write(packet.getvalue())
|