Понадобилось мне получить значения забитмапленных чисел. Числа грабились с экрана.
Я подумал, а не попробовать ли мне OCR? Попробовал Tesseract.
Ниже я расскажу как я пытался приспособить Tesseract, зачем я его тренировал, и что из этого получилось. В проекте на гитхабе лежит cmd-скрипт, автоматизирующий насколько возможно процесс тренировки, и данные, на которых я проводил тренировку. Словом, есть все что нужно, чтобы с места в карьер обучить Tesseract чему-нибудь полезному.
Подготовка
Клонируем <a rel="nofollow" href="https://github.com/Zloy/tesseract-training">репозитарий или скачиваем zip-архив (~6Mb). Устанавливаем tesseract 3.01 с оф.сайта. Если его там уже нет, то из подкаталога zip-архив/distros.
Чтобы сравнивать распознанный текст с изображением удобнее расположить числа не в виде таблицы, а вертикально в виде списка.
Вертикально скомпоновать исходные изображения можно при помощи утилиты montage из пакета ImageMagick
Переходим в папку samples, запускаем montage_all.cmd
Этот скрипт создаст итоговое изображение samples/total.png, можно скрипт не запускать, т.к. я уже поместил его в корневую папку проекта.
Зачем тренировать?
Быть может и без тренировки результат будет хороший? Проверим.
./exp1 - as is> tesseract ../total.png total
Поместим исправленный результат в файл model_total.txt, чтобы сравнивать с ним результаты распознаваний. Звездочка маркирует неправильные значения.
model_total.txt | Распознавание по умолчанию |
---|---|
27 33 39 625.05 9 163 1,740.10 15 36 45 72 324 468 93 453 1,200.10 80.10 152.25 158.25 176.07 97.50 170.62 54 102 162 78 136.50 443.62 633.74 24 1,579.73 1,576.73 332.23 957.69 954.69 963.68 1,441.02 1,635.34 50 76 168 21 48 30 42 108 126 144 114 462 378 522 60 240 246 459.69 456.69 198 61 255 |
27 33 39 525 05* 9 153* 1,740 10* 15 35* 45 72 324 455* 93 453 1,200 10* 50 10* 152 25* 155 25* 175 07* 97 50* 170 52* 54 102 152* 75* 135 50* 443 52* 533 74* 24 1,579 73* 1,575 73* 332 23* 957 59* 954 59* 953 55* 1,441 02* 1,535 34* 50 75* 155* 21 45* 30 42 105* 125* 144 114 452* 375* 522 50* 240 245* 459 59* 455 59* 195* 51* 255 |
ошибки распознавания по умолчанию
Видно, что ошибок много. Если приглядеться, то можно заметить, что не распознается десятичная точка, цифры 6 и 8 распознаются как 5. Поможет ли тренировка избавиться от ошибок?
Тренировка
Тренировка tesseract позволяет натаскать его на распознавание изображений текстов в том виде, в котором вы будете скармливать ему аналогичные изображения в процессе распознавания.
Вы передаете tesseract тренировочные изображения, исправляете ошибки распознавания и передаете эти правки tesseract-у. А он корректирует коэффиценты в своих алгоритмах, чтобы впредь не допускать найденных вами ошибок.
Чтобы выполнить тренировку надо запустить ./exp2 - trained> train.cmd
В чем заключается процесс тренировки? А в том, что tesseract обрабатывает тренировочное изображение и формирует т.н. боксы символов — выделяет из текста отдельные символы создавая список ограничивающих прямоугольников. При этом он делает догадки относительно того, какой именно символ ограничен прямоугольником.
Результаты этой работы записывает в файл total.box, который выглядит так:
2 46 946 52 956 0
7 54 946 60 956 0
3 46 930 52 940 0
3 54 930 60 940 0
3 46 914 52 924 0
9 53 914 60 924 0
6 31 898 38 908 0
2 40 898 46 908 0
5 48 898 54 908 0
0 59 898 66 908 0
…
Здесь в певом столбце символ, а в 2 — 5 столбцах координаты левого нижнего угла прямоугольника, его высота и ширина.
Конечно редактировать его вручную сложно и неудобно, поэтому энтузиастами были созданы графические утилиты, облегчающие эту работу. Я воспользовался jTessBoxEditor, написанной на JAVA.
После запуска ./exp2 - trained> java -jar jTessBoxEditor-0.6jTessBoxEditor.jar
надо открыть файл ./exp2 - trained/total.png
, при этом будет автоматически открыт файл ./exp2 - trained/total.box
и определенные в нем прямоугольники будут наложены на тренировочное изображение.
В левой части приведено содержимое файла total.box, справа расположено тренировочное изображение. Над изображением расположена активная строка файла total.box
Синим изображены боксы, а красным — бокс, соответствующий активной строке.
Я исправил все неправильные 5-ки на правильные 6-ки и 8-ки, добавил строки с определениями всех десятичных точек, имеющихся в файле и сохранил total.box
После завершения редактирования надо, чтобы скрипт продолжил работу, надо закрыть jTessBoxEditor. Далее все действия выполняются скриптом автоматически без участия пользователя. Скрипт записывает результаты обучения под кодом ttn
Чтобы использовать результаты обучения при распознавании надо запустить tesseract c ключом -l ttn
./exp2 - trained/> tesseract ../total.png total-trained -l ttn
Видно, что все цифры стали распознаваться правильно, однако десятичная точка по-прежнему никак не распознается.
model_total.txt | Распознавание по умолчанию |
Распознавание после тренировки |
---|---|---|
27 33 39 625.05 9 163 1,740.10 15 36 45 72 324 468 93 453 1,200.10 80.10 152.25 158.25 176.07 97.50 170.62 54 102 162 78 136.50 443.62 633.74 24 1,579.73 1,576.73 332.23 957.69 954.69 963.68 1,441.02 1,635.34 50 76 168 21 48 30 42 108 126 144 114 462 378 522 60 240 246 459.69 456.69 198 61 255 |
27 33 39 525 05* 9 153* 1,740 10* 15 35* 45 72 324 455* 93 453 1,200 10* 50 10* 152 25* 155 25* 175 07* 97 50* 170 52* 54 102 152* 75* 135 50* 443 52* 533 74* 24 1,579 73* 1,575 73* 332 23* 957 59* 954 59* 953 55* 1,441 02* 1,535 34* 50 75* 155* 21 45* 30 42 105* 125* 144 114 452* 375* 522 50* 240 245* 459 59* 455 59* 195* 51* 255 |
27 33 39 625 05* 9 163 1,740 10* 15 36 45 72 324 468 93 453 1,200 10* 80 10* 152 25* 158 25* 176 07* 97 50* 170 62* 54 102 162 78 136 50* 443 62* 633 74* 24 1,579 73* 1,576 73* 332 23* 957 69* 954 69* 963 68* 1,441 02* 1,635 34* 50 76 168 21 48 30 42 108 126 144 114 462 378 522 60 240 246 459 69* 456 69* 198 61 255 |
ошибки распознавания с обучением
Дальше я решил, что наверное изображение точки слишком мало — всего 2 пискеля2, и что причина в этом, и увеличил изображение в два раза.
Увеличение изображения
Увеличивать можно по-разному, я попробовал два способа: scale и resize
total-scaled.png (фрагмент) | total-resized.png (фрагмент) |
---|---|
convert total.png total-scaled.png -scale "208x1920" |
convert total.png total-resized.png -resize "208x1920" |
Так как изображения символов увеличились вместе с самими изображениями, данные тренировки под кодом ttn устарели. Поэтому дальше я распознавал без ключа -l ttn.
Видно, что на изображении total-scaled.png tesseract путает 7-ку с 2-кой, а на total-resized.png не путает. На обоих изображениях корректно определяется десятичная точка. Распознавание изображения total-resized.png почти идеально. Есть только три ошибки — пробел между цифрами в числах 21, 114 и 61.
Но эта ошибка не критична, т.к. ее просто исправить простым удалением из строк пробелов.
ошибки распознавания total-scaled.png
ошибки распознавания total-resized.png
model_total.txt | Распознавание по умолчанию |
Распознавание после тренировки |
total-scaled.png | total-resized.png |
---|---|---|---|---|
27 33 39 625.05 9 163 1,740.10 15 36 45 72 324 468 93 453 1,200.10 80.10 152.25 158.25 176.07 97.50 170.62 54 102 162 78 136.50 443.62 633.74 24 1,579.73 1,576.73 332.23 957.69 954.69 963.68 1,441.02 1,635.34 50 76 168 21 48 30 42 108 126 144 114 462 378 522 60 240 246 459.69 456.69 198 61 255 |
27 33 39 525 05* 9 153* 1,740 10* 15 35* 45 72 324 455* 93 453 1,200 10* 50 10* 152 25* 155 25* 175 07* 97 50* 170 52* 54 102 152* 75* 135 50* 443 52* 533 74* 24 1,579 73* 1,575 73* 332 23* 957 59* 954 59* 953 55* 1,441 02* 1,535 34* 50 75* 155* 21 45* 30 42 105* 125* 144 114 452* 375* 522 50* 240 245* 459 59* 455 59* 195* 51* 255 |
27 33 39 625 05* 9 163 1,740 10* 15 36 45 72 324 468 93 453 1,200 10* 80 10* 152 25* 158 25* 176 07* 97 50* 170 62* 54 102 162 78 136 50* 443 62* 633 74* 24 1,579 73* 1,576 73* 332 23* 957 69* 954 69* 963 68* 1,441 02* 1,635 34* 50 76 168 21 48 30 42 108 126 144 114 462 378 522 60 240 246 459 69* 456 69* 198 61 255 |
22* 33 39 625.05 9 163 1,240.10* 15 36 45 22* 324 468 93 453 1,200.10 80.10 152.25 158.25 126.02* 92.50* 120.62* 54 102 162 28* 136.50 443.62 633.24* 24 1,529.23* 1,526.23* 332.23 952.69* 954.69 963.68 1,441.02 1,635.34 50 26* 168 2 1* 48 30 42 108 126 144 1 14* 462 328* 522 60 240 246 459.69 456.69 198 6 1* 255 |
27 33 39 625.05 9 163 1,740.10 15 36 45 72 324 468 93 453 1,200.10 80.10 152.25 158.25 176.07 97.50 170.62 54 102 162 78 136.50 443.62 633.74 24 1,579.73 1,576.73 332.23 957.69 954.69 963.68 1,441.02 1,635.34 50 76 168 2 1* 48 30 42 108 126 144 1 14* 462 378 522 60 240 246 459.69 456.69 198 6 1* 255 |
Оцифровка изображений по одному
Ок, что если требуется оцифровывать изображения одно за другим в режиме реального вренени?
Пробую по одному.
./exp5 - one by one> for /r %i in (*.png) do tesseract "%i" "%i"
Двух и трехзначные числа не определяются вовсе!
625.05 | |
1740.10 | |
Оцифровка небольшими пакетами
А если требуется оцифровывать изображения пакетами по несколько изображений (6 или 10 в пакете)? Пробую по десять.
./exp6 - ten in line> tesseract teninline.png teninline
Распознаются, и даже без пробела в числе 61.
378 522 60 240 246 459.69 456.69 198 61 255 |
Выводы
В общем-то я ожидал худшие результаты, т.к. мелкие растровые шрифты являются граничным случаем в силу их малого размера, отчетливой гранулярности и постоянства — разные изображения одного символа полностью совпадают. И практика показала, что лучше распознаются увеличенные в размере искусственно замутненные цифры.
Предварительная обработка изображения имеет больший эффект, чем обучение. Увеличивайте со сглаживанием: convert -resize…
Распознавание отдельно стоящих «коротких» двух и трехзначных чисел неудовлетворительно — числа надо собирать в пакеты.
Но в целом tesseract почти идеально справился с задачей, несмотря на то, что он заточен под другие задачи — распознавание надписей на фото и видео, сканах документов.
Автор: Zloy1