| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- from __future__ import annotations
-
- import importlib.resources
- from dataclasses import dataclass, field
- from typing import Any
-
- import cv2
- import yaml
- from paddlex import create_pipeline
-
-
- @dataclass
- class ParsedBlock:
- label: str
- content: str
- bbox: tuple[int, int, int, int]
- confidence: float = 0.9
-
-
- @dataclass
- class OcrPageResult:
- blocks: list[ParsedBlock] = field(default_factory=list)
- raw_json: dict[str, Any] = field(default_factory=dict)
- width: int = 0
- height: int = 0
-
-
- def _load_config() -> dict[str, Any]:
- ref = importlib.resources.files("paddlex") / "configs" / "pipelines" / "PP-StructureV3.yaml"
- with importlib.resources.as_file(ref) as path, open(path) as f:
- config: dict[str, Any] = yaml.safe_load(f)
-
- config["SubPipelines"]["GeneralOCR"]["SubModules"]["TextRecognition"]["model_name"] = (
- "eslav_PP-OCRv5_mobile_rec"
- )
- table_ocr = config["SubPipelines"]["TableRecognition"]["SubPipelines"]["GeneralOCR"]
- table_ocr["SubModules"]["TextRecognition"]["model_name"] = "eslav_PP-OCRv5_mobile_rec"
- return config
-
-
- class OcrEngine:
- def __init__(self) -> None:
- self._config: dict[str, Any] = _load_config()
- self._pipeline: Any = None
-
- def process(self, image_path: str) -> OcrPageResult:
- image = cv2.imread(image_path)
- if image is None:
- raise FileNotFoundError(f"Не удалось загрузить изображение: {image_path}")
-
- h, w = image.shape[:2]
- if self._pipeline is None:
- self._pipeline = create_pipeline(
- config=self._config,
- use_doc_orientation_classify=False,
- use_doc_unwarping=False,
- )
- raw_results = list(self._pipeline.predict(image))
-
- blocks, raw_json = self._parse_results(raw_results)
- return OcrPageResult(blocks=blocks, raw_json=raw_json, width=w, height=h)
-
- @staticmethod
- def _parse_results(raw_results: list[Any]) -> tuple[list[ParsedBlock], dict[str, Any]]:
- if not raw_results:
- return [], {}
-
- raw_json: dict[str, Any] = raw_results[0].json["res"]
- blocks: list[ParsedBlock] = []
- for item in raw_json.get("parsing_res_list", []):
- text = item.get("block_content", "")
- label = item.get("block_label", "text")
- bbox = item.get("block_bbox", [0, 0, 0, 0])
- if not text.strip():
- continue
- blocks.append(ParsedBlock(
- label=label, content=text,
- bbox=(int(bbox[0]), int(bbox[1]), int(bbox[2]), int(bbox[3])),
- ))
- return blocks, raw_json
-
-
- _engine: OcrEngine | None = None
-
-
- def ocr_image(image_path: str) -> OcrPageResult:
- global _engine
- if _engine is None:
- _engine = OcrEngine()
- return _engine.process(image_path)
|