Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Attenzione
L'accesso al servizio di riconoscimento facciale è limitato in base a criteri di idoneità e di utilizzo, per supportare i nostri principi di Intelligenza Artificiale responsabile. Il servizio Face è disponibile solo per i clienti e i partner gestiti da Microsoft. Usare il modulo di richiesta per il riconoscimento facciale per richiedere l'accesso. Per altre informazioni, vedere la pagina Accesso limitato alla funzione Viso.
Questa guida illustra come aumentare le prestazioni da oggetti PersonGroup e FaceList esistenti rispettivamente a oggetti LargePersonGroup e LargeFaceList . PersonGroups può contenere fino a 1000 persone nel livello gratuito e 10.000 nel livello a pagamento, mentre LargePersonGroups può contenere fino a un milione di persone nel livello a pagamento.
Importante
La struttura di dati più recente PersonDirectory è consigliata per il nuovo sviluppo. Può contenere fino a 20 milioni di identità e non richiede l'addestramento manuale. Per altre informazioni, vedere la Guida di PersonDirectory.
Questa guida illustra il processo di migrazione. Presuppone una conoscenza di base degli oggetti PersonGroup e FaceList , dell'operazione Train e delle funzioni di riconoscimento del viso. Per altre informazioni su questi argomenti, vedere la guida concettuale al riconoscimento del viso .
LargePersonGroup e LargeFaceList sono collettivamente definiti operazioni su larga scala. LargePersonGroup può contenere fino a 1 milione di persone, ognuna con un massimo di 248 visi. LargeFaceList può contenere fino a 1 milione di visi. Le operazioni su larga scala sono simili a PersonGroup e FaceList convenzionali, ma presentano alcune differenze a causa della nuova architettura.
Gli esempi sono scritti in C#.
Annotazioni
Per abilitare le prestazioni di ricerca del viso per Identificazione e FindSimilar a larga scala, introdurre un'operazione di Train per pre-elaborare LargeFaceList e LargePersonGroup. Il tempo di training varia da secondi a circa mezz'ora in base alla capacità effettiva. Durante il periodo di training, è possibile eseguire Identificazione e FindSimilar se un'operazione di training è stata eseguita correttamente in precedenza. Nuove persone e nuovi visi aggiunti non vengono visualizzati nel risultato fino a quando non viene completata una nuova post-migrazione al training su larga scala.
Passaggio 1: Migrazione del codice
Questa sezione è incentrata su come eseguire la migrazione dell'implementazione PersonGroup o FaceList a LargePersonGroup o LargeFaceList. Anche se LargePersonGroup e LargeFaceList differiscono da PersonGroup e FaceList nella progettazione e nell'implementazione interna, le interfacce API sono simili per la compatibilità con le versioni precedenti.
La migrazione dei dati non è supportata. È invece possibile ricreare LargePersonGroup o LargeFaceList .
Eseguire la migrazione di un PersonGroup in un LargePersonGroup
La migrazione da un persongroup a un oggetto LargePersonGroup è semplice. Condividono esattamente le stesse operazioni a livello di gruppo.
Per l'implementazione relativa a PersonGroup o a persona, è necessario modificare solo i percorsi API o la classe o il modulo SDK in LargePersonGroup e LargePersonGroupPerson.
Aggiungere tutti i volti e le persone del PersonGroup al nuovo LargePersonGroup. Per ulteriori informazioni, consultare Aggiungere volti.
Eseguire la migrazione di un oggetto FaceList a un oggetto LargeFaceList
| FaceList API | LargeFaceList API |
|---|---|
| Creazione | Creazione |
| Elimina | Elimina |
| GET | GET |
| Elenco | Elenco |
| Update | Update |
| - | Eseguire il training |
| - | Visualizzare lo stato della formazione |
La tabella precedente è un confronto delle operazioni a livello di elenco tra FaceList e LargeFaceList. Come illustrato, LargeFaceList include nuove operazioni, Train e Get Training Status, rispetto a FaceList. L'addestramento di LargeFaceList è un prerequisito per l'operazione FindSimilar. Il training non è necessario per FaceList. Il frammento di codice seguente è una funzione helper che attende il training di un oggetto LargeFaceList:
/// <summary>
/// Helper function to train LargeFaceList and wait for finish.
/// </summary>
/// <remarks>
/// The time interval can be adjusted considering the following factors:
/// - The training time which depends on the capacity of the LargeFaceList.
/// - The acceptable latency for getting the training status.
/// - The call frequency and cost.
///
/// Estimated training time for LargeFaceList in different scale:
/// - 1,000 faces cost about 1 to 2 seconds.
/// - 10,000 faces cost about 5 to 10 seconds.
/// - 100,000 faces cost about 1 to 2 minutes.
/// - 1,000,000 faces cost about 10 to 30 minutes.
/// </remarks>
/// <param name="largeFaceListId">The Id of the LargeFaceList for training.</param>
/// <param name="timeIntervalInMilliseconds">The time interval for getting training status in milliseconds.</param>
/// <returns>A task of waiting for LargeFaceList training finish.</returns>
private static async Task TrainLargeFaceList(
string largeFaceListId,
int timeIntervalInMilliseconds = 1000)
{
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", SUBSCRIPTION_KEY);
// Trigger a train call.
await httpClient.PostAsync($"{ENDPOINT}/face/v1.0/largefacelists/{largeFaceListId}/train", null);
// Wait for training finish.
while (true)
{
await Task.Delay(timeIntervalInMilliseconds);
string? trainingStatus = null;
using (var response = await httpClient.GetAsync($"{ENDPOINT}/face/v1.0/largefacelists/{largeFaceListId}/training"))
{
string contentString = await response.Content.ReadAsStringAsync();
trainingStatus = (string?)(JsonConvert.DeserializeObject<Dictionary<string, object>>(contentString)?["status"]);
}
if ("running".Equals(trainingStatus))
{
continue;
}
else if ("succeeded".Equals(trainingStatus))
{
break;
}
else
{
throw new Exception("The train operation is failed!");
}
}
}
In precedenza, un uso tipico di FaceList con visi aggiunti e FindSimilar ha un aspetto simile al seguente:
// Create a FaceList.
const string FaceListId = "myfacelistid_001";
const string FaceListName = "MyFaceListDisplayName";
const string ImageDir = @"/path/to/FaceList/images";
using (var content = new ByteArrayContent(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new Dictionary<string, object> { ["name"] = FaceListName, ["recognitionModel"] = "recognition_04" }))))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
await httpClient.PutAsync($"{ENDPOINT}/face/v1.0/facelists/{FaceListId}", content);
}
// Add Faces to the FaceList.
Parallel.ForEach(
Directory.GetFiles(ImageDir, "*.jpg"),
async imagePath =>
{
using (Stream stream = File.OpenRead(imagePath))
{
using (var content = new StreamContent(stream))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
await httpClient.PostAsync($"{ENDPOINT}/face/v1.0/facelists/{FaceListId}/persistedfaces?detectionModel=detection_03", content);
}
}
});
// Perform FindSimilar.
const string QueryImagePath = @"/path/to/query/image";
var results = new List<HttpResponseMessage>();
using (Stream stream = File.OpenRead(QueryImagePath))
{
var response = await faceClient.DetectAsync(BinaryData.FromStream(stream), FaceDetectionModel.Detection03, FaceRecognitionModel.Recognition04, returnFaceId: true);
var faces = response.Value;
foreach (var face in faces)
{
using (var content = new ByteArrayContent(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new Dictionary<string, object> { ["faceId"] = face.FaceId, ["faceListId"] = FaceListId }))))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
results.Add(await httpClient.PostAsync($"{ENDPOINT}/face/v1.0/findsimilars", content));
}
}
}
Quando si esegue la migrazione a LargeFaceList, diventa il seguente:
// Create a LargeFaceList.
const string LargeFaceListId = "mylargefacelistid_001";
const string LargeFaceListName = "MyLargeFaceListDisplayName";
const string ImageDir = @"/path/to/FaceList/images";
using (var content = new ByteArrayContent(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new Dictionary<string, object> { ["name"] = LargeFaceListName, ["recognitionModel"] = "recognition_04" }))))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
await httpClient.PutAsync($"{ENDPOINT}/face/v1.0/largefacelists/{LargeFaceListId}", content);
}
// Add Faces to the LargeFaceList.
Parallel.ForEach(
Directory.GetFiles(ImageDir, "*.jpg"),
async imagePath =>
{
using (Stream stream = File.OpenRead(imagePath))
{
using (var content = new StreamContent(stream))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
await httpClient.PostAsync($"{ENDPOINT}/face/v1.0/largefacelists/{LargeFaceListId}/persistedfaces?detectionModel=detection_03", content);
}
}
});
// Train() is newly added operation for LargeFaceList.
// Must call it before FindSimilar to ensure the newly added faces searchable.
await TrainLargeFaceList(LargeFaceListId);
// Perform FindSimilar.
const string QueryImagePath = @"/path/to/query/image";
var results = new List<HttpResponseMessage>();
using (Stream stream = File.OpenRead(QueryImagePath))
{
var response = await faceClient.DetectAsync(BinaryData.FromStream(stream), FaceDetectionModel.Detection03, FaceRecognitionModel.Recognition04, returnFaceId: true);
var faces = response.Value;
foreach (var face in faces)
{
using (var content = new ByteArrayContent(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new Dictionary<string, object> { ["faceId"] = face.FaceId, ["largeFaceListId"] = LargeFaceListId }))))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
results.Add(await httpClient.PostAsync($"{ENDPOINT}/face/v1.0/findsimilars", content));
}
}
}
Come illustrato in precedenza, la gestione dei dati e la parte FindSimilar sono quasi uguali. L'unica eccezione è che un'operazione di pre-elaborazione aggiornata Train deve essere completata in LargeFaceList prima che FindSimilar funzioni.
Passaggio 2: Formare i suggerimenti
Anche se l'operazione Train accelera FindSimilar e Identificazione, il tempo di addestramento ne risente, soprattutto su larga scala. Il tempo di training stimato in scale diverse è elencato nella tabella seguente.
| Dimensionamento dei volti o degli individui | Tempo di training stimato |
|---|---|
| 1,000 | 1-2 s |
| 10.000 | 5-10 sec |
| 100,000 | 1-2 min |
| 1,000,000 | 10-30 minuti |
Per usare meglio la funzionalità su larga scala, è consigliabile usare le strategie seguenti.
Passaggio 2a: Personalizzare l'intervallo di tempo
Come illustrato in TrainLargeFaceList(), è presente un intervallo di tempo, espresso in millisecondi, per ritardare il processo di verifica dello stato di training infinito. Per LargeFaceList contenente più volti, l'uso di un intervallo maggiore riduce il numero di chiamate e i costi. Personalizzare l'intervallo di tempo in base alla capacità prevista di LargeFaceList.
La stessa strategia si applica anche a LargePersonGroup. Ad esempio, quando si addestra un LargePersonGroup con 1 milione di persone, timeIntervalInMilliseconds potrebbe essere 60.000, equivalente a un intervallo di 1 minuto.
Passaggio 2b: Buffer su scala ridotta
Le persone o i visi in un LargePersonGroup o in un LargeFaceList possono diventare ricercabili solo dopo l'addestramento. In uno scenario dinamico, le nuove persone o i visi vengono aggiunti costantemente e devono essere immediatamente ricercabili, ma la formazione potrebbe richiedere più tempo del previsto.
Per attenuare questo problema, usare un LargePersonGroup o LargeFaceList su scala extra-piccola come buffer solo per le voci appena aggiunte. Questo buffer richiede meno tempo per l'addestramento a causa delle dimensioni ridotte. La funzionalità di ricerca immediata in questo buffer temporaneo dovrebbe funzionare. Usare il buffer in combinazione con il training nell'oggetto LargePersonGroup o LargeFaceList principale eseguendo il training principale a intervalli meno frequenti. Gli esempi sono nel cuore della notte e tutti i giorni.
Flusso di lavoro di esempio:
- Creare un LargePersonGroup principale o un LargeFaceList, che è la collezione principale. Creare un buffer LargePersonGroup o LargeFaceList, ovvero la raccolta di buffer. La raccolta buffer è relativa solo alle persone o ai visi nuovi aggiunti.
- Aggiungere nuove persone o volti alla raccolta principale e alla collezione tampone.
- Eseguire solo il training della raccolta buffer con un breve intervallo di tempo per verificare che le voci appena aggiunte diventino effettive.
- Chiamare l'operazione Identification o FindSimilar sia sulla raccolta principale che sulla raccolta buffer. Unire i risultati.
- Quando le dimensioni della raccolta di buffer aumentano fino a una soglia o a un tempo di inattività del sistema, creare una nuova raccolta di buffer. Attivare l'operazione Train sulla raccolta principale.
- Dopo il termine dell'operazione Train nella raccolta master, eliminare la vecchia raccolta di buffer.
Passaggio 2c: Training autonomo
Se una latenza relativamente lunga è accettabile, non è necessario attivare l'operazione Train subito dopo l'aggiunta di nuovi dati. L'operazione Train può invece essere suddivisa dalla logica principale e attivata regolarmente. Questa strategia è adatta per scenari dinamici con latenza accettabile. Può essere applicato agli scenari statici per ridurre ulteriormente la frequenza di training .
Si supponga che sia presente una TrainLargePersonGroup funzione simile a TrainLargeFaceList. Un'implementazione tipica del training autonomo su un oggetto LargePersonGroup richiamando la classe Timer in System.Timers è la seguente:
private static void Main()
{
// Set up standalone training at regular intervals.
const int TimeIntervalForStatus = 1000 * 60; // 1-minute interval for getting training status.
const double TimeIntervalForTrain = 1000 * 60 * 60; // 1-hour interval for training.
var trainTimer = new Timer(TimeIntervalForTrain);
trainTimer.Elapsed += (sender, args) => TrainTimerOnElapsed("mylargepersongroupid_001", TimeIntervalForStatus);
trainTimer.AutoReset = true;
trainTimer.Enabled = true;
// Other operations like creating persons, adding faces, and identification, except for Train.
// ...
}
private static void TrainTimerOnElapsed(string largePersonGroupId, int timeIntervalInMilliseconds)
{
TrainLargePersonGroup(largePersonGroupId, timeIntervalInMilliseconds).Wait();
}
Per altre informazioni sulla gestione dei dati e sulle implementazioni correlate all'identificazione, vedere Aggiungere visi.
Sommario
In questa guida si è appreso come eseguire la migrazione del codice PersonGroup o FaceList esistente, non dei dati, a LargePersonGroup o LargeFaceList:
- LargePersonGroup e LargeFaceList funzionano in modo simile a PersonGroup o FaceList, ad eccezione del fatto che l'operazione Train è richiesta da LargeFaceList.
- Adottare l'approccio di addestramento adeguato per l'aggiornamento dinamico dei dati per set di dati su larga scala.
Contenuti correlati
Seguire una guida pratica per informazioni su come aggiungere visi a un PersonGroup o scrivere uno script per eseguire l'operazione Di identificazione in un PersonGroup.