19

Это обсуждалось год назад здесь:

Пакетное распознавание текста для многих PDF-файлов (еще не распознано)?

Есть ли способ пакетной обработки документов OCR PDF, которые еще не были распознаны? Это, я думаю, текущее состояние дел, связанных с двумя проблемами:

Пакетное распознавание PDF

Windows

  • Acrobat - это самый простой движок OCR, который будет использовать OCR. Единственная проблема, по-видимому, заключается в том, что: 1) он не пропускает файлы, которые уже были распознаны; 2) попробуйте бросить в него кучу PDF-файлов (некоторые старые) и посмотреть, как он вылетает. Это немного глючит. Он будет предупреждать вас при каждой ошибке (хотя вы можете указать программному обеспечению не уведомлять об этом). Но опять же, он ужасно умирает на некоторых типах PDF, поэтому ваш пробег может отличаться.

  • ABBYY FineReader (Batch/Scansnap), Omnipage - Это, должно быть, некоторые из худших запрограммированных частей программного обеспечения, известных человеку. Если вы можете узнать, как полностью автоматизировать (без подсказок) пакетное OCR сохранения PDF-файлов с тем же именем, пожалуйста, напишите здесь. Кажется, единственные решения, которые я мог найти где-то не удалось - переименование, не полностью автоматизировано и т.д. И т.д. В лучшем случае, есть способ сделать это, но документация и программирование настолько ужасны, что вы никогда не узнаете.

  • ABBYY FineReader Engine, ABBYY Recognition Server - это действительно больше корпоративных решений, вам, вероятно, было бы лучше просто заставить acrobat запускать над папкой и пытаться отсеивать PDF-файлы, которые приводят к ошибкам / сбоям программы, чем испытывать трудности с попытками установить оценочное программное обеспечение (при условии, что вы простой конечный пользователь). Не кажется конкурентоспособным по цене для маленького пользователя.

  • ** Рабочая станция Autobahn DX ** стоимость этого продукта настолько непомерно высока, что вы, вероятно, можете купить 6 копий акробата. Не совсем решение для конечного пользователя. Если вы настроены на предприятии, это может стоить вам.

Linux

  • WatchOCR - больше не разрабатывается и практически не работает на современных дистрибутивах Ubuntu
  • pdfsandwich - больше не разрабатывается, практически невозможно запустить на современных дистрибутивах Ubuntu
  • ** ABBY LINUX OCR ** - это должно быть сценарием, и, похоже, дает хорошие результаты:

http://www.splitbrain.org/blog/2010-06/15-linux_ocr_software_comparison

Однако, как и многие другие продукты ABBYY, которые они заряжают на странице, опять же, возможно, вам стоит попробовать заставить Acrobat Batch OCR работать.

  • ** Ocrad, GOCR, OCRopus, tesseract, ** - это может работать, но есть несколько проблем:

    1. Результаты распознавания не такие большие, как, скажем, у акробатов для некоторых из них (см. Ссылку выше).
    2. Ни одна из программ не берет файл PDF и не выводит файл PDF. Вы должны создать сценарий и сначала разбить PDF на части и запустить программы для каждого, а затем снова собрать файл в формате PDF.
    3. Как только вы это сделаете, вы, как и я, можете обнаружить, что (tesseract) создает слой OCR, который смещен. Поэтому, если вы ищете слово «the», вы выделите часть слова рядом с ним.
  • Пакетное DjVu → Конвертировать в PDF - не смотрел на это, но кажется ужасным решением.

онлайн

  • PDFcubed.com - давай, не совсем пакетное решение.
  • ABBYY Cloud OCR - не уверен, что это действительно пакетное решение, так или иначе, вам придется платить за страницу, и это может быть довольно дорогим.

Выявление неопубликованных PDF-файлов

Это немного более простая проблема, которая может быть легко решена в Linux и намного меньше в Windows. Мне удалось закодировать Perl-скрипт, используя pdffont чтобы определить, встроены ли шрифты, чтобы определить, какие файлы не-OCRed.


