Skip to content

Commit 7e2fe30

Browse files
authored
Merge pull request #145 from wiazur/patch-16
Face - Added facelist and large facelist examples
2 parents 21b1c0c + 0c66a4d commit 7e2fe30

File tree

1 file changed

+176
-14
lines changed

1 file changed

+176
-14
lines changed

documentation-samples/quickstarts/Face/Program.cs

Lines changed: 176 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
* - Identify faces (and person group operations)
2020
* - Large Person Group
2121
* - Group Faces
22+
* - FaceList
23+
* - Large FaceList
2224
* - Snapshot Operations
2325
*
2426
* Prerequisites:
@@ -34,7 +36,7 @@
3436
*
3537
* How to run:
3638
* - Create a new C# Console app in Visual Studio 2019.
37-
* - Copy/paste the Program.cs file in the Github quickstart into your own Program.cs file. Make sure to rename the namespace if different.
39+
* - Copy/paste the Program.cs file in the Github quickstart into your own Program.cs file.
3840
*
3941
* Dependencies within the samples:
4042
* - Authenticate produces a client that's used by all samples.
@@ -73,7 +75,7 @@ static void Main(string[] args)
7375
// Used in Authenticate and Snapshot examples. The client these help create is used by all examples.
7476
// <snippet_mainvars>
7577
// From your Face subscription in the Azure portal, get your subscription key and endpoint.
76-
// Set your environment variables, using the names below. Close and reopen your project for changes to take effect.
78+
// Set your environment variables using the names below. Close and reopen your project for changes to take effect.
7779
string SUBSCRIPTION_KEY = Environment.GetEnvironmentVariable("FACE_SUBSCRIPTION_KEY");
7880
string ENDPOINT = Environment.GetEnvironmentVariable("FACE_ENDPOINT");
7981
// </snippet_mainvars>
@@ -98,40 +100,51 @@ static void Main(string[] args)
98100
const string RECOGNITION_MODEL1 = RecognitionModel.Recognition01;
99101
// </snippet_detect_models>
100102

103+
// Large FaceList variables
104+
const string LargeFaceListId = "mylargefacelistid_001"; // must be lowercase, 0-9, "_" or "-" characters
105+
const string LargeFaceListName = "MyLargeFaceListName";
106+
101107
// <snippet_client>
102108
// Authenticate.
103109
IFaceClient client = Authenticate(ENDPOINT, SUBSCRIPTION_KEY);
104110
// </snippet_client>
105111
// <snippet_snapshot_client>
106-
// Authenticate for another region (used in Snapshot only).
112+
// Authenticate for another region or subscription (used in Snapshot only).
107113
IFaceClient clientTarget = Authenticate(TARGET_ENDPOINT, TARGET_SUBSCRIPTION_KEY);
108114
// </snippet_snapshot_client>
115+
109116
// <snippet_detect_call>
110-
// Detect features from faces.
117+
// Detect - get features from faces.
111118
DetectFaceExtract(client, IMAGE_BASE_URL, RECOGNITION_MODEL2).Wait();
112119
// </snippet_detect_call>
113-
114-
// Find a similar face from a list of faces.
120+
// Find Similar - find a similar face from a list of faces.
115121
FindSimilar(client, IMAGE_BASE_URL, RECOGNITION_MODEL1).Wait();
116-
// Compare two images if the same person or not.
122+
// Verify - compare two images if the same person or not.
117123
Verify(client, IMAGE_BASE_URL, RECOGNITION_MODEL2).Wait();
118-
// Identify a face(s) in a person group (a person group is created in this example).
124+
125+
// Identify - recognize a face(s) in a person group (a person group is created in this example).
119126
IdentifyInPersonGroup(client, IMAGE_BASE_URL, RECOGNITION_MODEL1).Wait();
120-
// Create a LargePersonGroup, then get data.
127+
// LargePersonGroup - create, then get data.
121128
LargePersonGroup(client, IMAGE_BASE_URL, RECOGNITION_MODEL1).Wait();
122-
// Automatically group similar faces.
129+
// Group faces - automatically group similar faces.
123130
Group(client, IMAGE_BASE_URL, RECOGNITION_MODEL1).Wait();
131+
// FaceList - create a face list, then get data
132+
FaceListOperations(client, IMAGE_BASE_URL).Wait();
133+
// Large FaceList - create a large face list, then get data
134+
LargeFaceListOperations(client, IMAGE_BASE_URL).Wait();
124135
// Take a snapshot of a person group in one region, move it to the next region.
125136
// Can also be used for moving a person group from one Azure subscription to the next.
126137
Snapshot(client, clientTarget, sourcePersonGroup, AZURE_SUBSCRIPTION_ID, TARGET_AZURE_SUBSCRIPTION_ID).Wait();
127138

