Condividi tramite


Utilizzare la struttura dei dati PersonDirectory (anteprima)

Attenzione

L'accesso al servizio Viso è limitato in base ai criteri di idoneità e utilizzo al fine di supportare i nostri principi di intelligenza artificiale responsabile. Il servizio Viso è disponibile solo per i clienti e i partner gestiti da Microsoft. Usare il modulo di acquisizione riconoscimento volto per richiedere l'accesso. Per altre informazioni, vedere la pagina Accesso limitato dalla funzione Viso.

Per eseguire operazioni di riconoscimento volto, quali Identifica e Trova simile, i clienti dell'API Viso devono creare un elenco variegato di oggetti Persona. PersonDirectory è una struttura dei dati in anteprima pubblica che contiene ID univoci, stringhe di nomi facoltative e stringhe di metadati utente facoltative per ogni identità di Persona aggiunta alla directory. Seguire le istruzioni della presente guida per informazioni su come eseguire le attività di base con PersonDirectory.

Vantaggi di PersonDirectory

Attualmente, l'API Viso offre la struttura LargePersonGroup, che ha una funzionalità simile, ma è limitata a un milione di identità. La struttura PersonDirectory può aumentare fino a 20 milioni di identità.

Un'altra differenza fondamentale tra PersonDirectory e le strutture dei dati precedenti è che non sarà più necessario effettuare chiamate API Training dopo avere aggiunto visi a un oggetto Persona. Il processo di aggiornamento viene eseguito automaticamente.

Prerequisiti

  • Sottoscrizione di Azure: creare un account gratuito.
  • Dopo aver creato la sottoscrizione di Azure, Creare una risorsa Viso nel portale di Azure per ottenere la chiave e l'endpoint. Al termine della distribuzione, fare clic su Vai alla risorsa.
    • La chiave e l'endpoint della risorsa creata saranno necessari per connettere l'applicazione all'API Viso. Quindi si dovranno incollare la chiave e l'endpoint nel codice riportato di seguito.
    • È possibile usare il piano tariffario gratuito (F0) per provare il servizio ed eseguire in un secondo momento l'aggiornamento a un livello a pagamento per la produzione.

Aggiungere persone a PersonDirectory

Le persone sono le unità di registrazione di base in PersonDirectory. Dopo aver aggiunto una Persona alla directory, è possibile aggiungere fino a 248 immagini viso a tale Persona, per modello di riconoscimento. È quindi possibile identificare i visi in base ai dati inseriti, utilizzando ambiti diversi.

Creare la persona

Per creare una Persona, è necessario richiamare l'API CreatePerson e specificare un nome o un valore per la proprietà userData.

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

var addPersonUri = "https://{endpoint}/face/v1.0-preview/persons";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("name", "Example Person");
body.Add("userData", "User defined data");
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PostAsync(addPersonUri, content); 
}

La chiamata CreatePerson restituirà un ID generato per la Persona e una posizione dell'operazione. I dati relativi alla Persona saranno elaborati in modo asincrono, pertanto è possibile utilizzare la posizione dell'operazione per recuperare i risultati.

Attendere il completamento dell'operazione asincrona

Per controllare lo stato di avanzamento dell'operazione asincrona, è necessario eseguire una query sullo stato dell'operazione asincrona mediante la stringa della posizione dell'operazione restituita.

In primo luogo, è necessario definire un modello di dati simile a quello riportato di seguito, per gestire la risposta dello stato.

[Serializable]
public class AsyncStatus
{
    [DataMember(Name = "status")]
    public string Status { get; set; }

    [DataMember(Name = "createdTime")]
    public DateTime CreatedTime { get; set; }

    [DataMember(Name = "lastActionTime")]
    public DateTime? LastActionTime { get; set; }

    [DataMember(Name = "finishedTime", EmitDefaultValue = false)]
    public DateTime? FinishedTime { get; set; }

    [DataMember(Name = "resourceLocation", EmitDefaultValue = false)]
    public string ResourceLocation { get; set; }

    [DataMember(Name = "message", EmitDefaultValue = false)]
    public string Message { get; set; }
}

Con HttpResponseMessage, riportato sopra, è possibile eseguire il polling dell'URL e attendere i risultati.

string operationLocation = response.Headers.GetValues("Operation-Location").FirstOrDefault();

Stopwatch s = Stopwatch.StartNew();
string status = "notstarted";
do
{
    await Task.Delay(500);

    var operationResponseMessage = await client.GetAsync(operationLocation);

    var asyncOperationObj = JsonConvert.DeserializeObject<AsyncStatus>(await operationResponseMessage.Content.ReadAsStringAsync());
    status = asyncOperationObj.Status;

} while ((status == "running" || status == "notstarted") && s.Elapsed < TimeSpan.FromSeconds(30));