Актуальные "решения"

  1. Используйте сценарий для идентификации PDF-файлов без OCR (чтобы вы не перезапускали более тысячи PDF-файлов с OCR) и скопируйте их во временный каталог (сохраняя правильное дерево каталогов), а затем используйте Acrobat в Windows, чтобы запустить их, надеясь, что меньший размер партии не потерпят крах.

  2. используйте тот же скрипт, но получите один из инструментов linux ocr для правильной работы, рискуя качеством ocr.

Я думаю, что я собираюсь попробовать # 1, я просто слишком беспокоюсь о результатах инструментов OCR в Linux (я не думаю, что кто-то сделал сравнение), и кажется, что разбить файлы и соединить их снова быть ненужным кодированием, если Adobe может на самом деле пакетное OCR каталог без удушья.

Если вы хотите получить полностью бесплатное решение, вам нужно будет использовать сценарий, чтобы идентифицировать pdf-файлы без OCR (или просто перезапустить OCR-файлы), а затем использовать один из инструментов linux, чтобы попытаться их OCR. Тезеракт, кажется, дает лучшие результаты, но, опять же, некоторые из этих инструментов не очень хорошо поддерживаются в современных версиях Ubuntu, хотя, если вы можете установить его и исправить проблему, у меня была проблема, когда слой изображения не соответствовал слою соответствия текста ( с tesseract) тогда у вас будет довольно работоспособное решение и еще раз Linux> Windows.


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


Скрипт Perl для перемещения файлов без OCRed во временный каталог. Не могу гарантировать, что это работает, и, вероятно, его нужно переписать, но если кто-то заставляет его работать (если он не работает) или работает лучше, дайте мне знать, и я выложу лучшую версию здесь.


#!/usr/bin/perl

# move non-ocred files to a directory
# change variables below, you need a base dir (like /home/joe/), and a sourcedirectory and output
# direcotry (e.g books and tempdir)
# move all your pdfs to the sourcedirectory

use warnings;
use strict;

# need to install these modules with CPAN or your distros installer (e.g. apt-get)
use CAM::PDF;
use File::Find;
use File::Basename;
use File::Copy;

#use PDF::OCR2;
#$PDF::OCR2::CHECK_PDF   = 1;
#$PDF::OCR2::REPAIR_XREF = 1;

my $basedir = '/your/base/directory';
my $sourcedirectory  = $basedir.'/books/';
my @exts       = qw(.pdf);
my $count      = 0;
my $outputroot = $basedir.'/tempdir/';
open( WRITE, >>$basedir.'/errors.txt' );

#check file
#my $pdf = PDF::OCR2->new($basedir.'/tempfile.pdf');
#print $pdf->page(10)->text;



find(
    {
        wanted => \&process_file,

        #       no_chdir => 1
    },
    $sourcedirectory
);
close(WRITE);

sub process_file {
    #must be a file
    if ( -f $_ ) {
        my $file = $_;
        #must be a pdf
        my ( $dir, $name, $ext ) = fileparse( $_, @exts );
        if ( $ext eq '.pdf' ) {
            #check if pdf is ocred
            my $command = "pdffonts \'$file\'";
            my $output  = `$command`;
            if ( !( $output =~ /yes/ || $output =~ /no/ ) ) {
                #print "$file - Not OCRed\n";
                my $currentdir = $File::Find::dir;
                if ( $currentdir =~ /$sourcedirectory(.+)/ ) {
                    #if directory doesn't exist, create
                    unless(-d $outputroot.$1){
                    system("mkdir -p $outputroot$1");
                    }
                    #copy over file
                    my $fromfile = "$currentdir/$file";
                    my $tofile = "$outputroot$1/$file";
                    print "copy from: $fromfile\n";
                    print "copy to: $tofile\n";
                    copy($fromfile, $tofile) or die "Copy failed: $!";
#                       `touch $outputroot$1/\'$file\'`;
                }
            }

        }

    }
}

5 ответов5

3

