15

Reconocimiento de objetos en JavaScript con Serverless Framework y AWS Rekognition

54936Puntos

hace un mes

Curso de Fundamentos de AWS Cloud
Curso de Fundamentos de AWS Cloud

Curso de Fundamentos de AWS Cloud

Aprende a utilizar Amazon Web Services, la plataforma de servicios de cómputo en la nube de Amazon que prevé la carga a futuro de tus propios servidores. Empieza a desplegar tus aplicaciones en la nube y ahorra tiempo para que te enfoques en las labores más importantes de tu trabajo.

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 🔌

CommitStrip 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 Framework
  • aws-sdk nos proporciona los métodos necesarios para conectarnos con AWS Rekognition
  • request para convertir la URL de nuestras imágenes en información que AWS Rekognition pueda entender
  • serverless-webpack para traducir nuestro código JavaScript a Serverless Framework
  • webpack
  • 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.ymlservice: 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.jsconst 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:

functionGetImageLabels(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(newError('The image param cannot be null.'));
  if (params.img.length <= 8) return func(newError('The image param length can not be <= 8.'));

  requests.get(params.img, (reqErr, _, body) => {
    if (reqErr) return func(newError('Error in request: ' + reqErr));

    const rekParams = {
      Image: { Bytes: body },
      MaxLabels: params.maxLabels,
      MinConfidence: params.minConfidence,
    };

    rek.detectLabels(rekParams, (rekErr, data) => {
      if (rekErr) return func(newError('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:

exportdefault serverless(app);

Nuestro archivo completo quedaría así:

// api.jsimport 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,
    });
  });
});

functionGetImageLabels(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(newError('The image param cannot be null.'));
  if (params.img.length <= 8) return func(newError('The image param length can not be <= 8.'));

  requests.get(params.img, (reqErr, _, body) => {
    if (reqErr) return func(newError('Error in request: ' + reqErr));

    const rekParams = {
      Image: { Bytes: body },
      MaxLabels: params.maxLabels,
      MinConfidence: params.minConfidence,
    };

    rek.detectLabels(rekParams, (rekErr, data) => {
      if (rekErr) return func(newError('Error in rek: ' + rekErr));
      return func(null, data);
    });
  });
}

exportdefault 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 de Fundamentos de AWS Cloud
Curso de Fundamentos de AWS Cloud

Curso de Fundamentos de AWS Cloud

Aprende a utilizar Amazon Web Services, la plataforma de servicios de cómputo en la nube de Amazon que prevé la carga a futuro de tus propios servidores. Empieza a desplegar tus aplicaciones en la nube y ahorra tiempo para que te enfoques en las labores más importantes de tu trabajo.
Juan David
Juan David
@juandc

54936Puntos

hace un mes

Todas sus entradas
Escribe tu comentario
+ 2