Vamos construir una aplicación de reconocimiento de objetos en imágenes. No olvides que puedes encontrar el código fuente de la aplicación en github.com/juandc/serverless-rekognition.
Si quieres aprender todo sobre los servicios de Amazon Web Services puedes tomar el Curso de Fundamentos de AWS Cloud.
Serverless 🔌

Los servidores no son más que computadoras que atienden las peticiones de un usuario y le devuelven una respuesta por internet.
Muchas empresas nos ofrecen un alquiler de sus servidores, pero no siempre es lo más conveniente: Tenemos que ocuparnos del sistema operativo, las actualizaciones, instalar los lenguajes de programación, aumentar o disminuir el número de servidores que necesitamos (porque debemos pagar aunque nadie esté usando nuestra aplicación), entre muchas otras complicaciones.
Serverless resuelve todos estos problemas: En vez de pagar por una cantidad de servidores durante un tiempo, le pediremos a nuestros proveedores (Amazon, Google, Microsoft) que nos cobren únicamente por las veces que nuestros usuarios entren a nuestra aplicación. Ahora no debemos preocuparnos por la administración de nuestros servidores, solo por programar.
Serverless Framework ⚡️
Serverless Framework es una herramienta open source para construir e implementar aplicaciones serverless. Tiene soporte para las tecnologías más populares como AWS Lambda, Microsoft Azure, Google Cloud Platform e IBM OpenWhisk. Nos va a ser muy útil para desarrollar nuestra aplicación super rápido y simple.
AWS Rekognition 🔥
AWS Recognition es un servicio basado en Deep Learning (inteligencia artificial). Su trabajo es detectar objetos, personas, celebridades o actividades especiales en el contenido de fotografías y videos. Nuestra aplicación va a utilizar esta herramienta para etiquetar el contenido de nuestras imágenes.
Requisitos para empezar:
- Node.js y NPM.
- Una cuenta gratis en AWS: No te preocupes, ¡seguir este tutorial no va a generar cobros a tu cuenta! 😏
- Cuenta IAM: AWS IAM nos ayuda a administrar los accesos y permisos de usuarios y máquinas. En este caso necesitamos una cuenta para Serverless Framework y AWS Rekognition. Para crear la cuenta puedes seguir esta guía: IAM - Creating AWS Access Keys.
Instalación de Serverless Framework:
Para instalar la herramienta podemos ejecutar el siguiente comando: npm install serverless --global
.
Recuerda pasar las credenciales de IAM a la configuración de Serverless Framework:
sls config credentials -p aws --key TOKEN -s PASSWORD
Estructura de Serverless Framework:
Para usar esta herramienta solo necesitamos crear el archivo serverless.yml
con los siguientes campos:
service
: El nombre de nuestra aplicación.- provider: Serverless es compatible con Amazon, Google Cloud, Microsoft Azure, entre otros. En este tutorial usaremos AWS, pero tú usa el que te resulte más cómodo.
plugins
: Podemos darle aún más super poderes a nuestra aplicación usando los plugins de serverless. En este caso usaremos serverless-webpack y serverless-offline, pero puedes ver la lista de plugins disponibles en github.com/serverless/plugins.functions
: En esta sección describimos los archivos y eventos que necesita nuestra aplicación para funcionar. Puedes separar tu aplicación en muchas funciones.
Organización del Proyecto:
El objetivo de nuestra aplicación es construir una API a la que podamos pasar la URL de una imagen y nos devuelve información sobre su contenido.
Necesitaremos los siguientes paquetes:
express
para manejar nuestras rutas (/, /api, /api?img=…)serverless-http
para traducir la información de Expressjs a Serverless Frameworkaws-sdk
nos proporciona los métodos necesarios para conectarnos con AWS Rekognitionrequest
para convertir la URL de nuestras imágenes en información que AWS Rekognition pueda entenderserverless-webpack
para traducir nuestro código JavaScript a Serverless Frameworkwebpack
webpack-node-externals
serverless-offline
para probar nuestro código en etapa de desarrollo (por defecto no podemos 😅)
Puedes instalar estos paquetes usando los siguientes comandos:
npm i express serverless-http aws-sdk request -S
npm i webpack webpack-node-externals serverless-webpack serverless-offline -D
Configuración:
Ahora vamos a crear los archivos serverless.yml
y webpack.config.js
:
# severless.yml
service: EL_NOMBRE_DE_TU_APLICACIÓN
provider:
name: aws
runtime: nodejs8.10
stage: test
environment:
ACCESS_KEY_ID: TU_ACCESS_KEY_ID_DE_IAM
SECRET_ACCESS_KEY: TU_SECRET_ACCESS_KEY_DE_IAM
plugins:
- serverless-webpack
- serverless-offline
functions:
rekognition:
handler: api.default
events:
- http: ANY /
- http: 'ANY {proxi+}'
// webpack.config.js
const path = require('path');
const slsw = require('serverless-webpack');
const nodeExternals = require('webpack-node-externals');
module.exports = {
entry: slsw.lib.entries,
output: {
libraryTarget: 'commonjs2',
path: path.join(__dirname, '.webpack'),
filename: '[name].js',
},
target: 'node',
externals: [nodeExternals()],
mode: slsw.lib.webpack.isLocal ? 'development' : 'production'
};
Nuestra aplicación:
El código de nuestra aplicación la vamos a escribir en el archivo api.js, se divide en 5 secciones:
1. Importamos las dependencias:
import serverless from 'serverless-http';
import express from 'express';
import AWS from 'aws-sdk';
import request from 'request';
2. Configuración de express
, request
y AWS Rekognition:
const app = express();
const requests = request.defaults({ encoding: null });
const rek = new AWS.Rekognition({
region: 'us-west-2',
accessKeyId: process.env.ACCESS_KEY_ID,
secretAccessKey: process.env.SECRET_ACCESS_KEY,
});
3. Creamos la función GetImageLabels
que nos devuelve la información de nuestras imágenes:
function GetImageLabels(params, func) {
params = {
img: params.img || params.image || null,
maxLabels: params.maxLabels || params.MaxLabels || 10,
minConfidence: params.minConfidence || params.MinConfidence || 80,
};
if (!params.img) return func(new Error('The image param cannot be null.'));
if (params.img.length <= 8) return func(new Error('The image param length can not be <= 8.'));
requests.get(params.img, (reqErr, _, body) => {
if (reqErr) return func(new Error('Error in request: ' + reqErr));
const rekParams = {
Image: { Bytes: body },
MaxLabels: params.maxLabels,
MinConfidence: params.minConfidence,
};
rek.detectLabels(rekParams, (rekErr, data) => {
if (rekErr) return func(new Error('Error in rek: ' + rekErr));
return func(null, data);
});
});
}
4. Definimos las rutas de nuestra API usando la función GetImageLabels
:
app.get('/', (req, res) => {
GetImageLabels(req.query, (err, data) => {
if (err) return res.json({ message: err.message, error: true });
res.json({
image: req.query.img || req.query.image,
message: 'Success!',
data,
});
});
});
5. Y por último, exportamos las rutas de expressjs con ayuda de serverless-http
:
export default serverless(app);
Nuestro archivo completo quedaría así:
// api.js
import serverless from 'serverless-http';
import express from 'express';
import AWS from 'aws-sdk';
import request from 'request';
const app = express();
const requests = request.defaults({ encoding: null });
const rek = new AWS.Rekognition({
region: 'us-west-2',
accessKeyId: process.env.ACCESS_KEY_ID,
secretAccessKey: process.env.SECRET_ACCESS_KEY,
});
app.get('/', (req, res) => {
GetImageLabels(req.query, (err, data) => {
if (err) return res.json({ message: err.message, error: true });
res.json({
image: req.query.img || req.query.image,
message: 'Success!',
data,
});
});
});
function GetImageLabels(params, func) {
params = {
img: params.img || params.image || null,
maxLabels: params.maxLabels || params.MaxLabels || 10,
minConfidence: params.minConfidence || params.MinConfidence || 80,
};
if (!params.img) return func(new Error('The image param cannot be null.'));
if (params.img.length <= 8) return func(new Error('The image param length can not be <= 8.'));
requests.get(params.img, (reqErr, _, body) => {
if (reqErr) return func(new Error('Error in request: ' + reqErr));
const rekParams = {
Image: { Bytes: body },
MaxLabels: params.maxLabels,
MinConfidence: params.minConfidence,
};
rek.detectLabels(rekParams, (rekErr, data) => {
if (rekErr) return func(new Error('Error in rek: ' + rekErr));
return func(null, data);
});
});
}
export default serverless(app);
Para probar que nuestra aplicación esté funcionando podemos correr el siguiente comando:
sls offline start
Ahora si navegamos a http://localhost:3000/?img=http://www.grupocanton.com/all/imagenes/1/2018/07/16/447131_grande_EPFBUm8C.jpg (con una imagen de ejemplo, por supuesto) obtenemos un resultado en tipo JSON con los objetos que Rekognition detecto en nuestra imagen:
{
"image": "http://www.grupocanton.com/all/imagenes/1/2018/07/16/447131_grande_EPFBUm8C.jpg",
"message": "Success!",
"data": {
"Labels": [
{
"Name": "Human",
"Confidence": 99.18035125732422
},
{
"Name": "People",
"Confidence": 99.18035125732422
},
{
"Name": "Person",
"Confidence": 99.18035125732422
},
{
"Name": "Clothing",
"Confidence": 91.23234558105469
},
{
"Name": "Coat",
"Confidence": 91.23234558105469
},
{
"Name": "Overcoat",
"Confidence": 91.23234558105469
},
{
"Name": "Suit",
"Confidence": 91.23234558105469
}
],
"OrientationCorrection": "ROTATE_0"
}
}
Deploy en AWS Lambda:
Serverless Framework también se puede encargar de configurar nuestro entorno en AWS para hacer deploy, solo tenemos que ejecutar el siguiente comando dentro de la carpeta de nuestro proyecto:
sls deploy
Conclusiones
¡Felicidades! Nuestra aplicación funciona correctamente y devuelve las etiquetas de nuestras imágenes. Ahora es tu turno: ¿Cómo podrías mejorar esta aplicación? Puedes dejar el link a tu proyecto en los comentarios. 😏😌
Existen muchos otros servicios de AWS que puedes utilizar con Lambda y Serverless Framework. Recuerda tomar el Curso de Fundamentos de AWS Cloud y toda la Carrera de Amazon Web Services para aprender a integrar los servicios de AWS y construir tu mejor aplicación.
#NuncaParesDeAprender 🤓💚
Curso Práctico de AWS Cloud