En plataformas de comercio electrónico y agregadores de marketplaces que gestionan catálogos masivos, el procesamiento de imágenes representa un cuello de botella crítico. Las fotografías suministradas por fabricantes y proveedores presentan discrepancias de relación de aspecto, fondos recargados y condiciones lumínicas deficientes. Si bien existen herramientas de escritorio para edición por lotes, estas requieren intervención manual y carecen de integración nativa con los sistemas centrales de ERP, PIM (Product Information Management) o CMS. Por su parte, recurrir a diseñadores gráficos manuales introduce demoras de 24 a 72 horas por SKU y dispara los costes operativos.
Cutout.pro ofrece una API REST de visión artificial diseñada específicamente para automatizar el recorte de fondos, el encuadre de objetos y la generación de fondos de color uniforme. Al integrar esta API en una canalización de procesamiento asíncrona, los equipos de desarrollo pueden estandarizar miles de imágenes en segundos, convirtiendo fotografías en bruto en activos de catálogo conformes a los estándares de Amazon, Shopify y Google Shopping: fondo blanco puro (#FFFFFF), márgenes uniformes y sombras de contacto realistas.
1. Arquitectura de la API y proceso de autenticación
La API de Cutout.pro expone sus capacidades a través de llamadas HTTPS estándar. La autenticación se gestiona de manera homogénea en todos los extremos incluyendo una cabecera HTTP personalizada:
APIKEY: su_clave_de_api_cutout_pro
Comprobación previa de créditos en entornos de producción
Las subidas de catálogos durante campañas de temporada pueden implicar decenas de miles de imágenes en un único lote. Si el saldo se agota durante el procesamiento, las tareas fallarán de forma masiva con el código de error 4001 (créditos insuficientes). Por ello, el pipeline debe verificar el saldo disponible antes de disparar las ejecuciones.
Cutout.pro proporciona un endpoint dedicado para consultar la suscripción y el balance:
- Endpoint:
GET https://www.cutout.pro/api/v1/mySubscription - Cabeceras:
APIKEY: <SU_API_KEY>,Accept: application/json
Respuesta JSON devuelta:
{
"code": 0,
"data": {
"monthBalance": 1250,
"imageBalance": 5000,
"videoBalance": 0,
"monthStartDate": "2026-10-01 00:00:00",
"monthExpireDate": "2026-11-01 00:00:00"
},
"msg": null,
"time": 1728729600000
}
Incorporar esta verificación en el orquestador de ingesta permite pausar el pipeline y notificar al equipo de operaciones antes de lanzar miles de llamadas de pago.
2. Modos de integración y parámetros clave
Para el recorte de artículos y productos de ecommerce, Cutout.pro recomienda utilizar mattingType=6 (recorte general de productos, ropa y objetos) o mattingType=1. La plataforma ofrece tres modalidades de consulta según la arquitectura de datos:
| Modalidad | Endpoint | Método y Content-Type | Carga de respuesta | Caso de uso ideal |
|---|---|---|---|---|
| Modo 1: Flujo binario | https://www.cutout.pro/api/v1/matting | POST / multipart/form-data | Imagen binaria cruda (image/png) | Almacenamiento local directo en disco o búfer de memoria |
| Modo 2: Base64 en JSON | https://www.cutout.pro/api/v1/matting2 | POST / multipart/form-data | JSON con data.imageBase64 | Microservicios que operan mediante mensajería JSON RPC |
| Modo 3: URL remota | https://www.cutout.pro/api/v1/mattingByUrl | GET / query string | JSON con data.imageBase64 | Imágenes ya alojadas en Amazon S3, Cloudflare R2 o CDN |
Parámetros esenciales para la estandarización en ecommerce
mattingType(entero, obligatorio): Establecer en6para el recorte de productos de ecommerce.crop(booleano, opcional): Al configurarse comotrue, el algoritmo recorta automáticamente los márgenes vacíos y transparentes, ajustando el encuadre a la caja delimitadora del producto.cropMargin(cadena, opcional): Define un margen exterior alrededor del producto recortado cuandocrop=true. Acepta píxeles absolutos (ej."30px") o porcentajes relativos (ej."10%").bgcolor(cadena hexadecimal, opcional): Sustituye la transparencia por un color sólido en formato hexadecimal sin#(ej.FFFFFFpara blanco puro). El valor especial'blur'aplica desenfoque al fondo.outputFormat(cadena, opcional): Admitepng,webpojpg_<calidad>(por ejemplo,jpg_85).preview(booleano, opcional): Cuando estrue, limita la resolución a 500x500 píxeles y deduce únicamente 0.25 créditos por llamada exitosa (en lugar de 1 crédito por imagen de resolución completa de hasta 4096x4096px y <15MB). Muy útil para vistas previas en paneles de vendedores.
3. Procesamiento por lotes y gestión de concurrencia (Colas asíncronas)
La API de Cutout.pro funciona de manera síncrona: cada llamada HTTP espera a que el modelo compute la máscara y devuelva el resultado. No obstante, Cutout.pro impone un límite de concurrencia estricto de 5 peticiones por segundo (5 QPS).
Si un script local ejecuta peticiones concurrentes sin limitador de tasa, el servicio devolverá repetidamente el código 5005 (Too many requests in the queue, please wait). Para procesar catálogos de más de 10.000 referencias de forma fiable, es indispensable articular la arquitectura mediante colas de mensajes asíncronas.
Diagrama de arquitectura recomendada
[ERP / PIM Ingesta por Lote]
│ (Lote de SKUs a procesar)
▼
[Message Broker: Redis / RabbitMQ]
│
▼
[Grupo de Workers (Celery / BullMQ)]
├── Limitador Token Bucket (Capado a <= 4.5 QPS)
├── Llamada a Cutout.pro API (POST /api/v1/matting?mattingType=6)
│ └── Retroceso exponencial ante error 5005
├── Motor local de post-procesamiento (Pillow / Sharp)
│ ├── Centrado en lienzo cuadrado (ej. 2000x2000px)
│ ├── Factor de ocupación del 85%
│ └── Generación de sombra de contacto suave
├── Almacenamiento en la nube (AWS S3 / Cloudflare R2)
└── Callback Webhook al ERP (Actualización de URLs de producto)
Estrategia de resiliencia y gestión de errores
- Limitación de tasa por Token Bucket: Implementar un limitador centralizado en Redis para que todas las instancias combinadas no superen 4.5 peticiones por segundo.
- Matriz de errores:
5005(Cola llena / QPS excedido): Reintentar con retroceso exponencial y variación aleatoria (espera: 1.5s, 3s, 6s).1002(Archivo superior a 15MB) o5008(Formato inválido): Desviar el SKU a una cola de mensajes no entregados (Dead-Letter Queue) para revisión humana en el ERP.4001(Saldo agotado): Pausar inmediatamente los workers y disparar una alerta crítica al canal de operaciones.
4. Pipeline completo de estandarización: Dimensiones, encuadre y sombras
Aunque el parámetro bgcolor=FFFFFF permite generar fondos blancos directamente, los estándares de Amazon, Google Shopping y Shopify exigen normas geométricas estrictas:
- Formato de lienzo estrictamente cuadrado (relación 1:1, ej. 2000x2000 píxeles).
- El producto debe ocupar entre el 80% y el 85% del área total del encuadre.
- Los fondos blancos artificiales sin sombras hacen que los productos parezcan calcomanías flotantes. Añadir una sombra de contacto suave en la base aporta tridimensionalidad y realismo comercial.
El patrón más robusto consiste en solicitar a Cutout.pro una imagen PNG transparente recortada (crop=true, sin bgcolor) y realizar el centrado y la proyección de sombra en el worker local con librerías de alto rendimiento como Pillow (Python) o Sharp (Node.js).
Implementación del pipeline en Python con Pillow
import io
import time
import requests
from PIL import Image, ImageFilter
CUTOUT_API_KEY = "SU_API_KEY_AQUI"
API_URL = "https://www.cutout.pro/api/v1/matting?mattingType=6&crop=true"
def remove_background(image_bytes: bytes, max_retries: int = 3) -> bytes:
"""Llama a Cutout.pro con retroceso exponencial ante límites de tasa."""
headers = {"APIKEY": CUTOUT_API_KEY}
files = {"file": ("product.jpg", image_bytes, "image/jpeg")}
for attempt in range(max_retries):
response = requests.post(API_URL, headers=headers, files=files, timeout=30)
if response.status_code == 200 and response.headers.get("Content-Type", "").startswith("image/"):
return response.content
try:
err = response.json()
code = err.get("code")
msg = err.get("msg")
if code == 5005: # Límite de tasa
time.sleep((2 ** attempt) + 0.5)
continue
elif code == 4001:
raise RuntimeError("Créditos agotados en Cutout.pro API.")
else:
raise ValueError(f"Error en Cutout.pro: {code} - {msg}")
except requests.exceptions.JSONDecodeError:
response.raise_for_status()
raise TimeoutError("Límite de reintentos alcanzado en Cutout.pro.")
def standardize_product_image(
transparent_png_bytes: bytes,
target_canvas_size: int = 2000,
fill_ratio: float = 0.85
) -> Image.Image:
"""
Normaliza la imagen a un lienzo blanco cuadrado, escala el producto al 85%
del encuadre y añade una sombra de contacto en la base.
"""
# 1. Cargar el recorte transparente
product = Image.open(io.BytesIO(transparent_png_bytes)).convert("RGBA")
prod_w, prod_h = product.size
# 2. Escalar manteniendo la proporción
max_dim = int(target_canvas_size * fill_ratio)
scale = min(max_dim / prod_w, max_dim / prod_h)
new_w, new_h = int(prod_w * scale), int(prod_h * scale)
product_resized = product.resize((new_w, new_h), Image.Resampling.LANCZOS)
# 3. Crear lienzo blanco puro cuadrado
canvas = Image.new("RGBA", (target_canvas_size, target_canvas_size), (255, 255, 255, 255))
# 4. Sintetizar sombra de contacto suave
alpha_channel = product_resized.split()[3]
shadow_height = max(10, int(new_h * 0.08))
# Comprimir verticalmente el canal alfa para crear la silueta de contacto
shadow_footprint = alpha_channel.resize((new_w, shadow_height), Image.Resampling.BILINEAR)
shadow_footprint = shadow_footprint.filter(ImageFilter.GaussianBlur(radius=15))
# Crear capa gris oscura y aplicar opacidad reducida (35%)
shadow_layer = Image.new("RGBA", (new_w, shadow_height), (40, 40, 40, 0))
shadow_layer.putalpha(shadow_footprint.point(lambda p: int(p * 0.35)))
# 5. Componer capas en el lienzo
pos_x = (target_canvas_size - new_w) // 2
pos_y = (target_canvas_size - new_h) // 2
# Posicionar la sombra justo en la base del artículo
shadow_y = pos_y + new_h - int(shadow_height * 0.6)
canvas.paste(shadow_layer, (pos_x, shadow_y), shadow_layer)
# Pegar el producto en primer plano
canvas.paste(product_resized, (pos_x, pos_y), product_resized)
# Devolver imagen en formato RGB lista para producción
return canvas.convert("RGB")
def process_sku(raw_path: str, output_path: str):
with open(raw_path, "rb") as f:
raw_data = f.read()
# Paso 1: Recorte en la nube
cutout_png = remove_background(raw_data)
# Paso 2: Estandarización de proporciones y sombra
final_image = standardize_product_image(cutout_png)
# Paso 3: Guardar master JPEG optimizado
final_image.save(output_path, "JPEG", quality=90, optimize=True)
5. Prácticas recomendadas y optimización de costes
- Aprovechar
mattingByUrlpara ahorrar ancho de banda: Si las fotos de los proveedores ya están en Amazon S3 o Cloudflare R2, recurra al endpointmattingByUrl. Al transmitir la URL pública en lugar de subir archivos binarios multipart, su infraestructura ahorra tráfico de subida y reduce la latencia. - Flujo de calidad en dos etapas: Configure la ingesta preliminar de catálogos con
preview=true(0.25 créditos). Cuando el equipo de compras o el comercio valide el borrador, se dispara la llamada de resolución completa (1 crédito). - Persistir las máscaras PNG transparentes: Guarde siempre el PNG transparente original devuelto por Cutout.pro en un almacenamiento de respaldo. Si la política de diseño del marketplace cambia (por ejemplo, de fondo blanco a fondo gris perla o si se modifican los márgenes), podrá reensamblar las imágenes localmente sin volver a consumir créditos de la API.