Skala för att hantera fler registrerade användare
Varning
Åtkomsten till ansiktstjänsten är begränsad baserat på berättigande- och användningskriterier för att stödja våra principer för ansvarsfull AI. Ansiktstjänsten är endast tillgänglig för Microsofts hanterade kunder och partner. Använd formuläret ansiktsigenkänning för att ansöka om åtkomst. Mer information finns på sidan ansiktsbegränsade åtkomst .
Den här guiden visar hur du skalar upp från befintliga PersonGroup - och FaceList-objekt till LargePersonGroup - respektive LargeFaceList-objekt . PersonGroups kan innehålla upp till 1 000 personer på den kostnadsfria nivån och 10 000 på den betalda nivån, medan LargePersonGroups kan rymma upp till en miljon personer på den betalda nivån.
Viktigt!
Den nyare datastrukturen PersonDirectory rekommenderas för ny utveckling. Det kan innehålla upp till 75 miljoner identiteter och kräver inte manuell utbildning. Mer information finns i PersonDirectory-guiden.
Den här guiden visar migreringsprocessen. Den förutsätter grundläggande kunskaper om PersonGroup- och FaceList-objekt, träningsåtgärden och ansiktsigenkänningsfunktionerna. Mer information om dessa ämnen finns i konceptguiden för ansiktsigenkänning .
LargePersonGroup och LargeFaceList kallas tillsammans för storskaliga åtgärder. LargePersonGroup kan innehålla upp till 1 miljon personer, var och en med högst 248 ansikten. LargeFaceList kan innehålla upp till 1 miljon ansikten. De storskaliga åtgärderna liknar den konventionella PersonGroup och FaceList men har vissa skillnader på grund av den nya arkitekturen.
Exemplen är skrivna i C#.
Kommentar
Om du vill aktivera prestanda för ansiktssökning för identifiering och FindSimilar i stor skala introducerar du en train-åtgärd för att förbearbeta LargeFaceList och LargePersonGroup. Träningstiden varierar från sekunder till ungefär en halvtimme baserat på den faktiska kapaciteten. Under träningsperioden är det möjligt att utföra Identifiering och FindSimilar om en lyckad träningsdrift utfördes tidigare. Nackdelen är att de nya tillagda personerna och ansiktena inte visas i resultatet förrän en ny eftermigrering till storskalig utbildning har slutförts.
Steg 1: Kodmigrering
Det här avsnittet fokuserar på hur du migrerar PersonGroup - eller FaceList-implementering till LargePersonGroup eller LargeFaceList. Även om LargePersonGroup eller LargeFaceList skiljer sig från PersonGroup eller FaceList i design och intern implementering, är API-gränssnitten liknande för bakåtkompatibilitet.
Datamigrering stöds inte. Du återskapar LargePersonGroup eller LargeFaceList i stället.
Migrera en PersonGroup till en LargePersonGroup
Migrering från en PersonGroup till en LargePersonGroup är enkel. De delar exakt samma åtgärder på gruppnivå.
För PersonGroup eller personrelaterad implementering är det nödvändigt att endast ändra API-sökvägarna eller SDK-klassen/modulen till LargePersonGroup och LargePersonGroup Person.
Lägg till alla ansikten och personer från PersonGroup till den nya LargePersonGroup. Mer information finns i Lägg till ansikten.
Migrera en ansiktslista till en LargeFaceList
Api:er för Ansiktslista | LargeFaceList-API :er |
---|---|
Skapa | Skapa |
Delete | Delete |
Hämta | Hämta |
List | List |
Uppdatera | Uppdatera |
- | Utbilda |
- | Hämta träningsstatus |
Föregående tabell är en jämförelse av listnivååtgärder mellan FaceList och LargeFaceList. Som visas levereras LargeFaceList med nya åtgärder, Träna och Hämta träningsstatus, jämfört med FaceList. Att träna LargeFaceList är en förutsättning för FindSimilar-åtgärden. Träning krävs inte för FaceList. Följande kodfragment är en hjälpfunktion som väntar på träning av en 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!");
}
}
}
Tidigare såg en typisk användning av FaceList med tillagda ansikten och FindSimilar ut så här:
// 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));
}
}
}
När du migrerar den till LargeFaceList blir den följande:
// 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));
}
}
}
Som tidigare visats är datahanteringen och FindSimilar-delen nästan desamma. Det enda undantaget är att en ny förbearbetningsåtgärd måste slutföras i LargeFaceList innan FindSimilar fungerar.
Steg 2: Träna förslag
Även om tågåtgärden påskyndar FindSimilar och Identifiering, blir träningstiden lidande, särskilt när den kommer till stor skala. Den uppskattade träningstiden i olika skalor visas i följande tabell.
Skala för ansikten eller personer | Uppskattad träningstid |
---|---|
1 000 | 1–2 sek |
10,000 | 5-10 sek |
100,000 | 1–2 min |
1 000 000 | 10-30 min |
För att bättre utnyttja den storskaliga funktionen rekommenderar vi följande strategier.
Steg 2a: Anpassa tidsintervall
Som visas i TrainLargeFaceList()
finns det ett tidsintervall i millisekunder för att fördröja den oändliga processen för kontroll av träningsstatus. För LargeFaceList med fler ansikten minskar antalet samtal och kostnaden med ett större intervall. Anpassa tidsintervallet enligt den förväntade kapaciteten för LargeFaceList.
Samma strategi gäller även för LargePersonGroup. När du till exempel tränar en LargePersonGroup med 1 miljon personer timeIntervalInMilliseconds
kan det vara 60 000, vilket är ett intervall på 1 minut.
Steg 2b: Buffert i liten skala
Personer eller ansikten i en LargePersonGroup eller en LargeFaceList kan endast sökas efter att ha tränats. I ett dynamiskt scenario läggs nya personer eller ansikten ständigt till och måste vara omedelbart sökbara, men träningen kan ta längre tid än önskat.
Du kan åtgärda det här problemet genom att använda en extra storskalig LargePersonGroup eller LargeFaceList som buffert endast för de nyligen tillagda posterna. Den här bufferten tar kortare tid att träna på grund av den mindre storleken. Den omedelbara sökfunktionen på den här tillfälliga bufferten bör fungera. Använd den här bufferten i kombination med träning på originalet LargePersonGroup eller LargeFaceList genom att köra masterträningen med ett sparserintervall. Exempel är mitt i natten och varje dag.
Ett exempelarbetsflöde:
- Skapa en master LargePersonGroup eller LargeFaceList, som är huvudsamlingen. Skapa en buffert LargePersonGroup eller LargeFaceList, som är buffertsamlingen. Buffertsamlingen är endast avsedd för nyligen tillagda personer eller ansikten.
- Lägg till nya personer eller ansikten i både huvudsamlingen och buffertsamlingen.
- Träna bara buffertsamlingen med ett kort tidsintervall för att säkerställa att de nyligen tillagda posterna börjar gälla.
- Anropa Identifiering eller FindSimilar mot både huvudsamlingen och buffertsamlingen. Sammanfoga resultatet.
- När buffertsamlingens storlek ökar till ett tröskelvärde eller vid en systeminaktiv tid skapar du en ny buffertsamling. Utlös åtgärden Träna i huvudsamlingen.
- Ta bort den gamla buffertsamlingen när åtgärden Träna har slutförts i huvudsamlingen.
Steg 2c: Fristående utbildning
Om en relativt lång svarstid är acceptabel behöver du inte utlösa åtgärden Träna direkt efter att du har lagt till nya data. I stället kan åtgärden Träna delas upp från huvudlogik och utlösas regelbundet. Den här strategin är lämplig för dynamiska scenarier med acceptabel svarstid. Den kan användas för statiska scenarier för att ytterligare minska träningsfrekvensen .
Anta att det finns en TrainLargePersonGroup
funktion som liknar TrainLargeFaceList
. En typisk implementering av den fristående träningen på en LargePersonGroup genom att Timer
anropa klassen i System.Timers
är:
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();
}
Mer information om datahantering och identifieringsrelaterade implementeringar finns i Lägga till ansikten.
Sammanfattning
I den här guiden har du lärt dig hur du migrerar den befintliga PersonGroup - eller FaceList-koden , inte data, till LargePersonGroup eller LargeFaceList:
- LargePersonGroup och LargeFaceList fungerar ungefär som PersonGroup eller FaceList, förutom att träningsåtgärden krävs av LargeFaceList.
- Ta rätt träningsstrategi för dynamisk datauppdatering för storskaliga datauppsättningar.
Nästa steg
Följ en instruktionsguide för att lära dig hur du lägger till ansikten i en PersonGroup eller skriver ett skript för att utföra åtgärden Identifiera på en PersonGroup.