image

Сегодня я покажу, как добавить опцию распознавания текста (OCR) в Ваше Android приложение.

Наш тестовый проект — это один единственный Activity, в который я запихнула и распознавание. Итого в общем счете всего 200 строк кода.

Замечу сразу, что опция OCR работает offline. OCR увеличивает ваш .apk приблизительно на 17mb.

Tesseract — пожалуй, самая популярная и качественная бесплатная OCR библиотека, у которой до сих пор выходят апдейты. Создатели Tesseract — разработчики из Google.

Tesseract написан на С, но существует проект tess-two — готовый инструмент по использованию Tesseract на Android платформе. Он предоставляет Java API для доступа к изначально скомпилированным Tesseract классам. Все, что нужно — это добавить tess-two в ваш build.gradle:

dependencies {
    compile 'com.rmtheis:tess-two:5.4.1'
}

Кроме этого тессеракту потребуется .traineddata файл. Этот файл содержит данные для эффективного распознавания, словари слов и прочее. Файл уникален для каждого языка. Скачать .traineddata для любого языка можно по ссылке. Замечу, что есть возможность создать свой собственный .traineddata файл. Это может быть полезно, если вы распознаете специфический текст или у вас свой словарь возможных слов. Теоретически, кастомизация повысит качество распознавания.

Перед тем, как перейти к java коду, убедитесь в том, что вы положили в проект файл для английского языка eng.traideddata. Например, в src\main\assets\tessdata.

Вам потребуется сконфигурировать тессеракт, перед тем как запускать распознавание. Для этого нужно передать в метод конфигурации (init) два параметра — путь к папке tessdata на вашем Android устройстве и язык («eng»). Будьте внимательны, путь к папке tessdata, а не к .traideddata файлу, если папка будет названа иначе, код не будет работать. Очевидно, вам эту папку нужно создать на external storage и поместить в неё eng.traideddata.

Привожу метод, который из Bitmap получает распознанный текст:

import com.googlecode.tesseract.android.TessBaseAPI;
//...

private String extractText(Bitmap bitmap) throws Exception
{
	TessBaseAPI tessBaseApi = new TessBaseAPI();
	tessBaseApi.init(DATA_PATH, "eng");
	tessBaseApi.setImage(bitmap);
	String extractedText = tessBaseApi.getUTF8Text();
	tessBaseApi.end();
	return extractedText;
}

Да-да, очень просто.

Результат

image

Рекомендации

1. Лучше запускать OCR на сервер стороне. Если у вас Java проект — используйте tess4j — JNA wrapper для Tesseract. Качество распознавания выше на 20-30%. Не садит батарею, не утяжеляет .apk.

2. Используйте предобработку изображения, перед тем как распознавать. Самый простой способ — заставить юзера выделить блок с текстом, что бы уменьшить площадь распознавания. Сюда можно отнести и выравнивание искажений, удаление шумов, цветокоррекцию.

Исходный код доступен здесь.

На этом все.

Комментарии (8)


  1. darkAlert
    27.04.2016 15:02
    +1

    эмм… ну как бы все эти инструкции и примеры приведены на гитхабе (и там даже больше). Т.е. вы сделали просто перевод? В чем ценность вашей статьи?


    1. ashomokdev
      27.04.2016 15:07

      Ценность в том, что я написала короткое введение — для тех, кто вообще ничего не знает об OCR на Android. Читателю будет понятно, с чего начать изучать вопрос и на какой результат можно рассчитывать. Мой гитхаб проект тоже нацелен облегчить задачу понимания работы Tesseract.


  1. Klukonin
    27.04.2016 15:07

    Хотелось бы больше про реальное применение аффинных преобразований и как можно это реализовать в интерфейсе приложения =)

    На сколько помню, в лептонике предобработка неплохая получается, правда некоторые заморачиваются и пытаются делать преобразования на стороне. На сколько это оправданно?


    1. ashomokdev
      27.04.2016 15:11

      Не отвечу, не приходилось использовать. Если Вы знаете, как можно быстро повысить качество картинки перед распознаванием — напишите сюда в двух-трех словах.


      1. darkAlert
        27.04.2016 15:22

        Tesseract чувствителен к перепадам яркости, поэтому нелишним будет использовать в качестве препроцессинга либо классический алгоритм автоуровней, либо CLAHE (есть реализация в opencv)


        1. Klukonin
          27.04.2016 17:55

          На сколько я смотрел вывод лептоники — там как раз и делается суперконтрастность перед распознаванием. То есть, как можно более резкие перепады яркости. Автоуровень или динамическая контрастность — это совсем не то что нужно для правильного распознавания текста. С разпознаванием лиц и объектов немного другая тема и там совершенно другие приемы.


          1. darkAlert
            27.04.2016 18:08

            Автоуровни не регулируют контрастность, они выравнивают яркость пикселей так, чтобы максимумы яркости в разных частях изображение были примерно одинаковыми. А вот CLAHE в добавок еще и усиляет контрастность.

            «Автоуровень или динамическая контрастность — это совсем не то что нужно для правильного распознавания текста.»
            Я бы был осторожен с такими смелыми выводами, если бы у меня не было фактов, подтверждающих это. А у вас они есть? Где можно почитать?


            1. Klukonin
              28.04.2016 08:33

              Ах, если бы каждый технарь где-то документировал свой ежедневный опыт в доступной для чтения форме — вот зажили бы.
              С чего такая уверенность наличия печатны источников, отражающих конкретное мнение автора, высказывающего ту или иную идею?
              Можно предположить, что автор работал с распознаванием текста, возможно, даже не только текста, возможно, даже и не один.
              В любом случае, нить здравого диалога вы уже оборвали.
              Выводы могут быть сколь угодно смелыми, пока это не рецензия, не платная консультация или нечто подобное.
              А отчитываться перед первым встречным никто не будет ;-)