Пользователь
0,0
рейтинг
26 января 2011 в 18:57

Разработка → Знакомство с OCR библиотекой tessnet2 (язык C#) из песочницы

example
Буквально на днях у меня появилась необходимость распознать простой текст на картинке и совсем не было желания реализовывать свой алгоритм, т.к. знаком с теорией и знаю, что это не такое простое дело, поэтому сразу решил изучить сначала рынок готовых библиотек. Буквально несколько запросов в гугл и я понял, что ничего более подходящего мне как библиотека tessnet2 невозможно найти. Постоянно читаю хабр и знаю, что тут есть уйма статей посвященных теории OCR и очень удивился, что нет ничего о библиотеке tessnet2.

tessnet2 основана на Tesseract OCR


Движок Tesseract OCR был одним из 3-х лучших движков представленных в 1995 году на UNLV Accuracy test. В период между 1995 годом и 2006 годом он был немного доработан, но, вероятно, это один из наиболее точных OCR движков, который доступен с открытым исходным кодом. Код, который доступен будет читать бинарные, серые или цветное изображение и выводить текст. Чтение TIFF построено так, что будут читаться несжатые TIFF изображения или могут быть добавлены Libtiff для чтения сжатых изображений.

Как использовать Tessnet2:
1. Загружаем библиотеку, добавляем ссылку (reference) на Tessnet2.dll в .NET проекте.
2. Загружаем нужный нам язык (лично мне необходим английский) (tesseract-2.00.eng.tar.gz) и складываем в папку tessdata. Папка tessdata обязательно должна быть рядом с исполняемым файлом нашего приложения.

Для того, чтобы прочитать текст с картинки достаточно такого текста:
Bitmap image = new Bitmap("eurotext.tif");
tessnet2.Tesseract ocr = new tessnet2.Tesseract();
ocr.SetVariable("tessedit_char_whitelist", "0123456789"); // If digit only
ocr.Init(@"c:\temp", " eng ", false); // To use correct tessdata
List<tessnet2.Word> result = ocr.DoOCR(image, Rectangle.Empty);
foreach (tessnet2.Word word in result)
  Console.WriteLine("{0} : {1}", word.Confidence, word.Text);


* This source code was highlighted with Source Code Highlighter.

Я был очень рад результату, поэтому сразу вспомнил о том, что несколько месяцев назад прикручивал сервис для разгадывания каптч для одного проекта, сразу скажу, что ничего хорошего из этого не вышло, там нужна была скорость, но её не удалось там получить, т.к. подобные сервисы не способны её обеспечить, да и результат как правило плачевный, оно и понятно, т.к. платят там от 1 доллара за 1000 правильно введённых каптч, что мягко сказать ужасно. Поэтому эксперимента ради я решил поиграть с данной библиотекой на том примере.
Исходными данными для нас будет являться каптча, на которой нужно произвести простейшие действия над двумя числами и получить ответ. Звучит довольно просто, но вот проблема ещё в том, что все символы разных цветов и имеется динамический фон, порой даже мне (человеку) сложно понять сходу, что там написано.

Сразу привожу результаты работы программы, после чего я расскажу как это всё работает:

screenshot1

screenshot2

screenshot3

screenshot4

screenshot5

На скриншотах чётко видно, что библиотека не может ничего разгадать из-за кучи линий, порой мешает и фон, который был убран не целиком. Поэтому я разработал свой небольшой алгоритм для чистки картинки, ничего в нём грандиозного нет, я просто отступаю несколько пикселей от края и пробегаю по прямоугольнику и собираю там цвета, также собираю цвета после первой цифры и перед знаком равно (последнее это больше хак, но т.к. статья посвящена другому, то оставил так). Всё что мне надо сделать потом – это закрасить все цвета, которые попали ко мне в коллекцию и не являются белым цветом.

Из всех алгоритмов наиболее полезным может быть только алгоритм закрашивания области на Bitmap`е:
void FloodFill(Bitmap bitmap, int x, int y, Color color)
    {
      BitmapData data = bitmap.LockBits(
        new Rectangle(0, 0, bitmap.Width, bitmap.Height),
        ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
      int[] bits = new int[data.Stride / 4 * data.Height];
      Marshal.Copy(data.Scan0, bits, 0, bits.Length);

      LinkedList<Point> check = new LinkedList<Point>();
      int floodTo = color.ToArgb();
      int floodFrom = bits[x + y * data.Stride / 4];
      bits[x + y * data.Stride / 4] = floodTo;

      if (floodFrom != floodTo)
      {
        check.AddLast(new Point(x, y));
        while (check.Count > 0)
        {
          Point cur = check.First.Value;
          check.RemoveFirst();

          foreach (Point off in new Point[] {
        new Point(0, -1), new Point(0, 1),
        new Point(-1, 0), new Point(1, 0)})
          {
            Point next = new Point(cur.X + off.X, cur.Y + off.Y);
            if (next.X >= 0 && next.Y >= 0 &&
              next.X < data.Width &&
              next.Y < data.Height)
            {
              if (bits[next.X + next.Y * data.Stride / 4] == floodFrom)
              {
                check.AddLast(next);
                bits[next.X + next.Y * data.Stride / 4] = floodTo;
              }
            }
          }
        }
      }

      Marshal.Copy(bits, 0, data.Scan0, bits.Length);
      bitmap.UnlockBits(data);
    }
  }


* This source code was highlighted with Source Code Highlighter.

Для тех кому интересно самому поэкспериментировать прикрепляю исходный код.

Итог


Мы познакомились с довольно интересной библиотекой tessnet2, проверили её работу в реальных условиях, добились довольно неплохих результатов разгадывания для сложных картинок (каптч), конечно ошибки есть, но их количество ничтожно мало, тем более для данного вида каптч можно добавить проверку с помощью регулярного выражения и Вы точно будете знать, что разгаданный текст соответствует нужному формату.
@eforce
карма
46,5
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

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

  • +3
    Простите, но первая картинка вырвиглазна.
    • 0
      Уменьшил её более чем на 20 процентов, теперь она не режет так глаза.
    • +2
      Как ты умудряешься быть первым в который раз? O_o
      • +13
        F5-Джедай
  • –1
    Движок Tesseract OCR был одним из лучших 3 двигателей в 1995 году на UNLV Accuracy test. В период между 1995 и 2006 годах он был немного доработан, но это, вероятно, один из наиболее точных OCR движков доступный с открытым исходным. Исходный код будет читать бинарные, серые или цветное изображение и выводить текст.

    Местами читать очень тяжело, например, как в приведенном примере.
    • +2
      Спасибо за критику, выделенный кусок текста — это описание, которое я взял с сайта и перевёл, поэтому получилось не очень красиво, теперь как мне кажется стало лучше.
  • –3
    Статья в помощь спамерам.
  • 0
    Не поверите, но на днях игрался с этой библиотекой и тоже хотел написать статью:)
    Мне удалось распознать капчи двух крупнейших сотовых операторов и суверенного лепрозория. Занимался этим для саморазвития, даже не знаю, что теперь с этими наработками делать… спамерам отдавать не хочу.
    • +1
      Отдайте админам крупнейших сотовых операторов и суверенного лепрозория. Им пригодится.
      • +1
        ога, и новую капчу, которую после этого поставят не разгадает даже человек)
  • +2
    Меня убивают некоторые капчи из статьи. Такое ощущение что авторы специально старались усложнить жизнь не спамерам, а обычным пользователям. Ставить оранжевые чифры на красном фоне, учитывая то, что машине абсолютно пофиг как сильно в этом случае различаются цвета фона и шрифта — верх глупости.
  • +1
    Друзья, что насчет кириллицы?
    • 0
      В списке он есть:
      code.google.com/p/tesseract-ocr/downloads/list
      • 0
        Но похоже, это для третьей версии :(
        Для второй нет.
    • 0
      Как показал мой личный опыт, третий тессеракт работает с кириллицей довольно скверно. У меня результаты получились хуже, чем на cuneiform.
  • 0
    Небольшая ложка дегтя:
    «Tesseract C++ source code is full of memory leak. Using tessnet2 assembly several time will cause memory overflow. This is not tessnet2 leak, this is tesseract leak and I spent two days in tesseract source code trying to improve this with no success. See what I think about this
  • 0
    Шикарно, использовал tessnet2 для License plate recognition. Но были проблемы с нахождением номера на фото, а также если сфотографирован под углом…
    Автор подобным не занимался?
    • 0
      Хороший пример реального приложения, но, к сожалению подобных задач я ещё не встречал в своей работе, думаю ещё все впереди.
  • 0
    А вы случайно не заморачивались подготовкой этой библиотеки для распознавания какого-нибудь особенного шрифта? Просто я столкнулся с пробемой, что абсолютно читаемые человеческому глазу черные цифры на белом фоне очень криво распознаются этой библиотекой. А так как распознавать надо только цифры, хочется прям чуть ли не задать ей все картинки цифр вручную. Как лучше это сделать?
    Пробовал по инструкции code.google.com/p/tesseract-ocr/wiki/TrainingTesseract3, но что-то очень тяжело все для меня…
    • 0
      Уже нашел и обучалку под .Net, и отличную программу VietOCR, которая позволяет проверить подготовленные по шрифту данные. Ну и чтобы их потом использовать, нужно было просто подобрать работающую библиотечку. Кстати, можно ее взять и из той же программы.
      Но в конечном итоге я столкнулся с ситуацией, что несмотря на все обучение и качественную пред-обработку, программа иногда отказывалась распознавать число без указания рамки… В общем, вернулся на старую tesseract2, она работает с дефолтным языком даже стабильнее, чем новая почему-то.
      А еще позже я выяснил (это есть в комментарии выше), что эти библиотеки страдают утечками памяти.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.