diff --git a/Distance/Models/DistanceLimits.cs b/Distance/Models/DistanceLimits.cs index 31f6b29..3b88ebf 100644 --- a/Distance/Models/DistanceLimits.cs +++ b/Distance/Models/DistanceLimits.cs @@ -10,37 +10,38 @@ public class DistanceLimits : IDistanceLimits private int _Distance; private int _Confidence; - public double FaceAreaPermille { init; get; } + public double FaceAreaPermyriad { init; get; } public double RangeDaysDeltaTolerance { init; get; } public double FaceConfidencePercent { init; get; } public double FaceDistancePermyriad { init; get; } public int SortingMaximumPerFaceShouldBeHigh { init; get; } public bool RangeDaysDeltaTargetLessThenUpper { init; get; } - public DistanceLimits(int faceConfidencePercent, - int faceDistancePermyriad, - int[] rangeDaysDeltaTolerance, - double[] rangeDistanceTolerance, - int[] rangeFaceAreaPermilleTolerance, - double[] rangeFaceConfidence, - int sortingMaximumPerFaceShouldBeHigh, - int? useFiltersCounter = null) + public DistanceLimits(int faceAreaPermyriad, + int faceConfidencePercent, + int faceDistancePermyriad, + int[] rangeDaysDeltaTolerance, + float[] rangeDistanceTolerance, + float[] rangeFaceAreaPermyriadTolerance, + float[] rangeFaceConfidence, + int sortingMaximumPerFaceShouldBeHigh, + int? useFiltersCounter = null) { SortingMaximumPerFaceShouldBeHigh = sortingMaximumPerFaceShouldBeHigh; RangeDaysDeltaTargetLessThenUpper = rangeDaysDeltaTolerance[1] > rangeDaysDeltaTolerance[2]; if (useFiltersCounter is null) { - FaceAreaPermille = rangeFaceAreaPermilleTolerance[1]; RangeDaysDeltaTolerance = rangeDaysDeltaTolerance[1]; FaceConfidencePercent = faceConfidencePercent * rangeFaceConfidence[1]; + FaceAreaPermyriad = faceAreaPermyriad * rangeFaceAreaPermyriadTolerance[1]; FaceDistancePermyriad = faceDistancePermyriad * rangeDistanceTolerance[1]; } else { RangeDaysDeltaTolerance = ((rangeDaysDeltaTolerance[2] - rangeDaysDeltaTolerance[0]) * 0.01 * useFiltersCounter.Value) + rangeDaysDeltaTolerance[1]; FaceConfidencePercent = faceConfidencePercent * ((rangeFaceConfidence[2] - rangeFaceConfidence[0]) * 0.01 * useFiltersCounter.Value) + rangeFaceConfidence[1]; - FaceAreaPermille = ((rangeFaceAreaPermilleTolerance[2] - rangeFaceAreaPermilleTolerance[0]) * 0.01 * useFiltersCounter.Value) + rangeFaceAreaPermilleTolerance[1]; FaceDistancePermyriad = faceDistancePermyriad * ((rangeDistanceTolerance[2] - rangeDistanceTolerance[0]) * 0.01 * useFiltersCounter.Value) + rangeDistanceTolerance[1]; + FaceAreaPermyriad = faceAreaPermyriad * ((rangeFaceAreaPermyriadTolerance[2] - rangeFaceAreaPermyriadTolerance[0]) * 0.01 * useFiltersCounter.Value) + rangeFaceAreaPermyriadTolerance[1]; } } diff --git a/Distance/Models/_E_Distance.cs b/Distance/Models/_E_Distance.cs index 53d149b..c0d6a6d 100644 --- a/Distance/Models/_E_Distance.cs +++ b/Distance/Models/_E_Distance.cs @@ -15,13 +15,13 @@ public partial class E_Distance private readonly Serilog.ILogger? _Log; private readonly int _FaceConfidencePercent; private readonly bool _DistanceRenameToMatch; - private readonly double[] _RangeFaceConfidence; + private readonly float[] _RangeFaceConfidence; private readonly bool _DistanceMoveUnableToMatch; private readonly List _AllMappedFaceFiles; private readonly List _AllMappedFaceFileNames; private readonly List _DuplicateMappedFaceFiles; - public E_Distance(bool distanceMoveUnableToMatch, bool distanceRenameToMatch, int faceConfidencePercent, double[] rangeFaceConfidence) + public E_Distance(bool distanceMoveUnableToMatch, bool distanceRenameToMatch, int faceConfidencePercent, float[] rangeFaceConfidence) { _Debug = new(); _Moved = new(); @@ -423,7 +423,7 @@ public partial class E_Distance confidence += 1; continue; } - if (face.Mapping.MappingFromLocation.AreaPermille < distanceLimits.FaceAreaPermille) + if (face.Mapping.MappingFromLocation.AreaPermyriad < distanceLimits.FaceAreaPermyriad) { area += 1; continue; @@ -445,7 +445,7 @@ public partial class E_Distance return results; } - private static FaceDistanceContainer[] GetFaceDistanceContainers(Map.Models.MapLogic mapLogic, List distinctFilteredFaces) + public static FaceDistanceContainer[] GetFaceDistanceContainers(List distinctFilteredFaces) { FaceDistanceContainer[] results; FaceDistance faceDistance; @@ -455,12 +455,8 @@ public partial class E_Distance { if (face.Mapping?.MappingFromLocation is null) throw new NotSupportedException(); - if (face.Mapping.MappingFromItem.IsIgnoreRelativePath) - continue; if (face.FaceDistance?.Encoding is not FaceRecognitionDotNet.FaceEncoding faceEncoding) continue; - if (mapLogic.Used(face.FaceDistance)) - continue; faceDistance = new(face.Mapping.MappingFromLocation.ConfidencePercent, faceEncoding, face.Mapping.MappingFromItem.Id, face.Mapping.MappingFromItem.IsWrongYear, face.Mapping.MappingFromItem.MinimumDateTime, face.Mapping.MappingFromLocation.NormalizedRectangle); faceDistanceContainer = new(face, faceDistance); collection.Add(faceDistanceContainer); @@ -469,7 +465,7 @@ public partial class E_Distance return results; } - private static List GetFaceDistanceEncodings(FaceDistanceContainer[] faceDistanceContainers, List missingFaceDistanceContainers) + public static List GetFaceDistanceEncodings(FaceDistanceContainer[] faceDistanceContainers, List missingFaceDistanceContainers) { List faceDistanceEncodings = new(); foreach (FaceDistanceContainer faceDistanceContainer in faceDistanceContainers) @@ -487,22 +483,40 @@ public partial class E_Distance return faceDistanceEncodings; } - public static SortingContainer[] SetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, Map.Models.Configuration mapConfiguration, long ticks, Map.Models.MapLogic mapLogic, Shared.Models.Methods.IDistanceLimits distanceLimits, List distinctFilteredFaces, List missingFaceDistanceContainers) + public static FaceDistanceContainer[] FilteredFaceDistanceContainers(Map.Models.MapLogic mapLogic, FaceDistanceContainer[] faceDistanceContainers) + { + List results = new(); + foreach (FaceDistanceContainer faceDistanceContainer in faceDistanceContainers) + { + if (faceDistanceContainer.FaceDistance is null || faceDistanceContainer.Face.Mapping?.MappingFromLocation is null) + throw new NotSupportedException(); + if (faceDistanceContainer.Face.Mapping.MappingFromFilter.IsFocusModel is not null && !faceDistanceContainer.Face.Mapping.MappingFromFilter.IsFocusModel.Value) + continue; + if (faceDistanceContainer.Face.Mapping.MappingFromFilter.IsFocusRelativePath is not null && !faceDistanceContainer.Face.Mapping.MappingFromFilter.IsFocusRelativePath.Value) + continue; + if (faceDistanceContainer.Face.Mapping.MappingFromFilter.IsIgnoreRelativePath is not null && faceDistanceContainer.Face.Mapping.MappingFromFilter.IsIgnoreRelativePath.Value) + continue; + if (mapLogic.Used(faceDistanceContainer.FaceDistance)) + continue; + results.Add(faceDistanceContainer); + } + return results.ToArray(); + } + + public static SortingContainer[] SetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, Map.Models.Configuration mapConfiguration, long ticks, Map.Models.MapLogic mapLogic, Shared.Models.Methods.IDistanceLimits distanceLimits, List faceDistanceEncodings, FaceDistanceContainer[] filteredFaceDistanceContainers) { SortingContainer[] results; List collection = new(); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; - FaceDistanceContainer[] faceDistanceContainers = GetFaceDistanceContainers(mapLogic, distinctFilteredFaces); - List faceDistanceEncodings = GetFaceDistanceEncodings(faceDistanceContainers, missingFaceDistanceContainers); - string message = $") {faceDistanceContainers.Length:000} Get Sorting Containers Then Set Face Mapping Sorting Collection - {totalSeconds} total second(s)"; + string message = $") {filteredFaceDistanceContainers.Length:000} Get Sorting Containers Then Set Face Mapping Sorting Collection - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; - using ProgressBar progressBar = new(faceDistanceContainers.Length, message, options); - _ = Parallel.For(0, faceDistanceContainers.Length, parallelOptions, (i, state) => + using ProgressBar progressBar = new(filteredFaceDistanceContainers.Length, message, options); + _ = Parallel.For(0, filteredFaceDistanceContainers.Length, parallelOptions, (i, state) => { progressBar.Tick(); - FaceDistance faceDistanceEncoding = faceDistanceContainers[i].FaceDistance; - Face face = faceDistanceContainers[i].Face; + FaceDistance faceDistanceEncoding = filteredFaceDistanceContainers[i].FaceDistance; + Face face = filteredFaceDistanceContainers[i].Face; List sortingCollection = GetSortingCollection(mapLogic, faceDistanceEncodings, i, faceDistanceEncoding); if (!sortingCollection.Any()) return; diff --git a/Duplicate-Search/DuplicateSearch.cs b/Duplicate-Search/DuplicateSearch.cs index 0b61af3..0790729 100644 --- a/Duplicate-Search/DuplicateSearch.cs +++ b/Duplicate-Search/DuplicateSearch.cs @@ -154,7 +154,6 @@ public class DuplicateSearch DateTime[] containerDateTimes; MappingFromItem? mappingFromItem; List? collection; - const bool isIgnoreRelativePath = false; const string duplicates = "-Duplicate(s)"; if (containers.Any()) { @@ -193,11 +192,11 @@ public class DuplicateSearch if (mappingFromItem is not null) { resizedFileHolder = new(mappingFromItem.ResizedFileHolder.FullName.Replace($"0{duplicates}", $"1{duplicates}")); - collection[0] = new(mappingFromItem.ContainerDateTimes, mappingFromItem.Id, mappingFromItem.ImageFileHolder, mappingFromItem.IsIgnoreRelativePath, mappingFromItem.IsWrongYear, mappingFromItem.MinimumDateTime, mappingFromItem.RelativePath, resizedFileHolder); + collection[0] = new(mappingFromItem.ContainerDateTimes, mappingFromItem.Id, mappingFromItem.ImageFileHolder, mappingFromItem.IsWrongYear, mappingFromItem.MinimumDateTime, mappingFromItem.RelativePath, resizedFileHolder); } } resizedFileHolder = new(string.Concat(Path.Combine(destinationRoot, directory), item.RelativePath)); - mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder, isIgnoreRelativePath); + mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder); collection.Add(mappingFromItem); } } diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index 9cfee8f..a887d56 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -326,8 +326,7 @@ public partial class DlibDotNet item.SetResizedFileHolder(_Resize.FileNameExtension, resizedFileHolder); string facesDirectory = _Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution) ? _Faces.GetFacesDirectory(dResultsFullGroupDirectory, item) : string.Empty; string facePartsDirectory = _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution) ? _FaceParts.GetFacePartsDirectory(_Configuration.PropertyConfiguration, dResultsFullGroupDirectory, item) : string.Empty; - bool isIgnoreRelativePath = _Configuration.IgnoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && Shared.Models.Stateless.Methods.IContainer.IsIgnoreRelativePath(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, container.SourceDirectory); - MappingFromItem mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder, isIgnoreRelativePath); + MappingFromItem mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder); (int metadataGroups, metadataCollection) = metadata.GetMetadataCollection(subFileTuples, parseExceptions, mappingFromItem); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(B_Metadata.GetMetadataCollection)); @@ -590,19 +589,26 @@ public partial class DlibDotNet } } - private void SetMapping(Dictionary> fileNameToCollection, string argZero, Container[] containers) + private void SetMapping(string argZero, Container[] containers, Dictionary> fileNameToCollection, Dictionary>> idToLocationContainers) { + string? model; Mapping mapping; - int faceAreaPermille; + bool? isFocusModel; + int faceAreaPermyriad; Item[] filteredItems; int confidencePercent; int normalizedRectangle; - bool isIgnoreRelativePath; + 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()) @@ -613,12 +619,35 @@ public partial class DlibDotNet if (!filteredItems.Any()) continue; containerDateTimes = Shared.Models.Stateless.Methods.IContainer.GetContainerDateTimes(filteredItems); - isIgnoreRelativePath = _Configuration.IgnoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && Shared.Models.Stateless.Methods.IContainer.IsIgnoreRelativePath(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, container.SourceDirectory); + 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, isIgnoreRelativePath); + 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) @@ -626,14 +655,14 @@ public partial class DlibDotNet else { confidencePercent = Shared.Models.Stateless.Methods.ILocation.GetConfidencePercent(_Configuration.FaceConfidencePercent, _Configuration.RangeFaceConfidence, face.Location.Confidence); - faceAreaPermille = Shared.Models.Stateless.Methods.IMapping.GetAreaPermille(_Configuration.FaceAreaPermille, face.Location, face.OutputResolution); + 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(faceAreaPermille, confidencePercent, deterministicHashCodeKey, normalizedRectangle); + mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, normalizedRectangle); } if (!fileNameToCollection.TryGetValue(mappingFromItem.RelativePath[1..], out mappingFromPhotoPrismCollection)) mappingFromPhotoPrismCollection = null; - mapping = new(mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection); + mapping = new(mappingFromItem, mappingFromFilter, mappingFromLocation, mappingFromPhotoPrismCollection); face.SetMapping(mapping); } } @@ -695,10 +724,51 @@ public partial class DlibDotNet return items; } - private void MapLogic(string argZero, long ticks, Container[] containers, string a2PeopleSingletonDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, string fPhotoPrismContentDirectory, MapLogic mapLogic, string outputResolution, Dictionary> personKeyToIds, List distinctFilteredFaces, Mapping[] mappingCollection, int totalNotMapped) + private void SaveFaceDistances(long ticks, MapLogic mapLogic, Mapping[] mappingCollection, string dFacesContentDirectory, string d2FacePartsContentDirectory, Dictionary> idToNormalizedRectangleToMapping, List faceDistanceEncodings, FaceDistanceContainer[] filteredFaceDistanceContainers) { + DistanceLimits distanceLimits; int? useFiltersCounter = null; SortingContainer[] sortingContainers; + distanceLimits = new(_Configuration.FaceAreaPermyriad, _Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeDistanceTolerance, _Configuration.RangeFaceAreaTolerance, _Configuration.RangeFaceConfidence, _Configuration.SortingMaximumPerFaceShouldBeHigh); + sortingContainers = E_Distance.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, _MapConfiguration, ticks, mapLogic, distanceLimits, faceDistanceEncodings, filteredFaceDistanceContainers); + if (!sortingContainers.Any()) + { + for (useFiltersCounter = 1; useFiltersCounter < _Configuration.UseFilterTries; useFiltersCounter++) + { + distanceLimits = new(_Configuration.FaceAreaPermyriad, _Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeDistanceTolerance, _Configuration.RangeFaceAreaTolerance, _Configuration.RangeFaceConfidence, _Configuration.SortingMaximumPerFaceShouldBeHigh, useFiltersCounter); + sortingContainers = E_Distance.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, _MapConfiguration, ticks, mapLogic, distanceLimits, faceDistanceEncodings, filteredFaceDistanceContainers); + if (sortingContainers.Any()) + break; + } + } + E_Distance.SaveFaceDistances(_Configuration.PropertyConfiguration, sortingContainers); + if (filteredFaceDistanceContainers.Length > 0) + { + int updated = mapLogic.UpdateFromSortingContainers(distanceLimits, sortingContainers); + List saveContainers = mapLogic.GetSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, mappingCollection, idToNormalizedRectangleToMapping, useFiltersCounter, sortingContainers.Any()); + mapLogic.SaveContainers(filteredFaceDistanceContainers.Length, updated, saveContainers); + } + } + + private void SaveFaceDistances(long ticks, MapLogic mapLogic, List distinctFilteredFaces, Mapping[] mappingCollection, string dFacesContentDirectory, string d2FacePartsContentDirectory, string dFacesCollectionDirectory, Dictionary> idToNormalizedRectangleToMapping) + { + if (_Log is null) + throw new NullReferenceException(nameof(_Log)); + E_Distance.SetFaceDistances(_AppSettings.MaxDegreeOfParallelism, ticks, distinctFilteredFaces); + FaceDistanceContainer[] faceDistanceContainers = E_Distance.GetFaceDistanceContainers(distinctFilteredFaces); + Dictionary> missingIdThenNormalizedRectangleToPersonContainers = mapLogic.GetMissing(idToNormalizedRectangleToMapping); + List missingFaceDistanceContainers = _Distance.GetMissingFaceDistanceContainer(_AppSettings.MaxDegreeOfParallelism, ticks, dFacesCollectionDirectory, missingIdThenNormalizedRectangleToPersonContainers); + List faceDistanceEncodings = E_Distance.GetFaceDistanceEncodings(faceDistanceContainers, missingFaceDistanceContainers); + FaceDistanceContainer[] filteredFaceDistanceContainers = E_Distance.FilteredFaceDistanceContainers(mapLogic, faceDistanceContainers); + int totalNotMappedAfterFiltered = filteredFaceDistanceContainers.Length; + if (totalNotMappedAfterFiltered == 0) + _Log.Information("All images have been filtered!"); + else + SaveFaceDistances(ticks, mapLogic, mappingCollection, dFacesContentDirectory, d2FacePartsContentDirectory, idToNormalizedRectangleToMapping, faceDistanceEncodings, filteredFaceDistanceContainers); + } + + private void MapLogic(string argZero, long ticks, Container[] containers, string a2PeopleSingletonDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, string fPhotoPrismContentDirectory, MapLogic mapLogic, string outputResolution, Dictionary> personKeyToIds, List distinctFilteredFaces, Mapping[] mappingCollection, int totalNotMapped) + { string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, "()"); string d2FacePartsContentDirectory = Path.Combine(d2ResultsFullGroupDirectory, "()"); string dFacesCollectionDirectory = Path.Combine(dResultsFullGroupDirectory, "[]", _Configuration.PropertyConfiguration.ResultAllInOne); @@ -716,31 +786,7 @@ public partial class DlibDotNet if (_Configuration.SaveMappedForOutputResolutions.Contains(outputResolution)) mapLogic.SaveMapped(dFacesContentDirectory, d2FacePartsContentDirectory, personKeyToIds, mappingCollection, idToNormalizedRectangleToMapping, totalNotMapped); if (_Configuration.SaveFaceDistancesForOutputResolutions.Contains(outputResolution)) - { - DistanceLimits distanceLimits; - E_Distance.SetFaceDistances(_AppSettings.MaxDegreeOfParallelism, ticks, distinctFilteredFaces); - Dictionary> missingIdThenNormalizedRectangleToPersonContainers = mapLogic.GetMissing(idToNormalizedRectangleToMapping); - List missingFaceDistanceContainers = _Distance.GetMissingFaceDistanceContainer(_AppSettings.MaxDegreeOfParallelism, ticks, dFacesCollectionDirectory, missingIdThenNormalizedRectangleToPersonContainers); - distanceLimits = new(_Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeDistanceTolerance, _Configuration.RangeFaceAreaPermilleTolerance, _Configuration.RangeFaceConfidence, _Configuration.SortingMaximumPerFaceShouldBeHigh); - sortingContainers = E_Distance.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, _MapConfiguration, ticks, mapLogic, distanceLimits, distinctFilteredFaces, missingFaceDistanceContainers); - if (!sortingContainers.Any()) - { - for (useFiltersCounter = 1; useFiltersCounter < _Configuration.UseFilterTries; useFiltersCounter++) - { - distanceLimits = new(_Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeDistanceTolerance, _Configuration.RangeFaceAreaPermilleTolerance, _Configuration.RangeFaceConfidence, _Configuration.SortingMaximumPerFaceShouldBeHigh, useFiltersCounter); - sortingContainers = E_Distance.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, _MapConfiguration, ticks, mapLogic, distanceLimits, distinctFilteredFaces, missingFaceDistanceContainers); - if (sortingContainers.Any()) - break; - } - } - E_Distance.SaveFaceDistances(_Configuration.PropertyConfiguration, sortingContainers); - if (totalNotMapped > 0) - { - int updated = mapLogic.UpdateFromSortingContainers(distanceLimits, sortingContainers); - List saveContainers = mapLogic.GetSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, mappingCollection, idToNormalizedRectangleToMapping, useFiltersCounter, sortingContainers.Any()); - mapLogic.SaveContainers(totalNotMapped, updated, saveContainers); - } - } + SaveFaceDistances(ticks, mapLogic, distinctFilteredFaces, mappingCollection, dFacesContentDirectory, d2FacePartsContentDirectory, dFacesCollectionDirectory, idToNormalizedRectangleToMapping); } private static Container? AreAllSameEndsWith(string argZero, Container[] containers) @@ -1052,7 +1098,7 @@ public partial class DlibDotNet FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, t, containers, propertyLogic, metadata, eDistanceContentDirectory, fileNameToCollection, idToLocationContainers); _Distance.Clear(); mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, ticks, _PersonContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory); - SetMapping(fileNameToCollection, argZero, containers); + SetMapping(argZero, containers, fileNameToCollection, idToLocationContainers); if (!personKeyToIds.Any()) personKeyToIds = mapLogic.GetPersonKeyToIds(); (List distinctFilteredIds, List distinctFilteredFaces) = GetFilteredDistinct(argZero, containers); diff --git a/Instance/Models/Binder/Configuration.cs b/Instance/Models/Binder/Configuration.cs index c98eafd..68bcce9 100644 --- a/Instance/Models/Binder/Configuration.cs +++ b/Instance/Models/Binder/Configuration.cs @@ -18,10 +18,12 @@ public class Configuration [Display(Name = "Distance Move Unable to Match by 1 Tick"), Required] public bool? DistanceMoveUnableToMatch { get; set; } [Display(Name = "Distance Pixel Distance Tolerance"), Required] public int? DistancePixelDistanceTolerance { get; set; } [Display(Name = "Distance Rename to Match"), Required] public bool? DistanceRenameToMatch { get; set; } - [Display(Name = "Face Area Permille"), Required] public int? FaceAreaPermille { get; set; } + [Display(Name = "Face Area Permille"), Required] public int? FaceAreaPermyriad { get; set; } [Display(Name = "Face Distance Hidden Image Factor"), Required] public int? FaceDistanceHiddenImageFactor { get; set; } [Display(Name = "Face Confidence Percent"), Required] public int? FaceConfidencePercent { get; set; } [Display(Name = "Face Distance Permyriad"), Required] public int? FaceDistancePermyriad { get; set; } + [Display(Name = "Focus Directory"), Required] public string FocusDirectory { get; set; } + [Display(Name = "Focus Model"), Required] public string FocusModel { get; set; } [Display(Name = "Force Face Last Write Time to Creation Time"), Required] public bool? ForceFaceLastWriteTimeToCreationTime { get; set; } [Display(Name = "Force Metadata Last Write Time to Creation Time"), Required] public bool? ForceMetadataLastWriteTimeToCreationTime { get; set; } [Display(Name = "Force Resize Last Write Time to Creation Time"), Required] public bool? ForceResizeLastWriteTimeToCreationTime { get; set; } @@ -59,9 +61,9 @@ public class Configuration [Display(Name = "Properties Changed For Resize"), Required] public bool? PropertiesChangedForResize { get; set; } [Display(Name = "Property Configuration"), Required] public Property.Models.Configuration PropertyConfiguration { get; set; } [Display(Name = "Sorting Days Delta Tolerance"), Required] public int[] RangeDaysDeltaTolerance { get; set; } - [Display(Name = "Face Distance Tolerance"), Required] public double[] RangeDistanceTolerance { get; set; } - [Display(Name = "Face Area Permille Tolerance"), Required] public int[] RangeFaceAreaPermilleTolerance { get; set; } - [Display(Name = "Location Minimum Confidence"), Required] public double[] RangeFaceConfidence { get; set; } + [Display(Name = "Face Distance Tolerance"), Required] public float[] RangeDistanceTolerance { get; set; } + [Display(Name = "Face Area Permille Tolerance"), Required] public float[] RangeFaceAreaTolerance { get; set; } + [Display(Name = "Location Minimum Confidence"), Required] public float[] RangeFaceConfidence { get; set; } [Display(Name = "Reverse"), Required] public bool? Reverse { get; set; } [Display(Name = "Save Face Distances"), Required] public string[] SaveFaceDistancesForOutputResolutions { get; set; } [Display(Name = "Save Face Landmark For Output Resolutions"), Required] public string[] SaveFaceLandmarkForOutputResolutions { get; set; } @@ -110,14 +112,18 @@ public class Configuration throw new NullReferenceException(nameof(configuration.DistancePixelDistanceTolerance)); if (configuration.DistanceRenameToMatch is null) throw new NullReferenceException(nameof(configuration.DistanceRenameToMatch)); - if (configuration.FaceAreaPermille is null) - throw new NullReferenceException(nameof(configuration.FaceAreaPermille)); + if (configuration.FaceAreaPermyriad is null) + throw new NullReferenceException(nameof(configuration.FaceAreaPermyriad)); if (configuration.FaceDistanceHiddenImageFactor is null) throw new NullReferenceException(nameof(configuration.FaceDistanceHiddenImageFactor)); if (configuration.FaceConfidencePercent is null) throw new NullReferenceException(nameof(configuration.FaceConfidencePercent)); if (configuration.FaceDistancePermyriad is null) throw new NullReferenceException(nameof(configuration.FaceDistancePermyriad)); + if (configuration.FocusDirectory is null) + throw new NullReferenceException(nameof(configuration.FocusDirectory)); + if (configuration.FocusModel is null) + throw new NullReferenceException(nameof(configuration.FocusModel)); if (configuration.ForceFaceLastWriteTimeToCreationTime is null) throw new NullReferenceException(nameof(configuration.ForceFaceLastWriteTimeToCreationTime)); if (configuration.ForceMetadataLastWriteTimeToCreationTime is null) @@ -178,8 +184,8 @@ public class Configuration throw new NullReferenceException(nameof(configuration.PropertiesChangedForResize)); if (configuration.RangeDaysDeltaTolerance is null || configuration.RangeDaysDeltaTolerance.Length != 3) throw new NullReferenceException(nameof(configuration.RangeDaysDeltaTolerance)); - if (configuration.RangeFaceAreaPermilleTolerance is null || configuration.RangeFaceAreaPermilleTolerance.Length != 3) - throw new NullReferenceException(nameof(configuration.RangeFaceAreaPermilleTolerance)); + if (configuration.RangeFaceAreaTolerance is null || configuration.RangeFaceAreaTolerance.Length != 3) + throw new NullReferenceException(nameof(configuration.RangeFaceAreaTolerance)); if (configuration.RangeFaceConfidence is null || configuration.RangeFaceConfidence.Length != 3) throw new NullReferenceException(nameof(configuration.RangeFaceConfidence)); if (configuration.RangeDistanceTolerance is null || configuration.RangeDistanceTolerance.Length != 3) @@ -224,10 +230,12 @@ public class Configuration configuration.DistanceMoveUnableToMatch.Value, configuration.DistancePixelDistanceTolerance.Value, configuration.DistanceRenameToMatch.Value, - configuration.FaceAreaPermille.Value, + configuration.FaceAreaPermyriad.Value, configuration.FaceConfidencePercent.Value, configuration.FaceDistanceHiddenImageFactor.Value, configuration.FaceDistancePermyriad.Value, + configuration.FocusDirectory, + configuration.FocusModel, configuration.ForceFaceLastWriteTimeToCreationTime.Value, configuration.ForceMetadataLastWriteTimeToCreationTime.Value, configuration.ForceResizeLastWriteTimeToCreationTime.Value, @@ -263,7 +271,7 @@ public class Configuration configuration.PropertiesChangedForResize.Value, configuration.RangeDaysDeltaTolerance, configuration.RangeDistanceTolerance, - configuration.RangeFaceAreaPermilleTolerance, + configuration.RangeFaceAreaTolerance, configuration.RangeFaceConfidence, configuration.Reverse.Value, configuration.SaveFaceDistancesForOutputResolutions, diff --git a/Instance/Models/Configuration.cs b/Instance/Models/Configuration.cs index ee64ef6..468e4b6 100644 --- a/Instance/Models/Configuration.cs +++ b/Instance/Models/Configuration.cs @@ -17,10 +17,12 @@ public class Configuration public bool DistanceMoveUnableToMatch { init; get; } public int DistancePixelDistanceTolerance { init; get; } public bool DistanceRenameToMatch { init; get; } - public int FaceAreaPermille { init; get; } + public int FaceAreaPermyriad { init; get; } public int FaceDistanceHiddenImageFactor { init; get; } public int FaceConfidencePercent { init; get; } public int FaceDistancePermyriad { init; get; } + public string FocusDirectory { init; get; } + public string FocusModel { init; get; } public bool ForceFaceLastWriteTimeToCreationTime { init; get; } public bool ForceMetadataLastWriteTimeToCreationTime { init; get; } public bool ForceResizeLastWriteTimeToCreationTime { init; get; } @@ -55,9 +57,9 @@ public class Configuration public bool PropertiesChangedForMetadata { init; get; } public bool PropertiesChangedForResize { init; get; } public int[] RangeDaysDeltaTolerance { init; get; } - public double[] RangeDistanceTolerance { init; get; } - public int[] RangeFaceAreaPermilleTolerance { init; get; } - public double[] RangeFaceConfidence { init; get; } + public float[] RangeDistanceTolerance { init; get; } + public float[] RangeFaceAreaTolerance { init; get; } + public float[] RangeFaceConfidence { init; get; } public bool Reverse { init; get; } public string[] SaveFaceDistancesForOutputResolutions { init; get; } public string[] SaveFaceLandmarkForOutputResolutions { init; get; } @@ -87,10 +89,12 @@ public class Configuration bool distanceMoveUnableToMatch, int distancePixelDistanceTolerance, bool distanceRenameToMatch, - int faceAreaPermille, + int faceAreaPermyriad, int faceConfidencePercent, int faceDistanceHiddenImageFactor, int faceDistancePermyriad, + string focusDirectory, + string focusModel, bool forceFaceLastWriteTimeToCreationTime, bool forceMetadataLastWriteTimeToCreationTime, bool forceResizeLastWriteTimeToCreationTime, @@ -125,9 +129,9 @@ public class Configuration bool propertiesChangedForMetadata, bool propertiesChangedForResize, int[] rangeDaysDeltaTolerance, - double[] rangeDistanceTolerance, - int[] rangeFaceAreaPermilleTolerance, - double[] rangeFaceConfidence, + float[] rangeDistanceTolerance, + float[] rangeFaceAreaPermyriadTolerance, + float[] rangeFaceConfidence, bool reverse, string[] saveFaceDistancesForOutputResolutions, string[] saveFaceLandmarkForOutputResolutions, @@ -156,10 +160,12 @@ public class Configuration DistanceMoveUnableToMatch = distanceMoveUnableToMatch; DistancePixelDistanceTolerance = distancePixelDistanceTolerance; DistanceRenameToMatch = distanceRenameToMatch; - FaceAreaPermille = faceAreaPermille; + FaceAreaPermyriad = faceAreaPermyriad; FaceDistanceHiddenImageFactor = faceDistanceHiddenImageFactor; FaceConfidencePercent = faceConfidencePercent; FaceDistancePermyriad = faceDistancePermyriad; + FocusDirectory = focusDirectory; + FocusModel = focusModel; ForceFaceLastWriteTimeToCreationTime = forceFaceLastWriteTimeToCreationTime; ForceMetadataLastWriteTimeToCreationTime = forceMetadataLastWriteTimeToCreationTime; ForceResizeLastWriteTimeToCreationTime = forceResizeLastWriteTimeToCreationTime; @@ -194,7 +200,7 @@ public class Configuration PropertiesChangedForMetadata = propertiesChangedForMetadata; PropertiesChangedForResize = propertiesChangedForResize; RangeDaysDeltaTolerance = rangeDaysDeltaTolerance; - RangeFaceAreaPermilleTolerance = rangeFaceAreaPermilleTolerance; + RangeFaceAreaTolerance = rangeFaceAreaPermyriadTolerance; RangeFaceConfidence = rangeFaceConfidence; RangeDistanceTolerance = rangeDistanceTolerance; Reverse = reverse; diff --git a/Instance/Models/_F_Random.cs b/Instance/Models/_F_Random.cs index 3303ea6..9351862 100644 --- a/Instance/Models/_F_Random.cs +++ b/Instance/Models/_F_Random.cs @@ -77,7 +77,7 @@ internal class F_Random { if (mapping.MappingFromItem.ImageFileHolder.DirectoryName is null) continue; - if (mapping.MappingFromItem.IsIgnoreRelativePath) + if (mapping.MappingFromFilter.IsIgnoreRelativePath is not null && mapping.MappingFromFilter.IsIgnoreRelativePath.Value) continue; relativePaths.Add(mapping.MappingFromItem.RelativePath); } diff --git a/Instance/appsettings.Development.json b/Instance/appsettings.Development.json index 6f680b2..0abb5a1 100644 --- a/Instance/appsettings.Development.json +++ b/Instance/appsettings.Development.json @@ -16,6 +16,10 @@ "DistanceMoveUnableToMatch": true, "xFaceDistanceHiddenImageFactor": 2, "FaceDistanceHiddenImageFactor": 3, + "FocusDirectory": "", + "xFocusDirectory": "/Hawaii 2022", + "FocusModel": "", + "xxFocusModel": "NIKON D3400", "PersonCharactersCopyCount": 0, "xPersonCharactersCopyCount": 2, "xRootDirectory": "D:/Tmp/phares/Pictures", @@ -39,22 +43,22 @@ "PropertyContentCollectionFiles": [], "RangeDaysDeltaTolerance": [ 0, - 4000, + 7000, 7300 ], "RangeDistanceTolerance": [ 0, - 0.4, - 1.2 + 0.65, + 1.8 ], - "RangeFaceAreaPermilleTolerance": [ + "RangeFaceAreaTolerance": [ 0, - 1, - 1000 + 0.0001, + 1 ], "RangeFaceConfidence": [ 0, - 0.2, + 0.8, 1.6 ], "SaveFaceDistancesForOutputResolutions": [ diff --git a/Instance/appsettings.json b/Instance/appsettings.json index b1e64e5..b97fa6a 100644 --- a/Instance/appsettings.json +++ b/Instance/appsettings.json @@ -59,7 +59,7 @@ "DistanceMoveUnableToMatch": false, "DistancePixelDistanceTolerance": 1, "DistanceRenameToMatch": false, - "FaceAreaPermille": 1000, + "FaceAreaPermyriad": 10000, "FaceDistanceHiddenImageFactor": 2, "FaceConfidencePercent": 100, "FaceDistancePermyriad": 10000, @@ -68,6 +68,8 @@ "ForceMetadataLastWriteTimeToCreationTime": false, "ForcePropertyLastWriteTimeToCreationTime": false, "ForceResizeLastWriteTimeToCreationTime": false, + "FocusDirectory": "", + "FocusModel": "", "LocationDigits": 9, "LocationFactor": 10000, "MappingDefaultName": "John Doe~25", @@ -138,10 +140,10 @@ 0.4, 0.6 ], - "RangeFaceAreaPermilleTolerance": [ + "RangeFaceAreaTolerance": [ 0, - 10, - 1000 + 0.001, + 1 ], "RangeFaceConfidence": [ 0, diff --git a/Map/Models/Configuration.cs b/Map/Models/Configuration.cs index 2eb06fd..f79a838 100644 --- a/Map/Models/Configuration.cs +++ b/Map/Models/Configuration.cs @@ -32,7 +32,7 @@ public class Configuration char[] personCharacters, int personCharactersCopyCount, int[] rangeDaysDeltaTolerance, - double[] rangeDistanceTolerance, + float[] rangeDistanceTolerance, bool saveSortingWithoutPerson, string[] skipNotSkipDirectories, int sortingMaximumPerKey, diff --git a/Map/Models/MapLogic.cs b/Map/Models/MapLogic.cs index d60f87b..6f3eb9b 100644 --- a/Map/Models/MapLogic.cs +++ b/Map/Models/MapLogic.cs @@ -1123,7 +1123,8 @@ public class MapLogic : Shared.Models.Methods.IMapLogic directoryName = Path.GetFileName(mapping.MappingFromItem.ImageFileHolder.DirectoryName); if (!string.IsNullOrEmpty(model) && !string.IsNullOrEmpty(model.Trim())) { - model = Regex.Replace(model, @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]", "_"); + // Remove-Item -LiteralPath "\\?\D:\Tmp\a\EX-Z70 " + model = Regex.Replace(model.Trim(), @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]", "_"); directory = Path.Combine($"{eDistanceContentDirectory}---", "Model Shortcuts", model, directoryName); fileName = Path.Combine(directory, $"{mapping.MappingFromItem.ImageFileHolder.Name}.lnk"); results.Add(new(mapping.MappingFromItem.ImageFileHolder.FullName, directory, mapping.MappingFromItem.MinimumDateTime, fileName, mapping.MappingFromLocation.DeterministicHashCodeKey, MakeAllHidden: false)); diff --git a/Shared/Models/Mapping.cs b/Shared/Models/Mapping.cs index eebabf4..42400cb 100644 --- a/Shared/Models/Mapping.cs +++ b/Shared/Models/Mapping.cs @@ -10,18 +10,16 @@ public class MappingFromItem : Properties.IMappingFromItem public int Id { init; get; } public FileHolder ImageFileHolder { init; get; } public bool? IsWrongYear { init; get; } - public bool IsIgnoreRelativePath { init; get; } public DateTime MinimumDateTime { init; get; } public string RelativePath { init; get; } public FileHolder ResizedFileHolder { init; get; } [JsonConstructor] - public MappingFromItem(DateTime[] containerDateTimes, int id, FileHolder imageFileHolder, bool isIgnoreRelativePath, bool? isWrongYear, DateTime minimumDateTime, string relativePath, FileHolder resizedFileHolder) + public MappingFromItem(DateTime[] containerDateTimes, int id, FileHolder imageFileHolder, bool? isWrongYear, DateTime minimumDateTime, string relativePath, FileHolder resizedFileHolder) { ContainerDateTimes = containerDateTimes; Id = id; ImageFileHolder = imageFileHolder; - IsIgnoreRelativePath = isIgnoreRelativePath; IsWrongYear = isWrongYear; MinimumDateTime = minimumDateTime; RelativePath = relativePath; @@ -34,7 +32,7 @@ public class MappingFromItem : Properties.IMappingFromItem return result; } - internal static MappingFromItem GetMappingFromItem(DateTime[] containerDateTimes, Item item, FileHolder? resizedFileHolder, bool isIgnoreRelativePath) + internal static MappingFromItem GetMappingFromItem(DateTime[] containerDateTimes, Item item, FileHolder? resizedFileHolder) { MappingFromItem result; bool? isWrongYear; @@ -45,7 +43,7 @@ public class MappingFromItem : Properties.IMappingFromItem throw new NotSupportedException(); minimumDateTime = Stateless.Methods.IProperty.GetMinimumDateTime(item.Property); (isWrongYear, _) = item.Property.IsWrongYear(item.ImageFileHolder, minimumDateTime); - result = new(containerDateTimes, item.Property.Id.Value, item.ImageFileHolder, isIgnoreRelativePath, isWrongYear, minimumDateTime, item.RelativePath, resizedFileHolder); + result = new(containerDateTimes, item.Property.Id.Value, item.ImageFileHolder, isWrongYear, minimumDateTime, item.RelativePath, resizedFileHolder); return result; } @@ -54,15 +52,15 @@ public class MappingFromItem : Properties.IMappingFromItem public class MappingFromLocation : Properties.IMappingFromLocation { - public int AreaPermille { init; get; } + public int AreaPermyriad { init; get; } public int ConfidencePercent { init; get; } public string DeterministicHashCodeKey { init; get; } public int NormalizedRectangle { init; get; } [JsonConstructor] - public MappingFromLocation(int areaPermille, int confidencePercent, string deterministicHashCodeKey, int normalizedRectangle) + public MappingFromLocation(int areaPermyriad, int confidencePercent, string deterministicHashCodeKey, int normalizedRectangle) { - AreaPermille = areaPermille; + AreaPermyriad = areaPermyriad; ConfidencePercent = confidencePercent; DeterministicHashCodeKey = deterministicHashCodeKey; NormalizedRectangle = normalizedRectangle; @@ -76,6 +74,29 @@ public class MappingFromLocation : Properties.IMappingFromLocation } +public class MappingFromFilter : Properties.IMappingFromFilter +{ + + public bool? IsFocusModel { init; get; } + public bool? IsFocusRelativePath { init; get; } + public bool? IsIgnoreRelativePath { init; get; } + + [JsonConstructor] + public MappingFromFilter(bool? isFocusModel, bool? isFocusRelativePath, bool? isIgnoreRelativePath) + { + IsFocusModel = isFocusModel; + IsFocusRelativePath = isFocusRelativePath; + IsIgnoreRelativePath = isIgnoreRelativePath; + } + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + +} + public class MappingFromPhotoPrism : Properties.IMappingFromPhotoPrism { @@ -125,6 +146,7 @@ public class Mapping : Properties.IMapping protected SortingContainer? _SortingContainer; public int? By => _By; public MappingFromItem MappingFromItem { init; get; } + public MappingFromFilter MappingFromFilter { init; get; } public MappingFromLocation? MappingFromLocation { init; get; } public List? MappingFromPhotoPrismCollection { init; get; } public MappingFromPerson? MappingFromPerson => _MappingFromPerson; @@ -132,19 +154,20 @@ public class Mapping : Properties.IMapping public SortingContainer? SortingContainer => _SortingContainer; [JsonConstructor] - public Mapping(int? by, MappingFromItem mappingFromItem, MappingFromLocation? mappingFromLocation, List? mappingFromPhotoPrismCollection, MappingFromPerson? mappingFromPerson, string? segmentC, SortingContainer? sortingContainer) + public Mapping(int? by, MappingFromItem mappingFromItem, MappingFromFilter mappingFromFilter, MappingFromLocation? mappingFromLocation, List? mappingFromPhotoPrismCollection, MappingFromPerson? mappingFromPerson, string? segmentC, SortingContainer? sortingContainer) { _By = by; _SegmentC = segmentC; MappingFromItem = mappingFromItem; + MappingFromFilter = mappingFromFilter; MappingFromLocation = mappingFromLocation; MappingFromPhotoPrismCollection = mappingFromPhotoPrismCollection; _MappingFromPerson = mappingFromPerson; _SortingContainer = sortingContainer; } - public Mapping(MappingFromItem mappingFromItem, MappingFromLocation? mappingFromLocation, List? mappingFromPhotoPrismCollection) : - this(null, mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection, null, null, null) + public Mapping(MappingFromItem mappingFromItem, MappingFromFilter mappingFromFilter, MappingFromLocation? mappingFromLocation, List? mappingFromPhotoPrismCollection) : + this(null, mappingFromItem, mappingFromFilter, mappingFromLocation, mappingFromPhotoPrismCollection, null, null, null) { } public override string ToString() diff --git a/Shared/Models/Methods/IDistanceLimits.cs b/Shared/Models/Methods/IDistanceLimits.cs index ef9df9b..400cd85 100644 --- a/Shared/Models/Methods/IDistanceLimits.cs +++ b/Shared/Models/Methods/IDistanceLimits.cs @@ -3,7 +3,7 @@ namespace View_by_Distance.Shared.Models.Methods; public interface IDistanceLimits { - public double FaceAreaPermille { init; get; } + public double FaceAreaPermyriad { init; get; } public double RangeDaysDeltaTolerance { init; get; } public double FaceConfidencePercent { init; get; } public double FaceDistancePermyriad { init; get; } diff --git a/Shared/Models/Properties/IMapping.cs b/Shared/Models/Properties/IMapping.cs index f23df16..b6fd62f 100644 --- a/Shared/Models/Properties/IMapping.cs +++ b/Shared/Models/Properties/IMapping.cs @@ -6,7 +6,6 @@ public interface IMappingFromItem public DateTime[] ContainerDateTimes { init; get; } public int Id { init; get; } public FileHolder ImageFileHolder { init; get; } - public bool IsIgnoreRelativePath { init; get; } public bool? IsWrongYear { init; get; } public DateTime MinimumDateTime { init; get; } public string RelativePath { init; get; } @@ -14,10 +13,19 @@ public interface IMappingFromItem } +public interface IMappingFromFilter +{ + + public bool? IsFocusModel { init; get; } + public bool? IsFocusRelativePath { init; get; } + public bool? IsIgnoreRelativePath { init; get; } + +} + public interface IMappingFromLocation { - public int AreaPermille { init; get; } + public int AreaPermyriad { init; get; } public int ConfidencePercent { init; get; } public string DeterministicHashCodeKey { init; get; } public int NormalizedRectangle { init; get; } diff --git a/Shared/Models/Stateless/Methods/ILocation.cs b/Shared/Models/Stateless/Methods/ILocation.cs index 4ec0bc8..95a1bec 100644 --- a/Shared/Models/Stateless/Methods/ILocation.cs +++ b/Shared/Models/Stateless/Methods/ILocation.cs @@ -50,9 +50,9 @@ public interface ILocation static string GetLeftPadded(int locationDigits, string value) => Location.GetLeftPadded(locationDigits, value); - int TestStatic_GetConfidencePercent(int faceConfidencePercent, double[] rangeFaceConfidence, double confidence) => + int TestStatic_GetConfidencePercent(int faceConfidencePercent, float[] rangeFaceConfidence, double confidence) => GetConfidencePercent(faceConfidencePercent, rangeFaceConfidence, confidence); - static int GetConfidencePercent(int faceConfidencePercent, double[] rangeFaceConfidence, double confidence) => + static int GetConfidencePercent(int faceConfidencePercent, float[] rangeFaceConfidence, double confidence) => Location.GetConfidencePercent(faceConfidencePercent, rangeFaceConfidence, confidence); string TestStatic_GetLeftPadded(int locationDigits, int value) => diff --git a/Shared/Models/Stateless/Methods/IMapping.cs b/Shared/Models/Stateless/Methods/IMapping.cs index c05463f..8f92099 100644 --- a/Shared/Models/Stateless/Methods/IMapping.cs +++ b/Shared/Models/Stateless/Methods/IMapping.cs @@ -8,20 +8,20 @@ public interface IMapping static (string?, string?, string?, bool?) GetSegments(string facesFileNameExtension, string fileName) => Mapping.GetSegments(facesFileNameExtension, fileName); - int TestStatic_GetAreaPermille(int faceAreaPermille, int height, Models.Location location, int width) - => GetAreaPermille(faceAreaPermille, height, location, width); - static int GetAreaPermille(int faceAreaPermille, int height, Models.Location location, int width) - => Mapping.GetAreaPermille(faceAreaPermille, location.Bottom, height, location.Left, location.Right, location.Top, width); + int TestStatic_GetAreaPermyriad(int faceAreaPermyriad, int height, Models.Location location, int width) + => GetAreaPermyriad(faceAreaPermyriad, height, location, width); + static int GetAreaPermyriad(int faceAreaPermyriad, int height, Models.Location location, int width) + => Mapping.GetAreaPermyriad(faceAreaPermyriad, location.Bottom, height, location.Left, location.Right, location.Top, width); - int TestStatic_GetAreaPermille(int faceAreaPermille, int bottom, int height, int left, int right, int top, int width) - => GetAreaPermille(faceAreaPermille, bottom, height, left, right, top, width); - static int GetAreaPermille(int faceAreaPermille, int bottom, int height, int left, int right, int top, int width) - => Mapping.GetAreaPermille(faceAreaPermille, bottom, height, left, right, top, width); + int TestStatic_GetAreaPermyriad(int faceAreaPermyriad, int bottom, int height, int left, int right, int top, int width) + => GetAreaPermyriad(faceAreaPermyriad, bottom, height, left, right, top, width); + static int GetAreaPermyriad(int faceAreaPermyriad, int bottom, int height, int left, int right, int top, int width) + => Mapping.GetAreaPermyriad(faceAreaPermyriad, bottom, height, left, right, top, width); - int TestStatic_GetAreaPermille(int faceAreaPermille, Models.Location location, Models.OutputResolution outputResolution) - => GetAreaPermille(faceAreaPermille, location, outputResolution); - static int GetAreaPermille(int faceAreaPermille, Models.Location location, Models.OutputResolution outputResolution) - => Mapping.GetAreaPermille(faceAreaPermille, location.Bottom, outputResolution.Height, location.Left, location.Right, location.Top, outputResolution.Width); + int TestStatic_GetAreaPermyriad(int faceAreaPermyriad, Models.Location location, Models.OutputResolution outputResolution) + => GetAreaPermyriad(faceAreaPermyriad, location, outputResolution); + static int GetAreaPermyriad(int faceAreaPermyriad, Models.Location location, Models.OutputResolution outputResolution) + => Mapping.GetAreaPermyriad(faceAreaPermyriad, location.Bottom, outputResolution.Height, location.Left, location.Right, location.Top, outputResolution.Width); string TestStatic_GetDeterministicHashCodeKey(int id, Models.Location location, int locationDigits, Models.OutputResolution outputResolution) => GetDeterministicHashCodeKey(id, location, locationDigits, outputResolution); diff --git a/Shared/Models/Stateless/Methods/IMappingFromItem.cs b/Shared/Models/Stateless/Methods/IMappingFromItem.cs index 4726e06..0ed6a86 100644 --- a/Shared/Models/Stateless/Methods/IMappingFromItem.cs +++ b/Shared/Models/Stateless/Methods/IMappingFromItem.cs @@ -3,19 +3,19 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; public interface IMappingFromItem { // ... - MappingFromItem TestStatic_GetMappingFromItem(DateTime[] containerDateTimes, Models.Item item, Models.FileHolder? resizedFileHolder, bool isIgnoreRelativePath) - => GetMappingFromItem(containerDateTimes, item, resizedFileHolder, isIgnoreRelativePath); - static MappingFromItem GetMappingFromItem(DateTime[] containerDateTimes, Models.Item item, Models.FileHolder? resizedFileHolder, bool isIgnoreRelativePath) - => MappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder, isIgnoreRelativePath); + MappingFromItem TestStatic_GetMappingFromItem(DateTime[] containerDateTimes, Models.Item item, Models.FileHolder? resizedFileHolder) + => GetMappingFromItem(containerDateTimes, item, resizedFileHolder); + static MappingFromItem GetMappingFromItem(DateTime[] containerDateTimes, Models.Item item, Models.FileHolder? resizedFileHolder) + => MappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder); - MappingFromItem TestStatic_GetMappingFromItem(DateTime[] containerDateTimes, Models.Item item, bool isIgnoreRelativePath) - => GetMappingFromItem(containerDateTimes, item, isIgnoreRelativePath); - static MappingFromItem GetMappingFromItem(DateTime[] containerDateTimes, Models.Item item, bool isIgnoreRelativePath) - => GetMappingFromItem(containerDateTimes, item, item.ResizedFileHolder, isIgnoreRelativePath); + 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, bool isIgnoreRelativePath) - => GetMappingFromItem(item, isIgnoreRelativePath); - static MappingFromItem GetMappingFromItem(Models.Item item, bool isIgnoreRelativePath) - => GetMappingFromItem(containerDateTimes: Array.Empty(), item, item.ResizedFileHolder, isIgnoreRelativePath); + MappingFromItem TestStatic_GetMappingFromItem(Models.Item item) + => GetMappingFromItem(item); + static MappingFromItem GetMappingFromItem(Models.Item item) + => GetMappingFromItem(containerDateTimes: Array.Empty(), item, item.ResizedFileHolder); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/Location.cs b/Shared/Models/Stateless/Methods/Location.cs index c715576..e264500 100644 --- a/Shared/Models/Stateless/Methods/Location.cs +++ b/Shared/Models/Stateless/Methods/Location.cs @@ -132,7 +132,7 @@ internal abstract class Location return new(x, y); } - internal static int GetConfidencePercent(int faceConfidencePercent, double[] rangeFaceConfidence, double confidence) + internal static int GetConfidencePercent(int faceConfidencePercent, float[] rangeFaceConfidence, double confidence) { int result = (int)(confidence / rangeFaceConfidence[1] * faceConfidencePercent); return result; diff --git a/Shared/Models/Stateless/Methods/Mapping.cs b/Shared/Models/Stateless/Methods/Mapping.cs index a5807bc..82ea00e 100644 --- a/Shared/Models/Stateless/Methods/Mapping.cs +++ b/Shared/Models/Stateless/Methods/Mapping.cs @@ -65,12 +65,12 @@ internal abstract class Mapping return new(id, normalizedRectangle); } - internal static int GetAreaPermille(int faceAreaPermille, int bottom, int height, int left, int right, int top, int width) + internal static int GetAreaPermyriad(int faceAreaPermyriad, int bottom, int height, int left, int right, int top, int width) { int result; double area = width * height; double locationArea = (right - left) * (bottom - top); - result = (int)Math.Round(locationArea / area * faceAreaPermille, 0); + result = (int)Math.Round(locationArea / area * faceAreaPermyriad, 0); return result; } diff --git a/Tests/UnitTestCalculations.cs b/Tests/UnitTestCalculations.cs index 6d781b1..a1040b2 100644 --- a/Tests/UnitTestCalculations.cs +++ b/Tests/UnitTestCalculations.cs @@ -232,20 +232,20 @@ public partial class UnitTestCalculations } [TestMethod] - public void TestAreaPermille() + public void TestAreaPermyriad() { - int faceAreaPermille = 1000; + int faceAreaPermyriad = 10000; Location location; double confidence = 0.1D; - int areaPermille, left, top, right, bottom, width, height; + int areaPermyriad, left, top, right, bottom, width, height; left = 0; right = 100; top = 0; bottom = 100; width = 100; height = 100; - areaPermille = IMapping.GetAreaPermille(faceAreaPermille, bottom, height, left, right, top, width); - Assert.IsTrue(areaPermille == 1000); + areaPermyriad = IMapping.GetAreaPermyriad(faceAreaPermyriad, bottom, height, left, right, top, width); + Assert.IsTrue(areaPermyriad == 1000); left = 0; right = 50; top = 0; @@ -253,8 +253,8 @@ public partial class UnitTestCalculations width = 100; height = 100; location = new(bottom, confidence, height, left, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, right, top, width, 1); - areaPermille = IMapping.GetAreaPermille(faceAreaPermille, height, location, width); - Assert.IsTrue(areaPermille == 250); + areaPermyriad = IMapping.GetAreaPermyriad(faceAreaPermyriad, height, location, width); + Assert.IsTrue(areaPermyriad == 250); left = 0; right = 25; top = 0; @@ -263,8 +263,8 @@ public partial class UnitTestCalculations height = 100; location = new(bottom, confidence, height, left, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, right, top, width, 1); OutputResolution outputResolution = new(height, 0, width); - areaPermille = IMapping.GetAreaPermille(faceAreaPermille, location, outputResolution); - Assert.IsTrue(areaPermille == 62); + areaPermyriad = IMapping.GetAreaPermyriad(faceAreaPermyriad, location, outputResolution); + Assert.IsTrue(areaPermyriad == 62); } [TestMethod] @@ -371,24 +371,24 @@ public partial class UnitTestCalculations public void TestGetConfidencePercent() { int faceConfidencePercent = 100; - double minimum, target, maximum, value, check; + float minimum, target, maximum, value, check; minimum = 0.8f; target = 0.8f; maximum = int.MaxValue; value = 0f; - check = ILocation.GetConfidencePercent(faceConfidencePercent, new double[] { minimum, target, maximum }, value); + check = ILocation.GetConfidencePercent(faceConfidencePercent, new float[] { minimum, target, maximum }, value); Assert.IsTrue(check == 0); target = 0.8f; value = 0.4f; - check = ILocation.GetConfidencePercent(faceConfidencePercent, new double[] { minimum, target, maximum }, value); + check = ILocation.GetConfidencePercent(faceConfidencePercent, new float[] { minimum, target, maximum }, value); Assert.IsTrue(check == 50); target = 0.8f; value = 0.8f; - check = ILocation.GetConfidencePercent(faceConfidencePercent, new double[] { minimum, target, maximum }, value); + check = ILocation.GetConfidencePercent(faceConfidencePercent, new float[] { minimum, target, maximum }, value); Assert.IsTrue(check == 100); target = 0.8f; value = 1.6f; - check = ILocation.GetConfidencePercent(faceConfidencePercent, new double[] { minimum, target, maximum }, value); + check = ILocation.GetConfidencePercent(faceConfidencePercent, new float[] { minimum, target, maximum }, value); Assert.IsTrue(check == 200); } diff --git a/Tests/UnitTestResize.cs b/Tests/UnitTestResize.cs index 6277c04..458b0df 100644 --- a/Tests/UnitTestResize.cs +++ b/Tests/UnitTestResize.cs @@ -137,7 +137,6 @@ public class UnitTestResize bool reverse = false; FileHolder resizedFileHolder; List parseExceptions = new(); - const bool isIgnoreRelativePath = false; Shared.Models.Property? property = null; const bool isValidImageFormatExtension = true; Dictionary outputResolutionToResize; @@ -176,7 +175,7 @@ public class UnitTestResize throw new NullReferenceException(nameof(property)); resizedFileHolder = resize.GetResizedFileHolder(item); item.SetResizedFileHolder(resize.FileNameExtension, resizedFileHolder); - MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(item, isIgnoreRelativePath); + MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(item); (int _, metadataCollection) = metadata.GetMetadataCollection(subFileTuples, parseExceptions, mappingFromItem); outputResolutionToResize = resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, subFileTuples, parseExceptions, metadataCollection, item.Property, mappingFromItem); Assert.IsNotNull(mappingFromItem.ResizedFileHolder); diff --git a/TestsWithFaceRecognitionDotNet/Models/Binder/Configuration.cs b/TestsWithFaceRecognitionDotNet/Models/Binder/Configuration.cs index 6f299c4..6f40eae 100644 --- a/TestsWithFaceRecognitionDotNet/Models/Binder/Configuration.cs +++ b/TestsWithFaceRecognitionDotNet/Models/Binder/Configuration.cs @@ -55,9 +55,9 @@ public class Configuration [Display(Name = "Properties Changed For Resize"), Required] public bool? PropertiesChangedForResize { get; set; } [Display(Name = "Property Configuration"), Required] public Property.Models.Configuration PropertyConfiguration { get; set; } [Display(Name = "Sorting Days Delta Tolerance"), Required] public int[] RangeDaysDeltaTolerance { get; set; } - [Display(Name = "Face Area Permille Tolerance"), Required] public int[] RangeFaceAreaPermilleTolerance { get; set; } - [Display(Name = "Location Minimum Confidence"), Required] public double[] RangeFaceConfidence { get; set; } - [Display(Name = "Face Distance Tolerance"), Required] public double[] RangeDistanceTolerance { get; set; } + [Display(Name = "Face Area Permille Tolerance"), Required] public float[] RangeFaceAreaTolerance { get; set; } + [Display(Name = "Location Minimum Confidence"), Required] public float[] RangeFaceConfidence { get; set; } + [Display(Name = "Face Distance Tolerance"), Required] public float[] RangeDistanceTolerance { get; set; } [Display(Name = "Reverse"), Required] public bool? Reverse { get; set; } [Display(Name = "Save Face Landmark For Output Resolutions"), Required] public string[] SaveFaceLandmarkForOutputResolutions { get; set; } [Display(Name = "Save Full Year Of Random Files"), Required] public bool? SaveFullYearOfRandomFiles { get; set; } @@ -160,8 +160,8 @@ public class Configuration throw new NullReferenceException(nameof(configuration.PropertiesChangedForResize)); if (configuration.RangeDaysDeltaTolerance is null || configuration.RangeDaysDeltaTolerance.Length != 3) throw new NullReferenceException(nameof(configuration.RangeDaysDeltaTolerance)); - if (configuration.RangeFaceAreaPermilleTolerance is null || configuration.RangeFaceAreaPermilleTolerance.Length != 3) - throw new NullReferenceException(nameof(configuration.RangeFaceAreaPermilleTolerance)); + if (configuration.RangeFaceAreaTolerance is null || configuration.RangeFaceAreaTolerance.Length != 3) + throw new NullReferenceException(nameof(configuration.RangeFaceAreaTolerance)); if (configuration.RangeFaceConfidence is null || configuration.RangeFaceConfidence.Length != 3) throw new NullReferenceException(nameof(configuration.RangeFaceConfidence)); if (configuration.RangeDistanceTolerance is null || configuration.RangeDistanceTolerance.Length != 3) @@ -233,7 +233,7 @@ public class Configuration configuration.PropertiesChangedForMetadata.Value, configuration.PropertiesChangedForResize.Value, configuration.RangeDaysDeltaTolerance, - configuration.RangeFaceAreaPermilleTolerance, + configuration.RangeFaceAreaTolerance, configuration.RangeFaceConfidence, configuration.RangeDistanceTolerance, configuration.Reverse.Value, diff --git a/TestsWithFaceRecognitionDotNet/Models/Configuration.cs b/TestsWithFaceRecognitionDotNet/Models/Configuration.cs index 8df9a94..9f76d45 100644 --- a/TestsWithFaceRecognitionDotNet/Models/Configuration.cs +++ b/TestsWithFaceRecognitionDotNet/Models/Configuration.cs @@ -53,9 +53,9 @@ public class Configuration public bool PropertiesChangedForMetadata { init; get; } public bool PropertiesChangedForResize { init; get; } public int[] RangeDaysDeltaTolerance { init; get; } - public int[] RangeFaceAreaPermilleTolerance { init; get; } - public double[] RangeFaceConfidence { init; get; } - public double[] RangeDistanceTolerance { init; get; } + public float[] RangeFaceAreaTolerance { init; get; } + public float[] RangeFaceConfidence { init; get; } + public float[] RangeDistanceTolerance { init; get; } public bool Reverse { init; get; } public string[] SaveFaceLandmarkForOutputResolutions { init; get; } public bool SaveFullYearOfRandomFiles { init; get; } @@ -115,9 +115,9 @@ public class Configuration bool propertiesChangedForMetadata, bool propertiesChangedForResize, int[] rangeDaysDeltaTolerance, - int[] rangeFaceAreaPermilleTolerance, - double[] rangeFaceConfidence, - double[] rangeDistanceTolerance, + float[] rangeFaceAreaPermyriadTolerance, + float[] rangeFaceConfidence, + float[] rangeDistanceTolerance, bool reverse, string[] saveFaceLandmarkForOutputResolutions, bool saveFullYearOfRandomFiles, @@ -176,7 +176,7 @@ public class Configuration PropertiesChangedForMetadata = propertiesChangedForMetadata; PropertiesChangedForResize = propertiesChangedForResize; RangeDaysDeltaTolerance = rangeDaysDeltaTolerance; - RangeFaceAreaPermilleTolerance = rangeFaceAreaPermilleTolerance; + RangeFaceAreaTolerance = rangeFaceAreaPermyriadTolerance; RangeFaceConfidence = rangeFaceConfidence; RangeDistanceTolerance = rangeDistanceTolerance; Reverse = reverse; diff --git a/TestsWithFaceRecognitionDotNet/UnitTestFace.cs b/TestsWithFaceRecognitionDotNet/UnitTestFace.cs index a1f20a7..f51e49e 100644 --- a/TestsWithFaceRecognitionDotNet/UnitTestFace.cs +++ b/TestsWithFaceRecognitionDotNet/UnitTestFace.cs @@ -212,7 +212,6 @@ public class UnitTestFace bool reverse = false; FileHolder resizedFileHolder; List parseExceptions = new(); - const bool isIgnoreRelativePath = false; Shared.Models.Property? property = null; const bool isValidImageFormatExtension = true; Dictionary outputResolutionToResize; @@ -252,7 +251,7 @@ public class UnitTestFace throw new NullReferenceException(nameof(property)); resizedFileHolder = resize.GetResizedFileHolder(item); item.SetResizedFileHolder(resize.FileNameExtension, resizedFileHolder); - MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(item, isIgnoreRelativePath); + MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(item); (int _, metadataCollection) = metadata.GetMetadataCollection(subFileTuples, parseExceptions, mappingFromItem); outputResolutionToResize = resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, subFileTuples, parseExceptions, metadataCollection, item.Property, mappingFromItem); Assert.IsNotNull(mappingFromItem.ResizedFileHolder);