Удалите текст OCR из документа PDF с помощью Apache PDFBox - PullRequest
0 голосов
/ 04 сентября 2018

Некоторые из документов PDF в системе были созданы путем сканирования с включенным текстом OCR. Однако распознавание не было выполнено правильно (смешанные символы кириллицы и латиницы), и хотя документ выглядит как доступный для поиска, эта информация совершенно неверна и непригодна для использования.

При просмотре документа PDF в Adobe Acrobat Reader DC (или Google Chrome) он отображается правильно, но на веб-странице, использующей PDF.js для визуализации документа, текст распознавания отображается спереди вместо отсканированного графического представления. оригинального текста.

Идея состоит в том, чтобы "восстановить" эти документы, удалив текст OCR из документа PDF, сохранив при этом отсканированное графическое представление исходного текста.

Для этой цели я использовал Apache PDFBox 2.0.11 для проверки содержимого документа PDF. Следующий фрагмент кода распечатывает весь текст, содержащийся в документе PDF, и в этом случае весь текст в точности совпадает с текстом OCR:

PDDocument document = PDDocument.load(new File("D:/input.pdf"));
PDFTextStripper stripper = new PDFTextStripper();
stripper.setStartPage(1);
stripper.setEndPage(document.getNumberOfPages());
String sText = stripper.getText(document);
System.out.println(sText);
document.close();

Затем я использовал пример класса RemoveAllText , предоставляемый с PDFBox, в надежде удалить текст OCR из документа PDF. К сожалению, он удалил не только текст OCR, но и графическое представление оригинального отсканированного текста. Метод, который проверяет текстовые элементы в PDF-документе и удаляет их, показан ниже:

private static List<Object> createTokensWithoutText(PDContentStream contentStream) throws IOException
{
    PDFStreamParser parser = new PDFStreamParser(contentStream);
    Object token = parser.parseNextToken();
    List<Object> newTokens = new ArrayList<Object>();
    while (token != null)
    {
        if (token instanceof Operator)
        {
            Operator op = (Operator) token;
            if ("TJ".equals(op.getName()) || "Tj".equals(op.getName()) ||
                "'".equals(op.getName()) || "\"".equals(op.getName()))
            {
                // remove the one argument to this operator
                newTokens.remove(newTokens.size() - 1);

                token = parser.parseNextToken();
                continue;
            }
        }
        newTokens.add(token);
        token = parser.parseNextToken();
    }
    return newTokens;
}

Я предполагаю, что этот метод должен быть изменен каким-либо образом (чтобы удалить только текст, а не удалять его графическое представление), но я не знаю, как это сделать.

Вот пример PDF-документа перед RemoveAllText , и вот пример документа PDF после RemoveAllText .

1 Ответ

0 голосов
/ 09 сентября 2018

В коде createTokensWithoutText, который вы скопировали из примеров PDFBox, действительно есть ошибка. Но причина того, что этот пример удаляет весь текст из вашего отсканированного PDF, заключается в том, что сканер уже удалил буквы с изображения, создал для них специальные шрифты и снова нарисовал их как текст, используя эти шрифты, поэтому пример просто делает то, что нужно предназначен для этого.

Ошибка в createTokensWithoutText

В то время как текст, показывающий операторы Tj , ' и TJ действительно имеют только один параметр, " имеет три:

a w a c string " - Перейдите к следующей строке и покажите текстовую строку, используя a w в качестве межстрочного интервала и a c в качестве межсимвольного интервала ( установка соответствующих параметров в текстовом состоянии). a w и a c должны быть числами, выраженными в немасштабированных единицах текста.

(ISO 32000-1 Таблица 109 - Операторы отображения текста)

Если в потоке есть операция ", следовательно, createTokensWithoutText удаляет только строковый аргумент и оператор, но оставляет числовые параметры a w и c на месте. Это, в свою очередь, приводит к неверному набору аргументов для следующей инструкции в newTokens.

Как сканируется пример PDF

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

Таким образом, оставшееся изображение содержит только некоторую грязь, которую программное обеспечение не связывало ни с одним глифом.

Специальные шрифты содержат следующие глифы:

screenshot

Как видите, шрифты даже содержат несколько глифов для одной и той же распознанной буквы, например, для «H» здесь 9, 13 и 15.

Преимущество этого подхода состоит в том, что PDF-файлы могут работать проще, текстовые блоки могут редактироваться.

К сожалению, для вашего случая, однако, программное обеспечение OCR, похоже, знает только латинские и арабские цифры, в частности, оно не знает кириллических символов. Таким образом, он присваивает кириллические глифы наиболее сходным латинским или арабским цифрам.

Это, конечно, делает бессмысленным извлечение текста. Кроме того, некоторые зрители показывают назначенный латинский символ, используя некоторый стандартный шрифт вместо символа из специального шрифта, в частности, при маркировке текста, и текст, показанный таким образом, также не имеет смысла.


Таким образом, вам следует либо снова сканировать с отключенным оптическим распознаванием символов, либо экспортировать PDF-файлы как изображения и создавать новые PDF-файлы только из этих изображений.

...