128139
// <snippet_persongroup_delete>
129140
// At end, delete person groups in both regions (since testing only)
130141
Console.WriteLine("========DELETE PERSON GROUP========");
142+
Console.WriteLine();
131143
DeletePersonGroup(client, sourcePersonGroup).Wait();
132144
// </snippet_persongroup_delete>
133145
// <snippet_target_persongroup_delete>
134146
DeletePersonGroup(clientTarget, targetPersonGroup).Wait();
147+
Console.WriteLine();
135148
// </snippet_target_persongroup_delete>
136149

137150
Console.WriteLine("End of quickstart.");
@@ -159,6 +172,7 @@ public static IFaceClient Authenticate(string endpoint, string key)
159172
public static async Task DetectFaceExtract(IFaceClient client, string url, string recognitionModel)
160173
{
161174
Console.WriteLine("========DETECT FACES========");
175+
Console.WriteLine();
162176

163177
// Create a list of images
164178
List<string> imageFileNames = new List<string>
@@ -279,6 +293,7 @@ private static async Task<List<DetectedFace>> DetectFaceRecognize(IFaceClient fa
279293
public static async Task FindSimilar(IFaceClient client, string url, string RECOGNITION_MODEL1)
280294
{
281295
Console.WriteLine("========FIND SIMILAR========");
296+
Console.WriteLine();
282297

283298
List<string> targetImageFileNames = new List<string>
284299
{
@@ -330,6 +345,7 @@ public static async Task FindSimilar(IFaceClient client, string url, string RECO
330345
public static async Task Verify(IFaceClient client, string url, string recognitionModel02)
331346
{
332347
Console.WriteLine("========VERIFY========");
348+
Console.WriteLine();
333349

334350
List<string> targetImageFileNames = new List<string> { "Family1-Dad1.jpg", "Family1-Dad2.jpg" };
335351
string sourceImageFileName1 = "Family1-Dad3.jpg";
@@ -385,6 +401,7 @@ public static async Task Verify(IFaceClient client, string url, string recogniti
385401
public static async Task IdentifyInPersonGroup(IFaceClient client, string url, string recognitionModel)
386402
{
387403
Console.WriteLine("========IDENTIFY FACES========");
404+
Console.WriteLine();
388405

389406
// <snippet_persongroup_files>
390407
// Create a dictionary for all your images, grouping similar ones under the same key.
@@ -477,6 +494,7 @@ public static async Task IdentifyInPersonGroup(IFaceClient client, string url, s
477494
public static async Task LargePersonGroup(IFaceClient client, string url, string recognitionModel)
478495
{
479496
Console.WriteLine("========LARGE PERSON GROUP========");
497+
Console.WriteLine();
480498

481499
// Create a dictionary for all your images, grouping similar ones under the same key.
482500
Dictionary<string, string[]> personDictionary =
@@ -551,6 +569,8 @@ public static async Task LargePersonGroup(IFaceClient client, string url, string
551569

552570
// After testing, delete the large person group, PersonGroupPersons also get deleted.
553571
await client.LargePersonGroup.DeleteAsync(largePersonGroupId);
572+
Console.WriteLine($"Deleted the large person group {largePersonGroupId}.");
573+
Console.WriteLine();
554574
}
555575
/*
556576
* END - LARGE PERSON GROUP
@@ -565,6 +585,8 @@ public static async Task LargePersonGroup(IFaceClient client, string url, string
565585
public static async Task Group(IFaceClient client, string url, string RECOGNITION_MODEL1)
566586
{
567587
Console.WriteLine("========GROUP FACES========");
588+
Console.WriteLine();
589+
568590
// Create list of image names
569591
List<string> imageFileNames = new List<string>
570592
{
@@ -613,7 +635,148 @@ public static async Task Group(IFaceClient client, string url, string RECOGNITIO
613635
* END - GROUP FACES
614636
*/
615637

616-
// <snippet_snapshot_take>
638+
/*
639+
* FACELIST OPERATIONS
640+
* Create a face list and add single-faced images to it, then retrieve data from the faces.
641+
* Images are used from URLs.
642+
*/
643+
public static async Task FaceListOperations(IFaceClient client, string baseUrl)
644+
{
645+
Console.WriteLine("========FACELIST OPERATIONS========");
646+
Console.WriteLine();
647+
648+
const string FaceListId = "myfacelistid_001";
649+
const string FaceListName = "MyFaceListName";
650+
651+
// Create an empty FaceList with user-defined specifications, it gets stored in the client.
652+
await client.FaceList.CreateAsync(faceListId: FaceListId, name: FaceListName);
653+
654+
// Create a list of single-faced images to append to base URL. Images with mulitple faces are not accepted.
655+
List<string> imageFileNames = new List<string>
656+
{
657+
"detection1.jpg", // single female with glasses
658+
"detection2.jpg", // single male
659+
"detection3.jpg", // single male construction worker
660+
};
661+
662+
// Add Faces to the FaceList.
663+
foreach (string image in imageFileNames)
664+
{
665+
string urlFull = baseUrl + image;
666+
// Returns a Task<PersistedFace> which contains a GUID, and is stored in the client.
667+
await client.FaceList.AddFaceFromUrlAsync(faceListId: FaceListId, url: urlFull);
668+
}
669+
670+
// Print the face list
671+
Console.WriteLine("Face IDs from the face list: ");
672+
Console.WriteLine();
673+
674+
// List the IDs of each stored image
675+
FaceList faceList = await client.FaceList.GetAsync(FaceListId);
676+
677+
foreach (PersistedFace face in faceList.PersistedFaces)
678+
{
679+
Console.WriteLine(face.PersistedFaceId);
680+
}
681+
682+
// Delete the face list, for repetitive testing purposes (cannot recreate list with same name).
683+
await client.FaceList.DeleteAsync(FaceListId);
684+
Console.WriteLine();
685+
Console.WriteLine("Deleted the face list.");
686+
Console.WriteLine();
687+
}
688+
/*
689+
* END - FACELIST OPERATIONS
690+
*/
691+
692+
/*
693+
* LARGE FACELIST OPERATIONS
694+
* Create a large face list and adds single-faced images to it, then retrieve data from the faces.
695+
* Images are used from URLs. Large face lists are preferred for scale, up to 1 million images.
696+
*/
697+
public static async Task LargeFaceListOperations(IFaceClient client, string baseUrl)
698+
{
699+
Console.WriteLine("======== LARGE FACELIST OPERATIONS========");
700+
Console.WriteLine();
701+
702+
const string LargeFaceListId = "mylargefacelistid_001"; // must be lowercase, 0-9, or "_"
703+
const string LargeFaceListName = "MyLargeFaceListName";
704+
const int timeIntervalInMilliseconds = 1000; // waiting time in training
705+
706+
List<string> singleImages = new List<string>
707+
{
708+
"Family1-Dad1.jpg",
709+
"Family1-Daughter1.jpg",
710+
"Family1-Mom1.jpg",
711+
"Family1-Son1.jpg",
712+
"Family2-Lady1.jpg",
713+
"Family2-Man1.jpg",
714+
"Family3-Lady1.jpg",
715+
"Family3-Man1.jpg"
716+
};
717+
718+
// Create a large face list
719+
Console.WriteLine("Creating a large face list...");
720+
await client.LargeFaceList.CreateAsync(largeFaceListId: LargeFaceListId, name: LargeFaceListName);
721+
722+
// Add Faces to the LargeFaceList.
723+
Console.WriteLine("Adding faces to a large face list...");
724+
foreach (string image in singleImages)
725+
{
726+
// Returns a PersistedFace which contains a GUID.
727+
await client.LargeFaceList.AddFaceFromUrlAsync(largeFaceListId: LargeFaceListId, url: $"{baseUrl}{image}");
728+
}
729+
730+
// Training a LargeFaceList is what sets it apart from a regular FaceList.
731+
// You must train before using the large face list, for example to use the Find Similar operations.
732+
Console.WriteLine("Training a large face list...");
733+
await client.LargeFaceList.TrainAsync(LargeFaceListId);
734+
735+
// Wait for training finish.
736+
while (true)
737+
{
738+
Task.Delay(timeIntervalInMilliseconds).Wait();
739+
var status = await client.LargeFaceList.GetTrainingStatusAsync(LargeFaceListId);
740+
741+
if (status.Status == TrainingStatusType.Running)
742+
{
743+
Console.WriteLine($"Training status: {status.Status}");
744+
continue;
745+
}
746+
else if (status.Status == TrainingStatusType.Succeeded)
747+
{
748+
Console.WriteLine($"Training status: {status.Status}");
749+
break;
750+
}
751+
else
752+
{
753+
throw new Exception("The train operation has failed!");
754+
}
755+
}
756+
757+
// Print the large face list
758+
Console.WriteLine();
759+
Console.WriteLine("Face IDs from the large face list: ");
760+
Console.WriteLine();
761+
Parallel.ForEach(
762+
await client.LargeFaceList.ListFacesAsync(LargeFaceListId),
763+
faceId =>
764+
{
765+
Console.WriteLine(faceId.PersistedFaceId);
766+
}
767+
);
768+
769+
// Delete the large face list, for repetitive testing purposes (cannot recreate list with same name).
770+
await client.LargeFaceList.DeleteAsync(LargeFaceListId);
771+
Console.WriteLine();
772+
Console.WriteLine("Deleted the large face list.");
773+
Console.WriteLine();
774+
}
775+
/*
776+
* END - LARGE FACELIST OPERATIONS
777+
*/
778+
779+
// <snippet_snapshot_take>
617780
/*
618781
* SNAPSHOT OPERATIONS
619782
* Copies a person group from one Azure region (or subscription) to another. For example: from the EastUS region to the WestUS.
@@ -623,6 +786,8 @@ public static async Task Group(IFaceClient client, string url, string RECOGNITIO
623786
public static async Task Snapshot(IFaceClient clientSource, IFaceClient clientTarget, string personGroupId, Guid azureId, Guid targetAzureId)
624787
{
625788
Console.WriteLine("========SNAPSHOT OPERATIONS========");
789+
Console.WriteLine();
790+
626791
// Take a snapshot for the person group that was previously created in your source region.
627792
var takeSnapshotResult = await clientSource.Snapshot.TakeAsync(SnapshotObjectType.PersonGroup, personGroupId, new[] { azureId }); // add targetAzureId to this array if your target ID is different from your source ID.
628793

@@ -695,11 +860,8 @@ public static async Task Snapshot(IFaceClient clientSource, IFaceClient clientTa
695860
*/
696861
public static async Task DeletePersonGroup(IFaceClient client, String personGroupId)
697862
{
698-
Console.WriteLine("Delete started... ");
699-
700863
await client.PersonGroup.DeleteAsync(personGroupId);
701864
Console.WriteLine($"Deleted the person group {personGroupId}.");
702-
Console.WriteLine();
703865
}
704866
// </snippet_deletepersongroup>
705867
/*

0 commit comments

Comments
 (0)