Los CAPTCHA de imágenes complejas utilizan letras conectadas, caracteres superpuestos, fuentes variadas y ruido para evitar el OCR. Aquí se explica cómo abordarlos con CaptchaAI.
Tipos de complejidad comunes
| Tipo | Descripción | dificultad |
|---|---|---|
| Texto limpio | Sin distorsión, fuente uniforme | fácil |
| Texto deformado | Letras rotadas individualmente/scaled | Medio |
| Letras conectadas | Los personajes se superponen o se tocan. | duro |
| Fuente múltiple | Diferentes fuentes por carácter | duro |
| Ruido + líneas | Ruido de fondo, líneas tachadas | Medio |
| variación de color | Diferentes colores por personaje. | Medio |
| expresión matemática | Números + operadores, resultado esperado | Medio |
Envío de CAPTCHA complejos
Para CAPTCHA estándar de varios caracteres, envíelo a través de base64 con las sugerencias adecuadas:
import requests
import base64
import time
import os
API_KEY = os.environ["CAPTCHAAI_API_KEY"]
def solve_complex_image(image_b64, hints=None):
"""Solve a complex multi-character image CAPTCHA."""
payload = {
"key": API_KEY,
"method": "base64",
"body": image_b64,
"json": 1,
}
if hints:
payload.update(hints)
resp = requests.post(
"https://ocr.captchaai.com/in.php",
data=payload,
timeout=30,
)
result = resp.json()
if result.get("status") != 1:
raise RuntimeError(f"Submit failed: {result.get('request')}")
task_id = result["request"]
time.sleep(8)
for _ in range(24):
resp = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "get",
"id": task_id,
"json": 1,
}, timeout=15)
data = resp.json()
if data.get("status") == 1:
return data["request"]
if data["request"] != "CAPCHA_NOT_READY":
raise RuntimeError(data["request"])
time.sleep(5)
raise TimeoutError("Solve timeout")
Estrategia: Letras conectadas
Las letras conectadas son las más difíciles para OCR básico pero no para CaptchaAI:
def solve_connected_letters(image_path):
"""Solve CAPTCHA with connected/overlapping characters."""
with open(image_path, "rb") as f:
b64 = base64.b64encode(f.read()).decode("ascii")
return solve_complex_image(b64, hints={
"textinstructions": "Characters may be connected or overlapping",
"minLen": 4,
"maxLen": 8,
})
Estrategia: caso mixto con ruido
def solve_noisy_mixed(image_path):
"""Solve CAPTCHA with background noise and mixed case."""
with open(image_path, "rb") as f:
b64 = base64.b64encode(f.read()).decode("ascii")
return solve_complex_image(b64, hints={
"regsense": 1, # Case-sensitive
"language": 2, # Latin characters
"textinstructions": "Ignore background lines and noise",
})
Estrategia: texto con varias fuentes
def solve_multi_font(image_path):
"""Solve CAPTCHA using multiple fonts per character."""
with open(image_path, "rb") as f:
b64 = base64.b64encode(f.read()).decode("ascii")
return solve_complex_image(b64, hints={
"textinstructions": "Each character may use a different font or style",
"minLen": 5,
"maxLen": 7,
})
Preprocesamiento de imágenes para obtener mejores resultados
El preprocesamiento antes del envío puede mejorar la precisión:
# preprocess.py
from PIL import Image, ImageFilter, ImageEnhance
import io
import base64
def preprocess_for_ocr(image_path):
"""Preprocess image to improve OCR accuracy."""
img = Image.open(image_path)
# Convert to grayscale
img = img.convert("L")
# Increase contrast
enhancer = ImageEnhance.Contrast(img)
img = enhancer.enhance(2.0)
# Sharpen
img = img.filter(ImageFilter.SHARPEN)
# Binarize (threshold)
threshold = 128
img = img.point(lambda p: 255 if p > threshold else 0)
# Encode back to base64
buffer = io.BytesIO()
img.save(buffer, format="PNG")
return base64.b64encode(buffer.getvalue()).decode("ascii")
Reintentar estrategia con informes
# retry_strategy.py
def solve_with_retry(image_b64, hints, max_retries=3):
"""Retry solving with fallback strategies."""
strategies = [
hints, # Original hints
{**hints, "textinstructions": ""}, # Without instructions
{**hints, "numeric": 0, "regsense": 0}, # Relaxed constraints
]
for i, strategy in enumerate(strategies[:max_retries]):
try:
result = solve_complex_image(image_b64, strategy)
return {"text": result, "strategy": i, "success": True}
except RuntimeError:
continue
return {"text": None, "strategy": -1, "success": False}
def report_bad_answer(task_id):
"""Report incorrect answer for quality feedback."""
requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "reportbad",
"id": task_id,
}, timeout=10)
Solución de problemas
| Problema | causa | Solución |
|---|---|---|
| personajes faltantes | Letras conectadas mal leídas | Agregue textinstructions sobre el texto conectado |
| Personajes adicionales | Ruido interpretado como texto. | Preproceso: eliminar el ruido antes del envío |
| caso equivocado | Caso no conservado | Establecer regsense=1 |
| Resultado matemático devuelto como expresión | Falta calc=1 |
Habilite el modo de cálculo para CAPTCHA matemáticos |
| Constantemente incorrecto en un sitio específico | Fuente específica del sitio | Reportar malas respuestas para mejorar el modelo |
Preguntas frecuentes
¿Debo preprocesar las imágenes antes de enviarlas?
Sólo si estás obteniendo malos resultados. CaptchaAI maneja la mayoría de las distorsiones de forma nativa. El preprocesamiento ayuda en el caso de imágenes muy ruidosas o de bajo contraste.
¿Qué pasa si el mismo tipo de imagen sigue fallando?
Informe malas respuestas con reportbad para ayudar a mejorar la precisión. También intente agregar textinstructions específico que describa las características del CAPTCHA.
¿Existe un límite de caracteres para los CAPTCHA de imágenes?
CaptchaAI puede manejar CAPTCHA de hasta unos 20 caracteres. La mayoría tiene entre 4 y 8 caracteres.
Guías relacionadas
Resolver CAPTCHA de imágenes complejas:empezar con CaptchaAI.