Мы используем php, pypdfocr и pdftotext для распознавания текста и извлекаем текст из документов, которые были отсканированы или отправлены нам по факсу. Проблема заключается в том, что документ сканируется или пересылается по факсу вверх ногами или если некоторые страницы предназначены для чтения в альбомной ориентации (поэтому текст на странице поворачивается на 90 градусов)
Вещи, которые я пробовал:
Результирующий текстовый слой OCR для страниц, которые имеют 90-градусный текст, неплох, однако страницы, которые перевернуты вверх ногами, содержат каждое слово OCR и переворачивают его на место, так что если в документе появляется «Это тест», а затем переворачивается текстовый слой может читать «проверить это»
Если есть способ обнаружить, что страница перевернута, я могу использовать pdftk, чтобы повернуть страницы, прежде чем запускать его через OCR (или я могу удалить текстовый слой, если он был OCR’d и запустить его через OCR снова после используя pdftk для вращения)
Любое решение, которое может быть выполнено из CLI linux на данный момент, является жизнеспособным решением.
Вы можете легко получить информацию об ориентации страницы с помощью tesseract (> = 3.03?). Например.
$ tesseract image.png - -psm 0
будет производить этот вывод
Orientation: 3
Orientation in degrees: 90
Orientation confidence: 25.40
Script: 1
Script confidence: 18.40
На основании этой информации вы можете настроить поворот изображения. Пример того, как это сделать в python, может быть, например. по сценарию Исправить поворот изображения с помощью tesseract.
У меня была такая же проблема. Мое исправление состояло в том, чтобы создать простое приложение на C ++, которое принимает имя файла PNG в качестве параметра и автоматически поворачивает / перемещает его.
Мой код
#include <iostream>
#include <cmath>
#include <tesseract/baseapi.h>
#include <leptonica/allheaders.h>
using namespace std;
int main(int argc, char **argv)
{
if (argc != 2) {
cerr << "usage: " << argv[0] << " <image>\n";
exit(1);
}
tesseract::TessBaseAPI *api = new tesseract::TessBaseAPI();
// Initialize tesseract-ocr with English, without specifying tessdata path
if (api->Init(NULL, "eng")) {
cerr << "Could not initialize tesseract.\n";
exit(2);
}
const char* inputfile = argv[1];
tesseract::Orientation orientation;
tesseract::WritingDirection direction;
tesseract::TextlineOrder order;
float deskew_angle;
PIX *image = pixRead(inputfile);
if (image == NULL) {
cerr << "could not open " << inputfile << endl;
return -2;
}
api->SetPageSegMode(tesseract::PSM_AUTO_OSD);
api->SetImage(image);
api->Recognize(0);
tesseract::PageIterator* it = api->AnalyseLayout();
it->Orientation(&orientation, &direction, &order, &deskew_angle);
cout << "Orientation: " << orientation <<
"\nWritingDirection: " << direction <<
"\nTextlineOrder: " << order <<
"\nDeskew angle: " << deskew_angle << "\n";
PIX* pixd = NULL;
switch (orientation) {
case 0:
cout << "image in the correct position, nothing to do\n";
if (fabs(deskew_angle) > 0.0001f) {
cout << "deskewing...\n";
pixd = pixRotate(image, -deskew_angle, L_ROTATE_SHEAR, L_BRING_IN_WHITE, 0, 0);
}
break;
case 1:
cout << "rotating image by 270 degrees\n";
pixd = pixRotate90(image, -1);
if (deskew_angle > 0.0001f) {
cout << "deskewing...\n";
pixd = pixRotate(pixd, -deskew_angle, L_ROTATE_SHEAR, L_BRING_IN_WHITE, 0, 0);
}
break;
case 2:
cout << "rotating image by 180 degrees\n";
pixd = pixRotate180(NULL, image);
if (deskew_angle > 0.0001f) {
cout << "deskewing...\n";
pixd = pixRotate(pixd, -deskew_angle, L_ROTATE_SHEAR, L_BRING_IN_WHITE, 0, 0);
}
break;
case 3:
cout << "rotating image by 90 degrees\n";
pixd = pixRotate90(image, 1);
if (deskew_angle > 0.0001f) {
cout << "deskewing...\n";
pixd = pixRotate(pixd, -deskew_angle, L_ROTATE_SHEAR, L_BRING_IN_WHITE, 0, 0);
}
break;
}
pixDestroy(&image);
if (pixd != NULL) {
pixWrite(inputfile, pixd, IFF_PNG);
pixDestroy(&pixd);
}
return 0;
}
Вы можете скомпилировать его с
g++ -o tesseract_fixposition tesseract_fixposition.cpp -llept -ltesseract
Это зависимости libtesseract и libleptonica. Я тестировал с Tesseract версий 3.03 и 3.04 и Leptonica 1.72. Я обработал несколько тысяч изображений и не нашел неправильной идентификации.
Надеюсь это поможет!
Если скорость является проблемой, вы не должны использовать tesseract для исправления ориентации страницы. Вы можете использовать только функции лептоники. Что-то вроде этого:
/*
* Compile with:
* g++ fixorientation.cpp -o fixorientation -llept
*
*/
#include <cstring>
#include <leptonica/allheaders.h>
int main(int argc, char *argv[]) {
const char* filename = NULL;
const char* outfile = NULL;
l_int32 orient, format;
l_int32 alt_rot = -1;
l_float32 upconf1, leftconf1;
PIX *fpixs, *pixs;
if (argc < 1) {
fprintf(stderr, "Usage is:\n\t%s -f filename [-o output]\n", argv[0]);
return(1);
} else {
for (int i = 1; i < argc; i++) {
if (i + 1 < argc) {
if (strcmp(argv[i], "-f") == 0) {
filename = argv[i + 1];
} else if (strcmp(argv[i], "-o") == 0) {
outfile = argv[i + 1];
}
}
}
}
if (filename) {
pixs = pixRead(filename);
} else {
fprintf(stderr, "Usage is:\n\t%s -f filename [-o output]\n", argv[0]);
return(1);
}
if (pixs == NULL) {
fprintf(stderr, "Unsupported image type.\n");
return(3);
}
format = pixGetInputFormat(pixs);
fpixs = pixConvertTo1(pixs, 130);
pixOrientDetect(fpixs, &upconf1, &leftconf1, 0, 0);
makeOrientDecision(upconf1, leftconf1, 0, 0, &orient, 1);
if (orient == L_TEXT_ORIENT_UNKNOWN) {
fprintf(stdout, "Confidence is low; no determination is made. ""But maybe there is %1 deg rotation.\n", alt_rot);
} else if (orient == L_TEXT_ORIENT_UP) {
fprintf(stdout, "Text is rightside-up\n");
alt_rot = 0;
} else if (orient == L_TEXT_ORIENT_LEFT) {
fprintf(stdout, "Text is rotated 90 deg ccw\n");
alt_rot = 1;
} else if (orient == L_TEXT_ORIENT_DOWN) {
fprintf(stdout, "Text is upside-down\n");
alt_rot = 2;
} else { /* orient == L_TEXT_ORIENT_RIGHT */
fprintf(stdout, "Text is rotated 90 deg cw\n");
alt_rot = 3;
}
if (alt_rot > -1) {
fpixs = pixRotateOrth(pixs, alt_rot);
if (outfile) {
pixWrite(outfile, fpixs, format);
} else {
char savefile[strlen("fixed_") + strlen(filename) + 1];
strcpy(savefile, "fixed_");
strcat(savefile, filename);
fprintf(stdout, "Output save to %s\n", savefile);
pixWrite(savefile, fpixs, format);
}
} else {
return(2);
}
pixDestroy(&fpixs);
pixDestroy(&pixs);
return(0);
}