From acb91efe486b1714b7df4fbef38fa3103ff1dd5b Mon Sep 17 00:00:00 2001 From: kba Date: Fri, 28 Nov 2025 11:15:53 +0100 Subject: [PATCH] WIP: reorganize OCR-D and start on ocrd-eynollah-ocr --- pyproject.toml | 5 ++-- src/eynollah/ocrd/__init__.py | 0 src/eynollah/ocrd/ocrd_cli_binarize.py | 9 +++++++ .../{ocrd_cli.py => ocrd/ocrd_cli_layout.py} | 6 ++--- .../processor_binarize.py} | 25 +++---------------- .../processor_layout.py} | 6 ++--- src/eynollah/ocrd/processor_ocr.py | 24 ++++++++++++++++++ 7 files changed, 44 insertions(+), 31 deletions(-) create mode 100644 src/eynollah/ocrd/__init__.py create mode 100644 src/eynollah/ocrd/ocrd_cli_binarize.py rename src/eynollah/{ocrd_cli.py => ocrd/ocrd_cli_layout.py} (74%) rename src/eynollah/{ocrd_cli_binarization.py => ocrd/processor_binarize.py} (86%) rename src/eynollah/{processor.py => ocrd/processor_layout.py} (97%) create mode 100644 src/eynollah/ocrd/processor_ocr.py diff --git a/pyproject.toml b/pyproject.toml index fde7967..e9b14a6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,8 +41,9 @@ classifiers = [ [project.scripts] eynollah = "eynollah.cli:main" eynollah-training = "eynollah.training.cli:main" -ocrd-eynollah-segment = "eynollah.ocrd_cli:main" -ocrd-sbb-binarize = "eynollah.ocrd_cli_binarization:main" +ocrd-eynollah-segment = "eynollah.ocrd.ocrd_cli_layout:main" +ocrd-sbb-binarize = "eynollah.ocrd.ocrd_cli_binarize:main" +ocrd-eynollah-ocr = "eynollah.ocrd.ocrd_cli_ocr:main" [project.urls] Homepage = "https://github.com/qurator-spk/eynollah" diff --git a/src/eynollah/ocrd/__init__.py b/src/eynollah/ocrd/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/eynollah/ocrd/ocrd_cli_binarize.py b/src/eynollah/ocrd/ocrd_cli_binarize.py new file mode 100644 index 0000000..1932ead --- /dev/null +++ b/src/eynollah/ocrd/ocrd_cli_binarize.py @@ -0,0 +1,9 @@ +from click import command +from ocrd.decorators import ocrd_cli_options, ocrd_cli_wrap_processor + +from .processor_binarize import SbbBinarizeProcessor + +@command() +@ocrd_cli_options +def main(*args, **kwargs): + return ocrd_cli_wrap_processor(SbbBinarizeProcessor, *args, **kwargs) diff --git a/src/eynollah/ocrd_cli.py b/src/eynollah/ocrd/ocrd_cli_layout.py similarity index 74% rename from src/eynollah/ocrd_cli.py rename to src/eynollah/ocrd/ocrd_cli_layout.py index 8929927..91cec69 100644 --- a/src/eynollah/ocrd_cli.py +++ b/src/eynollah/ocrd/ocrd_cli_layout.py @@ -1,11 +1,9 @@ -from .processor import EynollahProcessor from click import command from ocrd.decorators import ocrd_cli_options, ocrd_cli_wrap_processor +from .processor_layout import EynollahProcessor + @command() @ocrd_cli_options def main(*args, **kwargs): return ocrd_cli_wrap_processor(EynollahProcessor, *args, **kwargs) - -if __name__ == '__main__': - main() diff --git a/src/eynollah/ocrd_cli_binarization.py b/src/eynollah/ocrd/processor_binarize.py similarity index 86% rename from src/eynollah/ocrd_cli_binarization.py rename to src/eynollah/ocrd/processor_binarize.py index a199e72..b50eb33 100644 --- a/src/eynollah/ocrd_cli_binarization.py +++ b/src/eynollah/ocrd/processor_binarize.py @@ -1,29 +1,15 @@ from functools import cached_property from typing import Optional -from PIL import Image from frozendict import frozendict -import numpy as np -import cv2 -from click import command from ocrd import Processor, OcrdPageResult, OcrdPageResultImage from ocrd_models.ocrd_page import OcrdPage, AlternativeImageType -from ocrd.decorators import ocrd_cli_options, ocrd_cli_wrap_processor from eynollah.model_zoo.model_zoo import EynollahModelZoo -from .sbb_binarize import SbbBinarizer - - -def cv2pil(img): - return Image.fromarray(img.astype('uint8')) - -def pil2cv(img): - # from ocrd/workspace.py - color_conversion = cv2.COLOR_GRAY2BGR if img.mode in ('1', 'L') else cv2.COLOR_RGB2BGR - pil_as_np_array = np.array(img).astype('uint8') if img.mode == '1' else np.array(img) - return cv2.cvtColor(pil_as_np_array, color_conversion) +from ..sbb_binarize import SbbBinarizer +from ..utils.pil_cv2 import cv2pil, pil2cv class SbbBinarizeProcessor(Processor): # already employs GPU (without singleton process atm) @@ -103,12 +89,7 @@ class SbbBinarizeProcessor(Processor): line_image_bin = cv2pil(self.binarizer.run(image=pil2cv(line_image), use_patches=True)) # update PAGE (reference the image file): line_image_ref = AlternativeImageType(comments=line_xywh['features'] + ',binarized') - line.add_AlternativeImage(region_image_ref) + line.add_AlternativeImage(line_image_ref) result.images.append(OcrdPageResultImage(line_image_bin, line.id + '.IMG-BIN', line_image_ref)) return result - -@command() -@ocrd_cli_options -def main(*args, **kwargs): - return ocrd_cli_wrap_processor(SbbBinarizeProcessor, *args, **kwargs) diff --git a/src/eynollah/processor.py b/src/eynollah/ocrd/processor_layout.py similarity index 97% rename from src/eynollah/processor.py rename to src/eynollah/ocrd/processor_layout.py index 6d80281..0ac4cad 100644 --- a/src/eynollah/processor.py +++ b/src/eynollah/ocrd/processor_layout.py @@ -3,9 +3,9 @@ from typing import Optional from ocrd_models import OcrdPage from ocrd import OcrdPageResultImage, Processor, OcrdPageResult -from eynollah.model_zoo.model_zoo import EynollahModelZoo - -from .eynollah import Eynollah, EynollahXmlWriter +from ..model_zoo.model_zoo import EynollahModelZoo +from ..eynollah import Eynollah +from ..writer import EynollahXmlWriter class EynollahProcessor(Processor): # already employs background CPU multiprocessing per page diff --git a/src/eynollah/ocrd/processor_ocr.py b/src/eynollah/ocrd/processor_ocr.py new file mode 100644 index 0000000..d34235b --- /dev/null +++ b/src/eynollah/ocrd/processor_ocr.py @@ -0,0 +1,24 @@ + +from functools import cached_property +from frozendict import frozendict +from ocrd import Processor + +from ..model_zoo.model_zoo import EynollahModelZoo + + +class EynollahOcrProcessor(Processor): + # already employs GPU (without singleton process atm) + max_workers = 1 + + @cached_property + def executable(self): + return 'ocrd-eynollah-ocr' + + def setup(self): + """ + Set up the model prior to processing. + """ + # resolve relative path via OCR-D ResourceManager + assert isinstance(self.parameter, frozendict) + model_zoo = EynollahModelZoo(basedir=self.parameter['model']) + raise NotImplementedError()