Scarnox · Blog

OCR de captcha de imagen y texto: cómo leer captchas distorsionados

Un captcha de imagen muestra una cadena corta de letras o dígitos como una imagen, a veces con ruido, rotación y líneas onduladas. El reconocimiento óptico de caracteres (OCR) puede leer versiones sencillas de estos con un motor de código abierto como Tesseract. La precisión depende de lo limpia que esté la imagen, así que la mayor parte del trabajo es el preprocesado. Esta guía muestra una configuración de Python que funciona, explica dónde falla y deja clara una cosa: la API activa de Scarnox resuelve tokens de widgets PopularCaptcha, no captchas de imagen a texto. Planifica el OCR como código propio, no como una llamada a una API.

Cuándo funciona el OCR y cuándo no

El OCR es una primera opción razonable cuando el texto:

Le cuesta con las letras giradas, las letras que se tocan, las texturas de fondo y las líneas dibujadas sobre los glifos. Cada una de esas necesita un paso de preprocesado específico, y algunas requieren un modelo totalmente distinto. Prepárate para medir la precisión en lugar de darla por supuesta.

Instala las herramientas

Necesitas Python, el binario de Tesseract y dos paquetes de Python:

pip install pillow pytesseract

Tesseract es una instalación aparte. En Windows, usa el instalador del proyecto Tesseract y asegúrate de que el ejecutable está en el PATH, o apunta pytesseract.pytesseract.tesseract_cmd hacia él.

Preprocesa y luego lee

La mayor parte de la precisión viene de una entrada limpia. La secuencia siguiente convierte a escala de grises, aumenta el contraste, aplica un umbral fijo, escala la imagen y restringe la salida a los caracteres que usa el captcha:

from PIL import Image, ImageOps
import pytesseract

# Caracteres que puede usar el captcha. Deja fuera los que se parecen, como 0/O y 1/I, si el
# captcha nunca los usa.
ALLOWED = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"

def read_text(path: str) -> str:
    img = Image.open(path)
    gray = ImageOps.grayscale(img)
    gray = ImageOps.autocontrast(gray)
    # Umbral fijo: los píxeles más claros que 140 pasan a blanco, el resto a negro.
    bw = gray.point(lambda p: 255 if p > 140 else 0)
    # Tesseract funciona mejor con glifos más grandes.
    bw = bw.resize((bw.width * 3, bw.height * 3))
    config = f"--psm 7 -c tessedit_char_whitelist={ALLOWED}"  # psm 7: una línea de texto
    return pytesseract.image_to_string(bw, config=config).strip()

if __name__ == "__main__":
    print(read_text("sample_captcha.png"))

El valor de umbral 140 es un punto de partida. Imprime la imagen procesada, compárala con la original y ajusta hasta que las letras queden sólidas y el fondo esté limpio.

Mide la precisión antes de confiar en ella

Una lectura correcta de una imagen no demuestra nada. Guarda un conjunto de captchas con respuestas conocidas, ejecuta la función sobre todos ellos y cuenta las coincidencias:

def accuracy(samples: dict[str, str]) -> float:
    # samples asocia una ruta de archivo con el texto real
    hits = sum(read_text(path) == truth for path, truth in samples.items())
    return hits / len(samples)

labelled = {
    "samples/0001.png": "K7PQ2",
    "samples/0002.png": "M3XN9",
}
print(f"precisión: {accuracy(labelled):.0%}")

Anota este número cada vez que cambies el preprocesado. Si la cifra sigue siendo baja después de varios cambios, el OCR probablemente no es la herramienta adecuada para ese estilo de captcha, y deberías buscar otro enfoque.

Dónde se rompe

Una lista de comprobación de preprocesado

Cuando una lectura falla, revisa estos puntos en orden. Cambia una cosa cada vez para ver qué paso ayudó:

  1. Comprueba el tamaño de la entrada. Los captchas muy pequeños suelen leerse mejor tras un escalado 3x.
  2. Convierte a escala de grises y estira el contraste para que las letras destaquen.
  3. Aplica un umbral y prueba varios valores antes de decidirte por uno.
  4. Elimina el ruido de motas con un filtro de mediana y vuelve a aplicar el umbral si hace falta.
  5. Recorta la imagen al área del texto para que el fondo no confunda al motor.
  6. Restringe el conjunto de caracteres al que usa el captcha.
  7. Prueba otro modo de segmentación de página si el texto está disperso o apilado.

Guarda el orden y los ajustes en control de versiones junto a tus muestras etiquetadas. Una canalización de preprocesado es código, y debe revisarse como tal.

OCR o un modelo que ejecutes tú

El OCR clásico es rápido y funciona en un portátil, pero es frágil cuando un captcha cambia de estilo. Los modelos de imagen entrenados con tu propio conjunto etiquetado pueden manejar más variaciones, a cambio de recopilar datos y ejecutar la inferencia. Ambas opciones son responsabilidad tuya de construir y mantener. Hoy ninguna es un endpoint alojado de Scarnox, así que planifica la infraestructura antes de comprometerte con una.

Lo que Scarnox hace y no hace aquí

La API activa de Scarnox resuelve tokens de widgets PopularCaptcha. La petición es POST https://api.scarnox.com/api/tasks/create con un tipo de tarea PopularCaptcha, una sitekey y una URL de página, y la respuesta es un token para el campo del formulario. Es un trabajo distinto de leer el texto de una imagen, y Scarnox no ofrece hoy un endpoint de imagen a texto. Si tu problema es un captcha de imagen, usa OCR o un modelo que ejecutes tú, y consulta las otras guías para ver lo que cubre Scarnox. Puedes crear una cuenta y empezar con crédito de prueba gratis, sin tarjeta, para los flujos de PopularCaptcha que sí soporta. Los precios actuales están en la página de precios.

Usos legítimos

No uses OCR para saltarte un captcha en un sitio que no permite el acceso automatizado. Los captchas de imagen existen precisamente para frenar eso.

Próximos pasos