La tecnología está llena de cosas increíbles que nos sorprenden a cada paso que dan. Últimamente con el paso de los años parece como que todo es posible, y cada vez nos sorprendemos más con sus avances a pasos agigantados. Pero todo este progreso tecnológico tiene un precio ¿no? Seguro que los algoritmos de reconocimiento digital son lo más avanzado del mundo y a nivel tecnológico cuesta muchísimo desarrollar una app informática , un hito que solo grandes empresas bien organizadas (como Hamro) puede realizar, ¿verdad?
Antes de seguir, te diré que este es un tutorial técnico y que si quieres seguirlo debes de saber manejarte con Javascript y HTML. Si no eres técnico y no quieres ver la explicación y quieres tan solo ver como tu ordenador detecta tu cara , haz click en el enlace. (te prometemos que te va a parecer curioso)
Reconocimiento con inteligencia artificial y javascript
Lo cierto es que las tecnologías de inteligencia artificial y machine learning que tanto están dando que hablar ahora son tecnologías que llevan existiendo propiamente desde los años 80. Es solamente ahora que el resto de infraestructura tecnológica necesaria para adoptar estos sistemas empieza a ser económica, escalable y abundante.
Existen multiples librerías y servicios que sirven para aprovecharse del machine learning. En este caso, nosotros vamos a utilizar la libreria Face Api JS. Face Api JS es una librería Javascript que permite trabajar con modelos de entrenamiento para discernir caras la una de la otra.
Lo genial de esta librería es que es completamente open source, y - como comprobaremos ahora - es completamente funcional y es bastante rápido programar en ella.
Lo primero que tenemos que tener claro antes de lanzarnos a la librería es como funciona un sistema de machine learning e inteligencia artificial. Si algo aprendí en mis años universitarios con respecto a la inteligencia artificial es que la inteligencia artificial tiene mucho más de artificial que de inteligencia.
Todo el funcionamiento del reconocimiento de formas se basa en extraer una serie de propiedades asociadas a la forma (o señal) a interpretar, para después a partir de esas propiedades, obtener una serie de descriptores que serán interpretados por el sistema de inteligencia artificial para dar una respuesta sobre lo que el sistema de inteligencia artificial piensa que es.

Pero basta ya de cháchara. Vamos directos al grano con la librería. Lo primero que vamos a hacer es descargarnos el proyecto que se han gastado los chicos de Web Dev Simplified en el que explican el proceso y cuyo video colocaré al final. De momento, navegamos a la carpeta donde vamos a trabajar y - teniendo git instalado - clonamos ahi dentro el respositorio correspondiente.
Una vez dentro, repasamos los archivos que nos han descargado. Esta es la estructura de archivos y queda tal que así.

Recordemos que esta se trata de una aplicación Javascript. No obstante necesitaremos un servidor apache desde donde guardar y servir nuestros archivos para que funcione. Además, debido a que tenemos acceso a la cámara a través de Javascript, uno de los requisitos es que para poder acceder a los datos del navegador tan sensibles (y hacerlo bien) la conexión debe de estar cifrada en HTTPS . Por lo que aunque parezca tan sencillo como clickar index.html desde tu navegador para que funcione el ejemplo, necesitarás subirlo a un servidor con cifrado HTTPS para que este ejemplo funcione correctamente.
LOS ARCHIVOS.
Vamos a ver que es lo que está haciendo cada archivo paso a paso para entender que es lo que está ocurriendo. Lo que vereis de código son imágenes. No trateis de copiar pegarlo directamente de la web, pues lo que se pretende es que entendais el ejercicio y las lineas de código ahora mismo no son importantes. Podéis descargaros el código directamente desde el repositorio github que hemos comentado anteriormente.
Comenzemos con el index.html que no tiene nada de especial. Sencillamente carga la librería javascript minificada y el script.js donde ejecutaremos nuestros comandos. Luego añade un poco de estilo para mostrar la imagen centrada y por último en el DOM hay un elemento de video que será el que muestre los resultados de la cámara web por un lado, y por otro lado diseño de estilo para el canvas que se acabará poniendo justo encima de la imagen que venga de la cámara, y donde se "sobrepintará" por encima de la capa de video todo lo que la librería sea capaz de reconocer.

El siguiente archivo que vamos a inspeccionar es el script.js . Este script es también bastante rápido de interpretar, pero es aquí donde está pasando toda la magia de la detección de caras.

