Руководство по использованию Pipeline
Pipeline построен из этапов и передаёт один объект Page через все этапы:
detector -> layout -> recognizer -> corrector
По умолчанию Pipeline() создаёт:
детектор:
YOLO(weights="yolo26x_obb_text_g1")layout:
SimpleSorting()распознаватель:
TRBA(weights="trba_lite_g2")корректор:
None
Контракты этапов
Детектор
Детектор должен реализовывать:
def predict(self, image) -> Page:
...
Распознаватель
Распознаватель должен реализовывать:
def predict(self, page: Page, image: Optional[np.ndarray] = None) -> Page:
...
Layout
Layout-модель должна реализовывать:
def predict(self, page: Page, image: Optional[np.ndarray] = None) -> Page:
...
Корректор
Корректор должен реализовывать:
def predict(self, page: Page, image: Optional[np.ndarray] = None) -> Page:
...
Базовое использование
from manuscript import Pipeline
pipeline = Pipeline()
result = pipeline.predict("document.jpg")
text = pipeline.get_text(result["page"])
print(text)
Отключение этапов
Необязательные этапы можно отключать через None:
from manuscript import Pipeline
# Detection + layout only
pipeline = Pipeline(recognizer=None, corrector=None)
# Detection + recognition only
pipeline = Pipeline(layout=None, corrector=None)
# Detection + layout + recognition (no correction)
pipeline = Pipeline(corrector=None)
Положение этапа layout
Используйте layout_after, чтобы выбрать, после какого этапа запускать layout:
"detector"(по умолчанию)"recognizer""corrector"
from manuscript import Pipeline
from manuscript.layouts import SimpleSorting
pipeline = Pipeline(
layout=SimpleSorting(),
layout_after="recognizer",
)
Если опорный этап отключён, например recognizer=None при layout_after="recognizer", layout всё равно выполнится в этой позиции.
Встроенные компоненты
from manuscript.detectors import EAST
from manuscript.layouts import SimpleSorting
from manuscript.recognizers import TRBA
from manuscript.correctors import CharLM
from manuscript import Pipeline
detector = EAST(weights="east_50_g1", score_thresh=0.8, iou_threshold=0.2)
layout = SimpleSorting(max_splits=10, use_columns=True)
recognizer = TRBA(weights="trba_lite_g1", device="cuda", min_text_size=5)
corrector = CharLM()
pipeline = Pipeline(
detector=detector,
layout=layout,
recognizer=recognizer,
corrector=corrector,
layout_after="detector",
)
Подготовка регионов в TRBA
TRBA поддерживает настраиваемую подготовку кропов перед распознаванием.
Настройки по умолчанию:
region_preparer="bbox"вырезает осеориентированные bounding boxrotate_threshold=1.5автоматически поворачивает высокие кропы перед распознаваниемmin_text_size=5пропускает слишком маленькие детекции
Встроенные пресеты preparer:
"bbox": осеориентированный кроп"polygon_mask": плотный кроп с маскированием пикселей вне полигона в белый цвет"quad_warp": перспективное выравнивание для 4-точечных полигонов с переходом на bbox при необходимости
from manuscript.recognizers import TRBA
recognizer = TRBA(region_preparer="bbox")
recognizer = TRBA(region_preparer="polygon_mask")
recognizer = TRBA(region_preparer="quad_warp")
recognizer = TRBA(
region_preparer="bbox",
region_preparer_options={"pad": 2},
)
region_preparer_options зарезервирован для настройки встроенных пресетов:
"bbox"/"polygon_mask":pad"polygon_mask":background"quad_warp":output_size=(width, height),fallback_to_bbox
Для более сложных сценариев можно внедрить хуки в TRBA вместо того, чтобы писать полностью собственный распознаватель:
import numpy as np
def my_preparer(page, image, recognizer=None, options=None):
regions = []
for block in page.blocks:
for line in block.lines:
for text_span in line.text_spans:
poly = np.asarray(text_span.polygon, dtype=np.float32)
crop = image[10:40, 10:80]
regions.append(
{"text_span": text_span, "image": crop, "polygon": poly}
)
return regions
recognizer = TRBA(region_preparer=my_preparer)
Если нужен полный контроль над логикой распознавания, самым простым вариантом по-прежнему остаётся собственный класс распознавателя с predict(page, image) -> Page.
Объединение TextSpan
Некоторые распознаватели работают с целыми строками или блоками, а не с кропами отдельных text span. Используйте collapse_page_text_spans, чтобы перед распознаванием преобразовать узкую структуру страницы в более широкую.
from manuscript.utils import collapse_page_text_spans
line_level_page = collapse_page_text_spans(
page,
level="line",
method="bbox",
)
block_level_page = collapse_page_text_spans(
page,
level="block",
method="convex_hull",
)
"line" сохраняет те же блоки и строки, но заменяет каждую строку одним объединённым TextSpan. "block" заменяет каждый блок одной строкой, содержащей один объединённый TextSpan.
Также доступны низкоуровневые вспомогательные функции:
merge_text_spans(text_spans, method="bbox")collapse_line_text_spans(line, method="bbox")collapse_block_text_spans(block, method="bbox")
Визуализация и профилирование
result, vis_img = pipeline.predict("document.jpg", vis=True)
vis_img.save("output_visualization.jpg")
result = pipeline.predict("document.jpg", profile=True)
Промежуточные результаты
После каждого запуска pipeline сохраняет снимки промежуточных результатов:
pipeline.last_detection_pagepipeline.last_layout_pagepipeline.last_recognition_pagepipeline.last_correction_page
Для пропущенных этапов соответствующее значение last_* остаётся None.