обнаружить страницы PDF, которые перевернуты

Мы используем php, pypdfocr и pdftotext для распознавания текста и извлечения текста из документов, которые были отсканированы или отправлены нам по факсу. Проблема заключается в том, что документ сканируется или отправляется по факсу в перевернутом виде, или если некоторые страницы предназначены для чтения в альбомной ориентации (поэтому текст на странице повернут на 90 градусов).

Что я пробовал:

  • в tessdata cp eng.traineddata osd.traineddata

Результирующий текстовый слой OCR для страниц с текстом под углом 90 градусов неплох, однако страницы, которые перевернуты, распознают каждое слово и переворачивают его на место, так что если в документе появляется «Это тест», но перевернутый, то текстовый слой может читаться как «проверить это»

Если есть способ определить, что страница перевернута, я могу использовать pdftk для поворота страниц, прежде чем запускать их через OCR (или я могу удалить текстовый слой, если он был OCR, и снова запустить его через OCR после используя pdftk для поворота)

Любое решение, которое может быть выполнено из CLI Linux на данный момент, является жизнеспособным решением.


person tempcke    schedule 05.08.2015    source источник


Ответы (3)


Вы можете легко получить информацию об ориентации страницы с помощью 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, может быть, например. в скрипте Исправить поворот изображения с помощью тессеракта.

person user898678    schedule 05.08.2015
comment
Спасибо, с помощью этого я могу написать скрипт для автоматической обработки очереди (исправить ротацию и распознавание текста). Как только я закончу, я опубликую его здесь на случай, если он будет полезен кому-то еще в будущем. - person tempcke; 05.08.2015
comment
С tesseract v4 это работает: tesseract image.png - --psm 0 - person jftuga; 02.05.2019

У меня была такая же проблема. Мое исправление состояло в том, чтобы создать простое приложение 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. Я обработал несколько тысяч изображений и не нашел ни одной некорректной идентификации.

Надеюсь это поможет!

person gxrmr    schedule 06.08.2015
comment
Ницца. На самом деле я имею дело с PDF-файлом, поэтому я написал скрипт на php, который перебирает страницы PDF-файла, запускает команду оболочки convert для преобразования каждой страницы в png, затем я выполняю tesseract на странице png и анализировать вывод, создавая строку по мере того, как я прохожу цикл для передачи в pdftk. Это работает отлично, но потребовалось 4 минуты, чтобы исправить вращение, а затем распознать окончательный документ. Идея совместимого приложения на С++ кажется хорошей идеей, поскольку она, вероятно, значительно ускорит работу. Насколько сложно было бы изменить этот сценарий, чтобы исправить каждую страницу PDF-файла? - person tempcke; 06.08.2015
comment
В моем случае это занимает несколько секунд на страницу. Я использую это приложение в рабочем процессе, который извлекает каждую страницу с помощью muPDF, готовит ее для извлечения и запускает Tesseract для извлечения. Я использую mudraw -r 300 -g -o <PNG file> <PDF file> <page number> для каждой страницы, затем это приложение для сгенерированных PNG. - person gxrmr; 06.08.2015

Если проблема со скоростью, вам не нужно использовать tesseract для исправления ориентации страницы. Вы можете использовать только функции leptonica. Что-то вроде этого:

/*
 * 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);
}
person user898678    schedule 09.08.2015