pdf ocr batch-processing

Programa de OCR por lotes para archivos PDF



batch-processing (5)

Esto se ha preguntado anteriormente, pero realmente no sé si las respuestas me ayudan. Aquí está mi problema: tengo un montón de archivos (aproximadamente 10,000) en formato pdf. Algunos eran archivos de texto que se guardaron utilizando la función de impresión de adobe (por lo que su texto es perfecto y no quiero arriesgarme a arruinarlos). Y algunas fueron imágenes escaneadas (por lo que no tienen ningún texto y tendré que conformarme con OCR). Los archivos están en el mismo directorio y no puedo decir cuál es cuál. En última instancia, quiero convertirlos en archivos .txt y luego hacer el procesamiento de cadenas en ellos. Así que quiero el OCR más preciso posible.

Parece que la gente ha recomendado:

  1. adobe pdf (no tengo una copia con licencia de este, así que ... más si ABBYY finereader o algo es mejor, ¿por qué pagarlo si no lo uso)?
  2. ocropus (no puedo averiguar cómo usar esta cosa),
  3. Tesseract (que parece que fue genial en 1995, pero no estoy seguro de que haya algo más preciso, además de que no hace los archivos PDF de forma nativa y tengo que convertir a TIFF. Eso plantea su propio problema, ya que no tengo una copia con licencia de Acrobat, así que no sé cómo convertiría 10,000 archivos a Tiff. Además, no quiero que 10,000 documentos de 30 páginas se conviertan en 30,000 imágenes de Tiff individuales.
  4. wowocr
  5. pdftextstream (que fue de 2009)
  6. ABBYY FineReader (aparentemente es $ $ $, pero gastaré $ 600 para hacer esto si esta cosa es significativamente mejor, es decir, tiene un código más preciso).

También soy un n00b para la programación, por lo que si voy a tardar unas semanas en aprender a hacer algo, prefiero pagar el $$$. Gracias por las aportaciones / experiencias.

Por cierto, estoy ejecutando Linux Mint 11 de 64 bits y / o Windows 7 de 64 bits.

Aquí están los otros hilos:

Batch OCRing PDFs que aún no han sido OCR''d

OCR de código abierto

Enfoque de extracción de texto PDF utilizando OCR

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


El enfoque más simple sería utilizar una sola herramienta, como ABBYY FineReader, Omnipage, etc., para procesar las imágenes en un solo lote sin tener que clasificarlas en imágenes escaneadas o no escaneadas. Creo que FineReader convierte los PDF a imágenes antes de realizar el OCR de todos modos.

El uso de un motor de OCR le brindará funciones tales como ajuste automático, detección de orientación de la página, umbral de imágenes, eliminación de puntos, etc. Estas son características para las que tendría que comprar una biblioteca de procesamiento de imágenes y programarse, y puede resultar difícil encontrar un conjunto óptimo de Parámetros para tus 10,000 PDF''s.

El uso del enfoque de OCR automático tendrá otros efectos secundarios dependiendo de las imágenes de entrada y usted encontrará que obtendría mejores resultados si clasificara las imágenes y configurara los parámetros óptimos para cada tipo de imagen. Para mayor precisión, sería mucho mejor utilizar una rutina de extracción de texto de PDF adecuada para extraer los PDF que tienen texto perfecto.

Al final del día, se reducirá el tiempo y el dinero en comparación con la calidad de los resultados que necesita. Al final del día, un programa comercial de OCR será la solución más rápida y fácil. Si tiene solo documentos de texto limpio, entonces un programa de OCR barato funcionará tan bien como una solución costosa. Cuanto más complejos sean sus documentos, más dinero necesitará gastar para procesarlos.

Intentaría encontrar algunas versiones de demostración / prueba de los motores comerciales de OCR y solo vería cómo funcionan en sus diferentes tipos de documentos antes de gastar demasiado tiempo y dinero.


Este es un problema interesante. Si está dispuesto a trabajar en Windows en .NET, puede hacer esto con dotImage (descargo de responsabilidad, trabajo para Atalasoft y escribí la mayor parte del código del motor OCR). Rompamos el problema en partes: lo primero es iterar sobre todos sus archivos 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); } } }

Esto obtiene una lista de todos los archivos que terminan en .pdf y si el archivo es un pdf válido, llama a una rutina para procesarlo:

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++; } } }

Esto abre el archivo como un objeto de documento y pregunta si cada página es solo de imagen. Si es así, OCR la página, de lo contrario, extraerá texto:

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(); } } }

lo que esto hace es rasterizar la página PDF en una imagen y colocarla en una forma que sea aceptable para el motor. Traducción. Esto no tiene que hacerse estrictamente de esta manera; se podría obtener un objeto OcrPage del motor desde una AtalaImage llamando a Reconocer, pero luego sería responsabilidad del código del cliente recorrer la estructura y escribir el texto.

