public async Task <List <FullPersonDto> > RecognizeFullPersonsAsync(Face[] faces, string imagePath) { var selectedFaces = faces.Take(10).ToList(); List <FullPersonDto> persons = new List <FullPersonDto>(); IList <IdentifyResult> identifyResults = new List <IdentifyResult>(); IEnumerable <Person> recognizedPersons = new List <Person>(); try { identifyResults = (await _faceServiceClient.IdentifyAsync(Global.OxfordPersonGroupId, selectedFaces.Select(f => f.FaceId).ToArray())).ToList(); IList <Guid> candidatesId = identifyResults.Where(i => i.Candidates.Any()).Select(i => i.Candidates[0].PersonId).ToList(); recognizedPersons = _unit.PersonRepository.GetPersonsByCandidateIds(candidatesId); } catch (FaceAPIException e) { LogManager.GetLogger(GetType()).Info("Error during recognition", e); } foreach (Face face in selectedFaces) { Person person = null; IdentifyResult identifyResult = identifyResults.FirstOrDefault(i => i.FaceId == face.FaceId); if (identifyResult != null && identifyResult.Candidates.Any()) { person = recognizedPersons.FirstOrDefault(p => p.PersonApiId == identifyResult.Candidates[0].PersonId); } EmotionScores emotionTask = await ProcessRecognitionItemPicture(imagePath, face); persons.Add(new FullPersonDto { PersonId = face.FaceId, FirstName = person.FirstName, Age = face.FaceAttributes.Age, Gender = face.FaceAttributes.Gender, Beard = face.FaceAttributes.FacialHair.Beard, Glasses = face.FaceAttributes.Glasses, Mustache = face.FaceAttributes.FacialHair.Moustache, Anger = emotionTask.Anger, Contempt = emotionTask.Contempt, Disgust = emotionTask.Disgust, Fear = emotionTask.Fear, Happiness = emotionTask.Happiness, Neutral = emotionTask.Neutral, Sadness = emotionTask.Sadness, Surprise = emotionTask.Surprise }); } return(persons); }
/// <summary> /// Asynchronously remove the older face of a picture from oxford /// and update linked entity /// </summary> public async Task RemoveFaceFromOxford(Person person) { ProfilePicture pictureToDelete = _unit.ProfilePicturesRepository.GetOlderProfilePictureInOxford(person.Id); if (pictureToDelete == null) { return; } try { await _faceServiceClient.DeletePersonFaceAsync (Global.OxfordPersonGroupId, person.PersonApiId, pictureToDelete.FaceApiId); } catch (FaceAPIException e) { LogManager.GetLogger(GetType()).Info("Error occured during suppression of a face from api", e); } pictureToDelete.FaceApiId = default(Guid); }
/// <summary> /// Asynchronously add face in oxford for a person and link it with a profile picture /// <see cref="PersonCreationFallBack(Guid?)"/> /// </summary> public async Task <bool> AddFaceToPersonInOxford(Person person, ProfilePicture picture, Face face, string temporaryImage) { Guid faceApiId = default(Guid); try { // if the person has reached the limit of 64 faces in oxford if (person.HasReachedMaxLimitOfFaces()) { await RemoveFaceFromOxford(person); } AddPersistedFaceResult result = await _faceServiceClient.AddPersonFaceAsync(Global.OxfordPersonGroupId, person.PersonApiId, UrlHelpers.Content(Global.Host, temporaryImage), targetFace : face.FaceRectangle); faceApiId = result.PersistedFaceId; // Link profile picture with face on oxford api picture.FaceApiId = faceApiId; return(true); } catch (FaceAPIException e) { LogManager.GetLogger(GetType()).Info("Error occured during adding od face to person", e); // If is a new person we rollback its creation to avoid person without face if (person.Id == 0) { await PersonCreationFallBack(person.PersonApiId); File.Delete(MapPath(temporaryImage)); return(false); } return(true); } }
/// <summary> /// Asynchronously process a queue item /// </summary> public async Task <Person> ProcessRecognitionItem(RecognitionItem item) { Task <EmotionScores> emotionTask = RecognizeEmotions(item.ImageUrl, item.Face.FaceRectangle); #region Process of person Person person = item.Person; // if the person isn't recognized if (item.Person == null) { // Makes recognition to be sure the person isn't recognized var recognitionResults = await RecognizePersonsAsync(new[] { item.Face }, item.ImageUrl); if (recognitionResults.Any()) // be sure there is results { person = recognitionResults.First().Person; // If after that person is still not recognized, we create it // and add a new visit if (person == null) { person = await CreatePerson(item.Face); _unit.VisitsRepository.AddOrUpdateVisit(person, item.DateOfRecognition); } } } #endregion if (person != null) { #region Process of profilePictures ProfilePicture picture = item.ProfilePicture; // Creates a profile picture for new person if (item.ProfilePicture == null) { picture = _unit.ProfilePicturesRepository .CreateProfilePicture(person.PersonApiId, item.ImageUrl, item.Face, item.Confidence); person.Visits.Last().ProfilePictures.Add(picture); } // Adds picture to oxford, update information and clean temporary folder // If an erorr occured during addind face for a new person, stops process and rollback if (!await AddFaceToPersonInOxford(person, picture, item.Face, item.ImageUrl)) { return(null); } picture.EmotionScores = await emotionTask; // Clean temporary image file if (item.ImageCounter == 0) { File.Delete(MapPath(item.ImageUrl)); } #endregion // trains the person group await TrainPersonGroupAsync(); // Creates person is it's new if (person.Id == 0) { _unit.PersonRepository.Insert(person); } await _unit.SaveAsync(); } return(person); }
/// <summary> /// Asynchronously recognize persons from oxford and database and return /// recognition results /// </summary> public async Task <List <RecognitionItem> > RecognizePersonsAsync(Face[] faces, string imagePath) { List <RecognitionItem> results = new List <RecognitionItem>(); // Selects max 10 faces to make identification ordered by the size of rectangle of faces var selectedFaces = faces.Take(10).ToList(); // Makes identification from microsoft oxford IList <IdentifyResult> identifyResults = new List <IdentifyResult>(); IEnumerable <Person> recognizedPersons = new List <Person>(); try { identifyResults = (await _faceServiceClient.IdentifyAsync(Global.OxfordPersonGroupId, selectedFaces.Select(f => f.FaceId).ToArray())).ToList(); // Extracts guids of found candidates IList <Guid> candidatesId = identifyResults.Where(i => i.Candidates.Any()).Select(i => i.Candidates[0].PersonId).ToList(); // Gets candidates' information in database recognizedPersons = _unit.PersonRepository.GetPersonsByCandidateIds(candidatesId); } catch (FaceAPIException e) { var persons = await _faceServiceClient.GetPersonsAsync(Global.OxfordPersonGroupId); LogManager.GetLogger(GetType()).Info("Error during recognition", e); if (persons.Any()) { return(results); } } int imageCounter = 0; foreach (Face face in selectedFaces) { Person person = null; // Gets identification result which match with current face IdentifyResult identifyResult = identifyResults.FirstOrDefault(i => i.FaceId == face.FaceId); double confidence = 1; if (identifyResult != null && identifyResult.Candidates.Any()) { person = recognizedPersons.FirstOrDefault(p => p.PersonApiId == identifyResult.Candidates[0].PersonId); confidence = identifyResult.Candidates[0].Confidence; } imageCounter++; results.Add(new RecognitionItem { Face = face, Person = person, ImageUrl = imagePath, ImageCounter = imageCounter, Confidence = confidence, DateOfRecognition = DateTime.UtcNow, }); } return(results); }