Пакетная программа OCR для PDF-файлов

Об этом уже спрашивали, но я не знаю, помогают ли мне ответы. Вот моя проблема: я получил кучу (около 10 000) PDF-файлов. Некоторые из них были текстовыми файлами, которые были сохранены с использованием функции печати Adobe (поэтому их текст идеален, и я не хочу рисковать их испортить). А некоторые были отсканированными изображениями (поэтому у них нет текста, и мне придется согласиться на распознавание текста). Файлы находятся в одном и том же каталоге, и я не могу сказать, который есть какой. В конечном итоге я хочу превратить их в файлы.txt и затем обработать их. Поэтому я хочу максимально точное распознавание текста.

Кажется, что люди рекомендовали:

  1. Adobe PDF (у меня нет лицензионной копии этого, так что... плюс, если ABBYY Finereader или что-то лучше, зачем платить, если я не буду его использовать)
  2. ocropus (я не могу понять, как использовать эту вещь),
  3. Тессеракт (кажется, что это было здорово в 1995 году, но я не уверен, что есть что-то более точное, плюс он не работает с pdfs изначально, и мне приходится конвертировать в TIFF. Это поднимает свою проблему, так как у меня нет лицензионная копия acrobat, поэтому я не знаю, как конвертировать 10 000 файлов в формат TIFF. Кроме того, я не хочу, чтобы 10 000 документов на 30 страницах превращались в 30 000 отдельных изображений TIFF).
  4. wowocr
  5. pdftextstream (это было с 2009 года)
  6. ABBYY FineReader (очевидно, это $$$, но я потрачу 600 долларов, чтобы сделать это, если эта вещь значительно лучше, то есть имеет более точный ocr).

Кроме того, я неравнодушен к программированию, поэтому, если на изучение того, как что-то сделать, уйдут недели, я бы скорее заплатил $$$. Спасибо за вклад / опыт.

Кстати, я использую Linux Mint 11 64 бит и / или Windows 7 64 бит.

Вот другие темы:

Пакетное распознавание PDF-файлов, которые еще не были OCR'd

OCR с открытым исходным кодом

Подход к извлечению текста в PDF с использованием OCR

https://superuser.com/questions/107678/batch-ocr-for-many-pdf-files-not-already-ocred

5 ответов

Просто, чтобы исправить некоторые из ваших заблуждений...

"У меня нет лицензионной копии acrobat, поэтому я не знаю, как конвертировать 10000 файлов в формат TIFF".

Вы можете конвертировать PDF-файлы в формат TIFF с помощью бесплатного (как в свободе) и бесплатного (как в пиве) Ghostscript. На ваш выбор, если вы хотите сделать это на Linux Mint или на Windows 7. Командная строка для Linux:

gs \
 -o input.tif \
 -sDEVICE=tiffg4 \
  input.pdf

"Я не хочу, чтобы 10 000 документов на 30 страницах превратились в 30 000 отдельных изображений в формате TIFF"

Вы можете легко "многостраничные" TIFFs. Вышеприведенная команда создает такие TIFF-файлы типа G4 (Fax Tiff). Если вам даже нужны одностраничные TIFF, вы можете изменить команду:

gs \
 -o input_page_%03d.tif \
 -sDEVICE=tiffg4 \
  input.pdf

%03d часть выходного имени файла будет автоматически переведена в серию 001, 002, 003 и т.п.

Предостережения:

  1. Разрешение по умолчанию для tiffg4 Выходное устройство составляет 204х196 точек на дюйм. Вы, вероятно, хотите лучшую ценность. Чтобы получить 720 точек на дюйм вы должны добавить -r720x720 в командной строке.
  2. Кроме того, если ваша установка Ghostscript использует букву в качестве размера носителя по умолчанию, вы можете изменить его. Ты можешь использовать -gXxY установить widthxheight в точках устройства. Таким образом, чтобы получить размеры выходной страницы ISO A4 в альбомной ориентации, вы можете добавить -g8420x5950 параметр.

Таким образом, полная команда, которая управляет этими двумя параметрами, для вывода 720 точек на дюйм на A4 в портретной ориентации, будет выглядеть так:

gs \
 -o input.tif \
 -sDEVICE=tiffg4 \
 -r720x720 \
 -g5950x8420 \
  input.pdf

Я подумал, что постараюсь внести свой вклад, ответив на мой собственный вопрос (я написал хороший код для себя и не смог бы сделать это без помощи этой доски). Если вы просматриваете pdf-файлы в unix (ну, для меня osx), то в pdf-файлах с текстом будет слово "Font" (как строка, но смешанная с другим текстом), так как Файл сообщает Adobe, какие шрифты нужно отображать.

Команда cat в bash, похоже, имеет тот же результат, что и чтение файла в двоичном режиме в python (при открытии файла используется режим "rb" вместо "w", "r" или "a"). Таким образом, я предполагаю, что все PDF-файлы, содержащие текст, имеют слово "Font" в двоичном выводе, и что никакие файлы только для изображений никогда не будут. Если это всегда так, то этот код создаст список всех файлов pdf в одном каталоге, в котором есть текст, и отдельный список тех, в которых есть только изображения. Каждый список сохраняется в отдельный файл.txt, а затем вы можете использовать команду bash для перемещения файлов PDF в соответствующую папку.

