OCR para documentos escaneados
Tesseract mediante pytesseract, preprocesamiento de imágenes y mejora de la precisión.
OCR para documentos escaneados es una lección gratuita de AI Agents en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de AI Agents, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de AI Agents incluye 4 lecciones en total.
Cuándo es necesario usar OCR
No todos los documentos son PDF digitales nativos. Los documentos escaneados, las fotografías de texto, las notas manuscritas y los PDF basados en imágenes requieren reconocimiento óptico de caracteres (OCR) para extraer el texto.
OCR convierte las imágenes de texto formadas por píxeles en caracteres legibles por las máquinas. Dos bibliotecas de Python destacadas son pytesseract (Google Tesseract) y EasyOCR (aprendizaje profundo y compatibilidad multilingüe).
Conceptos básicos de pytesseract
pytesseract es un wrapper de Python para el motor de OCR Tesseract de Google. Instale primero Tesseract a nivel del sistema operativo y, después, ejecute pip install pytesseract Pillow.
import pytesseract
from PIL import Image
# Simple text extraction
image = Image.open('scanned_document.png')
text = pytesseract.image_to_string(image)
print(text)
# Specify language (default: English)
text_fr = pytesseract.image_to_string(
Image.open('french_doc.png'),
lang='fra'
)
# Get detailed output with bounding boxes
data = pytesseract.image_to_data(
image,
output_type=pytesseract.Output.DICT
)
for i, word in enumerate(data['text']):
if word.strip():
conf = data['conf'][i]
print(f'Word: {word!r:20} Confidence: {conf}')Preprocesamiento de imágenes: escala de grises
La precisión del OCR depende en gran medida de la calidad de la imagen. El primer paso de preprocesamiento consiste en convertirla a escala de grises: el color añade ruido sin ayudar al reconocimiento de caracteres.
Use Pillow u OpenCV para el preprocesamiento. La escala de grises reduce el ruido y mejora la detección de los límites de los caracteres por parte de Tesseract.
from PIL import Image, ImageOps
import numpy as np
def preprocess_grayscale(image_path):
img = Image.open(image_path)
# Convert to grayscale
img = img.convert('L') # 'L' = 8-bit grayscale
# Optionally resize for better OCR (Tesseract works best at ~300 DPI)
# Scale up small images
width, height = img.size
if width < 800:
scale = 800 / width
new_size = (int(width * scale), int(height * scale))
img = img.resize(new_size, Image.LANCZOS)
return img
img = preprocess_grayscale('scan.jpg')
text = pytesseract.image_to_string(img)
print(text[:300])Preprocesamiento de imágenes: umbralización
La umbralización convierte una imagen en escala de grises en una imagen completamente blanca y negra. Esto elimina las sombras grises, la iluminación irregular y el ruido de fondo, de modo que el texto destaque claramente para el OCR.
from PIL import Image, ImageFilter
import numpy as np
def apply_threshold(img):
# Method 1: Simple fixed threshold
img_array = np.array(img)
threshold = 128
binary = np.where(img_array > threshold, 255, 0).astype(np.uint8)
return Image.fromarray(binary)
def adaptive_threshold(img):
# Method 2: Otsu's method via OpenCV (better for uneven lighting)
try:
import cv2
img_array = np.array(img)
_, binary = cv2.threshold(
img_array, 0, 255,
cv2.THRESH_BINARY + cv2.THRESH_OTSU
)
return Image.fromarray(binary)
except ImportError:
return apply_threshold(img)
img = preprocess_grayscale('uneven_scan.png')
img_clean = adaptive_threshold(img)
text = pytesseract.image_to_string(img_clean)
print(text[:300])Preprocesamiento de imágenes: corrección de inclinación
Los documentos escaneados suelen estar ligeramente girados. Incluso una inclinación de 2 grados reduce significativamente la precisión del OCR. La corrección de inclinación detecta y corrige el ángulo de rotación antes de pasar la imagen al motor de OCR.
import numpy as np
from PIL import Image
def deskew(img):
try:
import cv2
img_array = np.array(img)
# Find rotation angle using Hough line transform
edges = cv2.Canny(img_array, 50, 150, apertureSize=3)
lines = cv2.HoughLines(edges, 1, np.pi/180, threshold=100)
if lines is None:
return img # no lines detected, return unchanged
angles = []
for line in lines:
rho, theta = line[0]
angle = np.degrees(theta) - 90
if -45 < angle < 45:
angles.append(angle)
if not angles:
return img
median_angle = np.median(angles)
if abs(median_angle) > 0.5: # only deskew if significant tilt
print(f'Deskewing by {median_angle:.2f} degrees')
return img.rotate(-median_angle, expand=True, fillcolor=255)
return img
except ImportError:
return img # OpenCV not available — skip deskewOpciones de idioma de Tesseract
Tesseract admite más de 100 idiomas. Descargue los paquetes de idiomas con el gestor de paquetes de su sistema operativo. Para documentos multilingües, especifique varios idiomas separándolos con +.
import pytesseract
from PIL import Image
# List available languages
import subprocess
result = subprocess.run(['tesseract', '--list-langs'], capture_output=True, text=True)
print('Available languages:')
print(result.stdout)
# Single language
text_en = pytesseract.image_to_string(Image.open('doc.png'), lang='eng')
# Multiple languages (auto-detect best match)
text_multi = pytesseract.image_to_string(
Image.open('doc.png'),
lang='eng+fra+deu' # English + French + German
)
# Tesseract config options for better accuracy
custom_config = r'--oem 3 --psm 6' # OEM 3=LSTM, PSM 6=assume uniform block of text
text_tuned = pytesseract.image_to_string(
Image.open('doc.png'),
config=custom_config
)EasyOCR: basado en aprendizaje profundo
EasyOCR utiliza modelos de aprendizaje profundo y supera a Tesseract en imágenes degradadas, texto curvado y alfabetos no latinos. No requiere ninguna instalación a nivel del sistema operativo.
Instálelo con pip install easyocr. La primera ejecución descarga los pesos del modelo (aproximadamente 200 MB).
import easyocr
# Initialize reader (downloads model on first run)
reader = easyocr.Reader(
['en', 'tr'], # list of languages
gpu=False # set True if CUDA available
)
# Read text from image
results = reader.readtext('scanned_page.png')
for (bbox, text, confidence) in results:
print(f'Text: {text!r:30} Confidence: {confidence:.2f}')
# bbox = [[x1,y1],[x2,y2],[x3,y3],[x4,y4]] (four corners)
# Get plain text only
text_only = ' '.join(result[1] for result in results)
print('Full text:', text_only[:300])EasyOCR para documentos multilingües
EasyOCR gestiona bien los documentos con varios idiomas, lo que resulta útil para contratos internacionales, artículos de investigación con pies de imagen en varios idiomas o documentos con términos técnicos escritos en otro alfabeto.
import easyocr
# For Arabic-English mixed document
reader_ar = easyocr.Reader(['ar', 'en'], gpu=False)
results = reader_ar.readtext('arabic_contract.png')
# For CJK languages
reader_cjk = easyocr.Reader(['ch_sim', 'en'], gpu=False) # Simplified Chinese + English
results_cjk = reader_cjk.readtext('chinese_report.png')
# Filter by confidence threshold
HIGH_CONFIDENCE = 0.7
def filter_confident_results(results, threshold=HIGH_CONFIDENCE):
return [
(bbox, text, conf)
for bbox, text, conf in results
if conf >= threshold
]Pipeline completo de preprocesamiento
Encadene todos los pasos de preprocesamiento —escala de grises, umbralización y corrección de inclinación— en una única función de pipeline. Ejecute el OCR sobre la imagen procesada y devuelva tanto el texto como las métricas de confianza.
import pytesseract
from PIL import Image
def ocr_pipeline(image_path, lang='eng', engine='tesseract'):
print(f'Processing: {image_path}')
# 1. Load
img = Image.open(image_path)
# 2. Preprocess
img = img.convert('L') # grayscale
img = adaptive_threshold(img) # binarize
img = deskew(img) # correct rotation
# 3. OCR
if engine == 'easyocr':
reader = easyocr.Reader([lang], gpu=False)
results = reader.readtext(image_path)
text = ' '.join(r[1] for r in results if r[2] > 0.5)
else:
config = f'--oem 3 --psm 6 -l {lang}'
text = pytesseract.image_to_string(img, config=config)
# 4. Clean
text = '\n'.join(
line.strip() for line in text.splitlines()
if line.strip()
)
return text
text = ocr_pipeline('invoice_scan.jpg')
print(text[:500])Gestión de PDF basados en imágenes
Algunos PDF contienen páginas escaneadas almacenadas como imágenes dentro del contenedor PDF. Detecte estos «PDF de imágenes» y aplique OCR página por página, utilizando PyMuPDF para extraer primero las imágenes.
import fitz
from PIL import Image
import io
import pytesseract
def is_image_pdf(doc):
# Check if first page has very little extractable text
text = doc[0].get_text().strip()
return len(text) < 50
def ocr_pdf(filepath):
doc = fitz.open(filepath)
if not is_image_pdf(doc):
# Native text — no OCR needed
return '\n'.join(doc[i].get_text() for i in range(len(doc)))
print('Image PDF detected — running OCR')
all_text = []
for page_num in range(len(doc)):
page = doc[page_num]
# Render page as image at 300 DPI
mat = fitz.Matrix(300/72, 300/72) # scale to 300 DPI
pix = page.get_pixmap(matrix=mat)
img = Image.open(io.BytesIO(pix.tobytes('png')))
text = pytesseract.image_to_string(img)
all_text.append(f'--- Page {page_num+1} ---\n{text}')
doc.close()
return '\n'.join(all_text)Filtrado por confianza y posprocesamiento
La salida del OCR contiene errores, especialmente en imágenes degradadas. Procese el texto posteriormente filtrando las palabras con baja confianza, corrigiendo errores comunes del OCR (0 frente a O, 1 frente a l) y normalizando los espacios en blanco.
import re
COMMON_OCR_ERRORS = {
r'\b0([a-z])\b': r'O\1',
r'\bl([0-9])\b': r'1\1',
r'\|': 'I',
r' +': ' ',
}
def post_process_ocr(text):
for pattern, replacement in COMMON_OCR_ERRORS.items():
text = re.sub(pattern, replacement, text)
lines = [line.strip() for line in text.splitlines()]
return '\n'.join(line for line in lines if line)
def high_confidence_ocr(words_with_conf, min_confidence=60):
words = [w for w, conf in words_with_conf if w.strip() and conf >= min_confidence]
return post_process_ocr(' '.join(words))
fake_ocr_output = [('0range', 90), ('|s', 40), ('l5', 85), ('good', 95)]
print(high_confidence_ocr(fake_ocr_output))Comprobación de conocimientos
¿Cuál es el propósito de aplicar un umbral (binarización) a una imagen antes del OCR?
Resumen: OCR para documentos escaneados
OCR convierte las imágenes escaneadas en texto legible por las máquinas. pytesseract es un wrapper de Google Tesseract: rápido, maduro y con más de 100 paquetes de idiomas. EasyOCR utiliza aprendizaje profundo y gestiona mejor las imágenes degradadas y el texto multilingüe.
Realice siempre un preprocesamiento: convierta la imagen a escala de grises, aplique la umbralización de Otsu para binarizarla y corrija la inclinación para ajustar la rotación. En el caso de los PDF basados en imágenes, renderice las páginas como imágenes de alta resolución con PyMuPDF y, después, ejecute el OCR. Filtre los resultados mediante un umbral de confianza para excluir el ruido.
Preguntas frecuentes
¿La lección «OCR para documentos escaneados» es gratis?
Sí — el texto completo de «OCR para documentos escaneados» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de AI Agents, actualiza a CoddyKit PRO. El curso de AI Agents incluye 4 lecciones en total.
¿Qué aprenderé en «OCR para documentos escaneados»?
Tesseract mediante pytesseract, preprocesamiento de imágenes y mejora de la precisión. Practicas AI Agents con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar AI Agents?
No se requiere experiencia previa. AI Agents en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.
¿Cuánto tiempo toma la lección «OCR para documentos escaneados»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de AI Agents?
Sí. Cada lección de AI Agents incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Análisis de PDF con PyMuPDF y pdfplumber
- OCR para documentos escaneados
- Agentes de preguntas y respuestas sobre varios documentos
- Clasificación y enrutamiento de documentos