Я тоже искал способ пакетного распознавания многих PDF-файлов в автоматическом режиме, без особой удачи. В конце концов, я нашел работоспособное решение, подобное вашему, используя Acrobat со следующим сценарием:

  1. Скопируйте все соответствующие PDF-файлы в определенный каталог.

  2. Удалите PDF-файлы, уже содержащие текст (при условии, что они уже OCRd или уже текст - я не знаю, что это идеально, но пока достаточно хорошо).

  3. Используйте AutoHotKey для автоматического запуска Acrobat, выбора определенного каталога и OCR для всех документов, добавляя «-ocr» к их имени файла.

  4. Переместите файлы OCRd обратно в исходное местоположение, используя файл «-ocr.pdf», чтобы определить, был ли он успешным.

Это немного Хит Робинсон, но на самом деле работает довольно хорошо.

2

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

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

  • Взгляните на ABBYY Recognition Server, это профессиональный продукт для автоматизации распознавания.

  • Что касается Linux, взгляните на http://ocr4linux.com, это утилита командной строки, которая может вам подойти.

  • Для более сложных задач у ABBYY есть очень гибкие SDK, такие как ABBYY FineReader Engine (собственный) или ABBYY Cloud OCR SDK (на основе облака Microsoft Azure), которые позволяют вам обрабатывать OCR так, как вы этого хотите.

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

Рассматривая поиск текстового слоя в PDF, я не могу дать никаких советов по этому поводу, потому что эта задача немного отличается от OCR, которая является моей специальностью, поэтому я считаю ваш подход к использованию внешнего сценария очень разумным. Может быть, эта дискуссия будет вам полезна: http://forum.ocrsdk.com/questions/108/check-if-pdf-is-scanned-image-or-contains-text

1

У меня был некоторый успех в начале 2015 года, когда я полностью использовал автоматическое распознавание текста с использованием Nuance OmniPage Ultimate для Windows. Не бесплатно, цена по прейскуранту 500 долларов. Используйте пакетную программу "DocuDirect", которая входит в комплект. У него есть опция «Запускать работу без каких-либо подсказок», которая кажется прямым ответом на ваш оригинальный вопрос.

Я использовал DocuDirect для вывода одного PDF-файла с возможностью поиска для каждого входного изображения (т. Е. PDF-файла без возможности поиска); можно сказать, чтобы реплицировать дерево входных каталогов в выходной папке, а также исходные имена входных файлов (почти - см. ниже). Использует несколько ядер тоже. Точность была лучшей из пакетов, которые я оценил. Защищенные паролем документы пропускаются (без остановки задания, без отображения диалогового окна).

Предупреждение 1: Почти оригинальные имена файлов - суффикс ".PDF "становится" .pdf "(т. Е. Из верхнего в нижний регистр), потому что эй, это все равно в Windows. (Уф).

Предостережение 2: Нет файла журнала, поэтому диагностика, какие файлы дают сбой во время распознавания - что они определенно делают - возвращается на вас. DocuDirect с удовольствием выдаст искаженные результаты, например, просто пропустив целые страницы. Я написал скрипт на Python, используя модуль PyPDF2 для реализации грубой проверки: проверки того, что число выходных страниц соответствует количеству входных страниц. Увидеть ниже.

Предупреждение 3: нечеткий, нечеткий входной файл изображения приведет к зависанию OmniPage навсегда, без использования какого-либо процессора; это просто никогда не восстанавливается. Это действительно срывает пакетную обработку, и я не нашел никаких обходных путей. Я также сообщил об этом Nuance, но ничего не получил.

@Joe прав насчет того, что программное обеспечение плохо программируется и документируется. Я отмечаю, что ядро OmniPage имеет удивительную магическую технологию распознавания символов, но внешней оболочки (GUI и пакетной обработки) достаточно, чтобы заставить вас выдернуть волосы.

Я поддерживаю предложение @ Joe's и @ Kiwi отсеивать файлы с использованием сценариев, чтобы представить пакет OCR только с незащищенными документами с изображениями.

Моя единственная связь с Nuance - не совсем довольный клиент - у меня есть партия неразрешенных билетов поддержки, чтобы доказать это :)

@Joe: поздний ответ, но, возможно, все еще актуален. Сообщество @SuperUser: надеюсь, вы считаете, что это по теме.

