19
19
* - Identify faces (and person group operations)
20
20
* - Large Person Group
21
21
* - Group Faces
22
+ * - FaceList
23
+ * - Large FaceList
22
24
* - Snapshot Operations
23
25
*
24
26
* Prerequisites:
34
36
*
35
37
* How to run:
36
38
* - 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.
38
40
*
39
41
* Dependencies within the samples:
40
42
* - Authenticate produces a client that's used by all samples.
@@ -73,7 +75,7 @@ static void Main(string[] args)
73
75
// Used in Authenticate and Snapshot examples. The client these help create is used by all examples.
74
76
// <snippet_mainvars>
75
77
// 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.
77
79
string SUBSCRIPTION_KEY = Environment . GetEnvironmentVariable ( "FACE_SUBSCRIPTION_KEY" ) ;
78
80
string ENDPOINT = Environment . GetEnvironmentVariable ( "FACE_ENDPOINT" ) ;
79
81
// </snippet_mainvars>
@@ -98,40 +100,51 @@ static void Main(string[] args)
98
100
const string RECOGNITION_MODEL1 = RecognitionModel . Recognition01 ;
99
101
// </snippet_detect_models>
100
102
103
+ // Large FaceList variables
104
+ const string LargeFaceListId = "mylargefacelistid_001" ; // must be lowercase, 0-9, "_" or "-" characters
105
+ const string LargeFaceListName = "MyLargeFaceListName" ;
106
+
101
107
// <snippet_client>
102
108
// Authenticate.
103
109
IFaceClient client = Authenticate ( ENDPOINT , SUBSCRIPTION_KEY ) ;
104
110
// </snippet_client>
105
111
// <snippet_snapshot_client>
106
- // Authenticate for another region (used in Snapshot only).
112
+ // Authenticate for another region or subscription (used in Snapshot only).
107
113
IFaceClient clientTarget = Authenticate ( TARGET_ENDPOINT , TARGET_SUBSCRIPTION_KEY ) ;
108
114
// </snippet_snapshot_client>
115
+
109
116
// <snippet_detect_call>
110
- // Detect features from faces.
117
+ // Detect - get features from faces.
111
118
DetectFaceExtract ( client , IMAGE_BASE_URL , RECOGNITION_MODEL2 ) . Wait ( ) ;
112
119
// </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.
115
121
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.
117
123
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).
119
126
IdentifyInPersonGroup ( client , IMAGE_BASE_URL , RECOGNITION_MODEL1 ) . Wait ( ) ;
120
- // Create a LargePersonGroup , then get data.
127
+ // LargePersonGroup - create , then get data.
121
128
LargePersonGroup ( client , IMAGE_BASE_URL , RECOGNITION_MODEL1 ) . Wait ( ) ;
122
- // Automatically group similar faces.
129
+ // Group faces - automatically group similar faces.
123
130
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 ( ) ;
124
135
// Take a snapshot of a person group in one region, move it to the next region.
125
136
// Can also be used for moving a person group from one Azure subscription to the next.
126
137
Snapshot ( client , clientTarget , sourcePersonGroup , AZURE_SUBSCRIPTION_ID , TARGET_AZURE_SUBSCRIPTION_ID ) . Wait ( ) ;
127
138
128
139
// <snippet_persongroup_delete>
129
140
// At end, delete person groups in both regions (since testing only)
130
141
Console . WriteLine ( "========DELETE PERSON GROUP========" ) ;
142
+ Console . WriteLine ( ) ;
131
143
DeletePersonGroup ( client , sourcePersonGroup ) . Wait ( ) ;
132
144
// </snippet_persongroup_delete>
133
145
// <snippet_target_persongroup_delete>
134
146
DeletePersonGroup ( clientTarget , targetPersonGroup ) . Wait ( ) ;
147
+ Console . WriteLine ( ) ;
135
148
// </snippet_target_persongroup_delete>
136
149
137
150
Console . WriteLine ( "End of quickstart." ) ;
@@ -159,6 +172,7 @@ public static IFaceClient Authenticate(string endpoint, string key)
159
172
public static async Task DetectFaceExtract ( IFaceClient client , string url , string recognitionModel )
160
173
{
161
174
Console . WriteLine ( "========DETECT FACES========" ) ;
175
+ Console . WriteLine ( ) ;
162
176
163
177
// Create a list of images
164
178
List < string > imageFileNames = new List < string >
@@ -279,6 +293,7 @@ private static async Task<List<DetectedFace>> DetectFaceRecognize(IFaceClient fa
279
293
public static async Task FindSimilar ( IFaceClient client , string url , string RECOGNITION_MODEL1 )
280
294
{
281
295
Console . WriteLine ( "========FIND SIMILAR========" ) ;
296
+ Console . WriteLine ( ) ;
282
297
283
298
List < string > targetImageFileNames = new List < string >
284
299
{
@@ -330,6 +345,7 @@ public static async Task FindSimilar(IFaceClient client, string url, string RECO
330
345
public static async Task Verify ( IFaceClient client , string url , string recognitionModel02 )
331
346
{
332
347
Console . WriteLine ( "========VERIFY========" ) ;
348
+ Console . WriteLine ( ) ;
333
349
334
350
List < string > targetImageFileNames = new List < string > { "Family1-Dad1.jpg" , "Family1-Dad2.jpg" } ;
335
351
string sourceImageFileName1 = "Family1-Dad3.jpg" ;
@@ -385,6 +401,7 @@ public static async Task Verify(IFaceClient client, string url, string recogniti
385
401
public static async Task IdentifyInPersonGroup ( IFaceClient client , string url , string recognitionModel )
386
402
{
387
403
Console . WriteLine ( "========IDENTIFY FACES========" ) ;
404
+ Console . WriteLine ( ) ;
388
405
389
406
// <snippet_persongroup_files>
390
407
// 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
477
494
public static async Task LargePersonGroup ( IFaceClient client , string url , string recognitionModel )
478
495
{
479
496
Console . WriteLine ( "========LARGE PERSON GROUP========" ) ;
497
+ Console . WriteLine ( ) ;
480
498
481
499
// Create a dictionary for all your images, grouping similar ones under the same key.
482
500
Dictionary < string , string [ ] > personDictionary =
@@ -551,6 +569,8 @@ public static async Task LargePersonGroup(IFaceClient client, string url, string
551
569
552
570
// After testing, delete the large person group, PersonGroupPersons also get deleted.
553
571
await client . LargePersonGroup . DeleteAsync ( largePersonGroupId ) ;
572
+ Console . WriteLine ( $ "Deleted the large person group { largePersonGroupId } .") ;
573
+ Console . WriteLine ( ) ;
554
574
}
555
575
/*
556
576
* END - LARGE PERSON GROUP
@@ -565,6 +585,8 @@ public static async Task LargePersonGroup(IFaceClient client, string url, string
565
585
public static async Task Group ( IFaceClient client , string url , string RECOGNITION_MODEL1 )
566
586
{
567
587
Console . WriteLine ( "========GROUP FACES========" ) ;
588
+ Console . WriteLine ( ) ;
589
+
568
590
// Create list of image names
569
591
List < string > imageFileNames = new List < string >
570
592
{
@@ -613,7 +635,148 @@ public static async Task Group(IFaceClient client, string url, string RECOGNITIO
613
635
* END - GROUP FACES
614
636
*/
615
637
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>
617
780
/*
618
781
* SNAPSHOT OPERATIONS
619
782
* 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
623
786
public static async Task Snapshot ( IFaceClient clientSource , IFaceClient clientTarget , string personGroupId , Guid azureId , Guid targetAzureId )
624
787
{
625
788
Console . WriteLine ( "========SNAPSHOT OPERATIONS========" ) ;
789
+ Console . WriteLine ( ) ;
790
+
626
791
// Take a snapshot for the person group that was previously created in your source region.
627
792
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.
628
793
@@ -695,11 +860,8 @@ public static async Task Snapshot(IFaceClient clientSource, IFaceClient clientTa
695
860
*/
696
861
public static async Task DeletePersonGroup ( IFaceClient client , String personGroupId )
697
862
{
698
- Console . WriteLine ( "Delete started... " ) ;
699
-
700
863
await client . PersonGroup . DeleteAsync ( personGroupId ) ;
701
864
Console . WriteLine ( $ "Deleted the person group { personGroupId } .") ;
702
- Console . WriteLine ( ) ;
703
865
}
704
866
// </snippet_deletepersongroup>
705
867
/*
0 commit comments