PDF y OCR: Documentos escaneados para RAG
Qué cubre este artículo sobre PDF y OCR
- Qué tipos de PDF existen y por qué algunos necesitan OCR mientras que otros no
- Cómo extraer texto de PDFs digitales usando PyPDF2, pdfplumber y PyMuPDF
- Cómo utilizar Tesseract y pytesseract para convertir documentos escaneados en texto
- Por qué el reconocimiento de layout y el preprocesamiento mejoran enormemente la calidad del OCR
- Un ejemplo práctico completo: desde un manual escaneado hasta texto buscable
Introducción: PDF y OCR explicados de manera clara
Estás construyendo un sistema RAG local y has recopilado tus documentos. Hay manuales en PDF, antiguos contratos escaneados, notas como fotos. Intentas extraer el texto y descubres que muchos archivos no producen nada útil. El PDF no contiene texto, solo imágenes.
Aquí es donde entran en juego el procesamiento de PDF y OCR. En este artículo te mostraré cómo preparar PDFs y documentos escaneados para que funcionen en tu pipeline RAG. Si aún no conoces los fundamentos de la preparación de documentos, te recomiendo que primero leas ese artículo. Aquí profundizamos en los desafíos específicos del procesamiento de PDF.
¿Por qué necesito procesamiento de PDF y OCR?
Imagina que tienes una carpeta llena de contratos antiguos, manuales de usuario y documentación técnica. La mayoría son PDFs escaneados, es decir, fotos de páginas en papel reunidas en un archivo PDF. No hay capa de texto, nada es buscable, nada se puede copiar.
Intentas cargar estos documentos en tu sistema RAG. La extracción te devuelve páginas vacías o genera errores. Tu sistema RAG no encuentra respuestas porque simplemente no hay texto. Los documentos están ahí, pero son invisibles para la IA.
Sin OCR, todos esos documentos escaneados quedan sin usar. Tienes una montaña de información pero no puedes acceder a ella. Con OCR conviertes las imágenes en texto buscable y los haces disponibles para RAG. Este es el paso decisivo si tu colección de documentos contiene materiales escaneados.
PDF y OCR explicados brevemente
La analogía: imagina una fotocopiadora que no solo copia, sino que también puede leer lo que copia. Una fotocopiadora normal produce una imagen de la página. OCR es como una fotocopiadora que toma la imagen y simultáneamente reconoce el texto, como si alguien estuviera transcribiendo la página.
Con los PDFs digitales esto no es necesario. Allí el texto ya está guardado como texto, como en un documento de procesamiento de texto. Puedes extraerlo directamente. Con PDFs escaneados cada página es solo una imagen. Allí OCR debe reconocer el texto de la imagen, carácter por carácter, palabra por palabra.
Para quién es este artículo
Este artículo está dirigido a principiantes que quieren construir un sistema RAG local y procesar documentos escaneados o PDFs. No necesitas conocimientos previos en OCR, pero debes entender básicamente qué es la IA local y cómo funciona RAG. Los ejemplos de código están escritos en Python y explicados de forma que puedas seguirlos incluso sin profundos conocimientos de programación.
Términos importantes relacionados con PDF y OCR
| Término | Explicación |
|---|---|
| Un formato de documento que puede contener texto e imágenes. No todo PDF contiene texto seleccionable. | |
| Capa de texto | La capa de texto en un PDF. Presente en PDFs digitales, ausente en escaneados. |
| OCR | Optical Character Recognition. Tecnología que reconoce texto a partir de imágenes. |
| Tesseract | Un motor OCR de código abierto que funciona localmente y soporta muchos idiomas. |
| Layout | La disposición de texto, imágenes y tablas en una página. Importante para el orden de lectura. |
| DPI | Dots per Inch. La resolución de una imagen. DPI más altos significan más detalle para OCR. |
| Formato de imagen | El formato de la imagen en un PDF, como JPEG o PNG. Afecta la calidad y el tamaño del archivo. |
| Página | Una página individual de un PDF. Se procesa individualmente durante el tratamiento. |
| Columna | Un área de texto vertical en un layout multicolumna. Puede arruinar el orden de lectura si se ignora. |
| Párrafo | Un bloque de texto continuo. Luego se convierte en un chunk para RAG. |
| Token | Un fragmento de texto procesado por modelos. Relevante para chunking e embeddings. |
Tipos de PDF
Antes de empezar, necesitas entender qué tipo de PDF tienes. El procesamiento difiere fundamentalmente.
PDFs basados en texto (born digital)
Estos PDFs se exportaron desde un programa de procesamiento de texto o software. El texto está guardado como texto, no como imagen. Puedes seleccionarlo, copiarlo y buscarlo. La extracción es sencilla y no requiere OCR. Ejemplos: PDFs de Word, LaTeX, exportes HTML.
PDFs escaneados (solo imagen)
Estos PDFs consisten en imágenes de páginas en papel. Cada página es una fotografía, no hay capa de texto. No puedes seleccionar o buscar el texto. Aquí necesitas OCR para extraer el texto. Ejemplos: contratos escaneados, manuales antiguos, documentos archivados.
PDFs mixtos
Algunos PDFs contienen tanto texto como páginas escaneadas. Por ejemplo, un manual cuyas primeras páginas fueron creadas digitalmente pero con anexos antiguos adjuntos como escaneos. Aquí tienes que verificar por página si el texto está presente y aplicar OCR solo donde sea necesario.
Así verificas en Python si una página contiene texto:
from pypdf import PdfReader
reader = PdfReader("dokument.pdf")
for i, page in enumerate(reader.pages):
text = page.extract_text()
if text and text.strip():
print(f"Seite {i+1}: Text vorhanden ({len(text)} Zeichen)")
else:
print(f"Seite {i+1}: Kein Text, OCR nötig")
Con esta verificación al inicio ahorras procesamiento OCR en páginas que no lo necesitan.
Extraer PDFs basados en texto
Para PDFs basados en texto existen varias buenas bibliotecas Python. Aquí están las tres más importantes con sus fortalezas.
PyPDF2 (pypdf)
PyPDF2 es la opción más sencilla. Extrae texto puro pero ignora la información de layout.
from pypdf import PdfReader
reader = PdfReader("handbuch.pdf")
text = ""
for page in reader.pages:
text += page.extract_text() + "\n"
print(text[:500])
PyPDF2 es rápido y confiable para PDFs simples. Con layouts multicolumna el orden de lectura puede quedar desordenado porque no se considera el layout.
pdfplumber
pdfplumber es más adecuado para layouts complejos. Reconoce columnas y tablas y te da más control sobre la extracción.
import pdfplumber
with pdfplumber.open("handbuch.pdf") as pdf:
for page in pdf.pages:
text = page.extract_text()
if text:
print(text[:500])
pdfplumber también ofrece métodos como extract_tables() para leer tablas de forma estructurada. Esto es valioso si tus PDFs contienen datos tabulares.
PyMuPDF (fitz)
PyMuPDF es la opción más rápida y extrae texto con información de layout.
import fitz # PyMuPDF
doc = fitz.open("handbuch.pdf")
for page in doc:
text = page.get_text()
print(text[:500])
PyMuPDF también te proporciona metadatos como tamaño de fuente y posición, lo que ayuda en layouts complejos a distinguir títulos de texto corrido.
Qué biblioteca uses depende de tus documentos. Para PDFs simples PyPDF2 es suficiente. Para layouts complejos usa pdfplumber o PyMuPDF.
PDFs escaneados con OCR
Si un PDF no tiene una capa de texto, necesitas OCR. La mejor opción de código abierto para procesamiento local es Tesseract.
Instalar Tesseract
En Ubuntu o Debian:
sudo apt install tesseract-ocr tesseract-ocr-deu
En macOS con Homebrew:
brew install tesseract tesseract-lang
En Windows descarga el instalador desde github.com/UB-Mannheim/tesseract.
El paquete tesseract-ocr-deu instala el modelo de idioma alemán. Para inglés usa tesseract-ocr-eng. Puedes instalar varios idiomas simultáneamente.
Instalar pytesseract
pip install pytesseract Pillow pdf2image
pytesseract es la interfaz Python para Tesseract. Pillow lo necesitas para procesamiento de imágenes, pdf2image convierte páginas PDF en imágenes.
Convertir PDF a imágenes y ejecutar OCR
from pdf2image import convert_from_path
import pytesseract
# Convertir PDF a imágenes, 300 DPI para buena calidad OCR
images = convert_from_path("scan.pdf", dpi=300)
full_text = ""
for i, image in enumerate(images):
# OCR con modelo de idioma alemán
text = pytesseract.image_to_string(image, lang="deu")
full_text += f"--- Página {i+1} ---\n{text}\n"
print(full_text[:500])
El parámetro lang="deu" indica a Tesseract que el texto está en alemán. Para documentos en inglés usa lang="eng". También puedes especificar varios idiomas: lang="deu+eng".
Reconocimiento de diseño
OCR simple reconoce caracteres, pero no entiende la estructura de una página. Con diseños multicolumna, tablas o imágenes incrustadas, el orden de lectura se mezcla. El texto se vuelve inutilizable para RAG porque las oraciones relacionadas se separan.
Por qué el diseño es importante
Imagina una página de periódico con tres columnas. OCR simple lee línea por línea atravesando todas las columnas. El texto resultante es una confusión incomprensible. La primera columna debe leerse completamente antes de pasar a la segunda. Solo así se conserva el sentido.
LayoutLM
LayoutLM es un modelo de Microsoft que procesa texto e información de diseño conjuntamente. Reconoce qué bloques de texto van juntos y en qué orden deben leerse. LayoutLM es potente, pero más exigente en su configuración.
PaddleOCR
PaddleOCR es otra opción de código abierto que combina reconocimiento de diseño y OCR. Es más fácil de configurar que LayoutLM y ofrece buenos resultados con diseños multicolumna y tablas.
from paddleocr import PaddleOCR
ocr = PaddleOCR(use_angle_cls=True, lang="german")
result = ocr.ocr("scan.png", cls=True)
for line in result[0]:
print(line[1][0])
Para documentos simples, Tesseract es suficiente. Si tus documentos tienen diseños complejos, vale la pena el esfuerzo de usar PaddleOCR o LayoutLM.
Mejorar la calidad
La calidad del OCR depende mucho de la calidad de la imagen de entrada. Con preprocesamiento mejoras significativamente la tasa de reconocimiento.
Aumentar DPI
Escanea con al menos 300 DPI, preferiblemente 600 DPI para texto pequeño. Una resolución más baja genera errores porque Tesseract no puede reconocer los caracteres con claridad.
Binarización
La binarización convierte la imagen en blanco y negro, lo que facilita el trabajo a Tesseract.
from PIL import Image, ImageOps
image = Image.open("scan.png")
# Convertir a escala de grises
gray = ImageOps.grayscale(image)
# Binarización con umbral
bw = gray.point(lambda x: 0 if x < 128 else 255, "1")
bw.save("scan_bw.png")
Deskew (enderezar)
Los escaneos sesgados empeoran la calidad del OCR. Con deskew enderezas la imagen.
from skimage import io
from skimage.transform import rotate
from skimage.color import rgb2gray
import numpy as np
from scipy.ndimage import interpolation
def deskew(image_path):
image = io.imread(image_path, as_gray=True)
# Umbral para binarización
binary = image < 0.5
# Estimar ángulo
angles = np.linspace(-10, 10, 41)
scores = []
for angle in angles:
rotated = interpolation.rotate(binary, angle, reshape=False)
scores.append(np.sum(rotated))
best_angle = angles[np.argmax(scores)]
# Enderezar imagen
corrected = rotate(image, best_angle, resize=True)
io.imsave("scan_deskewed.png", corrected)
deskew("scan.png")
Estos tres pasos, aumentar DPI, binarización y deskew, pueden reducir drásticamente la tasa de errores de OCR. Invierte tiempo en preprocesamiento, se amortiza en cada consulta RAG posterior.
Ejemplo: procesar un manual escaneado
Vamos a través de un ejemplo completo. Tienes un manual escaneado como PDF y quieres prepararlo para RAG.
Paso 1: convertir PDF a imágenes
from pdf2image import convert_from_path
images = convert_from_path("handbuch_scan.pdf", dpi=300)
print(f"{len(images)} páginas cargadas")
Paso 2: aplicar preprocesamiento
from PIL import Image, ImageOps, ImageFilter
def preprocess(image):
# Escala de grises
gray = ImageOps.grayscale(image)
# Aumentar contraste
gray = ImageOps.autocontrast(gray)
# Ligero sharpening
gray = gray.filter(ImageFilter.SHARPEN)
# Binarización
bw = gray.point(lambda x: 0 if x < 140 else 255, "1")
return bw
processed_images = [preprocess(img) for img in images]
Paso 3: ejecutar OCR
import pytesseract
pages = []
for i, img in enumerate(processed_images):
text = pytesseract.image_to_string(img, lang="deu")
pages.append({"text": text, "page": i + 1})
print(f"Página {i+1}: {len(text)} caracteres reconocidos")
Paso 4: limpiar texto
import re
def clean_ocr_text(text):
# Normalizar espacios
text = re.sub(r"[ \t]+", " ", text)
# Reducir líneas en blanco
text = re.sub(r"\n{3,}", "\n\n", text)
# Corregir errores OCR comunes
text = text.replace("|", "l")
text = text.replace("0", "o") # Cuidado, solo si es necesario!
return text.strip()
for page in pages:
page["text"] = clean_ocr_text(page["text"])
Ten cuidado con la corrección automática de errores: reemplazos como 0 por o pueden alterar caracteres correctos. Verifica los resultados y adapta las correcciones a tus documentos.
Paso 5: añadir metadatos y crear chunks
chunks = []
for page in pages:
paragraphs = page["text"].split("\n\n")
for para in paragraphs:
if len(para.strip()) > 50:
chunks.append({
"text": para.strip(),
"metadata": {
"source": "handbuch_scan.pdf",
"page": page["page"],
"method": "ocr"
}
})
print(f"{len(chunks)} chunks creados")
A partir de aquí continúa como en el artículo sobre preparación de documentos: generas embeddings y cargas los chunks en tu base de datos vectorial.
Alternativas a OCR
Tesseract no es la única opción. Aquí hay alternativas, especialmente si necesitas mayor calidad.
Ollama con modelos de visión
Con Ollama puedes ejecutar modelos de visión como LLaVA localmente. Estos modelos pueden “leer” imágenes y extraer texto de ellas. Son más flexibles que Tesseract, especialmente para notas manuscritas o diseños inusuales, pero más lentos.
# Pseudocódigo, ver documentación de Ollama para detalles
import ollama
response = ollama.chat(
model="llava",
messages=[{
"role": "user",
"content": "Extrae el texto de esta imagen.",
"images": ["scan.png"]
}]
)
print(response["message"]["content"])
Los modelos de visión son un buen complemento a Tesseract cuando el OCR clásico llega a sus límites.
OCR en la nube
Servicios en la nube como Google Cloud Vision o AWS Textract ofrecen excelente calidad OCR. La desventaja: tus documentos abandonan tu equipo. Para documentos sensibles, esto suele ser inaceptable. Si lees este artículo, probablemente te interese la IA local, así que nos mantenemos en soluciones locales.
Errores comunes en PDF y OCR
- DPI demasiado bajo: Los escaneos por debajo de 200 DPI generan errores masivos en OCR. Utiliza al menos 300 DPI.
- Idioma incorrecto configurado: Si aplicas Tesseract con un modelo en inglés a textos alemanes, el resultado es inutilizable. Verifica la configuración de idioma.
- Layout ignorado: Los documentos multicolumna sin reconocimiento de diseño producen un texto incomprensible. Utiliza PaddleOCR o LayoutLM para diseños complejos.
- Sin preprocesamiento: Los escaneos sin binarización y deskew degradan significativamente la calidad. Dedica tiempo al preprocesamiento.
- Errores de OCR no corregidos: OCR nunca es perfecto. Los errores típicos como
rnen lugar demo1en lugar delempeoran la calidad del RAG. Revisa y corrige. - Números de página y encabezados no eliminados: Incluso con texto OCR debes limpiar encabezados y pies de página, como se describe en el artículo sobre preparación de documentos.
- Imágenes demasiado grandes en memoria: Los escaneos a 600 DPI de una página A4 requieren mucha RAM. Procesa las páginas una por una, no todas simultáneamente.
- PDFs mixtos no detectados: Si aplicas OCR a páginas basadas en texto, empeoras el resultado. Primero verifica si el texto está presente.
Hardware, costos y seguridad en PDF y OCR
OCR requiere poder de cómputo, pero no es extremadamente demandante. Tesseract funciona sin problemas en un portátil normal sin GPU. El procesamiento de 100 páginas tarda aproximadamente 5 a 15 minutos en una CPU promedio, según el DPI y la complejidad.
Los costos son prácticamente nulos, ya que Tesseract es código abierto y se ejecuta localmente. No necesitas claves API ni suscripciones en la nube. El espacio de almacenamiento para las imágenes procesadas es el único factor de recursos.
La seguridad es una gran ventaja del OCR local. Tus documentos nunca salen de tu máquina. Esto es especialmente importante para contratos, registros médicos u otros documentos sensibles. No tienes que preocuparte por fugas de datos, algo que sería diferente con servicios OCR en la nube.
Enlaces relacionados e información sobre PDF y OCR
- RAG local - Descripción general de todos los artículos sobre RAG
- Fundamentos de RAG - Cómo funciona RAG
- Preparación de documentos - Procesar datos correctamente
- Chunking - Dividir textos correctamente
- Modelos de embedding - Generar vectores a partir de texto
- ¿Qué es IA local? - Fundamentos de la IA local
- Ollama - Ejecutar modelos locales
FAQ: PDF y OCR - Preguntas típicas
¿Necesito OCR para cada PDF?
No. Solo para PDFs escaneados que no tengan una capa de texto. Los PDFs digitales exportados desde procesadores de texto contienen texto seleccionable. Primero verifica con PyPDF2 si el texto se puede extraer.
¿Qué es mejor: Tesseract o un modelo de visión?
Para textos impresos estandarizados, Tesseract es más rápido y suficiente. Para notas manuscritas, diseños inusuales o textos con muchos caracteres especiales, un modelo de visión como LLaVA a través de Ollama puede proporcionar mejores resultados, aunque es más lento.
¿Cuál es el DPI óptimo para OCR?
300 DPI es un buen estándar. Para textos pequeños o detalles finos, utiliza 600 DPI. Por debajo de 200 DPI, la tasa de errores aumenta significativamente.
¿Cómo manejo diseños multicolumna?
Utiliza una herramienta con reconocimiento de diseño como PaddleOCR o LayoutLM. Tesseract simple lee línea por línea en todas las columnas y produce texto inutilizable.
¿Puede Tesseract reconocer escritura manuscrita?
Tesseract está optimizado para texto impreso. Reconoce la escritura manuscrita de manera muy poco confiable. Para notas manuscritas, los modelos de visión son más adecuados.
¿Cómo corrijo errores de OCR?
Compara los resultados de OCR con el original, verifica patrones de error frecuentes y utiliza reemplazos dirigidos. Para grandes volúmenes, puedes usar un modelo de lenguaje para la postcorrección que identifique errores obvios en contexto.
¿Cuánto tiempo tarda OCR para 100 páginas?
Aproximadamente 5 a 15 minutos en una CPU promedio a 300 DPI. Con GPU es mucho más rápido. La duración también depende de la complejidad de las páginas.
¿Necesito una GPU para OCR?
No, Tesseract se ejecuta en CPU. Para modelos de visión a través de Ollama se recomienda una GPU, pero no es estrictamente necesaria. El procesamiento será simplemente más lento.
¿Qué hago con tablas en documentos escaneados?
Las tablas son un desafío para OCR. PaddleOCR y LayoutLM pueden reconocer tablas. Alternativamente, puedes mantener las tablas como imágenes y extraerlas con un modelo de visión. Para RAG, a menudo es mejor almacenar tablas como metadatos estructurados en lugar de texto corrido.
¿Puedo procesar varios idiomas simultáneamente?
Sí, Tesseract admite múltiples idiomas simultáneamente con lang="deu+eng". Esto es útil para documentos que contienen textos mezclados en alemán e inglés. Sin embargo, la tasa de reconocimiento puede disminuir ligeramente en comparación con el procesamiento monolingüe.
Fuentes y lecturas adicionales
- Documentación de Tesseract: github.com/tesseract-ocr/tesseract
- Documentación de pytesseract: github.com/madmaze/pytesseract
- Documentación de pdfplumber: github.com/jsvine/pdfplumber
- Documentación de PyMuPDF: pymupdf.readthedocs.io
- PaddleOCR: github.com/PaddlePaddle/PaddleOCR
- LayoutLM: github.com/microsoft/unilm
- Artículo sobre preparación de documentos en esta serie
- Artículo sobre fundamentos de RAG en esta serie