Quando lo stato restituisce il risultato "riuscito", l'oggetto Persona sarà considerato come aggiunto alla directory.

Nota

L'operazione asincrona dalla chiamata Create Person non deve mostrare lo stato "riuscito" prima che si possano aggiungere visi, ma è richiesto il completamento prima di poter aggiungere la Persona a un DynamicPersonGroup (vedere di seguito, Creare e aggiornare un DynamicPersonGroup) o confrontarlo durante una chiamata Identifica. La verifica delle chiamate funziona immediatamente dopo aver aggiunto correttamente dei visi alla Persona.

Aggiungere visi alle persone

Dopo aver ottenuto l'ID della Persona dalla chiamata CreatePerson, è possibile aggiungere fino a 248 immagini di visi a una Persona per modello di riconoscimento. Specificare il modello di riconoscimento (e, facoltativamente, il modello di rilevamento) da usare nella chiamata, perché i dati in ogni modello di riconoscimento saranno elaborati separatamente all'interno di PersonDirectory.

I modelli di riconoscimento attualmente supportati sono:

  • Recognition_02
  • Recognition_03
  • Recognition_04

Inoltre, se l'immagine contiene più visi, sarà necessario specificare quale rettangolo delimitatore del viso è la destinazione desiderata. Il codice seguente consente di aggiungere visi a un oggetto Persona.

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

// Optional query strings for more fine grained face control
var queryString = "userData={userDefinedData}&targetFace={left,top,width,height}&detectionModel={detectionModel}";
var uri = "https://{endpoint}/face/v1.0-preview/persons/{personId}/recognitionModels/{recognitionModel}/persistedFaces?" + queryString;

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("url", "{image url}");
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PostAsync(uri, content);
}

Dopo la chiamata Aggiungi visi, i dati dei visi vengono elaborati in modo asincrono e sarà necessario attendere il completamento dell'operazione, come spiegato in precedenza.

Al termine dell'operazione di aggiunta viso, i dati saranno pronti in Identifica chiamate.

Creare e aggiornare un DynamicPersonGroup

DynamicPersonGroups sono raccolte di riferimenti agli oggetti Persona all'interno di una PersonDirectory. Consentono di creare subset della directory. Si usano comunemente se si vogliono ottenere meno falsi positivi e aumentare l’accuratezza di un'operazione di identificazione, limitando l'ambito solo agli oggetti Persona che si prevede di trovare come corrispondenze. Tra i casi d'uso pratici sono incluse le directory per l’accesso specifico a un edificio tra un campus o un'organizzazione di più grandi dimensioni. La directory dell'organizzazione può contenere 5 milioni di individui, ma sarà sufficiente eseguire la ricerca in un edificio specifico di 800 persone per creare un DynamicPersonGroup contenente individui specifici.

Se in precedenza è stato usato un PersonGroup, prendere nota delle due differenze principali:

  • Ogni Persona all'interno di un DynamicPersonGroup è un riferimento alla Persona effettiva in PersonDirectory; ciò significa che non è necessario ricreare una Persona in ogni gruppo.
  • Come accennato nelle sezioni precedenti, non è necessario effettuare chiamate di training, poiché che i dati dei visi vengono elaborati automaticamente a livello di directory.

Creare il gruppo

Per creare un DynamicPersonGroup, è necessario specificare un ID gruppo con caratteri alfanumerici o trattini. Tale ID sarà l’identificatore univoco per tutti gli scopi di utilizzo del gruppo.

Vi sono due metodi per inizializzare una raccolta di gruppi. È possibile creare inizialmente un gruppo vuoto e popolarlo in un secondo momento:

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

var uri = "https://{endpoint}/face/v1.0-preview/dynamicpersongroups/{dynamicPersonGroupId}";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("name", "Example DynamicPersonGroup");
body.Add("userData", "User defined data");
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PutAsync(uri, content);
}

Questo processo è immediato e non è necessario attendere che il corretto completamento delle operazioni asincrone.

In alternativa, è possibile creare un gruppo con un set di ID di persone per contenere tali riferimenti fin dall'inizio, specificando il set nell'argomento AddPersonIds:

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

var uri = "https://{endpoint}/face/v1.0-preview/dynamicpersongroups/{dynamicPersonGroupId}";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("name", "Example DynamicPersonGroup");
body.Add("userData", "User defined data");
body.Add("addPersonIds", new List<string>{"{guid1}", "{guid2}", …});
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PutAsync(uri, content);

    // Async operation location to query the completion status from
    var operationLocation = response.Headers.Get("Operation-Location");
}

