Tesseract OCR en Python
con pytesseract.
Guía completa y probada de pytesseract: instalación, API principal, preprocesado de imágenes, PDF, puntuaciones de confianza, configuración PSM/OEM, rendimiento y los errores más habituales.
Inicio rápido (tres líneas)
Instala primero el motor y ejecuta esto. La configuración completa viene después.
import pytesseract
from PIL import Image
text = pytesseract.image_to_string(Image.open("image.png"))
print(text)Instalar pytesseract
pytesseract es solo un wrapper: llama al binario de Tesseract, así que primero debes instalar el motor.
pip install pytesseract pillow
# opcional, para preprocesado:
pip install opencv-python numpy
# opcional, para entrada PDF:
pip install pdf2imageSi el motor no está en tu PATH (habitual en Windows), indícalo explícitamente:
import pytesseract
pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"¿Nuevo con el motor? Consulta la guía de instalación para Windows, macOS, Linux, Docker y WSL.
API principal
pytesseract expone una función por tipo de salida. Elige la que corresponda a lo que necesitas.
| Función | Devuelve | Úsala cuando |
|---|---|---|
image_to_string | Texto plano | Solo necesitas el texto reconocido |
image_to_data | Cajas por palabra + confianza | Resaltar texto, filtrar palabras de baja confianza |
image_to_boxes | Cajas por carácter | Geometría a nivel de carácter |
image_to_pdf_or_hocr | PDF con texto o hOCR | Crear PDF buscables u overlays web |
image_to_osd | Detección de orientación y escritura | Detectar rotación o escritura antes del OCR |
image_to_alto_xml | ALTO XML | Pipelines de archivo o bibliotecas |
Configuración: PSM, OEM, idiomas y lista de caracteres
Pasa las opciones como una cadena separada por espacios a config=.
# Un solo bloque de texto, motor LSTM, español
text = pytesseract.image_to_string(img, lang="spa", config="--oem 3 --psm 6")
# Solo dígitos (totales de recibos, lecturas de contadores)
text = pytesseract.image_to_string(img, config="--psm 7 -c tessedit_char_whitelist=0123456789.")
# Idiomas combinados
text = pytesseract.image_to_string(img, lang="eng+spa")| PSM | Modo | Ideal para |
|---|---|---|
| 3 | Totalmente automático (predeterminado) | Documentos estándar |
| 4 | Una columna de tamaños variables | Artículos, páginas a una columna |
| 6 | Un bloque uniforme de texto | Párrafos, etiquetas |
| 7 | Una sola línea de texto | Titulares de una línea, campos sueltos |
| 8 | Una sola palabra | Palabras individuales |
| 11 | Texto disperso | Recibos, texto de interfaz disperso |
| 13 | Línea sin procesar | Una línea sin trucos específicos |
Modos OEM: --oem 1 (solo LSTM, predeterminado en v5), --oem 0 (heredado), --oem 3 (automático). Referencia completa en la documentación.
Preprocesado de imágenes
Una entrada limpia es el mayor factor de precisión. Estos son los pasos que más importan.
import cv2, numpy as np, pytesseract
from PIL import Image
image = cv2.imread("recibo.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Escala el texto pequeño a un equivalente de ~300 DPI
gray = cv2.resize(gray, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC)
# Elimina ruido y aplica umbral Otsu a blanco y negro puro
blur = cv2.GaussianBlur(gray, (5, 5), 0)
_, binary = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
text = pytesseract.image_to_string(Image.fromarray(binary))- Escala de grises — elimina los canales de color antes del umbral.
- Escalado — el texto de menos de ~20 px se reconoce mal; amplíalo.
- Umbral — Otsu con luz uniforme, adaptativo con luz desigual.
- Reducción de ruido — un desenfoque suave elimina motas que se leen como puntuación.
- Enderezado — corrige la rotación con
cv2.minAreaRectantes del OCR. - Recorte de bordes — elimina bordes oscuros que confunden el análisis de diseño.
Posiciones y puntuaciones de confianza
Usa image_to_data para obtener cajas por palabra y una confianza de 0 a 100, y filtra el ruido.
from pytesseract import Output
data = pytesseract.image_to_data(img, output_type=Output.DICT)
for text, conf in zip(data["text"], data["conf"]):
if text.strip() and float(conf) > 60: # descarta ruido de baja confianza
print(round(float(conf)), text)Aplicar OCR a un PDF en Python
Tesseract trabaja con imágenes, así que primero rasteriza las páginas del PDF con pdf2image (que necesita las herramientas poppler).
import io, pytesseract
from pdf2image import convert_from_path
from pypdf import PdfWriter, PdfReader
pages = convert_from_path("escaneo.pdf", dpi=300) # requiere poppler
writer = PdfWriter()
for page in pages:
pdf_bytes = pytesseract.image_to_pdf_or_hocr(page, extension="pdf")
writer.add_page(PdfReader(io.BytesIO(pdf_bytes)).pages[0])
with open("escaneo_buscable.pdf", "wb") as f:
writer.write(f)En Windows, pasa la carpeta bin de poppler con poppler_path=. Para un flujo más completo, consulta la documentación sobre formatos de salida.
Rendimiento
pytesseract invoca la CLI en cada llamada, así que el rendimiento depende de cómo estructures el proceso.
| Enfoque | Cuándo | Compromiso |
|---|---|---|
pytesseract por llamada | Scripts y trabajos puntuales | Lanza un proceso por llamada — lento en bucles |
| Agrupar en TIFF multipágina | Muchas páginas con la misma configuración | Un proceso para muchas páginas |
multiprocessing | Muchas imágenes independientes | Usa todos los núcleos; más memoria |
tesserocr | Alto volumen, en proceso | Binding nativo, más configuración |
Catálogo de errores
Estos errores cubren la mayoría de problemas con pytesseract.
| Error | Causa | Solución |
|---|---|---|
TesseractNotFoundError | Binario no instalado o fuera del PATH | Instala el motor o define pytesseract.pytesseract.tesseract_cmd. |
(-215:Assertion failed) src.type() == CV_8UC1 | Umbral sobre una imagen de 3 canales | Convierte con cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) primero. |
Error opening data file ...fra.traineddata | Falta el paquete de idioma | Instala el idioma o define TESSDATA_PREFIX. |
| Salida vacía | DPI bajo, PSM incorrecto o sin texto | Escala, prueba --psm 6/7/11 y preprocesa. |
| Muy lento en bucle | Un proceso por llamada | Agrupa, usa multiprocessing o tesserocr. |
Medir la precisión
Mide la tasa de error de caracteres y palabras en lugar de juzgar la salida a ojo.
import pytesseract, jiwer
from PIL import Image
hypothesis = pytesseract.image_to_string(Image.open("muestra.png"))
reference = open("muestra.gt.txt").read()
print("CER:", jiwer.cer(reference, hypothesis))
print("WER:", jiwer.wer(reference, hypothesis))Guarda un conjunto pequeño de imágenes representativas con su texto de referencia como pruebas de regresión y vuelve a ejecutarlas cuando cambies el preprocesado o la configuración.
Preguntas frecuentes de Python
¿Cómo uso Tesseract OCR en Python?
Instala primero el motor Tesseract y luego pip install pytesseract pillow. Abre la imagen con Pillow y llama a pytesseract.image_to_string(img).
¿Por qué aparece TesseractNotFoundError?
pytesseract no encuentra el binario. Instala el motor, ponlo en el PATH o define pytesseract.pytesseract.tesseract_cmd con la ruta completa.
¿Cómo mejoro la precisión?
Escala a ~300 DPI, escala de grises, umbral, reducción de ruido, enderezado y el --psm correcto. Usa el lang= adecuado y, para campos fijos, una lista de caracteres permitidos.
¿Cómo aplico OCR a un PDF?
Usa pdf2image (con poppler) para convertir las páginas en imágenes, ejecuta pytesseract en cada una y combínalas con image_to_pdf_or_hocr(..., extension="pdf").
¿Cómo obtengo puntuaciones de confianza?
Usa image_to_data(..., output_type=Output.DICT) y filtra por la lista conf.
¿pytesseract es lento?
Cada llamada lanza un proceso. Agrupa, usa multiprocessing o cambia al binding en proceso tesserocr para alto rendimiento.
Siguientes pasos
Profundiza en el motor y el ecosistema.