Как только вы разместите их в своих собственных папках, вы сможете запустить пакетное решение ocr только для файлов pdf в папке images_only. Я еще не зашел так далеко (очевидно).

    import os, re

    #path is the directory with the files, other 2 are the names of the files you will store your lists in

    path = 'C:/folder_with_pdfs'
    files_with_text = open('files_with_text.txt', 'a')
    image_only_files = open('image_only_files.txt', 'a')


    #have os make a list of all files in that dir for a loop
    filelist = os.listdir(path)

    #compile regular expression that matches "Font"
    mysearch = re.compile(r'.*Font.*', re.DOTALL)

    #loop over all files in the directory, open them in binary ('rb'), search that binary for "Font"
    #if they have "Font" they have text, if not they don't
    #(pdf does something to understand the Font type and uses this word every time the pdf contains text)
    for pdf in filelist:
        openable_file = os.path.join(path, pdf)
        cat_file = open(openable_file, 'rb')
        usable_cat_file = cat_file.read()
        #print usable_cat_file
        if mysearch.match(usable_cat_file):
            files_with_text.write(pdf + '\n')
        else:
            image_only_files.write(pdf + '\n')

Чтобы переместить файлы, я ввел эту команду в оболочке bash:

cat files_with_text.txt | while read i; do mv $i Volumes/hard_drive_name/new_destination_directory_name; done 

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

Это интересная проблема. Если вы готовы работать на Windows в.NET, вы можете сделать это с помощью dotImage (отказ от ответственности, я работаю на Atalasoft и написал большую часть кода механизма OCR). Давайте разберем проблему на части - первая перебирает все ваши PDF-файлы:

string[] candidatePDFs = Directory.GetFiles(sourceDirectory, "*.pdf");
PdfDecoder decoder = new PdfDecoder();

foreach (string path in candidatePDFs) {
    using (FileStream stm = new FileStream(path, FileMode.Open)) {
        if (decoder.IsValidFormat(stm)) {
            ProcessPdf(path, stm);
        }
    }
}

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

public void ProcessPdf(string path, Stream stm)
{
    using (Document doc = new Document(stm)) {
        int i=0;
        foreach (Page p in doc.Pages) {
            if (p.SingleImageOnly) {
                ProcessWithOcr(path, stm, i);
            }
            else {
                ProcessWithTextExtract(path, stm, i);
            }
            i++;
        }
    }
}

Это открывает файл как объект Document и спрашивает, является ли каждая страница только изображением. Если это так, то это будет OCR на странице, иначе это будет текст извлечения:

public void ProcessWithOcr(string path, Stream pdfStm, int page)
{
    using (Stream textStream = GetTextStream(path, page)) {
        PdfDecoder decoder = new PdfDecoder();
        using (AtalaImage image = decoder.Read(pdfStm, page)) {
            ImageCollection coll = new ImageCollection();
            coll.Add(image);
            ImageCollectionImageSource source = new ImageCollectionImageSource(coll);
            OcrEngine engine = GetOcrEngine();
            engine.Initialize();
            engine.Translate(source, "text/plain", textStream);
            engine.Shutdown();
        }
    }
}

то, что это делает, растеризует страницу PDF в изображение и помещает ее в форму, приемлемую для engine.Translate. Строго этого делать не нужно - таким образом можно получить объект OcrPage из движка из AtalaImage, вызвав Recognize, но тогда клиентский код будет перебирать структуру и записывать текст.

Вы заметите, что я пропустил GetOcrEngine() - мы предоставляем 4 механизма распознавания для использования клиентом: Tesseract, GlyphReader, RecoStar и Iris. Вы бы выбрали тот, который будет наилучшим для ваших нужд.

Наконец, вам понадобится код для извлечения текста из страниц, на которых уже есть отличный текст:

public void ProcessWithTextExtract(string path, Stream pdfStream, int page)
{
    using (Stream textStream = GetTextStream(path, page)) {
        StreamWriter writer = new StreamWriter(textStream);
        using (PdfTextDocument doc = new PdfTextDocument(pdfStream)) {
            PdfTextPage page = doc.GetPage(i);
            writer.Write(page.GetText(0, page.CharCount));
        }
    }
}

Это извлекает текст с данной страницы и записывает его в выходной поток.

Наконец, вам нужен GetTextStream():

public Stream GetTextStream(string sourcePath, int pageNo)
{
    string dir = Path.GetDirectoryName(sourcePath);
    string fname = Path.GetFileNameWithoutExtension(sourcePath);
    string finalPath = Path.Combine(dir, String.Format("{0}p{1}.txt", fname, pageNo));
    return new FileStream(finalPath, FileMode.Create);
}

Будет ли это 100% решение? Нет, конечно нет. Вы могли бы представить страницы PDF, содержащие одно изображение с рамкой, нарисованной вокруг него - это явно провалило бы тест только изображения, но не принесло бы никакого полезного текста. Вероятно, лучший подход - просто использовать извлеченный текст, и если он ничего не возвращает, попробуйте механизм OCR. Переход от одного подхода к другому - это вопрос написания другого предиката.

Простейшим подходом было бы использование одного инструмента, такого как ABBYY FineReader, Omnipage и т. Д., Для обработки изображений в одном пакете без необходимости сортировки их в отсканированные и не отсканированные изображения. Я считаю, что FineReader в любом случае преобразует PDF-файлы в изображения перед выполнением распознавания текста.

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

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

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

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

Я написал небольшую оболочку для движка Abbyy OCR4LINUX CLI (IMHO, не так уж и дорого) и Tesseract 3.

Оболочка может конвертировать файлы как:
$ pmocr.sh --batch --target=pdf --skip-txt-pdf /some/directory

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

Сценарий можно найти здесь:
https://github.com/deajan/pmOCR

Надеюсь, это кому-нибудь поможет.

Другие вопросы по тегам