Потребовалось мне закачать в читалку в телефоне несколько исторических книжек. Да вот беда: все они доступны только в PDF или Djvu различного уровня паршивости сканирования. Если читать глазами - ещё куда ни шло. Но если подсунуть текст автоматическому чтецу, то будет фиаско.
У одной книжки был текстовая подложка. Распознование очень плохое. Внутри документа встречаются HTML теги. И тут решил попробовать модные ныне LLM на предмет обработки текст. Придумал запрос, залил файл и…
- ChatGPT - фиаско. Ну он начинает, выдаёт порцию (документ текстовый почти на 2 Мб) далее опять просит загрузить файл.
- Qween - тоже не справился
- DeepSeek - а вот он оказался кросавчегом! Про залитый файл не забывает, но может сбойнуть. Ну и выводит только в чат.
Результирующий текст получился очень годным плюс форматирование в Markdown. А по сути нужно было:
- убрать очевидные ошибки OCR
- склеить строки
- понять где заголовки и новые параграфы
- убрать колонтитулы
Как следствие, решил проверить на самой паскудно-отсканированной книге, где картинки в PDF.
Процедура обработки
Для начала нужно извлечь картинки из документа.
Для PDF:
mkdir OCR
cd OCR
pdftoppm ../Document.pdf out
будет создано куча файлов вида out-xxx.ppm. Есть вариант и pdftopng, почему-то воспользовался первый. Сейчас бы воспользовался вторым.
Для Djvu:
ddjvu -format=ppm ../Document.djvu -eachpage out-%03d.png
Первая страница обычно обложка, сразу стоит сохранить её как title.png:
magick out-001.ppm ../title.png
# или
cp out-001.png ../title.png
Далее, упрощения жизни распозавальщику, если книга отсканирована или отфотографирована в виде разворота, то крайней желательно разделить на стриницы, поможет ImageMagick:
mkdir split
cd split
for i in ../*.png; do nm=$(basename "$i" .png); magick $i -crop 50%x100% ${nm}_%d.png; done
Стоить перепроверить отдельные страницы, что не порезался текст и им поправить пропорции резки вручную.
Теперь очередь Tesseract. Для его запуска сделал вспомогательный скрипт ocr-tesseract-my.sh:
#!/usr/bin/env bash
set -e
#set -x
IN=$1
DIR=$(dirname "$IN")
BASE=$(basename -- "${IN%.*}")
OCR_LANG=rus
OUT="${DIR}/${BASE}_out"
PSM=1
echo "OCR: $IN"
tesseract --psm $PSM "$IN" "$OUT" -l $OCR_LANG
Запуск на файлах (далее допускаю, что работаем с PNG):
for i in *.png; do ocr-tesseract-my.sh "$i"; done
А результат уже собрать в один документ:
rm -f out.txt; for i in *.txt; do cat $i >> out.txt; done
Вот out.txt и будет тем самым полуфабрикатом, который мы подсунем DeepSeek.
DeepSeek
Загружаем файл out.txt и я сформулировал такой набор требований:
Вот текстовый файл
1. Соединить строки, убрать знаки переноса по смыслу
2. Заменить HTML символы типа & заменить на печатные аналоги
3. Заменить HTML символы типа <hr> на двойной перевод строки
4. Заменить HTML символы типа <br> на одинарный перевод строки
5. Строки набранные CAPS LOCK считать заголовками. Так же попытаться выделить заголовки по смыслу. Например: короткое предложение без точки в конце на отдельной строке, а продолжение текста с большой буквы
6. Определять по смыслу начало параграфа, отделять пустой строки: тут сложность: по смыслу понять: после перевода строки продолжается строка и просто нужно соединить и, возможно, убрать знак переноса, или это новое предложение или параграф. Если сомневаешься, не делай параграф.
7. Исправить очевидные OCR шибки
8. Убрать колонтитулы, номера страниц
9. Форматировать в Markdown с отформатированным выводом в чат
Результат выдавать в чат порциями по 64кб, далее ждать команды на продолжение.
Последнее уточнение родилось из-за того, что на одном документе DeepSeek аварийно завершал обработку и пропадал весь вывод. Мне показалось куда надёжнее, просить порцию, сохранять её, если пошло что-то не так, то разбираться именно с текущим чанком. Запрос следующего чанка - это отправка текста “далее” в чат.
Процесс не быстрый. Возможно, на платных подписках будет шустрее, но результат мне понравился. Стоит отметить, что не всегда он начинает давать ожидаемое форатирование. Решается путём остановки и переотправки запроса, как есть, без правки. У меня со второй или третьей попытки начинал выводить форматированный Markdown, который при копировании давал что-то вроде:
# Как начинался Владивосток
**А.И АЛЕКСЕЕВ**
## Содержание
После этого шага получается вполне себе годный Markdown документ. Теперь можно, по желанию, расставить вручную картинки, но моя задача этого не требовала.
Как я писал выше, процедура изначально была прогнана на документе самого плохого качества сканирования. И он блестяще справился. Вот наглядный пример, что было на входе:
В книге, по,
и ПОдГотовленной к юби-
лею Впдди.оае›н, его — 125-ле-
тию, рассказывается ©
шёегах нового горо,
›да Росси
Редины прошпого вна аи -
дены портреты его. основателей
от адмиралов и генералов до
дивостока, ставшего для всех нас
Родным, города, в котором мы
сегодня живем и трудимся,
40 коп.
И результат:
В книге, подготовленной к юбилею Владивостока, его 125-летию, рассказывается о первых днях и годах нового города, о том, как начинался Владивосток. Автор воссоздал картины далекого прошлого, показал портреты его основателей — от адмиралов и генералов до первых поселенцев Владивостока, ставшего для всех нас родным городом, в котором мы сегодня живем и трудимся.
А что было по факту:
В книге, подготовленной к юбилейю Владивостока, его 125-летию, рассказывается о первых шагах нового города России середины прошлого века. В ней даны портреты его основателей от адмиралов и генералов до матросов и солдат, положивших свой камень в фундамент Владивостока, ставшего для всех нас родным, города, в котором мы сегодня живём и трудимся.
Видно, что текст домыслен. Но смысл не утерян. Учитывать это стоит и всё таки искать качественный источник данных для OCR.
EPUB
Для подготовки EPUB использовал pandoc. Для начала в Markdown документ добавил front-matter с метаданными книги:
---
title:
- type: main
text: ВЛАДИВОСТОКЪ
- type: subtitle
text: ЭТЮДЫ К ИСТОРИИ СТАРОГО ГОРОДА
author: А. А. Хисамутдинов
publisher: Private Publishing
cover-image: title.png
---
Тут нам и пригодилась сохранённая ранее обложка: её будем использовать для EPUB.
После всего этого достаточно запустить:
pandoc Document.md -o Document.epub
и книжка - ваша.
Выводы
ЛЛМ могут реально помогать. Особенно в нехарактерных для постоянного использования задач. Но относиться нужно с осторожность (чего стоит только домыслевание непонятного текста, пример о чём был выше). Как минимум я бы поостерёгся использовать данный подход к текстам с формулами (но я слабо представляю, как такие тексты вообще слушать как аудио-книги). Да и в текущем виде по хорошему нужна вычитка и проверка дат, фамилий и географических названий. Но в целом, результатом для себя я крайне доволен!