La primera linea lo único que está haciendo es quedarse con la posición del video a partir del DOM HTML. Lo siguiente que hacemos a continuación es crear una serie de promesas. Recordemos que - debido a la naturaleza asíncrona de Javascript - no todo el código puede esperar a que una parte del mismo se ejecute si su ejecución va a depender de otro servidor ajeno (como por ejemplo una llamada al servidor).
Es por eso que se crean estas "promesas". Una promesa en Javascript - en el mundo asíncrono - quiere decir que realizará la petición a cambio de una "promesa" (de que la va a realizar) y cuando la petición esté realizada, esa promesa se resolverá y se ejecutará un código (es la parte del then).
En este caso , lo que está haciendo este código es cargar los modelos que se van a emplear para el sistema de reconocimiento de formas. ¿Qué es un modelo? Un modelo es cualquier cosa ( hay varias formas de obtenerlos) que nos ayude a...a partir de unos datos percibidos y un conjunto de objetos que queremos identificar, realice una estimación de que esos datos percibidos sean el objeto a identificar.
Por ejemplo (y simplificando mucho) , en un sistema muy simplificado en el que queremos averiguar si un vehículo es un coche o una motocicleta en función del número de ruedas que tiene, un modelo sería un conjunto de coches y motocicletas con sus características importantes ( cuantas ruedas tiene) que el sistema utilizaría para, a partir de una foto nueva de un coche o motocicleta, saber si tiene 2 o 4 ruedas, y dar la solución.
Un ejemplo perfecto de modelo es una red neuronal. En informática, las redes neuronales emulan el comportamiento de una red neuronal humana.

En este caso en cuestión, estamos cargando modelos de la carpeta models para inicializar las siguientes redes neuronales:
- tinyFaceDetector: que es una versión reducida y rápida del sistema de detección de caras (para que funcione en el navegador a tiempo real). Tiene un error de precisión mas grande pero a cambio lo permite reconocer casi al instante (como podréis observar en el ejemplo)
- faceLandmark68: En este caso, se trata de una red neuronal que se encarga de definir el perfil, los bordes ,los ojos, el contorno y en definitiva, los puntos de la cara.
- faceRecognition: Sirve para reconocer caras y distinguirlas entre ellas
- faceExpression: sirve para reconocer la expresión de las caras y saber si están alegres, tristes, confundidos etc...
Estas redes neuronales a priori parten de estar creadas pero sin ningún tipo de entrenamiento. Los modelos sirven para indicarle a cada red neuronal, lo que un ser humano entiende por una cara (ojos, cabello etc) y lo alimenta al sistema para que la red neuronal sea capaz de obtener la información pertinente para poder funcionar correctamente y reconocer los errores.
Una vez se han cargados los modelos y las redes neuronales podemos empezar a utilizar el framework en nuestro dispositivo, de ahí a que utilicemos "then" . De esta manera javascript esperará a que todas las promesas hayan sido resueltas (Promise.all) y una vez se hayan resuelto todas (es decir, tengamos toda la información necesaria) se ejecutará startVideo, que es la función inicial

Esta función como podemos ver llama a navigator.getUserMedia. GetUserMedia permite acceso (si el usuario lo concede) a utilizar el video del navegador y ponernos a grabar. La función tiene 3 parámetros - opciones de inicialización, lo que ocurre si va bien, y lo que ocurre si va mal. Nosotros con Javascript y sus lambda functions estamos pasando estas funciones por referencia para indicarle que en cuanto tengamos video / audio, pasemos ese stream de datos al src de la capa de video que hemos creado anteriormente. Por último, en caso de error logearemos el error en la consola javascript.
Por último. El script lo que hace es añadir un event listener para cuando el video comience a reproducirse (play).
En ese momento, crea un espacio canvas donde poder dibujar y lo asocia a las dimensiones del video.
Luego, de forma asíncrona y a través de una función setInterval (que recordemos, lanza a ejecutar un código cada X milisegundos, en este caso 100) va a esperar a que face API JS detecte todas las caras del video para luego, sobre ese canvas en 2D que hemos creado antes y puesto al final del video a través de append (y que como tiene una posición absoluta, se queda puesto justo por encima de la imagen de video original) vamos a pintar todas las detecciones, las caras, las expresiones y las "face landmarks".

Este es un ejemplo claro de cómo se pueden obtener funcionalidades muy avanzadas y de inteligencia artificial a partir de soluciones relativamente low cost y al alcance de la mano de cualquier programador o desarrollador con algo de experiencia.
Para ver este código en acción, click en el enlace más abajo. Para hacerlo correr recuerda que deberás servirlo desde un servidor con HTTPS (conexión segura).
Y si quieres evolucionar un poco más el código, aquí te dejo el video donde los chicos de Web Dev Simplified explican paso a paso (en Inglés) como hacerlo y algunos otros consejos más.
De nuevo este es un proceso muy reducido, pero sirve para comenzar tus pinitos con detección de caras a través de javascript. ¿Serías capaz de añadirle la funcionalidad de que reconozca tu propia cara a partir de un set de fotos propias?