Переход с 0.1.12 на 0.1.13

В версии 0.1.13 вместо фиксированной иерархии OCR используется дерево документа. Потребуется обновить код, который создаёт регионы, обходит результаты и читает сохранённый JSON. Структура данных описана в Структуры данных, остальные изменения — в Изменения версий.

Элементы и порядок чтения

Прежний API

0.1.13

Block, Line, TextSpan (или Word)

TextRegion(type="block" / "line" / "word")

page.blocks, block.lines, line.text_spans

Дочерние элементы в children. Для обхода всех уровней используйте descendants.

Поля order

Положение элемента в children его родителя.

Списки дочерних элементов в конструкторах

Назначайте children или parent после создания элементов.

Дерево может быть плоским или вложенным: слово не обязательно входит в строку и блок. Чтобы построить прежнюю трёхуровневую иерархию:

from manuscript.data import Page, TextRegion

page = Page(image_width=200, image_height=80)
block = TextRegion(type="block")
line = TextRegion(type="line")
word = TextRegion(
    type="word", text="Archive",
    polygon=[(10, 10), (100, 10), (100, 30), (10, 30)],
)
page.children = [block]
block.children = [line]
line.children = [word]
page.validate_tree()
assert word.parent is line
assert page.get_text() == "Archive"

Чтобы собрать слова независимо от глубины:

words = [node for node in page.descendants
         if isinstance(node, TextRegion) and node.type == "word"]
assert words == [word]

Для вывода текста используйте page.get_text(). Метод учитывает порядок детей и предпочитает текст потомков тексту родителя. SimpleSorting группирует плоский список слов в строки и блоки; ReadingSorting упорядочивает существующие регионы и при необходимости определяет вложенность.

Сохранённые результаты

page.to_dict() теперь возвращает полигональный COCO для одного изображения с расширениями Manuscript. Прежние варианты schema="v0_1_10" и schema="v0_1_11" удалены. Для записи в файл замените page.to_json(path) на page.save(path). В отличие от to_json(), save() требует путь и возвращает None, а не JSON-строку:

page.save("page.json")
restored = Page.load("page.json")
assert restored.to_tree_dict() == page.to_tree_dict()

Чтобы работать с JSON-строками, используйте функции кодирования и декодирования JSON. Метод Page.from_json() удалён, а Page.load() принимает только путь к файлу:

import json
from manuscript.data import from_coco

payload = json.dumps(page.to_dict(), ensure_ascii=False)
restored = from_coco(json.loads(payload))
assert restored.to_tree_dict() == page.to_tree_dict()

Page.load() принимает новый формат и поддерживаемый полигональный COCO без версии; старый вложенный OCR JSON он не преобразует. Конвертируйте такие файлы явно, создавая типизированные элементы и восстанавливая связи, либо сначала прочитайте их соответствующей старой версией библиотеки. Для вложенного представления в новых интеграциях используйте to_tree_dict() и Page.from_tree_dict(). Маркер manuscript-coco-v1 обозначает формат сериализации независимо от версии пакета.