private async Task <SimilarFaceMatch> GetSimilarFace(Face detectedFace) { SimilarFaceMatch result = new SimilarFaceMatch(); try { Tuple <SimilarPersistedFace, string> similarPersistedFace = await FaceListManager.FindSimilarPersistedFaceAsync(await this.GetImageStreamCallback(), detectedFace.FaceId, detectedFace.FaceRectangle); if (similarPersistedFace != null) { bool isNew = (similarPersistedFace.Item2 == null); result = new SimilarFaceMatch() { Face = detectedFace, SimilarPersistedFace = similarPersistedFace.Item1, isNew = isNew }; } } catch (Exception e) { ErrorTrackingHelper.TrackException(e, "FaceListManager.FindSimilarPersistedFaceAsync error"); if (this.ShowDialogOnFaceApiErrors) { await ErrorTrackingHelper.GenericApiCallExceptionHandler(e, "Failure finding similar faces"); } } return(result); }
private async Task CreatePrsonIfNoSimilarFaceExistsAsync(List <FaceSendInfo> facesInfo, Guid newPersonID, Face f) { //TODO return person result so we can change candidate if we are not going with the one selected //We try to find person also thru similar face api SimilarFaceMatch result = await GetSimilarFace(f); using (var db = new KioskDBContext()) { //If we create new similar face, we create also new person if (result.isNew) { //We create db where we map SimilarPersonID to PersonID, because those are different in cognitive services var perResult = await CreatePerson(facesInfo, newPersonID, f); db.SimilarFaces.Add(new DBSimilarFace() { CreatedAt = DateTime.Now, FaceId = result.SimilarPersistedFace.PersistedFaceId.ToString(), PersonId = perResult.ToString() }); await db.SaveChangesAsync(); } else { string personId = ""; try { personId = db.SimilarFaces.Where(sf => sf.FaceId == result.SimilarPersistedFace.PersistedFaceId.ToString()).FirstOrDefault().PersonId; var person = await FaceServiceHelper.GetPersonAsync(groupId, new Guid(personId)); //Fill new info var fi = facesInfo.Where(fin => fin.faceId == f.FaceId.ToString()).FirstOrDefault(); fi.canid = personId; fi.canname = person.Name; fi.canconf = result.SimilarPersistedFace.Confidence; //We did not identified person thru person group and we needed to use silimar face api, so we add picture await AddFaceToPerson(f, person, new Guid(personId)); } catch (Exception) { //Person was not found due to old entry in local DB (Exception thrown by FaceApi GetPersonAsync) or face was created only in list when not using complex identification //If person is only in list, we need to create it also in person list if (personId == "") { var perResult2 = await CreatePerson(facesInfo, newPersonID, f); db.SimilarFaces.Add(new DBSimilarFace() { CreatedAt = DateTime.Now, FaceId = result.SimilarPersistedFace.PersistedFaceId.ToString(), PersonId = perResult2.ToString() }); await db.SaveChangesAsync(); } //We clean the old entry from DB and create new Person var oldDbEntry = db.SimilarFaces.Where(sf => sf.FaceId == result.SimilarPersistedFace.PersistedFaceId.ToString()).FirstOrDefault(); var perResult = await CreatePerson(facesInfo, newPersonID, f); if (oldDbEntry != null) { db.SimilarFaces.Update(oldDbEntry); oldDbEntry.FaceId = result.SimilarPersistedFace.PersistedFaceId.ToString(); oldDbEntry.PersonId = perResult.ToString(); } else { db.SimilarFaces.Add(new DBSimilarFace() { CreatedAt = DateTime.Now, FaceId = result.SimilarPersistedFace.PersistedFaceId.ToString(), PersonId = perResult.ToString() }); } await db.SaveChangesAsync(); } } } }
public async Task <List <FaceSendInfo> > IdentifyOrAddPersonWithEmotionsAsync(string groupName, double confidence) { var time = DateTime.Now; //We also add emotions var facesInfo = new List <FaceSendInfo>(); foreach (var f in this.DetectedFaces) { var fsi = new FaceSendInfo(); var e = CoreUtil.FindEmotionForFace(f, this.DetectedEmotion); fsi.faceId = f.FaceId.ToString(); fsi.age = f.FaceAttributes.Age; fsi.faceRecHeight = f.FaceRectangle.Height; fsi.faceRecLeft = f.FaceRectangle.Left; fsi.faceRecTop = f.FaceRectangle.Top; fsi.faceRecWidth = f.FaceRectangle.Width; fsi.gender = f.FaceAttributes.Gender; fsi.smile = f.FaceAttributes.Smile; fsi.beard = f.FaceAttributes.FacialHair.Beard; fsi.moustache = f.FaceAttributes.FacialHair.Moustache; fsi.sideburns = f.FaceAttributes.FacialHair.Sideburns; fsi.glasses = f.FaceAttributes.Glasses.ToString(); fsi.headYaw = f.FaceAttributes.HeadPose.Yaw; fsi.headRoll = f.FaceAttributes.HeadPose.Roll; fsi.headPitch = f.FaceAttributes.HeadPose.Pitch; fsi.anger = e.Scores.Anger; fsi.contempt = e.Scores.Contempt; fsi.disgust = e.Scores.Disgust; fsi.fear = e.Scores.Fear; fsi.happiness = e.Scores.Happiness; fsi.neutral = e.Scores.Neutral; fsi.sadness = e.Scores.Sadness; fsi.surprise = e.Scores.Surprise; fsi.timeStamp = time; fsi.facesNo = this.DetectedFaces.Count(); facesInfo.Add(fsi); } var newPersonID = Guid.NewGuid(); //Move to initialization try { var g = await FaceServiceHelper.CreatePersonGroupIfNoGroupExists(groupName); groupId = g.PersonGroupId; } catch (Exception e) { // Catch errors with individual groups so we can continue looping through all groups. Maybe an answer will come from // another one. ErrorTrackingHelper.TrackException(e, "Problem creating group"); if (this.ShowDialogOnFaceApiErrors) { await ErrorTrackingHelper.GenericApiCallExceptionHandler(e, "Problem creating group"); } } List <IdentifiedPerson> ipresult = new List <IdentifiedPerson>(); // Compute Face Identification and Unique Face Ids //We need to map detected faceID with actual personID (Identified face) try { IdentifyResult[] groupResults = await this.IdentifyFacesAsync(groupId); foreach (var f in this.DetectedFaces) { if (groupResults != null && groupResults.Where(gr => gr.FaceId == f.FaceId).Any() && groupResults.Where(gr => gr.FaceId == f.FaceId).FirstOrDefault().Candidates.Any()) { var candidates = groupResults.Where(gr => gr.FaceId == f.FaceId).FirstOrDefault().Candidates.OrderByDescending(ca => ca.Confidence); var fi = facesInfo.Where(fin => fin.faceId == f.FaceId.ToString()).FirstOrDefault(); int i = 0; Person p = new Person(); foreach (var can in candidates) { switch (i) { case 0: fi.can1id = can.PersonId.ToString(); fi.can1conf = can.Confidence; p = await FaceServiceHelper.GetPersonAsync(groupId, can.PersonId); fi.can1name = p.Name; if (can.Confidence >= confidence) { ipresult.Add(new IdentifiedPerson() { Person = p, Confidence = can.Confidence, FaceId = f.FaceId }); if (p.PersistedFaceIds.Length == 248) { Guid persistedFaceId = p.PersistedFaceIds.OrderBy(x => Guid.NewGuid()).FirstOrDefault(); await FaceServiceHelper.DeletePersonFaceAsync(groupId, can.PersonId, persistedFaceId); } try { await FaceServiceHelper.AddPersonFaceAsync(groupId, can.PersonId, await this.GetImageStreamCallback(), "", f.FaceRectangle); } catch (Exception e) { // Catch errors with individual groups so we can continue looping through all groups. Maybe an answer will come from // another one. ErrorTrackingHelper.TrackException(e, "Problem adding face to group"); if (this.ShowDialogOnFaceApiErrors) { await ErrorTrackingHelper.GenericApiCallExceptionHandler(e, "Problem adding face to group"); } } } else { //create new Guy if confidence not sufficient SimilarFaceMatch result = await GetSimilarFace(f); //using (var db = new KioskDbContext()) //{ // Blogs.ItemsSource = db.Blogs.ToList(); //} await CreatePerson(facesInfo, newPersonID, f); } break; case 1: fi.can2id = can.PersonId.ToString(); fi.can2conf = can.Confidence; p = await FaceServiceHelper.GetPersonAsync(groupId, can.PersonId); fi.can2name = p.Name; break; case 2: fi.can3id = can.PersonId.ToString(); fi.can3conf = can.Confidence; p = await FaceServiceHelper.GetPersonAsync(groupId, can.PersonId); fi.can3name = p.Name; break; case 3: fi.can4id = can.PersonId.ToString(); fi.can4conf = can.Confidence; p = await FaceServiceHelper.GetPersonAsync(groupId, can.PersonId); fi.can4name = p.Name; break; } i++; } } else { //if no candidate we also need to create new person await CreatePerson(facesInfo, newPersonID, f); } try { await FaceServiceHelper.TrainPersonGroupAsync(groupId); } catch (Exception e) { // Catch error with training of group ErrorTrackingHelper.TrackException(e, "Problem training group"); if (this.ShowDialogOnFaceApiErrors) { await ErrorTrackingHelper.GenericApiCallExceptionHandler(e, "Problem training group"); } } } } catch (Exception e) { // Catch error with training of group ErrorTrackingHelper.TrackException(e, "Problem with cognitive services"); if (this.ShowDialogOnFaceApiErrors) { await ErrorTrackingHelper.GenericApiCallExceptionHandler(e, "Problem with cognitive services"); } } return(facesInfo); }