** Обновление ** преемник пакета Nuance PowerPDF Advanced, цена по прейскуранту всего $ 150. У меня был еще больший успех с этим, он такой же точный, но гораздо более стабильный.

Сценарий Python для проверки дерева до / после OCR приведен ниже.

'''
Script to validate OCR outputs against inputs.
Both input and output are PDF documents in a directory tree.
For each input document, checks for the corresponding output
document and its page count.

Requires PyPDF2 from https://pypi.python.org/pypi/PyPDF2
'''

from __future__ import print_function
from PyPDF2 import PdfFileReader
import getopt
import os
import stat
import sys

def get_pdf_page_count(filename):
    '''
    Gets number of pages in the named PDF file.
    Fails on an encrypted or invalid file, returns None.
    '''
    with open(filename, "rb") as pdf_file:
        page_count = None
        err = None
        try:
            # slurp the file
            pdf_obj = PdfFileReader(pdf_file)
            # extract properties
            page_count = pdf_obj.getNumPages()
            err = ""
        except Exception:
            # Invalid PDF.
            # Limit exception so we don't catch KeyboardInterrupt etc.
            err = str(sys.exc_info())
            # This should be rare
            print("Warning: failed on file %s: %s" % (filename, err), file=sys.stderr)
            return None

    return page_count

def validate_pdf_pair(verbose, img_file, txt_file):
    '''
    Checks for existence and size of target PDF file;
    number of pages should match source PDF file.
    Returns True on match, else False.
    '''
    #if verbose: 
    #    print("Image PDF is %s" % img_file)
    #    print("Text PDF is %s" % txt_file)

    # Get source and target page counts
    img_pages = get_pdf_page_count(img_file)
    txt_pages = get_pdf_page_count(txt_file)
    if img_pages is None:
        # Bogus PDF, skip.
        print("Warning: failed to get page count for %s" % img_file, file=sys.stderr)
        return None
    if txt_pages is None:
        # Bogus PDF, skip.
        print("Warning: failed to get page count for %s" % txt_file, file=sys.stderr)
        return None

    retval = True
    if img_pages != txt_pages:
        retval = False
        print("Mismatch page count: %d in source %s, %d in target %s" % (img_pages, img_file, txt_pages, txt_file), file=sys.stderr)

    return retval


def validate_ocr_output(verbose, process_count, total_count, img_dir, txt_dir):
    '''
    Walks a tree of files to compare against output tree, calling self recursively.
    Returns a tuple with PDF file counts (matched, non-matched).
    '''
    # Iterate over the this directory
    match = 0
    nonmatch = 0
    for dirent in os.listdir(img_dir):
        src_path = os.path.join(img_dir, dirent)
        tgt_path = os.path.join(txt_dir, dirent)
        if os.path.isdir(src_path):
            if verbose: print("Found source dir %s" % src_path)
            # check target
            if os.path.isdir(tgt_path):
                # Ok to process
                (sub_match, sub_nonmatch) = validate_ocr_output(verbose, process_count + match + nonmatch, total_count, 
                                         src_path, tgt_path)
                match += sub_match
                nonmatch += sub_nonmatch
            else:
                # Target is missing!?
                print("Fatal: target dir not found: %s" % tgt_path, file=sys.stderr)

        elif os.path.isfile(src_path):
            # it's a plain file
            if src_path.lower().endswith(".pdf"):
                # check target
                # HACK: OmniPage changes upper-case PDF suffix to pdf;
                # of course not visible in Windohs with the case-insensitive 
                # file system, but it's a problem on linux.
                if not os.path.isfile(tgt_path):
                    # Flip lower to upper and VV
                    if tgt_path.endswith(".PDF"):
                        # use a slice
                        tgt_path = tgt_path[:-4] + ".pdf"
                    elif tgt_path.endswith(".pdf"):
                        tgt_path = tgt_path[:-4] + ".PDF"
                # hopefully it will be found now!
                if os.path.isfile(tgt_path):
                    # Ok to process
                    sub_match = validate_pdf_pair(verbose, src_path, tgt_path)
                    if sub_match:
                        match += 1
                    else:
                        nonmatch += 1
                    if verbose: print("File %d vs %d matches: %s" % (process_count + match + nonmatch, total_count, sub_match))

                else:
                    # Target is missing!?
                    print("Fatal: target file not found: %s" % tgt_path, file=sys.stderr)
                    nonmatch += 1

        else:
            # This should never happen
            print("Warning: not a directory nor file: %s" % src_path, file=sys.stderr)
    return (match, nonmatch)

