Tesseract имеет тенденцию отбрасывать строки или фрагменты текста в нескольких случаях:
- Есть некоторые нетекстовые вещи, которые мешают (линии, артефакты, градиенты освещения)
- Там слишком много вещей, которые не распознаются как символы с достаточной уверенностью
- Линия неровная (неровности) / плохо выровнена, а также искажения, такие как перспектива
- Внутри линии слишком большие пробелы
- Текст расположен слишком близко к другому тексту, особенно если размер шрифта также неравномерный
Я не буду публиковать готовое решение или код, но могу написать, что бы я попробовал, основываясь на моем опыте работы с Tesseract:
Не устанавливайте пороговые значения для сканированных изображений, это часто ухудшает эффект, поскольку информация теряется, это имеет больше смысла, когда сканируется не текст, а фотография с градиентами света / тени и т. Д. c. (в таких сценах относительно хорошо работает адаптивный порог или другие фильтры + порог). В противном случае - нет причин для этого, Tesseract выполняет внутреннюю бинаризацию (которая довольно плохо работает для градиентов молний / теней, поскольку она не адаптивна, но довольно хорошо подходит для отсканированных изображений).
Попробуйте проверить как это происходит с разными DPI / размерами изображений. Может работать лучше, если вы найдете оптимальный вариант (это больше о более старой версии Tesseract, в настоящее время это имеет меньшее значение).
РЕДАКТИРОВАТЬ: Для изменения размера в opencv можно использовать:
cv::resize(inImg, outImg, cv::Size(), 0.7, 0.7);
Удаление прямоугольников вокруг текста может помочь.
- Это может быть сделано путем обнаружения линий, прямоугольников или контуров, фильтрации по длине / размеру относительно ширины изображения (или абсолютной, если он всегда один и тот же) и рисует на нем белым, поэтому он удаляется.
EDIT: на inte rnet есть несколько руководств по обнаружению прямоугольников. Большинство из них обнаруживают и рисуют. Например, alyssaq / opencv / squares. cpp на Github . Вы можете обнаружить квадраты, затем отфильтровать их по размеру в C ++, а затем нарисовать их белым, чтобы он рисовал белым поверх черного и эффективно удалял их.
- В качестве альтернативы это можно сделать путем копирования с маскированием, но это может быть труднее писать и хуже по производительности
Может быть полезно обрабатывать строку за строкой. Если сканирование всегда хорошо выровнено или может быть выровнено (например, измеряя углы прямоугольников), вы можете составить гистограмму чисел темных пикселей по Y (по вертикали) и найти промежутки между строками, вырезать эти строки, добавить белые отступы каждому из них и обрабатывать каждую из них по очереди. Конечно, все это после удаления строк из ящиков. Это хуже, когда дело доходит до производительности, но строки реже теряются.
EDIT: для гистограммы по Y и поиска пробелов между строками см. Этот вопрос Найти все пики для Mat () в OpenCV C ++ - это должно быть сделано аналогично, но на другой оси.
для обрезки см. этот вопрос и ответы Как обрезать CvMat в OpenCV?
для добавления отступов есть метод copyMakeBorder (), см. Добавление границ к изображениям в документации.
Вы также можете попытаться найти текст другими методами и обработать каждое поле / слово индивидуально (что еще менее эффективно, но с меньшей вероятностью потеряет текст). Затем можно соединиться обратно в строки (сопоставив по Y в строки и сортируя в строке по X).
- может размывать изображение с пороговым значением, чтобы сгруппировать буквы, найти контуры, отфильтровать их, взять их определенных c размеров для обработки, вырезать их с помощью маски, дополнить их белым, обработать каждый
РЕДАКТИРОВАТЬ: для этого вы можете найти вопросы и ответы по этой полезной ссылке: Извлечение текста OpenCV
- может использовать те прямоугольники, которые у вас есть - найти их положение с обнаружением формы, вырезать содержимое, обработать индивидуально
Вы также можете попробовать использовать Tesseract для получения слов или символов, ограничивающих прямоугольники + определенность, вместо текста, который с меньшей вероятностью отбросит некоторые части текста (но все же он может это сделать). Затем вы можете самостоятельно соединять блоки в линии (что довольно сложно, если у вас есть фотография с неровным листом бумаги + разные размеры шрифта + перспектива, но довольно легко, если у вас хорошо выровненный скан нормального документа). Вам также, вероятно, потребуется установить порог для фильтрации артефактов, которые могут появиться.
РЕДАКТИРОВАТЬ: Чтобы узнать слова или символы, можно использовать этот код:
tesseract::ResultIterator *iter = tess.GetIterator();
tesseract::PageIteratorLevel level = tesseract::RIL_WORD; // may use RIL_SYMBOL
if (iter != 0) {
do {
const char *word = iter->GetUTF8Text(level);
float conf = iter->Confidence(level);
int x1, y1, x2, y2;
iter->BoundingBox(level, &x1, &y1, &x2, &y2);
if (word) {
printf("word: '%s'; \tconfidence: %.2f\t bounding box: [%d,%d,%d,%d]\n", word, conf, x1, y1, x2, y2);
// ... use that info
delete[] word;
}
} while (iter->Next(level));
}
Код не тестировался, правильный код может отличаться для разных версий Tesseract, это для 3.0.
И последнее, но не менее важное: если не все изображения хорошо выровнены при сканировании, то, конечно, необходимо провести некоторую обработку, чтобы сделать его хорошо выровненным и выровненным, также вам нужно будет удалить градиенты / тени, если изображения создаются по фотографии, а не со сканера. . Тем не менее на примере я вижу, что это относительно хорошие отсканированные изображения, поэтому здесь нет необходимости (я вижу проблему с некоторыми символами, которые плохо напечатаны / ксерокопированы, с этим будет сложно что-либо сделать).
РЕДАКТИРОВАТЬ: не буду помещать примеры или ссылки для этого пункта, так как это очень широкая тема c и зависит от качества изображений, от того, как это делается, как выглядит текст, какой фон и c.