In questo post, io e te, realizziamo insieme una pagina con capacità di analisi video in tempo reale. In inglese? Real Time Face Detection WebSite!
Si tratta di un progetto d’intelligenza artificiale semplice e veloce da realizzare, anche se di grande effetto capace di stupire e sorprendere.
La parte di training dei modelli è stata eseguita per noi dalla community. Il codice, reso open-source, è pronto per essere modificato!
Andremo quindi a creare una pagine web con capacità di face detection, di analisi delle espressioni in tempo reale, e individuazione dei contorni facciali.
Real Time Face Detection
Per prima cosa creiamo una repository su gitlab, in questo modo terremo il codice ordinato e facilmente accessibile.
Cloniamo la repository appena creata, che sarà un directory vuota.
Per comodità e amore delle cose fatte bene, useremo un framework gratuito chiamato MDB Bootstrap che agevolerà il lavoro estetico.

Predisponiamo la pagina per la visualizzazione del video, e ci spostiamo subito ai file javascript.

Iniziamo con l’importare il file script.js (che ancora non esiste) e quello face-api.min.js che devi scaricare.

È arrivato il momento di rendere il sistema funzionante: creiamo il file script.js all’interno della cartella /js e scriviamo il seguente codice.
const video = document.getElementById('video') function showVideo(){ navigator.mediaDevices.getUserMedia({ video: {} }, stream => video.srcObject = stream, err => console.log(err) ) } showVideo()
In questo modo inseriamo all’interno del body della pagina, all’altezza del tag video l’input della webcam catturato con getUserMedia, ovviamente concedendo prima i permessi.

Scarichiamo i modelli, fulcro dell’intero progetto, e li importiamo in modo asincrono, usando una comoda funzione di Javascript che basa il suo funzionamento sul concetto di promise.
Promise.all([ faceapi.nets.tinyFaceDetector.loadFromUri('/models'), faceapi.nets.faceLandmark68Net.loadFromUri('/models'), faceapi.nets.faceRecognitionNet.loadFromUri('/models'), faceapi.nets.faceExpressionNet.loadFromUri('/models') ]).then(showVideo)
Esploriamo rapidamente i modelli:
- tinyFaceDetector, è il modello capace d’identificare i volti delle persone: il face detection nudo e crudo. Tiny, per poter essere eseguito dai browser senza troppe difficoltà;
- faceLandmark68Net, è il modello che adempie al riconoscimento dei contorni facciali;
- il faceRecognitionNet è il modello preposto all’individuazione della faccia all’interno del campo visivo della fotocamera;
- faceExpressionNet, è il modello che si occupa di determinare le espressioni facciali di: sorpresa, disgusto, rabbia, felicità, tristezza, delusione e paura (spoiler, non ti aspettare granché)
Bene bene, stiamo procedendo spediti!
Ora, alcuni ultimi ritocchi.
Sempre nel file script.js:
video.addEventListener('play', () => { const canvas = faceapi.createCanvasFromMedia(video) document.body.append(canvas) const displaySize = { width: video.width, height: video.height } faceapi.matchDimensions(canvas, displaySize) setInterval(async () => { const detections = await faceapi.detectAllFaces(video, new faceapi.TinyFaceDetectorOptions()).withFaceLandmarks().withFaceExpressions() const resizedDetections = faceapi.resizeResults(detections, displaySize) canvas.getContext('2d').clearRect(10, 0, canvas.width, canvas.height) faceapi.draw.drawDetections(canvas, resizedDetections) faceapi.draw.drawFaceLandmarks(canvas, resizedDetections) faceapi.draw.drawFaceExpressions(canvas, resizedDetections) }, 10) })
Aggiungiamo un EventListener sul play del video, e avendolo settato in autoplay, la funzione sarà eseguita subito (in realtà non appena i modelli saranno caricati).
Sarà generato un canvas, fondamentale per il render dinamico dei poligoni, e sovrapposto al video.
Non ci resta che perfezionare la nostra index.html con un po’ di css:
body{ margin: 0; padding: 0; width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } video{ border-radius: .6em; } canvas { position: absolute; }
Debugging
Ho testato il codice solo su chrome, riscontrando due problemucci che ti ho prontamente risolto:

Alcuni servizi devono essere forniti attraverso un server. Niente panico.
Possiamo creare un localserver in pochi secondi. Iniziamo scaricando node e installando npm globalmente (in tutto il sistema).
Quindi installiamo http-server digitando:
npm i http-server -g
e nella cartella del progetto:
http-server -p 3000
Ora possiamo recarci all’indirizzo sottostante per vedere live il nostro sito:
localhost:3000/index.html
È fondamentale inoltre abilitare l’accelerazione hardware del browser, e il supporto a WebGL per consentire il rendering grafico.
Quindi digitiamo chrome://settings e abilitiamo prima l’accelerazione, riavviando chrome.

In seguito passiamo all’abilitazione di WebGl, digitando chrome://flags

Et voila!
Un caldo abbraccio, Andrea.
P.S. Qui, il progetto completo