Alessandro Del Sole's Blog

{ A programming space about Microsoft® .NET® }
posts - 1894, comments - 2047, trackbacks - 352

My Links

News

Your host

This is me! Questo spazio è dedicato a Microsoft® .NET®, di cui sono molto appassionato :-)

Cookie e Privacy

Disabilita cookie ShinyStat

Microsoft MVP

My MVP Profile

Microsoft Certified Professional

Microsoft Specialist

Il mio libro su VB 2015!

Pre-ordina il mio libro su VB 2015 Pre-ordina il mio libro "Visual Basic 2015 Unleashed". Clicca sulla copertina per informazioni!

Il mio libro su WPF 4.5.1!

Clicca sulla copertina per informazioni! E' uscito il mio libro "Programmare con WPF 4.5.1". Clicca sulla copertina per informazioni!

These postings are provided 'AS IS' for entertainment purposes only with absolutely no warranty expressed or implied and confer no rights.
If you're not an Italian user, please visit my English blog

Le vostre visite

I'm a VB!

Guarda la mia intervista a Seattle

Follow me on Twitter!

Altri spazi

GitHub
I miei progetti open-source su GitHub

Article Categories

Archives

Post Categories

Image Galleries

Privacy Policy

Xamarin.Forms e i Cognitive Services di Microsoft - Face APIs

Nel post precedente abbiamo introdotto i Microsoft Cognitive Services, facendo una panoramica dei servizi che vengono offerti. Da questo post cominciamo a fare degli esempi pratici di alcuni servizi a disposizione e inizieremo dalle Face API. Cosa sono?

Le Face API consentono di riconoscere i tratti fisici e caratteristici dei visi nelle immagini e nei video, inclusi quelli "live". Tra le numerose informazioni, ci consentono di rilevare la posizione di tratti come la bocca, il naso, gli occhi, le orecchie attraverso 27 punti del viso. Grazie a questi punti, le Face API ci consentono di rilevare altre informazioni come la presenza (o meno, come nel mio caso :-)) di capelli, di occhiali, la posa, il sorriso ma soprattutto l'età approssimativa della persona in foto o in video.

Non limitato a questo, con le Face API si possono confrontare due o più immagini per verificare la corrispondenza tra visi oppure si possono implementare tecniche di riconoscimento delle persone attraverso la creazione di una sorta di database. Quest'ultimo scenario non verrà trattato, però prima vi costringo a leggere e in fondo al post vi lascio il link ad un esempio sviluppato da Xamarin

Come tutti gli altri Cognitive Services, le Face API sono esposte da un servizio REST quindi ricevono una richiesta HTTP POST e restituiscono il risultato dell'analisi sull'immagine in formato JSON. Un esempio di richiesta è la seguente:



Dove dovrò specificare la subscription key ottenuta nel portale di registrazione e l'URL (o il byte array corrispondente) dell'immagine da analizzare più gli elementi che voglio ottenere e che vedremo nel corso del post.

Se come me non amate JSON ma ve lo fate piacere per forza, non c'è da temere: siamo in ambito Xamarin.Forms e, per le API che discuteremo, ci sono delle librerie client che ci permettono di fare richieste da codice C# e senza impazzire. Diverso è il caso di Xamarin.Android, dove al momento queste librerie client non sono disponibili e allora le richieste vanno costruite e il loro JSON deserializzato. Il caro amico Fabio Cozzolino ha un bell'articolo a riguardo. Un esempio di JSON restituito dalle Face API è proprio nella relativa pagina ufficiale.

Diciamo che ci piace ragionare per oggetti e quindi scriveremo delle classi che serviranno a rappresentare il risultato delle chiamate.

Creazione del progetto

Ci serve chiaramente un progetto Xamarin.Forms. In Visual Studio 2015, File -> New Project -> C# -> Cross-Platform -> Blank Xaml App (portable). Per il progetto UWP, potete liberamente scegliere la versione. Per quanto riguarda i progetti Windows 8.1 e Windows Phone 8.1, potete tranquillamente rimuoverli anche per evitare problemi di compatibilità delle PCL.

Le librerie

Dobbiamo gestire le librerie esistenti e quelle che ci occorronno tramite NuGet. In particolare, a livello di pacchetti della solution faremo l'aggiornamento del pacchetto Xamarin.Forms all'ultima versione stabile. Fatto questo, ci occorrono i due seguenti package:

  • Microsoft.ProjectOxford.Face: da installare solo a livello di PCL nella solution Xamarin, questa è una libreria client per C# e .NET che consente di interagire ad oggetti col servizio Face
  • Xam.Plugin.Media: plugin per Xamarin che consente di selezionare foto esistenti o di scattarne dalla fotocamera in modo cross-platform e senza ricorrere ad API specifiche. Va installato a livello di intera solution


Nota: la libreria client, ad oggi, invia le richieste ad un endpoint che non è più quello principale e che tra tre mesi verrà deprecato, conseguentemente ci si attende un aggiornamento della libreria stessa. Installati i pacchetti, occupiamoci ora del codice.

