CER для OCR: собрать текст и посчитать ошибки Python
Соберите текст страницы из результатов OCR и сравните его с эталоном. CER — расстояние Левенштейна, делённое на число символов непустого эталона. Из-за лишних вставок CER может быть больше 1. Правила очистки и порядка чтения заданы ниже.
Программа курса «Computer Vision Engineer: от детекции и Doc-AI до продакшна».
CER страницы по находкам движка
Задание
Реализуйте функцию page_cer(findings, reference). Она получает находки движка на одной странице и эталонный текст этой страницы, собирает из находок текст страницы и возвращает его CER — тот самый, которым в уроке мерили чтение.
findings — список кортежей (text, top, left): текст находки, верхняя и левая координаты её рамки в пикселях. Порядок находок в списке — тот, в котором их отдал движок, то есть никакой. reference — непустая строка эталона.
Снятие разметки. Текст находки может прийти с тегами: движки страницы отдают куски HTML. В каждой находке замените всё, что попадает под <...> — открывающую угловую скобку, хотя бы один символ кроме закрывающей и закрывающую, — на пробел. Затем разверните три сущности: & в &, < в <, > в > — именно в этом порядке. После этого схлопните любые подряд идущие пробельные символы в один пробел и обрежьте пробелы по краям.
Сборка страницы. Находка, от которой после снятия разметки не осталось ничего, в текст страницы не попадает. Остальные идут по возрастанию top, при равном — по возрастанию left, при равном — в порядке входного списка, и склеиваются через один пробел.
Расстояние правок. Число правок между собранным текстом и эталоном — это расстояние Левенштейна: наименьшее число вставок, удалений и замен одного символа, которым один текст приводится к другому. Готовой реализации в стандартной библиотеке нет, напишите её сами. Что дальше делают с этим числом, чтобы получить CER, сказано в уроке — там же сказано и почему у метрики бывают значения больше единицы.
Ответ. Дробное число.
Пример
findings = [
("<b>65,00O</b>", 30, 70),
("<td>Fish & Chips</td>", 30, 12),
("<td>TOTAL</td>", 10, 12),
]
page_cer(findings, "TOTAL Fish & Chips 65,000")
# 0.04
Собранный текст — TOTAL Fish & Chips 65,00O: цена стоит справа от названия и потому идёт последней. Отличается он от эталона одной заменой — буква вместо нуля в цене.
Примечание
Вход уже разобран и приходит аргументами: список кортежей и строка. Координаты целые. Кроме трёх перечисленных сущностей других в тексте находок нет, а сам текст и эталон не длиннее пары сотен символов — на скорость реализации ограничений нет. Менять входной список нельзя, в том числе сортировать его на месте. Вызывать функцию вручную не нужно, проверка запускает её сама.
Что проверяется
Код проверок скрыт, так что вот полный список того, что в них разбирается:
- формат ответа: дробное число, не меньше нуля;
- входной список после вызова не изменился;
- пример из условия;
- находки идут в списке не в том порядке, в каком читаются;
- находки с одинаковой верхней координатой;
- находки, у которых совпадают обе координаты;
- теги и сущности внутри текста находки;
- подряд идущие пробелы и переводы строк внутри находки;
- находка, от которой после снятия разметки ничего не осталось;
- совпадение с эталоном символ в символ;
- случай, когда движок вернул текста заметно больше, чем есть в эталоне;
- пустой список находок и одна находка.
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