Nota

Non appena viene restituita la chiamata, il DynamicPersonGroup creato sarà pronto per l'uso in una chiamata Identifica, con eventuali riferimenti alla Persona forniti nel processo. Lo stato di completamento dell'ID operazione restituito, invece, indica solo lo stato di aggiornamento per le chiamate di ricerca Get Dynamic Person Group References .

Aggiornare DynamicPersonGroup

Dopo la creazione iniziale, è possibile aggiungere e rimuovere i riferimento alla Persona dal DynamicPersonGroup con l'API per l’aggiornamento di DynamicPersonGroup. Per aggiungere oggetti Persona al gruppo, elencare gli ID Persona nell'argomento addPersonsIds. Per rimuovere gli oggetti Persona, elencarli nell'argomento removePersonIds. L’aggiunta e la rimozione possono essere eseguite entrambe in una singola chiamata:

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

var uri = "https://{endpoint}/face/v1.0-preview/dynamicpersongroups/{dynamicPersonGroupId}";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("name", "Example Dynamic Person Group updated");
body.Add("userData", "User defined data updated");
body.Add("addPersonIds", new List<string>{"{guid1}", "{guid2}", …});
body.Add("removePersonIds", new List<string>{"{guid1}", "{guid2}", …});
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PatchAsync(uri, content);

    // Async operation location to query the completion status from
    var operationLocation = response.Headers.Get("Operation-Location");
}

Quando la chiamata viene restituita, gli aggiornamenti alla raccolta verranno visualizzati quando viene eseguita una query sul gruppo. Come per l'API di creazione, l'operazione restituita indica lo stato di aggiornamento del rapporto persona-gruppo per qualsiasi oggetto Persona interessato dall’aggiornamento. Non è necessario attendere il completamento dell’operazione per effettuare ulteriori chiamate di aggiornamento al gruppo.

Identificare i visi in PersonDirectory

Il modo più comune per utilizzare i dati dei visi in PersonDirectory consiste nel confrontare gli oggetti Persona registrati con un determinato viso e identificare il candidato più probabile a cui appartiene. Nella richiesta possono essere presenti più visi e ciascuno di essi riceverà il proprio set di risultati di confronto nella risposta.

In PersonDirectory vi sono tre tipi di ambiti nei quali è possibile identificare ogni viso mediante confronto:

Scenario 1 - Identificazione in base a un DynamicPersonGroup

Specificando la proprietà dynamicPersonGroupId nella richiesta, il viso viene confrontato con ogni Persona alla quale si fa riferimento nel gruppo. Un unico DynamicPersonGroup può essere identificato per confronto in una chiamata.

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

// Optional query strings for more fine grained face control
var uri = "https://{endpoint}/face/v1.0-preview/identify";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("faceIds", new List<string>{"{guid1}", "{guid2}", …});
body.Add("dynamicPersonGroupId", "{dynamicPersonGroupIdToIdentifyIn}");
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PostAsync(uri, content);
}

Scenario 2 - Identificazione in base a un elenco specifico di persone

È anche possibile specificare un elenco di ID Persona nella proprietà personIds per il confronto del viso con ciascuno di essi.

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");
            
var uri = "https://{endpoint}/face/v1.0-preview/identify";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("faceIds", new List<string>{"{guid1}", "{guid2}", …});
body.Add("personIds", new List<string>{"{guid1}", "{guid2}", …});
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PostAsync(uri, content);
}

Scenario 3 - Identificazione per confronto con l'intera PersonDirectory

Aggiungendo un singolo asterisco alla proprietà personIds nella richiesta, il viso viene confrontato con ogni singola Persona registrata in PersonDirectory.

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");
            
var uri = "https://{endpoint}/face/v1.0-preview/identify";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("faceIds", new List<string>{"{guid1}", "{guid2}", …});
body.Add("personIds", new List<string>{"*"});
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PostAsync(uri, content);
}

Per tutti e tre gli scenari, l'identificazione confronta solo il viso in ingresso con i visi la cui chiamata AddPersonFace è stata restituita con una risposta "riuscita".

Verificare i visi rispetto alle persone in PersonDirectory

Con un ID viso restituito da una chiamata di rilevamento, è possibile verificare se il viso appartiene a una Persona specifica registrata all'interno di PersonDirectory. Specificare la Persona tramite la proprietà personId.

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

var uri = "https://{endpoint}/face/v1.0-preview/verify";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("faceId", "{guid1}");
body.Add("personId", "{guid1}");
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PostAsync(uri, content);
}

La risposta conterrà un valore booleano che indica se il servizio ritiene che il nuovo viso appartenga alla stessa Personae fornisce un punteggio di attendibilità della stima.