L'obiettivo

L'obiettivo che ci proponiamo è nell'ottica della semplificazione :-) vogliamo consentire ad una nostra app cross-platform di analizzare immagini presenti sul dispositivo, o tramite fotocamera, di visualizzare l'immagine scelta e i risultati dell'analisi facciale. Ci basta quindi una UI molto essenziale e una classe che rappresenterà i risultati. Come spesso faccio, non uso MVVM per tre ragioni: non do per scontato che lo conosciate (e in Xamarin.Forms ci sono anche delle leggere differenze), non posso sapere quale libreria siete abituati ad usare e per un'app di questo tipo non ha alcun senso complicare.

Codice: lo XAML

E' sufficiente una pagina principale con una serie di Label in binding a una serie di proprietà del model che implementeremo a breve. Nomi e contenuti sono decisamente auto-esplicativi e servono a visualizzare elementi come il sorriso, l'età, tratti somatici:


Notate l'ActivityIndicator che ci permette di mostrare il progresso dell'operazione di riconoscimento, che sarà asincrona.

Una classe per il risultato

Come dicevamo prima, le Face API (e gli altri servizi REST) restituiscono JSON che, fortunatamente, la client library che abbiamo installato traduce in oggetti. Gli oggetti in questione sono molto specializzati e ci consentono di ottenere un numero elevatissimo di informazioni sui volti. Può essere conveniente estrarre un sotto-insieme di informazioni incapsulandolo in una classe, come quella seguente che memorizzerà i tratti salienti del viso:



Fatto questo, si passa alla parte interessante.

Gli oggetti con cui lavoriamo

Il punto di ingresso è una classe chiamata FaceServiceClient, di tipo IFaceServiceClient, al cui costruttore dobbiamo passare l'id della nostra subscription. Questa classe espone un metodo chiamato DetectAsync, che si occuperà di analizzare l'immagine passata come Stream o come URL. Il metodo può rilevare:

  • i visi nell'immagine sotto forma di array, ognuno rappresentato da un'istanza della classe Face
  • le caratteristiche di ciascun viso, sotto forma di classe FaceAttribute. Il risultato del rilevamento viene memorizzato in un array che devo aver precedentemente predisposto e che specifica le informazioni che mi servono.
  • nel rilevare i visi, restituisce un id di tipo Guid
  • 27 punti somatici tramite la proprietà Face.FaceLandmarks, di tipo FaceLandmarks. Ogni sotto-proprietà esposta da FaceLandmarks è di tipo FeatureCoordinate e contiene due valori X e Y che rappresentano la posizione del tratto somatico sull'immagine
  • un oggetto di tipo FaceRectangle che rappresenta il rettangolo virtuale che delimita il viso nella foto. Tale oggetto ha 4 proprietà di tipo int


Per praticità espositiva nell'esempio prenderemo in considerazione solamente il primo viso rilevato, indipendentemente da quanti ce ne sono nell'immagine. Inoltre, vi farò vedere come ottenere il face rectangle e i face landmark senza però utilizzarli nella demo. Immagino, comunque, che vi sia sufficiente sapere come ottenerli per poi eventualmente assegnarli a un view model da mettere in binding con la UI.
Per quanto riguarda la selezione delle immagini, o da locale o da fotocamera, il plugin Media di Xamarin ha una classe chiamata CrossMedia che espone i metodi PickPhotoAsync e TakePhotoAsync, i quali ottengono uno stream che poi inviamo al metodo di analisi.

Il codice

Ecco il codice, con i relativi commenti all'interno:

Di seguito invece due figure che mostrano, nell'IntelliSense, gli oggetti relativi ai landmarks e al face rectangle:






Ricordatevi di impostare a true gli opportuni parametri nell'invocazione di DetectAsync per ottenere queste informazioni.

Il risultato

Nota bene: si tratta a) di un servizio in preview e b) di un risultato che dipende molto dalla qualità della foto. Nel risultato sottostante si vedono i risultati ottenuti, con un'imprecisione sull'età (ne ho 39 e non 34 ), per il resto potete osservare come sia stato rilevato il genere, l'assenza di occhiali, una leggera barba e leggeri baffi:



I risultati ottenuti sono restituiti sotto forma di Double, che possono poi essere convertiti in altri tipi. In particolare, la scala va da 0 a 1 e un valore più alto indica un maggiore livello di rilevamento di un particolare aspetto o tratto.

Nel prossimo post ci occuperemo di Emotion API. Come promesso, vi lascio il link ad un esempio molto interessante prodotto da Xamarin in cui viene illustrato come creare una directory di visi per il successivo riconoscimento preciso.

Alessandro

Print | posted on mercoledì 18 gennaio 2017 20:22 | Filed Under [ Xamarin ]

Powered by:
Powered By Subtext Powered By ASP.NET