in Kiosk/ServiceHelpers/FaceServiceHelper.cs [333:417]
public static async Task UpdatePersonGroupsWithNewRecModelAsync(PersonGroup oldPersonGroup, string userDataFilder, IProgress<FaceIdentificationModelUpdateStatus> progress = null)
{
try
{
bool allPeopleHaveAtLeastOneFaceMigrated = true;
// just make sure the person group use previous recognition model
bool isOldPersonGroup = oldPersonGroup?.RecognitionModel != null && !oldPersonGroup.RecognitionModel.Equals(LatestRecognitionModelName, StringComparison.OrdinalIgnoreCase);
// get persons
IList<Person> personsInGroup = isOldPersonGroup ? await GetPersonsAsync(oldPersonGroup.PersonGroupId) : new List<Person>();
if (personsInGroup.Any())
{
// create new person group
string newPersonGroupId = Guid.NewGuid().ToString();
await CreatePersonGroupAsync(newPersonGroupId, oldPersonGroup.Name, userDataFilder);
// create new persons
var newPersonList = new List<Tuple<Person, Person>>();
foreach (Person oldPerson in personsInGroup)
{
Person newPerson = await CreatePersonAsync(newPersonGroupId, oldPerson.Name);
newPersonList.Add(new Tuple<Person, Person>(oldPerson, newPerson));
}
// add face images
foreach (var (personItem, index) in newPersonList.Select((v, i) => (v, i)))
{
Person oldPerson = personItem.Item1;
Person newPerson = personItem.Item2;
// get face images from the old model
var personFaces = new List<PersistedFace>();
foreach (Guid face in oldPerson.PersistedFaceIds)
{
PersistedFace personFace = await GetPersonFaceAsync(oldPersonGroup.PersonGroupId, oldPerson.PersonId, face);
personFaces.Add(personFace);
}
bool addedAtLeastOneFaceImageForPerson = false;
// add face images to the new model
foreach (PersistedFace persistedFace in personFaces)
{
try
{
bool isUri = !string.IsNullOrEmpty(persistedFace.UserData) ? Uri.IsWellFormedUriString(persistedFace.UserData, UriKind.Absolute) : false;
if (isUri)
{
await AddPersonFaceFromUrlAsync(newPersonGroupId, newPerson.PersonId, imageUrl: persistedFace.UserData, userData: persistedFace.UserData, targetFaceRect: null);
}
else
{
StorageFile localImage = await StorageFile.GetFileFromPathAsync(persistedFace.UserData);
await AddPersonFaceFromStreamAsync(newPersonGroupId, newPerson.PersonId, imageStreamCallback: localImage.OpenStreamForReadAsync, userData: localImage.Path, targetFaceRect: null);
}
addedAtLeastOneFaceImageForPerson = true;
}
catch { /* Ignore the error and continue. Other images might work */ }
}
if (!addedAtLeastOneFaceImageForPerson)
{
allPeopleHaveAtLeastOneFaceMigrated = false;
}
progress?.Report(new FaceIdentificationModelUpdateStatus { State = FaceIdentificationModelUpdateState.Running, Count = index + 1, Total = personsInGroup.Count });
}
// delete old person group
await DeletePersonGroupAsync(oldPersonGroup.PersonGroupId);
// train new person group
await TrainPersonGroupAsync(newPersonGroupId);
}
progress?.Report(new FaceIdentificationModelUpdateStatus { State = allPeopleHaveAtLeastOneFaceMigrated ? FaceIdentificationModelUpdateState.Complete : FaceIdentificationModelUpdateState.CompletedWithSomeEmptyPeople });
}
catch (Exception ex)
{
ErrorTrackingHelper.TrackException(ex, "Face API: Update PersonGroup using new recognition model error");
progress?.Report(new FaceIdentificationModelUpdateStatus { State = FaceIdentificationModelUpdateState.Error });
}
}