Redacta texto alternativo de imagen con AWS Rekognition y Node.js
Proporcionar texto alternativo descriptivo para las imágenes es fundamental para la accesibilidad y el SEO. Sin embargo, escribir manualmente el texto alternativo de muchas imágenes puede llevar mucho tiempo. AWS Rekognition y Node.js pueden sugerir etiquetas de imagen para ayudar a un editor a escribir una descripción. Rekognition detecta objetos y escenas; no genera un pie de foto contextual ni determina el propósito de la imagen en una página.
¿Por qué automatizar el texto alternativo?
El texto alternativo ayuda a las personas con discapacidad visual a entender el contenido de las
imágenes mediante lectores de pantalla y aporta contexto a los motores de búsqueda. Las sugerencias
de etiquetas pueden acelerar la revisión, pero no deben insertarse directamente en el atributo
alt de una imagen. Sigue el
árbol de decisión de texto alternativo del W3C para decidir si una
imagen necesita una descripción, si hay que describir el propósito de su enlace o botón, o si
necesita una alternativa vacía por tratarse de una imagen decorativa. Una lista de objetos
detectados no puede tomar esas decisiones.
Integración de AWS Rekognition y Node.js
AWS Rekognition es un potente servicio de análisis de imágenes capaz de detectar objetos, escenas y actividades dentro de las imágenes. Integrarlo con Node.js permite a los desarrolladores crear rápidamente aplicaciones escalables que ofrecen sugerencias para un flujo de trabajo de texto alternativo revisado por una persona.
Configuración de tu entorno
Primero, asegúrate de tener:
- Una cuenta de AWS y una identidad de IAM con permiso para llamar a
rekognition:DetectLabels - Node.js 22.12 o posterior instalado
- AWS SDK v3 para JavaScript
Instala el AWS SDK:
npm install @aws-sdk/client-rekognition@3 dotenv@17
Configura un perfil local de AWS o un rol de IAM mediante la cadena de proveedores de credenciales
predeterminada del SDK. Define la región en un archivo .env local y excluye ese archivo del control de versiones:
AWS_REGION=your-region
Si usas variables de entorno para las credenciales, las credenciales temporales también necesitan AWS_SESSION_TOKEN
junto con AWS_ACCESS_KEY_ID y AWS_SECRET_ACCESS_KEY. No incrustes credenciales en el código fuente.
Requisitos de las imágenes
Antes de implementar la solución, ten en cuenta los requisitos de imagen de AWS Rekognition:
- Formatos compatibles: JPEG y PNG
- Tamaño máximo de imagen: 5 MB para la subida directa de bytes
- Tamaño máximo de imagen: 15 MB cuando se referencia como objeto de S3
- Para
DetectLabels, cada dimensión debe estar entre 80 y 10.000 píxeles
Consulta las cuotas de Rekognition para conocer los requisitos específicos de cada operación.
Implementación de sugerencias de etiquetas
Este es un script de Node.js que devuelve sugerencias de etiquetas para la revisión editorial:
import { RekognitionClient, DetectLabelsCommand } from '@aws-sdk/client-rekognition'
import fs from 'fs'
import dotenv from 'dotenv'
dotenv.config({ quiet: true })
const client = new RekognitionClient({ region: process.env.AWS_REGION })
async function detectImageLabels(image, minConfidence = 75) {
if (!Number.isFinite(minConfidence) || minConfidence < 0 || minConfidence > 100) {
throw new Error('Confidence must be a number between 0 and 100.')
}
const command = new DetectLabelsCommand({
Image: image,
MaxLabels: 5,
MinConfidence: minConfidence,
})
const response = await client.send(command)
return (response.Labels ?? [])
.map((label) => label.Name)
.filter((name) => typeof name === 'string' && name.trim().length > 0)
}
async function suggestImageLabels(imagePath, minConfidence = 75) {
const imageBytes = fs.readFileSync(imagePath)
return detectImageLabels({ Bytes: imageBytes }, minConfidence)
}
// Example usage
suggestImageLabels('./example.jpg').then(console.log).catch(() => {
console.error('Unable to retrieve image label suggestions.')
process.exitCode = 1
})
Guarda este código con la extensión .mjs para usar módulos ES, o define "type": "module" en package.json.
Un array vacío significa que no se devolvieron etiquetas utilizables. Los fallos de solicitud y de
lectura de archivos rechazan la promesa para que la aplicación pueda distinguirlos de un análisis
exitoso.
Procesamiento de imágenes desde S3
En entornos de producción, a menudo necesitarás procesar imágenes almacenadas en Amazon S3. Así
puedes ampliar el script anterior para que funcione con S3. El bucket debe estar en la región del
cliente, y la identidad que hace la llamada necesita el permiso s3:GetObject sobre la imagen:
async function suggestImageLabelsFromS3(bucket, key, minConfidence = 75) {
return detectImageLabels({ S3Object: { Bucket: bucket, Name: key } }, minConfidence)
}
// Example usage
suggestImageLabelsFromS3('my-bucket', 'images/example.jpg').then(console.log).catch(() => {
console.error('Unable to retrieve image label suggestions from S3.')
process.exitCode = 1
})
Manejo de casos límite y errores
Gestiona los fallos en el punto donde tu aplicación llama al ayudante. Mantén los errores separados de los datos de las etiquetas; un mensaje de error nunca debe convertirse en texto alternativo ni en una respuesta exitosa almacenada en caché:
try {
const labels = await suggestImageLabels('./example.jpg')
console.log('Labels for review:', labels)
} catch (error) {
if (error.name === 'InvalidImageFormatException') {
console.error('Invalid image format. Only JPEG and PNG are supported.')
} else if (error.name === 'InvalidParameterException') {
console.error('Invalid parameters provided to AWS Rekognition')
} else if (error.name === 'ImageTooLargeException') {
console.error('Image exceeds the input limit: 5MB for bytes, 15MB for S3 objects.')
} else if (error.name === 'AccessDeniedException') {
console.error('AWS credentials lack permission to use Rekognition')
} else if (error.name === 'ThrottlingException') {
console.error('AWS request rate exceeded limits')
} else {
console.error('Unable to retrieve image label suggestions.')
}
process.exitCode = 1
}
Mejora de la funcionalidad
Para mejorar aún más tu flujo de trabajo de sugerencia de etiquetas:
Implementar el almacenamiento en caché
Guarda las sugerencias de etiquetas exitosas para evitar llamadas redundantes a la API. Este ejemplo
opcional necesita un servidor Redis en ejecución y npm install redis@5. Añádelo al script anterior. Aplica
un hash a los bytes reales de la imagen y analiza ese mismo búfer para que, al cambiar un archivo en
la misma ruta, se invalide su caché:
import { createHash } from 'node:crypto'
import { createClient } from 'redis'
const redisClient = createClient()
redisClient.on('error', () => console.error('Redis connection error.'))
await redisClient.connect()
async function getCachedOrSuggestImageLabels(imagePath) {
const imageBytes = fs.readFileSync(imagePath)
const imageHash = createHash('sha256').update(imageBytes).digest('hex')
// Change the version if label settings or the interpretation of the result changes.
const cacheKey = `image_labels:v1:${process.env.AWS_REGION}:${imageHash}`
const cachedLabels = await redisClient.get(cacheKey)
if (cachedLabels !== null) return JSON.parse(cachedLabels)
const labels = await detectImageLabels({ Bytes: imageBytes })
await redisClient.set(cacheKey, JSON.stringify(labels), { EX: 60 * 60 * 24 * 30 })
return labels
}
try {
console.log(await getCachedOrSuggestImageLabels('./example.jpg'))
} catch {
console.error('Unable to retrieve cached image label suggestions.')
process.exitCode = 1
} finally {
await redisClient.close()
}
Procesamiento por lotes
Para un lote pequeño, procesa varias imágenes simultáneamente. Usa una cola limitada para listas más grandes y mantén la concurrencia dentro de tu cuota de Rekognition:
async function batchProcessImages(imagePaths) {
return Promise.all(imagePaths.map((path) => suggestImageLabels(path)))
}
// Example usage
try {
const results = await batchProcessImages(['image1.jpg', 'image2.jpg', 'image3.jpg'])
console.log(results)
} catch {
console.error('Unable to retrieve suggestions for the complete batch.')
process.exitCode = 1
}
Ajuste del umbral de confianza
Ajusta el umbral de confianza según tus necesidades:
suggestImageLabels('./example.jpg', 90)
.then(console.log)
.catch(() => {
console.error('Unable to retrieve image label suggestions.')
process.exitCode = 1
})
Reflexiones finales
AWS Rekognition y Node.js pueden apoyar un flujo de trabajo editorial sugiriendo etiquetas y reutilizando análisis exitosos. Revisa esas sugerencias comparándolas con la imagen real y con su propósito en la página antes de escribir el texto alternativo. Las puntuaciones de confianza describen predicciones del modelo, no la calidad de la accesibilidad.
Si buscas una solución gestionada, considera explorar el 🤖 servicio de inteligencia artificial de Transloadit, que simplifica el análisis de imágenes para este flujo de trabajo.