def count_pdfs_listdir(verbose, src_dir):
    '''
    Counts PDF files in a tree using os.listdir, os.stat and recursion.
    Not nearly as elegant as os.walk, but hopefully very fast on
    large trees; I don't need the whole list in memory.
    '''
    count = 0
    for dirent in os.listdir(src_dir):
        src_path = os.path.join(src_dir, dirent)
        # stat the entry just once
        mode = os.stat(src_path)[stat.ST_MODE]
        if stat.S_ISDIR(mode):
            # It's a directory, recurse into it
            count += count_pdfs_listdir(verbose, src_path)
        elif stat.S_ISREG(mode):
            # It's a file, count it
            if src_path.lower().endswith('.pdf'):
                count += 1
        else:
            # Unknown entry, print an error
            print("Warning: not a directory nor file: %s" % src_path, file=sys.stderr)
    return count

def main(args):
    '''
    Parses command-line arguments and processes the named dirs.
    '''
    try:
        opts, args = getopt.getopt(args, "vi:o:")
    except getopt.GetoptError:
        usage()
    # default values
    verbose = False
    in_dir = None
    out_dir = None
    for opt, optarg in opts:
        if opt in ("-i"):
            in_dir = optarg
        elif opt in ("-o"):
            out_dir = optarg
        elif opt in ("-v"):
            verbose = True
        else:
            usage()
    # validate args
    if in_dir is None or out_dir is None: usage()
    if not os.path.isdir(in_dir):
        print("Not found or not a directory: %s" % input, file=sys.stderr)
        usage()
    if not os.path.isdir(out_dir):
        print("Not found or not a directory: %s" % out_dir, file=sys.stderr)
        usage()
    if verbose: 
        print("Validating input %s -> output %s" % (in_dir, out_dir))
    # get to work
    print("Counting files in %s" % in_dir)
    count = count_pdfs_listdir(verbose, in_dir)
    print("PDF input file count is %d" % count)
    (match,nomatch) = validate_ocr_output(verbose=verbose, process_count=0, total_count=count, img_dir=in_dir, txt_dir=out_dir) 
    print("Results are: %d matches, %d mismatches" % (match, nomatch))

def usage():
    print('Usage: validate_ocr_output.py [options] -i input-dir -o output-dir')
    print('    Compares pre-OCR and post-OCR directory trees')
    print('    Options: -v = be verbose')
    sys.exit()

# Pass all params after program name to our main
if __name__ == "__main__":
    main(sys.argv[1:])
1

На Linux

Лучший и самый простой выход - использовать pypdfocr он не меняет PDF

pypdfocr your_document.pdf

В конце у вас будет другой your_document_ocr.pdf так, как вы хотите, с текстом для поиска. Приложение не меняет качество изображения. Немного увеличивает размер файла, добавляя наложенный текст.

Пакетные PDF-файлы

ls ./p*.pdf | xargs -L1 -I {}  pypdfocr {}

Если PDF-файлы находятся в подпапках:

tree -fai . | grep -P ".pdf$" | xargs -L1 -I {}  pypdfocr {}

Обновление 3 ноября 2018 года:

pypdfocr больше не поддерживается с 2016 года, и я заметил некоторые проблемы из-за отсутствия поддержки. ocrmypdf(модуль) выполняет знакомую работу и может использоваться следующим образом:

ocrmypdf in.pdf out.pdf

Установить:

pip install ocrmypdf

или же

apt install ocrmypdf

так что команда станет

tree -fai . | grep -P ".pdf$" | xargs -L1 -I {}  ocrmypdf {} {}_ocr.pdf 
0

Вы можете рассмотреть Autobahn DX Aquaforest: http://www.aquaforest.com/en/autobahn.asp

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .