Так случилось, что понадобилось нам внедрить в своё приложение возможность распознавания текста, поэтому начались поиски подходящей библиотеки. В конечном счёте остановились на двух опенсорсных проектах CuneiForm Linux и Tesseract-ocr. Внимательное изучение проекта CuneiForm показало, что это просто порт продукта компании Cognitive Technologies, исходники которого они открыли в 2008 году и благополучно забили получив свою порцию внимания (во всяком случае такое сложилось впечатление). По сути весь проект состоял в портировании, а о новых фичах даже речи не шло. Всё это, вкупе с печальной новостью на страничке проекта, заставило нас отказаться от CuneiForm в пользу Tesseract, который в данный момент принадлежит Google, что даёт некоторую уверенность в будущем проекта. Под катом опыт сборки Tesseract-ocr под Windows с использованием MinGW и последующего создания простейшего приложения на С++.
Я постараюсь описать всё что нужно сделать, чтобы собрать tesseract с минимальной головной болью, при этом постараюсь не углубляться в банальности.
Скачиваем и устанавливаем последний доступный инсталлятор с официального сайта проекта, не забываем выставить галочки для C++ Compiler и MSYS Basic System. После этого заходим в MinGW Shell и устанавливаем дополнительные пакеты, которые понадобятся нам позже, следующей командой:
Сразу заметим, что в /mingv примонтирован каталог, в который установлен MinGW, это нам также пригодится при сборке библиотек.
Tesseract-ocr использует для работы с изображениями библиотеку Leptonica, я опишу как собрать и установить её из исходных кодов, которые можно взять с официального сайта, но перед этим нам нужно установить библиотеки libJpeg, libPng и libTiff, которые в свою очередь использует Leptonica (сделаем это также сборкой из исходных кодов).
Скачиваем архив с исходными кодами с официального сайта и распаковываем в отдельный каталог (для простоты будем считать, что это D:\lib\jpeg). Возвращаемся в MinGW Shell и лёгким движением руки собираем и устанавливаем библиотеку в каталоги, в которых gcc ищет по умолчанию. Флаги переопределяем чтобы отключить вывод отладочных символов.
Также скачиваем архив с исходными кодами со странички проекта и распаковываем в каталог D:\lib\png (Вы, естественно, можете выбрать другой). Возвращаемся в MinGW Shell и повторяем то же самое, что и для libJpeg.
Архив с исходными кодами берём с рекомендуемого ftp и распаковываем в D:\lib\tiff. И собираем аналогично предыдущим двум.
Архив с исходными кодами у нас уже есть, осталось его распаковать в D:\lib\leptonica. А дальше впору вспомнить про напильник, сборка с поддержкой Zlib не удастся из-за небольшого бага, который впрочем легко исправить самостоятельно. Для этого открываем файл src/pngio.c, расположенный в каталоге, куда мы распаковали исходники Leptonica. Там необходимо найти строку #include «png.h» и вставить после неё директивы, чтобы получилось примерно вот так:
После этого собираем Leptonica так же как и предыдущие библиотеки.
Теперь у нас есть все необходимые зависимости. Скачивать исходники на этот раз будем из транка svn разработчиков:
*пробел между t преднащначен исключительно для хабрапарсера, уберите его.
После чего опять берёмся за напильник, я же предварительно сэкспортировал исходники в D:\lib\tesseract.
Пути к файлам я буду писать относительно каталога, в котором находятся исходники tesseract (напомню, что в моём случае это D:\lib\tesseract).
После этих манипуляций можно перейти в MinGW Shell и приступить к непосредственной сборке библиотеки:
Пока он собирался я успел попить чаю, а после обнаружил пачку заголовочных файлов в /mingw/include/tesseract, заголовочные файлы Leptonica расположились в /mingw/include/leptonica, все библиотеки закономерно оказались в /mingw/lib.
Я приведу код целиком, так как он весьма мал:
Собрать наше приложение можно командой:
Линковка статическая, так как текущая версия tesseract не поддерживает создание DLL.
По своему опыту знаю, что сложнее всего начать, поэтому надеюсь, что мой рассказ будет кому-нибудь полезен, особенно учитывая, что документации по Tesseract в сети преступно мало и основную, пожалуй, можно вытянуть из самих исходников с помощью doxygen.
PS: некоторые идеи для фиксов были почерпнуты в этом посте за что автору огромное спасибо.
Подготовка
Я постараюсь описать всё что нужно сделать, чтобы собрать tesseract с минимальной головной болью, при этом постараюсь не углубляться в банальности.
Установка и настройка MinGW
Скачиваем и устанавливаем последний доступный инсталлятор с официального сайта проекта, не забываем выставить галочки для C++ Compiler и MSYS Basic System. После этого заходим в MinGW Shell и устанавливаем дополнительные пакеты, которые понадобятся нам позже, следующей командой:
mingw-get install mingw32-automake mingw32-autoconf mingw32-autotools mingw32-libz
Сразу заметим, что в /mingv примонтирован каталог, в который установлен MinGW, это нам также пригодится при сборке библиотек.
Устанавливаем библиотеку Leptonica
Tesseract-ocr использует для работы с изображениями библиотеку Leptonica, я опишу как собрать и установить её из исходных кодов, которые можно взять с официального сайта, но перед этим нам нужно установить библиотеки libJpeg, libPng и libTiff, которые в свою очередь использует Leptonica (сделаем это также сборкой из исходных кодов).
Сборка libJpeg
Скачиваем архив с исходными кодами с официального сайта и распаковываем в отдельный каталог (для простоты будем считать, что это D:\lib\jpeg). Возвращаемся в MinGW Shell и лёгким движением руки собираем и устанавливаем библиотеку в каталоги, в которых gcc ищет по умолчанию. Флаги переопределяем чтобы отключить вывод отладочных символов.
cd /D/lib/jpeg
./configure CFLAGS='-O2' CXXFLAGS='-O2' --prefix=/mingw
make
make install
Сборка libPng
Также скачиваем архив с исходными кодами со странички проекта и распаковываем в каталог D:\lib\png (Вы, естественно, можете выбрать другой). Возвращаемся в MinGW Shell и повторяем то же самое, что и для libJpeg.
Сборка libTiff
Архив с исходными кодами берём с рекомендуемого ftp и распаковываем в D:\lib\tiff. И собираем аналогично предыдущим двум.
Сборка Leptonica
Архив с исходными кодами у нас уже есть, осталось его распаковать в D:\lib\leptonica. А дальше впору вспомнить про напильник, сборка с поддержкой Zlib не удастся из-за небольшого бага, который впрочем легко исправить самостоятельно. Для этого открываем файл src/pngio.c, расположенный в каталоге, куда мы распаковали исходники Leptonica. Там необходимо найти строку #include «png.h» и вставить после неё директивы, чтобы получилось примерно вот так:
#include "png.h"
#ifdef HAVE_LIBZ
#include "zlib.h"
#endif
/* ----------------Set defaults for read/write options ----------------- */
После этого собираем Leptonica так же как и предыдущие библиотеки.
Сборка и установка Tesseract-ocr
Теперь у нас есть все необходимые зависимости. Скачивать исходники на этот раз будем из транка svn разработчиков:
svn checkout ht tp://tesseract-ocr.googlecode.com/svn/trunk/ tesseract-ocr-read-only
*пробел между t преднащначен исключительно для хабрапарсера, уберите его.
После чего опять берёмся за напильник, я же предварительно сэкспортировал исходники в D:\lib\tesseract.
Пути к файлам я буду писать относительно каталога, в котором находятся исходники tesseract (напомню, что в моём случае это D:\lib\tesseract).
- Редактируем файл ccutil/platform.h. Нам нужно закомментировать повторное объявление типа BLOB, которое уже есть в winsock2.h. Должно получиться, что-то вроде:
/*typedef struct _BLOB {
unsigned int cbSize;
char *pBlobData;
} BLOB, *LPBLOB;*/ - Из vs2008/port копируем файлы strtok_r.h и strtok_r.cpp в каталог ccutil и добавляем strtok_r.cpp в переменную libtesseract_ccutil_la_SOURCES в файле ccutil/Makefile.am.
- Комментируем объявление класса PBLOB в api/baseapi.h.
- В файле api/Makefile.am дополняем переменную AM_CPPFLAGS значением -I$(top_srcdir)/vs2008/port
или просто копируем файл vs2008/port/version.h в каталог api - Дополняем переменную AM_CPPFLAGS в файле viewer/Makefile.am значением -I$(top_srcdir)/ccutil
После этих манипуляций можно перейти в MinGW Shell и приступить к непосредственной сборке библиотеки:
cd /D/lib/tesseract
./runautoconf
./configure CFLAGS='-D__MSW32__ -O2' CXXFLAGS='-D__MSW32__-O2' LIBS='-lws2_32' LIBLEPT_HEADERSDIR='/mingw/include' --prefix=/mingw
make
make install
Пока он собирался я успел попить чаю, а после обнаружил пачку заголовочных файлов в /mingw/include/tesseract, заголовочные файлы Leptonica расположились в /mingw/include/leptonica, все библиотеки закономерно оказались в /mingw/lib.
Простое приложение
Я приведу код целиком, так как он весьма мал:
#include <stdio.h>
#include <string.h>
#include <tesseract/baseapi.h>
#include <leptonica/allheaders.h>
int main(int argc, char* argv[]) {
tesseract::TessBaseAPI tessApi;
tessApi.Init("data", "rus");// тут data каталог в котором лежат файлы *.traineddata,
// а rus указывает какой именно из них использовать
if(argc > 1) {
PIX *pix = pixRead(argv[1]);// считываем картинку из файла с именем,
// переданным первым аргументом, это функционал Leptonica
tessApi.SetImage(pix);// говорим tesseract, что распознавать нужно эту картинку
char *text = tessApi.GetUTF8Text();//распознаём
//---генерируем имя файла в который будет записан распознанный текст
char *fileName = NULL;
long prefixLength;
const char* lastDotPosition = strrchr(argv[1], '.');
if(lastDotPosition != NULL) {
prefixLength = lastDotPosition - argv[1];
fileName = new char[prefixLength + 5];
strncpy(fileName, argv[1], prefixLength);
strcpy(fileName + prefixLength, ".txt\0");
} else {
exit(1);
}
//---
FILE *outF = fopen(fileName, "w");
fprintf(outF, "%s", text);
fclose(outF);
//---
pixDestroy(&pix);
delete [] fileName;
delete [] text;
}
return 0;
}
Собрать наше приложение можно командой:
g++ -O2 test.cpp -o test.exe -ltesseract_api -ltesseract_main -ltesseract_textord -ltesseract_wordrec -ltesseract_ccstruct -ltesseract_ccutil -ltesseract_classify -ltesseract_dict -ltesseract_image -ltesseract_viewer -ltesseract_cutil -ltesseract_cube -ltesseract_neural -llept -lws2_32
Линковка статическая, так как текущая версия tesseract не поддерживает создание DLL.
Заключение
По своему опыту знаю, что сложнее всего начать, поэтому надеюсь, что мой рассказ будет кому-нибудь полезен, особенно учитывая, что документации по Tesseract в сети преступно мало и основную, пожалуй, можно вытянуть из самих исходников с помощью doxygen.
PS: некоторые идеи для фиксов были почерпнуты в этом посте за что автору огромное спасибо.