Sebastian Gomez
Siguiendo con la temática de la Cloud Visión de Google en este post vamos a implementarla en NodeJS para detectar características sobre imágenes.
Lo primero que necesitamos entender es que la SDK de la Vision Cloud de Google debería operar sobre un servidor, es allí donde surge la necesidad de usar NodeJS sin embargo si tienes alguna experiencia con NodeJS sabrás que en la mayoría de los casos se requiere de una librería para procesar las peticiones HTTP Post, Get y Put. En este post usaremos ExpressJS ya que es la librería mas conocida para esta tarea. Si tienes dudas sobre las generalidades de la Cloud Vision de Google o la capa gratuita en este post puedes revisarlas.
En primer lugar vamos a revisar las característica que nos ofrece la API de visión de Google para implementar con NodeJs:
Revisemos las responsabilidades que tendría cada uno de los componentes de la arquitectura anterior:
Client Browser:
ExpressJS:
Google Vision SDK *:
Google Vision API:
(*) Un SDK (Software Development Kit), o kit de desarrollo de software, es un conjunto de herramientas que ayudan a la programación de aplicaciones para un entorno tecnológico particular.
Antes de empezar necesitamos obtener una clave y las credenciales del proyecto para hacer uso de la API y la SDK, esto lo podemos conseguir directamente en la consola: https://cloud.google.com/siguiendo estos simples pasos.
Manos a la obra con la implementación: en primer lugar creemos un proyecto en Node desde cero usando la línea de comandos.
...
"scripts": {
"test":"echo\\"Error: no test specified\\"&& exit 1",
"start":"node server.js"
},
...
Esto nos creará la estructura base del proyecto y deberás añadir ademas algunos archivos. A continuación te muestro exactamente como debería lucir tu carpeta del proyecto y la explicación de cada item:
Como notarás los únicos archivos sobre los cuales escribiremos código son server.js, index.html y app.js. Empecemos entonces con una funcionalidad básica: ¿Como tomar fotos con javascript?
https://codepen.io/seagomezar/pen/QayorL
Como verás simplemente creando un stream y accediendo a los elementos del DOM es posible obtener la mas sencilla funcionalidad de tomar desde la cámara de tu ordenador las imágenes y pintarlas dentro de la etiqueta img.
Ahora veremos como subir la imagen que tomamos a nuestro servidor: En primer lugar desde nuestra aplicación una vez que tomamos la imagen y la pintamos dentro de la etiqueta SRC necesitamos hacer una petición HTTP al servidor indicándole que allí va la imagen. Para esto abre tu archivo app.js y añade la función upload:
function upload() {
const http = new XMLHttpRequest();
const url = "upload";
snap().then((blob) => {
http.open("POST", url, true);
http.setRequestHeader("X-Requested-With", "XMLHttpRequest");
http.onreadystatechange = (data) => {
//Call a function when the state changes.
if (http.readyState == 4 && http.status == 200) {
console.log(http.response);
}
};
const formData = new FormData();
formData.append("uploads", blob);
http.send(formData);
});
}
Como verás en esta función invocamos a la función snap() que definimos para capturar imágenes desde nuestra cámara en el browser para enviar el contenido de la imagen mediante una XMLHttpRequest. Luego necesitamos crear nuestro servidor para que sea capaz de recibir y procesar dicha imagen, es en este punto entonces donde necesitamos crear y configurar un servidor básico con express que soporte la opción de subir la imagen. Por tanto tu archivo server.js debe lucir de ésta manera:
En la primera parte de este archivo verás la funcionalidad básica que tiene un servidor de NodeJs usando express y sus respectivas configuraciones, sin profundizar mucho en esto nuestra función de interés es la función upload la cual procesará la imagen y la guardará en la carpeta uploads. Verás que esta función también pondrá cada imagen en la carpeta de uploads con un numero consecutivo relacionado con el momento actual, esto lo hacemos para evitar duplicidades en las imágenes.
Hasta este momento solo hemos creado funciones utilitarias en el server.js para inicializar el server y para subir archivos. Pero no hemos realizado ningún proceso sobre la imagen, ahora vamos a aprender como detectar características sobre la imagen usando la SDK de Cloud Vision API:
const vision = require('@google-cloud/vision')({
projectId: 'vision-poc-180601',
keyFilename: './cloud-credentials.json'
});
app.post("/labels", upload.single('uploads'), function (req, res) {
const currentFile = req.file.path;
const request = {
source: {
filename: currentFile
}
};
vision.labelDetection(request)
.then((results) => {
const labels = results\[0\].labelAnnotations;
console.log('Labels:');
labels.forEach((label) => console.log(label.description));
res.send(labels);
})
.catch((err) => {
console.error('ERROR:', err);
res.send("BAD");
});
});
Primero vamos a añadir las líneas que inicializan nuestra configuración de la Cloud Vision de Google. Luego creamos con express un endpoint que se encarga de recibir una imagen y obtener todos los labels o etiquetas que se pueden obtener de dicha imagen. Y los retornaremos como respuesta de la petición para presentarlos en el front-end.
Finalmente podemos usar otra característica que nos permite hallar los rostros en una imagen con su respectiva traza y path de cada característica del rostro:
app.post("/faces", upload.single('uploads'), (req, res) => {
const currentFile = req.file.path;
vision.faceDetection({ source: { filename: currentFile } })
.then((results) => {
const faces = results\[0\].faceAnnotations;
res.send(faces);
})
.catch((err) => {
console.error('ERROR:', err);
res.send("BAD");
});
});
Una vez que tenemos nuestro archivo de servidor server.js completo, debemos modificar un poco nuestro index.html y app.js para mostrar nuestros hallazgos:
<!—index.html—>
<button class="shutter" onclick="upload()">
Tomar y subir una foto
</button>
<button class="shutter" onclick="sendToLabelDetection()">
Analizar imagen
</button>
<button class="shutter" onclick="sendToFaceDetection()">
Detectar rostros y características
</button>
<div>
<h2>Características de la imagen</h2>
<div id="labels"></div>
</div>
Poniendo todo lo anterior junto podrás ver las características(labels) de la imagen en una manera similar a esta en la detección de características:
Sin embargo para la detección y extracción de rostros he implementado solo el login por consola donde podrás ver un elemento de un array por rostro detectado y dentro de cada rostro detectado las “landmarks” que delimitan exactamente cada uno de los elementos del rostro:
Puedes jugar con estas funciones para crear combinaciones de características únicas para tu aplicación o producto. En este repositorio podrás jugar con este código y usarlo para la implementación de tus propias funcionalidades, también encontrarás algunas otras funciones como por ejemplo detectar personas felices, o tristes e una foto:
https://github.com/seagomezar/devfest-vision
Para consultar más información sobre las operaciones de la SDK y la API de cloud vision para NodeJS puedes ver el siguiente repositorio:
https://github.com/googleapis/nodejs-vision/tree/master/samples
Eso es todo, espero que este post te sea de utilidad y lo puedas aplicar a algún proyecto que tengas en mente, déjame un comentario si lograste implementarlo, si quieres añadir alguna otra funcionalidad o si tienes alguna duda no dudes en dejarme un comentario en la parte de abajo, recuerda que si te gustó también puedes compartir usando los links a las redes sociales en la parte de abajo.
Creador de contenido principalmente acerca de tecnología.