diff --git a/FaceParts/Models/_D2_FaceParts.cs b/FaceParts/Models/_D2_FaceParts.cs index a4cb721..ff8c5e3 100644 --- a/FaceParts/Models/_D2_FaceParts.cs +++ b/FaceParts/Models/_D2_FaceParts.cs @@ -237,6 +237,7 @@ public class D2_FaceParts { int x; int y; + Pen pen; string? firstFileName = null; using Image image = Image.FromFile(resizedFileHolder.FullName); using Graphics graphic = Graphics.FromImage(image); @@ -253,7 +254,8 @@ public class D2_FaceParts { if (face.Location is null) continue; - graphic.DrawEllipse(Pens.GreenYellow, facePoint.X - pointSize, facePoint.Y - pointSize, pointSize * 2, pointSize * 2); + pen = face.Mapping?.MappingFromPerson is null ? Pens.Red : Pens.GreenYellow; + graphic.DrawEllipse(pen, facePoint.X - pointSize, facePoint.Y - pointSize, pointSize * 2, pointSize * 2); } if (facePart == FacePart.Chin) continue; diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index 7e92bec..0c9f28c 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -261,9 +261,60 @@ public partial class DlibDotNet return result; } + private void SetMapping(Dictionary>> idToLocationContainers, MapLogic mapLogic, Item item, bool? isFocusRelativePath, bool? isIgnoreRelativePath, MappingFromItem mappingFromItem, List? mappingFromPhotoPrismCollection, List faces) + { + string? model; + Mapping mapping; + bool? isFocusModel; + int faceAreaPermyriad; + int confidencePercent; + int normalizedRectangle; + string deterministicHashCodeKey; + MappingFromFilter mappingFromFilter; + MappingFromLocation? mappingFromLocation; + IReadOnlyList directories; + List>? locationContainers; + if (string.IsNullOrEmpty(_Configuration.FocusModel)) + isFocusModel = null; + else + { + if (!idToLocationContainers.TryGetValue(mappingFromItem.Id, out locationContainers) || !locationContainers.Any()) + isFocusModel = false; + else + { + directories = locationContainers.First().Directories; + model = Metadata.Models.Stateless.Methods.IMetadata.GetModel(directories); + if (model is null) + directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(mappingFromItem.ResizedFileHolder.FullName); + model = Metadata.Models.Stateless.Methods.IMetadata.GetModel(directories); + isFocusModel = model is not null && model.Contains(_Configuration.FocusModel); + if (isFocusModel.Value) + isFocusModel = true; + } + } + mappingFromFilter = new(isFocusModel, isFocusRelativePath, isIgnoreRelativePath); + foreach (Shared.Models.Face face in faces) + { + if (item.Property?.Id is null || face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) + mappingFromLocation = null; + else + { + confidencePercent = Shared.Models.Stateless.Methods.ILocation.GetConfidencePercent(_Configuration.FaceConfidencePercent, _Configuration.RangeFaceConfidence, face.Location.Confidence); + faceAreaPermyriad = Shared.Models.Stateless.Methods.IMapping.GetAreaPermyriad(_Configuration.FaceAreaPermyriad, face.Location, face.OutputResolution); + normalizedRectangle = Shared.Models.Stateless.Methods.ILocation.GetNormalizedRectangle(face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); + deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); + mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, normalizedRectangle); + } + mapping = new(mappingFromItem, mappingFromFilter, mappingFromLocation, mappingFromPhotoPrismCollection); + _ = mapLogic.UpdateMappingFromPerson(mapping); + face.SetMapping(mapping); + } + } + private void FullParallelForWork(A_Property propertyLogic, B_Metadata metadata, Dictionary>> idToLocationContainers, + MapLogic mapLogic, string outputResolution, string cResultsFullGroupDirectory, string dResultsDateGroupDirectory, @@ -274,7 +325,9 @@ public partial class DlibDotNet Container container, int index, Item item, - DateTime[] containerDateTimes) + DateTime[] containerDateTimes, + bool? isFocusRelativePath, + bool? isIgnoreRelativePath) { if (_Log is null) throw new NullReferenceException(nameof(_Log)); @@ -364,6 +417,7 @@ public partial class DlibDotNet && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution) && !anyFacesSaved && collection is not null) _Distance.LookForMatchFacesAndPossiblyRename(_Faces.FileNameExtension, eDistanceContentDirectory, mappingFromItem, faces, collection); + SetMapping(idToLocationContainers, mapLogic, item, isFocusRelativePath, isIgnoreRelativePath, mappingFromItem, mappingFromPhotoPrismCollection, faces); if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) { bool saveRotated = false; @@ -384,6 +438,7 @@ public partial class DlibDotNet A_Property propertyLogic, B_Metadata metadata, Dictionary>> idToLocationContainers, + MapLogic mapLogic, string outputResolution, string cResultsFullGroupDirectory, string dResultsDateGroupDirectory, @@ -399,9 +454,12 @@ public partial class DlibDotNet throw new NullReferenceException(nameof(_Log)); int result = 0; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; - ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; DateTime[] containerDateTimes = Shared.Models.Stateless.Methods.IContainer.GetContainerDateTimes(filteredItems); + ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; using ProgressBar progressBar = new(filteredItems.Length, message, options); + string focusRelativePath = Path.GetFullPath(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, _Configuration.FocusDirectory)); + bool? isFocusRelativePath = string.IsNullOrEmpty(_Configuration.FocusDirectory) ? null : container.SourceDirectory.StartsWith(focusRelativePath); + bool? isIgnoreRelativePath = !_Configuration.IgnoreRelativePaths.Any() ? null : _Configuration.IgnoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && Shared.Models.Stateless.Methods.IContainer.IsIgnoreRelativePath(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, container.SourceDirectory); _ = Parallel.For(0, filteredItems.Length, parallelOptions, (i, state) => { try @@ -409,6 +467,7 @@ public partial class DlibDotNet FullParallelForWork(propertyLogic, metadata, idToLocationContainers, + mapLogic, outputResolution, cResultsFullGroupDirectory, dResultsDateGroupDirectory, @@ -419,7 +478,9 @@ public partial class DlibDotNet container, index: i, filteredItems[i], - containerDateTimes); + containerDateTimes, + isFocusRelativePath, + isIgnoreRelativePath); if (i == 0 || sourceDirectoryChanges.Any()) progressBar.Tick(); } @@ -514,7 +575,7 @@ public partial class DlibDotNet return new(cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory); } - private void FullDoWork(string argZero, string propertyRoot, long ticks, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, int t, Container[] containers, A_Property propertyLogic, B_Metadata metadata, string eDistanceContentDirectory, Dictionary> fileNameToCollection, Dictionary>> idToLocationContainers) + private void FullDoWork(string argZero, string propertyRoot, long ticks, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, int t, Container[] containers, A_Property propertyLogic, B_Metadata metadata, string eDistanceContentDirectory, Dictionary> fileNameToCollection, Dictionary>> idToLocationContainers, MapLogic mapLogic) { if (_Log is null) throw new NullReferenceException(nameof(_Log)); @@ -560,6 +621,7 @@ public partial class DlibDotNet propertyLogic, metadata, idToLocationContainers, + mapLogic, outputResolution, cResultsFullGroupDirectory, dResultsDateGroupDirectory, @@ -590,86 +652,6 @@ public partial class DlibDotNet } } - private void SetMapping(string argZero, Container[] containers, Dictionary> fileNameToCollection, Dictionary>> idToLocationContainers) - { - string? model; - Mapping mapping; - bool? isFocusModel; - int faceAreaPermyriad; - Item[] filteredItems; - int confidencePercent; - int normalizedRectangle; - bool? isFocusRelativePath; - bool? isIgnoreRelativePath; - DateTime[] containerDateTimes; - string deterministicHashCodeKey; - MappingFromItem mappingFromItem; - MappingFromFilter mappingFromFilter; - MappingFromLocation? mappingFromLocation; - IReadOnlyList directories; - List? mappingFromPhotoPrismCollection; - List>? locationContainers; - string focusRelativePath = Path.GetFullPath(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, _Configuration.FocusDirectory)); - foreach (Container container in containers) - { - if (!container.Items.Any()) - continue; - if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero)) - continue; - filteredItems = Shared.Models.Stateless.Methods.IContainer.GetFilterItems(_Configuration.PropertyConfiguration, container); - if (!filteredItems.Any()) - continue; - containerDateTimes = Shared.Models.Stateless.Methods.IContainer.GetContainerDateTimes(filteredItems); - isFocusRelativePath = string.IsNullOrEmpty(_Configuration.FocusDirectory) ? null : container.SourceDirectory.StartsWith(focusRelativePath); - if (!_Configuration.IgnoreRelativePaths.Any()) - isIgnoreRelativePath = null; - else - isIgnoreRelativePath = _Configuration.IgnoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && Shared.Models.Stateless.Methods.IContainer.IsIgnoreRelativePath(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, container.SourceDirectory); - foreach (Item item in filteredItems) - { - if (item.Property?.Id is null || item.ResizedFileHolder is null) - continue; - mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item); - if (string.IsNullOrEmpty(_Configuration.FocusModel)) - isFocusModel = null; - else - { - if (!idToLocationContainers.TryGetValue(mappingFromItem.Id, out locationContainers) || !locationContainers.Any()) - isFocusModel = false; - else - { - directories = locationContainers.First().Directories; - model = Metadata.Models.Stateless.Methods.IMetadata.GetModel(directories); - if (model is null) - directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(mappingFromItem.ResizedFileHolder.FullName); - model = Metadata.Models.Stateless.Methods.IMetadata.GetModel(directories); - isFocusModel = model is not null && model.Contains(_Configuration.FocusModel); - if (isFocusModel.Value) - isFocusModel = true; - } - } - mappingFromFilter = new(isFocusModel, isFocusRelativePath, isIgnoreRelativePath); - foreach (Shared.Models.Face face in item.Faces) - { - if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) - mappingFromLocation = null; - else - { - confidencePercent = Shared.Models.Stateless.Methods.ILocation.GetConfidencePercent(_Configuration.FaceConfidencePercent, _Configuration.RangeFaceConfidence, face.Location.Confidence); - faceAreaPermyriad = Shared.Models.Stateless.Methods.IMapping.GetAreaPermyriad(_Configuration.FaceAreaPermyriad, face.Location, face.OutputResolution); - normalizedRectangle = Shared.Models.Stateless.Methods.ILocation.GetNormalizedRectangle(face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); - deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution); - mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, normalizedRectangle); - } - if (!fileNameToCollection.TryGetValue(mappingFromItem.RelativePath[1..], out mappingFromPhotoPrismCollection)) - mappingFromPhotoPrismCollection = null; - mapping = new(mappingFromItem, mappingFromFilter, mappingFromLocation, mappingFromPhotoPrismCollection); - face.SetMapping(mapping); - } - } - } - } - private (List, List) GetFilteredDistinct(string argZero, Container[] containers) { List resultIds = new(); @@ -1103,14 +1085,12 @@ public partial class DlibDotNet propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory); } containers = Shared.Models.Stateless.Methods.IContainer.SortContainers(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, _ArgZeroIsConfigurationRootDirectory, argZero, containers); - MapLogic? mapLogic = _Configuration.DistanceMoveUnableToMatch ? null : new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, ticks, _PersonContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory); - personKeyToIds = mapLogic is null ? new() : mapLogic.GetPersonKeyToIds(); + MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, ticks, _PersonContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory); + personKeyToIds = mapLogic.GetPersonKeyToIds(); fileNameToCollection = !Directory.Exists(fPhotoPrismSingletonDirectory) ? fileNameToCollection = new() : F_PhotoPrism.GetFileNameToCollection(fPhotoPrismSingletonDirectory); Dictionary>> idToLocationContainers = GetDictionary(ticks, a2PeopleContentDirectory, eDistanceContentDirectory); - FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, t, containers, propertyLogic, metadata, eDistanceContentDirectory, fileNameToCollection, idToLocationContainers); + FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, t, containers, propertyLogic, metadata, eDistanceContentDirectory, fileNameToCollection, idToLocationContainers, mapLogic); _Distance.Clear(); - mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, ticks, _PersonContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory); - SetMapping(argZero, containers, fileNameToCollection, idToLocationContainers); if (!personKeyToIds.Any()) personKeyToIds = mapLogic.GetPersonKeyToIds(); (List distinctFilteredIds, List distinctFilteredFaces) = GetFilteredDistinct(argZero, containers); diff --git a/Map/Models/MapLogic.cs b/Map/Models/MapLogic.cs index 5bb15dc..f83554a 100644 --- a/Map/Models/MapLogic.cs +++ b/Map/Models/MapLogic.cs @@ -171,7 +171,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic return new(result, normalizedRectangleToPersonContainers); } - public int UpdateMappingFromPerson(Mapping[] mappingCollection) + public int UpdateMappingFromPerson(Mapping mapping) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); @@ -183,7 +183,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic List? normalizedRectangles; PersonContainer[]? personContainers; Dictionary? normalizedRectangleToPersonContainers; - foreach (Mapping mapping in mappingCollection) + for (int i = 1; i < 2; i++) { if (mapping.MappingFromLocation is null) continue; @@ -214,6 +214,18 @@ public class MapLogic : Shared.Models.Methods.IMapLogic return result; } + public int UpdateMappingFromPerson(Mapping[] mappingCollection) + { + int result = 0; + foreach (Mapping mapping in mappingCollection) + { + if (mapping.MappingFromLocation is null) + continue; + result += UpdateMappingFromPerson(mapping); + } + return result; + } + public void SaveContainers(int totalNotMapped, int? updated, List saveContainers) { if (_Configuration is null) diff --git a/Shared/Models/Stateless/Methods/IMappingFromItem.cs b/Shared/Models/Stateless/Methods/IMappingFromItem.cs index 0ed6a86..6f9a39c 100644 --- a/Shared/Models/Stateless/Methods/IMappingFromItem.cs +++ b/Shared/Models/Stateless/Methods/IMappingFromItem.cs @@ -8,11 +8,6 @@ public interface IMappingFromItem static MappingFromItem GetMappingFromItem(DateTime[] containerDateTimes, Models.Item item, Models.FileHolder? resizedFileHolder) => MappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder); - MappingFromItem TestStatic_GetMappingFromItem(DateTime[] containerDateTimes, Models.Item item) - => GetMappingFromItem(containerDateTimes, item); - static MappingFromItem GetMappingFromItem(DateTime[] containerDateTimes, Models.Item item) - => GetMappingFromItem(containerDateTimes, item, item.ResizedFileHolder); - MappingFromItem TestStatic_GetMappingFromItem(Models.Item item) => GetMappingFromItem(item); static MappingFromItem GetMappingFromItem(Models.Item item)