Notarás que he omitido GetOcrEngine (): ponemos a disposición 4 motores OCR para uso del cliente: Tesseract, GlyphReader, RecoStar e Iris. Usted seleccionaría el que sería mejor para sus necesidades.

Finalmente, necesitaría el código para extraer texto de las páginas que ya tienen texto perfectamente bueno en ellas:

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)); } } }

Esto extrae el texto de la página dada y lo escribe en el flujo de salida.

Finalmente, necesitas 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); }

¿Será esta una solución al 100%? No. Ciertamente no. Podría imaginar páginas PDF que contengan una sola imagen con un cuadro dibujando a su alrededor. Esto claramente fallaría en la prueba de la imagen, pero no devolvería ningún texto útil. Probablemente, un mejor enfoque es simplemente usar el texto extraído y si eso no devuelve nada, entonces pruebe un motor de OCR. Cambiar de un enfoque a otro es cuestión de escribir un predicado diferente.


He escrito un pequeño paquete para Abbyy OCR4LINUX CLI engine (IMHO, no cuesta mucho) y Tesseract 3.

El contenedor puede convertir archivos por lotes como:
$ pmocr.sh --batch --target=pdf --skip-txt-pdf /some/directory

La secuencia de comandos usa pdffonts para determinar si un archivo PDF ya ha sido OCR para omitirlos. Además, el script puede funcionar como un servicio del sistema para monitorear un directorio e iniciar una acción de OCR tan pronto como un archivo ingresa al directorio.

Script se puede encontrar aquí:
https://github.com/deajan/pmOCR

Con suerte, esto ayuda a alguien.


Pensé que trataría de contribuir respondiendo a mi propia pregunta (escribí un código bonito para mí y no podría haberlo hecho sin la ayuda de este foro). Si utiliza los archivos pdf en unix (bueno, osx para mí), entonces los archivos pdf que tienen texto tendrán la palabra "Fuente" (como una cadena, pero mezclada con otro texto) b / c, así es como archivo le dice a Adobe qué fuentes mostrar.

El comando cat en bash parece tener el mismo resultado que leer el archivo en modo binario en python (usando el modo ''rb'' al abrir el archivo en lugar de ''w'' o ''r'' o ''a''). Así que asumo que todos los archivos pdf que contienen texto tienen la palabra "Fuente" en la salida binaria y que ningún archivo de solo imagen lo hará. Si eso es siempre cierto, entonces este código hará una lista de todos los archivos pdf en un solo directorio que tienen texto y una lista separada de aquellos que solo tienen imágenes. Guarda cada lista en un archivo .txt separado, luego puede usar un comando en bash para mover los archivos pdf a la carpeta apropiada.

Una vez que los tenga en sus propias carpetas, puede ejecutar su solución de proceso por lotes solo en los archivos pdf en la carpeta images_only. No he llegado tan lejos todavía (obviamente).

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'')

Para mover los archivos, ingresé este comando en el shell bash:

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

Además, no volví a ejecutar el código de Python anterior, simplemente lo edité a mano, por lo que podría tener errores, Idk.


Sólo para poner en orden algunos de sus conceptos erróneos ...

"No tengo una copia con licencia de Acrobat, así que no sé cómo convertiría 10,000 archivos a tiff".

Puede convertir archivos PDF a TIFF con la ayuda de Ghostscript gratuito (como en liberty) y gratuito (como en beer). Tu elección si quieres hacerlo en Linux Mint o en Windows 7. La línea de comandos para Linux es:

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

"No quiero que 10,000 documentos de 30 páginas se conviertan en 30,000 imágenes individuales"

Puedes tener "TIFFs de varias páginas" fácilmente. El comando anterior crea dichos TIFF del sabor G4 (fax tiff). Si aún desea TIFF de una sola página, puede modificar el comando:

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

La parte %03d del nombre de archivo de salida se traducirá automáticamente en una serie de 001 , 002 , 003 , etc.

Advertencias:

  1. La resolución predeterminada para el dispositivo de salida tiffg4 es 204x196 dpi. Probablemente quieras un mejor valor. Para obtener 720 ppp, debe agregar -r720x720 a la línea de comandos.
  2. Además, si su instalación de Ghostscript usa la letra como su tamaño de medio predeterminado, es posible que desee cambiarla. Puede usar -gXxY para establecer widthxheight en puntos de dispositivo. Entonces, para obtener las dimensiones de la página de salida ISO A4 en horizontal, puede agregar un parámetro -g8420x5950 .

Entonces, el comando completo que controla estos dos parámetros, para producir una salida de 720 ppp en A4 en orientación vertical, diría:

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