Panoramica delle operazioni asincrone

Le tabelle seguenti riepilogano se una chiamata di gestione PersonDirectory è un'operazione a esecuzione prolungata (LRO) elaborata in modo asincrono oppure viene completata immediatamente e in modo sincrono:

Gestione persona/viso URI LRO?
Ottenere persone /Persone
Crea persona /Persone
Ottieni persona /persons/{personId}
Aggiorna persona /persons/{personId}
Elimina persona /persons/{personId}
Ottieni visi persona /persons/{personId}/recognitionModels/{model}/persistedfaces
Aggiungi viso persona /persons/{personId}/recognitionModels/{model}/persistedfaces
Aggiungi viso persona dall'URL /persons/{personId}/recognitionModels/{model}/persistedfaces
Get Person Face /persons/{personId}/recognitionModels/{model}/persistedfaces/{persistedFaceId}
Aggiornare il viso della persona /persons/{personId}/recognitionModels/{model}/persistedfaces/{persistedFaceId}
Elimina viso persona /persons/{personId}/recognitionModels/{model}/persistedfaces/{persistedFaceId}
Gestione di gruppi URI LRO?
Ottenere gruppi di persone dinamiche /dynamicpersongroups
Creare un gruppo di persone dinamiche /dynamicpersongroups/{dynamicPersonGroupId}
Creare un gruppo di persone dinamiche con persona /dynamicpersongroups/{dynamicPersonGroupId}
Get Dynamic Person Group /dynamicpersongroups/{dynamicPersonGroupId}
Aggiornare il gruppo di persone dinamiche /dynamicpersongroups/{dynamicPersonGroupId}
Aggiornare il gruppo di persone dinamiche con le modifiche delle persone /dynamicpersongroups/{dynamicPersonGroupId}
Elimina gruppo di persone dinamiche /dynamicpersongroups/{dynamicPersonGroupId}
Ottenere persone di gruppo di persone dinamiche /dynamicpersongroups/{dynamicPersonGroupId}/persons
Ottenere riferimenti a gruppi di persone dinamiche /persons/{personId}/dynamicPersonGroupReferences

Il codice seguente illustra le dipendenze di queste operazioni asincrone:

var createPersonResponse = await CreatePersonAsync();
var personId = createPersonResponse.PersonId;

// faces can be added once the person creation HTTP call returns, even if it's still processing
var addPersonFaceResponse = await AddPersonFaceAsync(personId);
var addPersonFaceFromUrlResponse = await AddPersonFaceFromUrlAsync(personId);

switch (scenario)
{
    case Scenario.Verify:
        // only need to ensure the addition of face data has propagated
        await WaitForLongRunningOperationsAsync(new[]
        {
            addPersonFaceResponse.OperationLocation,
            addPersonFaceFromUrlResponse.OperationLocation
        });
        await VerifyFromPersonDirectoryAsync(queryFaceId, personId);
        break;

    case Scenario.IdentifyInPersonDirectory:
        // ensure person creation and face data enrollment finish successfully
        await WaitForLongRunningOperationsAsync(new[]
        {
            createPersonResponse.OperationLocation,
            addPersonFaceResponse.OperationLocation,
            addPersonFaceFromUrlResponse.OperationLocation
        });
        await IdentifyFromPersonDirectoryAsync(queryFaceId);
        break;

    case Scenario.IdentifyAgainstDynamicPersonGroup:
        // person creation needs to be completed before it can be added to a group
        await WaitForLongRunningOperationsAsync(new[]
        {
            createPersonResponse.OperationLocation
        });
        var groupResponse = await CreateOrUpdateDynamicPersonGroupWithPersonChangesAsync(groupId, [personId]);
        // and make sure face data are ready before identification
        await WaitForLongRunningOperationsAsync(new[]
        {
            addPersonFaceResponse.OperationLocation,
            addPersonFaceFromUrlResponse.OperationLocation
        });
        await IdentifyFromDynamicPersonGroupAsync(queryFaceId, groupId);
        // optionally check the person-to-group relationship, which requires the completion of the group's creation or updating call
        await WaitForLongRunningOperationsAsync(new[]
        {
            groupResponse.OperationLocation
        });
        var groupIds = await GetDynamicPersonGroupReferencesAsync(personId);
        break;

    default:
        break;
}

Passaggi successivi

Grazie alla guida è stato possibile apprendere come usare la struttura PersonDirectory per archiviare i dati relativi a visi e persone per l'app Viso. Nel seguito, sarà possibile apprendere le procedure consigliate per aggiungere i dati dei visi degli utenti.