using Microsoft.Extensions.Configuration; using Phares.Shared; using ShellProgressBar; using System.Drawing.Imaging; using System.Text.Json; using View_by_Distance.FaceRecognitionDotNet; using View_by_Distance.Instance.Models; using View_by_Distance.Map.Models; using View_by_Distance.Metadata.Models; using View_by_Distance.Property.Models; using View_by_Distance.Resize.Models; using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models.Methods; using View_by_Distance.Shared.Models.Stateless; namespace View_by_Distance.Instance; public partial class DlibDotNet { private readonly D_Face _Faces; private readonly bool _FirstRun; private readonly G_Index _Index; private readonly C_Resize _Resize; private readonly F_Random _Random; private readonly A2_People _People; private readonly E3_Rename _Rename; private readonly B_Metadata _Metadata; private readonly Serilog.ILogger? _Log; private readonly D2_FaceParts _FaceParts; private readonly AppSettings _AppSettings; private readonly List _Exceptions; private readonly IsEnvironment _IsEnvironment; private readonly Models.Configuration _Configuration; private readonly bool _ArgZeroIsConfigurationRootDirectory; private readonly List> _FileKeyValuePairs; private readonly Dictionary>> _FilePropertiesKeyValuePairs; public DlibDotNet(List args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) { string argZero; Person[] people; _AppSettings = appSettings; _IsEnvironment = isEnvironment; _Exceptions = new List(); _Log = Serilog.Log.ForContext(); _FileKeyValuePairs = new List>(); _FilePropertiesKeyValuePairs = new Dictionary>>(); Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot); _Log.Information(propertyConfiguration.RootDirectory); Property.Models.Configuration.Verify(propertyConfiguration); Models.Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration); Verify(configuration); VerifyExtra(args, propertyConfiguration, configuration); _Configuration = configuration; _Index = new G_Index(configuration); _Random = new F_Random(configuration); _People = new A2_People(configuration); _Rename = new E3_Rename(configuration); if (configuration.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); string propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(propertyConfiguration, nameof(A_Property), create: false); _FirstRun = !Directory.Exists(propertyRoot); _Metadata = new(configuration.ForceMetadataLastWriteTimeToCreationTime, configuration.PropertiesChangedForMetadata); if (args.Count > 0) argZero = Path.GetFullPath(args[0]); else argZero = Path.GetFullPath(propertyConfiguration.RootDirectory); _ArgZeroIsConfigurationRootDirectory = propertyConfiguration.RootDirectory == argZero; _Log.Information(configuration.ModelDirectory); (Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(configuration); if (_FirstRun || !_ArgZeroIsConfigurationRootDirectory) people = Array.Empty(); else people = _People.GetPeople(propertyConfiguration); if (!isSilent && configuration.TestDistanceResults) { E2_Navigate e2Navigate = new(console, configuration, argZero); e2Navigate.Navigate(propertyConfiguration, model, predictorModel, configuration.OutputResolutions[0]); _Log.Information(propertyConfiguration.RootDirectory); } { (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetGifLowQuality(); _FaceParts = new D2_FaceParts(configuration, imageCodecInfo, encoderParameters, filenameExtension); } { (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetPngLowQuality(); (ImageCodecInfo hiddenImageCodecInfo, EncoderParameters hiddenEncoderParameters, string hiddenFilenameExtension) = C_Resize.GetGifLowQuality(); _Faces = new D_Face(configuration, argZero, model, modelParameter, predictorModel, imageCodecInfo, encoderParameters, filenameExtension, hiddenImageCodecInfo, hiddenEncoderParameters, hiddenFilenameExtension); } { (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetTuple(configuration.OutputExtension, configuration.OutputQuality); _Resize = new C_Resize(configuration.ForceResizeLastWriteTimeToCreationTime, configuration.OverrideForResizeImages, configuration.PropertiesChangedForResize, configuration.ValidResolutions, imageCodecInfo, encoderParameters, filenameExtension); } if (!configuration.SkipSearch) Search(model, predictorModel, argZero, propertyRoot, people); if (!_FirstRun && _Exceptions.Count == 0 && _ArgZeroIsConfigurationRootDirectory) { long ticks = DateTime.Now.Ticks; List directoryCollections = _Rename.GetDirectoryRenameCollections(propertyConfiguration, model, predictorModel, relativePath: string.Empty, newDirectoryName: string.Empty, jsonFiles4InfoAny: false); foreach (string[] directoryCollection in directoryCollections) { _Log.Information(string.Concat("Cleaning <", directoryCollection[0], ">")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(directoryCollection[0]); } string d2FacePartsRootDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(D2_FaceParts)); _Log.Information(string.Concat("Cleaning <", d2FacePartsRootDirectory, ">")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(d2FacePartsRootDirectory); if (appSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories)); } string message = $"There were {_Exceptions.Count} exception(s) thrown! {Environment.NewLine}{string.Join(Environment.NewLine, _Exceptions)}"; _Log.Information(message); if (_Exceptions.Count != 0) throw new Exception(message); if (_FirstRun) _Log.Information("First run completed. Run again if wanted"); } private long LogDelta(long ticks, string? methodName) { long result; if (_Log is null) throw new NullReferenceException(nameof(_Log)); double delta = new TimeSpan(DateTime.Now.Ticks - ticks).TotalMilliseconds; _Log.Debug($"{methodName} took {Math.Floor(delta)} millisecond(s)"); result = DateTime.Now.Ticks; return result; } private long LogDeltaInSeconds(long ticks, string methodName) { long result; if (_Log is null) throw new NullReferenceException(nameof(_Log)); double delta = new TimeSpan(DateTime.Now.Ticks - ticks).Seconds; _Log.Debug($"{methodName} took {Math.Floor(delta)} seconds(s)"); result = DateTime.Now.Ticks; return result; } private long LogDeltaInMinutes(long ticks, string methodName) { long result; if (_Log is null) throw new NullReferenceException(nameof(_Log)); double delta = new TimeSpan(DateTime.Now.Ticks - ticks).Minutes; _Log.Debug($"{methodName} took {Math.Floor(delta)} minutes(s)"); result = DateTime.Now.Ticks; return result; } #pragma warning disable CA1416 #pragma warning restore CA1416 private static (Model model, PredictorModel predictorModel, ModelParameter modelParameter) GetModel(Models.Configuration configuration) { (Model, PredictorModel, ModelParameter) result; Array array; Model? model = null; PredictorModel? predictorModel = null; array = Enum.GetValues(typeof(Model)); foreach (Model check in array) { if (configuration.ModelName.Contains(check.ToString())) { model = check; break; } } if (model is null) throw new Exception("Destination directory must have Model name!"); model = model.Value; array = Enum.GetValues(typeof(PredictorModel)); foreach (PredictorModel check in array) { if (configuration.PredictorModelName.Contains(check.ToString())) { predictorModel = check; break; } } if (predictorModel is null) throw new Exception("Destination directory must have Predictor Model name!"); predictorModel = predictorModel.Value; ModelParameter modelParameter = new() { CnnFaceDetectorModel = File.ReadAllBytes(Path.Combine(configuration.ModelDirectory, "mmod_human_face_detector.dat")), FaceRecognitionModel = File.ReadAllBytes(Path.Combine(configuration.ModelDirectory, "dlib_face_recognition_resnet_model_v1.dat")), PosePredictor5FaceLandmarksModel = File.ReadAllBytes(Path.Combine(configuration.ModelDirectory, "shape_predictor_5_face_landmarks.dat")), PosePredictor68FaceLandmarksModel = File.ReadAllBytes(Path.Combine(configuration.ModelDirectory, "shape_predictor_68_face_landmarks.dat")) }; result = new(model.Value, predictorModel.Value, modelParameter); return result; } private void Verify(Models.Configuration configuration) { if (!configuration.OutputResolutions.Any() || string.IsNullOrEmpty(configuration.OutputResolutions[0]) || !configuration.ValidResolutions.Contains(configuration.OutputResolutions[0])) throw new NullReferenceException($"{nameof(configuration.OutputResolutions)} must be a valid outputResolution!"); if ((from l in configuration.OutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any()) throw new Exception($"One or more {nameof(configuration.OutputResolutions)} are not in the ValidResolutions list!"); if ((from l in configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any()) throw new Exception($"One or more {nameof(configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions)} are not in the ValidResolutions list!"); if ((from l in configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any()) throw new Exception($"One or more {nameof(configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions)} are not in the ValidResolutions list!"); if ((from l in configuration.SaveShortcutsForOutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any()) throw new Exception($"One or more {nameof(configuration.SaveShortcutsForOutputResolutions)} are not in the ValidResolutions list!"); if ((from l in configuration.SaveFaceLandmarkForOutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any()) throw new Exception($"One or more {nameof(configuration.SaveFaceLandmarkForOutputResolutions)} are not in the ValidResolutions list!"); if (configuration.DistanceFactor + configuration.LocationConfidenceFactor != 10) throw new NullReferenceException(nameof(configuration.DistanceFactor)); if (string.IsNullOrEmpty(configuration.ModelName)) throw new NullReferenceException(nameof(configuration.ModelName)); if (string.IsNullOrEmpty(configuration.OutputExtension)) throw new NullReferenceException(nameof(configuration.OutputExtension)); if (string.IsNullOrEmpty(configuration.PredictorModelName)) throw new NullReferenceException(nameof(configuration.PredictorModelName)); if (string.IsNullOrEmpty(configuration.ModelDirectory) || !Directory.Exists(configuration.ModelDirectory)) throw new NullReferenceException(nameof(configuration.ModelDirectory)); if (configuration.MappedMaxIndex.HasValue && configuration.LoadOrCreateThenSaveIndex && !_IsEnvironment.DebuggerWasAttachedDuringConstructor) throw new NullReferenceException(nameof(configuration.MappedMaxIndex)); } private void VerifyExtra(List args, Property.Models.Configuration propertyConfiguration, Models.Configuration configuration) { string[] sourceDirectoryNames; if (!args.Any()) sourceDirectoryNames = Array.Empty(); else { string? century; string argZero = Path.GetFullPath(args[0]); sourceDirectoryNames = argZero.Split(Path.DirectorySeparatorChar); if (!argZero.StartsWith(propertyConfiguration.RootDirectory)) throw new Exception($"Source directory must be inside root directory! <{argZero}> <{propertyConfiguration.RootDirectory}>"); if (_ArgZeroIsConfigurationRootDirectory && propertyConfiguration.RootDirectory != argZero) { if (!configuration.MixedYearRelativePaths.Contains(sourceDirectoryNames[0])) { string[] segments = sourceDirectoryNames[0].Split(' '); century = segments[^1].Length == 4 ? segments[^1][..2] : null; if (segments.Length < 2 || century is null || (century != "18" && century != "19" && century != "20")) throw new Exception("root subdirectory must have a year at the end or directory name needs to be added to the exclude list!"); } } } string[] resizeMatch = (from l in sourceDirectoryNames where configuration.ValidResolutions.Contains(l) select l).ToArray(); if (resizeMatch.Any()) throw new Exception("Input directory should be the source and not a resized directory!"); if (configuration.LocationDigits != Shared.Models.Stateless.ILocation.Digits) throw new Exception("Configuration has to match interface!"); if (configuration.LocationFactor != Shared.Models.Stateless.ILocation.Factor) throw new Exception("Configuration has to match interface!"); } private void FullParallelForWork(A_Property propertyLogic, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, List> sourceDirectoryChanges, List propertyFileHolderCollection, List propertyCollection, List>> metadataCollections, List> resizeKeyValuePairs, List?> imageFaceCollections, Container container, int index, Item item) { if (item.ImageFileHolder is null) throw new NullReferenceException(nameof(item.ImageFileHolder)); List? faceCollection; string original = "Original"; FileHolder? resizedFileHolder; Shared.Models.Property property; long ticks = DateTime.Now.Ticks; DateTime dateTime = DateTime.Now; List parseExceptions = new(); Dictionary imageResizeKeyValuePairs; List> subFileTuples = new(); List> metadataCollection; if (item.Property is not null) { property = item.Property; if ((item.Changed.HasValue && item.Changed.Value) || (item.Moved.HasValue && item.Moved.Value) || (item.Abandoned.HasValue && item.Abandoned.Value)) throw new NotImplementedException(); } else { property = propertyLogic.GetProperty(item, subFileTuples, parseExceptions); item.Update(property); if (subFileTuples.Any()) { lock (sourceDirectoryChanges) sourceDirectoryChanges.Add(new Tuple(nameof(A_Property), (from l in subFileTuples select l.Item2).Max())); } } (int metadataGroups, metadataCollection) = _Metadata.GetMetadataCollection(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, subFileTuples, parseExceptions, item); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(B_Metadata.GetMetadataCollection)); imageResizeKeyValuePairs = _Resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, subFileTuples, parseExceptions, original, metadataCollection, item); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(C_Resize.GetResizeKeyValuePairs)); if (_Configuration.SaveResizedSubfiles) { _Resize.SaveResizedSubfile(outputResolution, cResultsFullGroupDirectory, subFileTuples, item, original, imageResizeKeyValuePairs); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(C_Resize.SaveResizedSubfile)); } else if (outputResolution == _Configuration.OutputResolutions[0] && false) { byte[] bytes = _Resize.GetResizedBytes(outputResolution, cResultsFullGroupDirectory, subFileTuples, item, imageResizeKeyValuePairs); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(C_Resize.GetResizedBytes)); string path = Path.Combine(resizedFileHolder.DirectoryName, resizedFileHolder.NameWithoutExtension); File.WriteAllBytes(path, bytes); } if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution)) faceCollection = null; else { int[] outputResolutionCollection = imageResizeKeyValuePairs[outputResolution]; int outputResolutionWidth = outputResolutionCollection[0]; int outputResolutionHeight = outputResolutionCollection[1]; int outputResolutionOrientation = outputResolutionCollection[2]; faceCollection = _Faces.GetFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, item, property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(D_Face.GetFaces)); _Faces.SaveFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, item, faceCollection); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(D_Face.SaveFaces)); int?[] normalizedPixelPercentageCollection = Shared.Models.Stateless.Methods.IFace.GetInts(faceCollection); int normalizedPixelPercentageDistinctCount = normalizedPixelPercentageCollection.Distinct().Count(); if (normalizedPixelPercentageDistinctCount != normalizedPixelPercentageCollection.Length || _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) { bool saveRotated = _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution); string sourceDirectorySegment = Property.Models.Stateless.IResult.GetRelativePath(_Configuration.PropertyConfiguration, container.SourceDirectory); string facesDirectory = Path.GetFullPath(Path.Combine($"{Path.Combine(d2ResultsFullGroupDirectory, "()")}{sourceDirectorySegment}", item.ImageFileHolder.NameWithoutExtension)); _FaceParts.SaveFaceLandmarkImages(facesDirectory, subFileTuples, parseExceptions, item, faceCollection, saveRotated); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(D2_FaceParts.SaveFaceLandmarkImages)); } } lock (sourceDirectoryChanges) { propertyCollection[index] = property; imageFaceCollections[index] = faceCollection; metadataCollections[index] = metadataCollection; resizeKeyValuePairs[index] = imageResizeKeyValuePairs; propertyFileHolderCollection[index] = item.ImageFileHolder; sourceDirectoryChanges.AddRange(from l in subFileTuples where l.Item2 > dateTime select l); } } private int FullParallelWork(int maxDegreeOfParallelism, A_Property propertyLogic, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, List> sourceDirectoryChanges, List propertyFileHolderCollection, List propertyCollection, List>> metadataCollection, List> resizeKeyValuePairs, List?> imageFaceCollections, Container container, Item[] filteredItems, string message) { if (_Log is null) throw new NullReferenceException(nameof(_Log)); int result = 0; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; if (imageFaceCollections.Count != filteredItems.Length || metadataCollection.Count != filteredItems.Length || resizeKeyValuePairs.Count != filteredItems.Length || propertyCollection.Count != filteredItems.Length) { for (int f = 0; f < filteredItems.Length; f++) { propertyCollection.Add(null); metadataCollection.Add(new()); imageFaceCollections.Add(null); resizeKeyValuePairs.Add(new()); propertyFileHolderCollection.Add(null); } } using ProgressBar progressBar = new(filteredItems.Length, message, options); _ = Parallel.For(0, filteredItems.Length, parallelOptions, (i, state) => { try { FullParallelForWork(propertyLogic, outputResolution, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, sourceDirectoryChanges, propertyFileHolderCollection, propertyCollection, metadataCollection, resizeKeyValuePairs, imageFaceCollections, container, index: i, filteredItems[i]); if (i == 0 || sourceDirectoryChanges.Any()) progressBar.Tick(); } catch (Exception ex) { result += 1; _Log.Error(string.Concat(container.SourceDirectory, Environment.NewLine, ex.Message, Environment.NewLine, ex.StackTrace), ex); if (result == filteredItems.Length) throw new Exception(string.Concat("All in [", container.SourceDirectory, "] failed!")); } }); return result; } private static void WriteTab(string checkDirectory, List<(string Id, string Line)> metadataIdLines, string fileName) { string text; FileInfo fileInfo; List duplicates = new(); List metadataIds = new(); fileInfo = new(Path.Combine(checkDirectory, "[()]", Path.ChangeExtension(fileName, "tsv"))); if (fileInfo?.Directory is null) throw new Exception(); if (!fileInfo.Directory.Exists) fileInfo.Directory.Create(); foreach ((string Id, string Line) metadataIdLine in metadataIdLines) { if (metadataIds.Contains(metadataIdLine.Id)) duplicates.Add(metadataIdLine.Id); else metadataIds.Add(metadataIdLine.Id); } for (int i = metadataIdLines.Count - 1; i > -1; i--) { if (duplicates.Contains(metadataIdLines[i].Id)) metadataIdLines.RemoveAt(i); } if (metadataIdLines.Any()) { text = string.Join(Environment.NewLine, from l in metadataIdLines orderby l.Id select l.Line); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, text, updateDateWhenMatches: true, compareBeforeWrite: true); } else { if (fileInfo.Exists) File.Delete(fileInfo.FullName); } } private void WriteGroup(A_Property propertyLogic, Shared.Models.Property[] propertyCollection, List>> metadataCollection, List> resizeKeyValuePairs, List?> imageFaceCollections, string outputResolution, Container container, Item[] filteredItems) { Item item; string key; string json; string checkFile; int sourceDirectoryLength = container.SourceDirectory.Length; if (_ArgZeroIsConfigurationRootDirectory && outputResolution == _Configuration.OutputResolutions[0]) _FilePropertiesKeyValuePairs.Add(container.SourceDirectory, new List>()); JsonSerializerOptions writeIndentedJsonSerializerOptions = new() { WriteIndented = false }; if (!(from l in propertyCollection where l?.Width is null select true).Any()) { string checkDirectory; List?>> imageFaceCollectionsKeyValuePairs = new(); List> propertyCollectionKeyValuePairs = new(); List>> resizeKeyValuePairsCollections = new(); List>>> metadataCollectionKeyValuePairs = new(); (int level, List directories) = Shared.Models.Stateless.Methods.IPath.Get(_Configuration.PropertyConfiguration.RootDirectory, container.SourceDirectory); string fileName = string.Concat(string.Join(_Configuration.PropertyConfiguration.FileNameDirectorySeparator, directories), ".json"); for (int i = 0; i < filteredItems.Length; i++) { item = filteredItems[i]; if (item.Property is null) continue; if (item.ImageFileHolder is null) continue; key = Shared.Models.Stateless.Methods.IPath.GetRelativePath(item.ImageFileHolder.FullName, sourceDirectoryLength); if (_ArgZeroIsConfigurationRootDirectory && outputResolution == _Configuration.OutputResolutions[0]) { _FileKeyValuePairs.Add(new KeyValuePair(container.SourceDirectory, key)); _FilePropertiesKeyValuePairs[container.SourceDirectory].Add(new Tuple(key, propertyCollection[i])); } imageFaceCollectionsKeyValuePairs.Add(new KeyValuePair?>(key, imageFaceCollections[i])); propertyCollectionKeyValuePairs.Add(new KeyValuePair(key, propertyCollection[i])); resizeKeyValuePairsCollections.Add(new KeyValuePair>(key, resizeKeyValuePairs[i])); metadataCollectionKeyValuePairs.Add(new KeyValuePair>>(key, metadataCollection[i])); } if (propertyLogic.AngleBracketCollection.Any()) { checkDirectory = Shared.Models.Stateless.Methods.IPath.GetDirectory(propertyLogic.AngleBracketCollection[0], level, "[{}]"); checkFile = Path.Combine(checkDirectory, fileName); if (File.Exists(checkFile)) File.Move(checkFile, Path.Combine(checkDirectory, fileName)); checkFile = Path.Combine(checkDirectory, fileName); json = JsonSerializer.Serialize(propertyCollectionKeyValuePairs, writeIndentedJsonSerializerOptions); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true); } if (_Metadata.AngleBracketCollection.Any()) { checkDirectory = Shared.Models.Stateless.Methods.IPath.GetDirectory(_Metadata.AngleBracketCollection[0], level, "[{}]"); checkFile = Path.Combine(checkDirectory, fileName); if (File.Exists(checkFile)) File.Move(checkFile, Path.Combine(checkDirectory, fileName)); checkFile = Path.Combine(checkDirectory, fileName); json = JsonSerializer.Serialize(metadataCollectionKeyValuePairs, writeIndentedJsonSerializerOptions); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true); } if (_Resize.AngleBracketCollection.Any()) { checkDirectory = Shared.Models.Stateless.Methods.IPath.GetDirectory(_Resize.AngleBracketCollection[0], level, "[{}]"); checkFile = Path.Combine(checkDirectory, fileName); if (File.Exists(checkFile)) File.Move(checkFile, Path.Combine(checkDirectory, fileName)); checkFile = Path.Combine(checkDirectory, fileName); json = JsonSerializer.Serialize(resizeKeyValuePairsCollections, writeIndentedJsonSerializerOptions); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true); } if (_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution) && _Faces.AngleBracketCollection.Any()) { checkDirectory = Shared.Models.Stateless.Methods.IPath.GetDirectory(_Faces.AngleBracketCollection[0], level, "[{}]"); checkFile = Path.Combine(checkDirectory, fileName); if (File.Exists(checkFile)) File.Move(checkFile, Path.Combine(checkDirectory, fileName)); checkFile = Path.Combine(checkDirectory, fileName); json = JsonSerializer.Serialize(imageFaceCollectionsKeyValuePairs, writeIndentedJsonSerializerOptions); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true); } } } private (string, string, string, string, string, string) GetResultsFullGroupDirectories(Model? model, PredictorModel? predictorModel, string outputResolution) { string aResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( _Configuration.PropertyConfiguration, model, predictorModel, nameof(A_Property), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false); string bResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( _Configuration.PropertyConfiguration, model, predictorModel, nameof(B_Metadata), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false); string cResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( _Configuration.PropertyConfiguration, model, predictorModel, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false); string dResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( _Configuration.PropertyConfiguration, model, predictorModel, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true); string d2ResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( _Configuration.PropertyConfiguration, model, predictorModel, nameof(D2_FaceParts), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true); string eResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( _Configuration.PropertyConfiguration, model, predictorModel, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true); return new(aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory); } private void SetAngleBracketCollections(A_Property propertyLogic, string outputResolution, Container container, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, string eResultsFullGroupDirectory) { _Faces.AngleBracketCollection.Clear(); _Resize.AngleBracketCollection.Clear(); _Metadata.AngleBracketCollection.Clear(); propertyLogic.AngleBracketCollection.Clear(); propertyLogic.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_Configuration.PropertyConfiguration, container.SourceDirectory, aResultsFullGroupDirectory, contentDescription: string.Empty, singletonDescription: "Properties for each image", collectionDescription: string.Empty, converted: false)); _Metadata.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_Configuration.PropertyConfiguration, container.SourceDirectory, bResultsFullGroupDirectory, contentDescription: string.Empty, singletonDescription: "Metadata as key value pairs", collectionDescription: string.Empty, converted: true)); _Resize.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_Configuration.PropertyConfiguration, container.SourceDirectory, cResultsFullGroupDirectory, contentDescription: "Resized image", singletonDescription: "Resize dimensions for each resolution", collectionDescription: string.Empty, converted: true)); if (_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution)) _Faces.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_Configuration.PropertyConfiguration, container.SourceDirectory, dResultsFullGroupDirectory, contentDescription: "n png file(s) for each face found", singletonDescription: string.Empty, collectionDescription: "For each image a json file with all faces found", converted: true)); if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) _ = Property.Models.Stateless.IResult.GetDirectoryInfoCollection( _Configuration.PropertyConfiguration, container.SourceDirectory, d2ResultsFullGroupDirectory, contentDescription: "n x 2 gif file(s) for each face found", singletonDescription: string.Empty, collectionDescription: string.Empty, converted: false); if (_Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)) _ = Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_Configuration.PropertyConfiguration, container.SourceDirectory, eResultsFullGroupDirectory, contentDescription: string.Empty, singletonDescription: "n json file(s) for each face found", collectionDescription: string.Empty, converted: true); } private void FullDoWork(string argZero, Model? model, PredictorModel? predictorModel, string propertyRoot, long ticks, A_Property propertyLogic, int t, Container[] containers) { if (_Log is null) throw new NullReferenceException(nameof(_Log)); int total; string message; int totalSeconds; int exceptionCount; Container container; Item[] filteredItems; string aResultsFullGroupDirectory; string bResultsFullGroupDirectory; string cResultsFullGroupDirectory; string dResultsFullGroupDirectory; string eResultsFullGroupDirectory; string d2ResultsFullGroupDirectory; int containersLength = containers.Length; Shared.Models.Property[] propertyCollection; List?> imageFaceCollections = new(); List propertyFileHolderCollection = new(); List> resizeKeyValuePairs = new(); List> sourceDirectoryChanges = new(); List nullablePropertyCollection = new(); int maxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism; List>> metadataCollection = new(); string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), "{}"); foreach (string outputResolution in _Configuration.OutputResolutions) { total = 0; _FileKeyValuePairs.Clear(); _FilePropertiesKeyValuePairs.Clear(); (aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory) = GetResultsFullGroupDirectories(model, predictorModel, outputResolution); for (int i = 0; i < containers.Length; i++) { container = containers[i]; if (!container.Items.Any()) continue; if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero)) continue; filteredItems = (from l in container.Items where l.ImageFileHolder is not null && (l.Abandoned is null || !l.Abandoned.Value) && l.ValidImageFormatExtension && !_Configuration.IgnoreExtensions.Contains(l.ImageFileHolder.ExtensionLowered) select l).ToArray(); if (!filteredItems.Any()) continue; metadataCollection.Clear(); resizeKeyValuePairs.Clear(); imageFaceCollections.Clear(); sourceDirectoryChanges.Clear(); nullablePropertyCollection.Clear(); propertyFileHolderCollection.Clear(); totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); message = $"{i + 1:000}.{container.G} [{filteredItems.Length:000} files] / {containersLength:000} - {total} / {t} total files - {totalSeconds} total second(s) - {outputResolution} - {container.SourceDirectory}"; SetAngleBracketCollections(propertyLogic, outputResolution, container, aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory); exceptionCount = FullParallelWork(maxDegreeOfParallelism, propertyLogic, outputResolution, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, sourceDirectoryChanges, propertyFileHolderCollection, nullablePropertyCollection, metadataCollection, resizeKeyValuePairs, imageFaceCollections, container, filteredItems, message); if (metadataCollection.Count != filteredItems.Length || nullablePropertyCollection.Count != filteredItems.Length || resizeKeyValuePairs.Count != filteredItems.Length || imageFaceCollections.Count != filteredItems.Length) throw new Exception("Counts don't match!"); if (exceptionCount != 0) _Exceptions.Add(container.SourceDirectory); for (int f = 0; f < imageFaceCollections.Count; f++) filteredItems[f].Faces.AddRange(from l in imageFaceCollections[f] select l); propertyCollection = (from l in nullablePropertyCollection where l is not null select l).ToArray(); if (_ArgZeroIsConfigurationRootDirectory && exceptionCount == 0) WriteGroup(propertyLogic, propertyCollection, metadataCollection, resizeKeyValuePairs, imageFaceCollections, outputResolution, container, filteredItems); if (Directory.GetFiles(propertyRoot, "*.txt", SearchOption.TopDirectoryOnly).Any()) { for (int y = 0; y < int.MaxValue; y++) { _Log.Information("Press \"Y\" key when ready to continue or close console"); if (System.Console.ReadKey().Key == ConsoleKey.Y) break; } _Log.Information(". . ."); } // if (isSilent && container.SourceDirectory.EndsWith("Bohdi Ray 2016")) // 7#.1 // break; // if (isSilent && container.SourceDirectory.EndsWith("Halloween 2013")) // 12#.1 // break; // if (isSilent && container.SourceDirectory.EndsWith("zzz =2014.4 Winter Tracy Pictures")) // 30#.2 // break; // if (isSilent && container.SourceDirectory.EndsWith("=2009.0 Winter Logan Michael")) //34#.2 // break; // if (isSilent && container.SourceDirectory.EndsWith("Animal Kingdom")) //35#.3 // break; // if (isSilent && container.SourceDirectory.EndsWith("Texas 2015")) //46#.4 // break; total += container.Items.Count; } } } private string GetMapLogicResultsFullGroupDirectory(Model? model, PredictorModel? predictorModel) { const int zero = 0; string outputResolution = _Configuration.OutputResolutions[zero]; string zResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( _Configuration.PropertyConfiguration, model, predictorModel, $"Z_{nameof(Item)}", outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false); return zResultsFullGroupDirectory; } private List SetMappingThenGetDistinctFilteredFacesWithMapping(string argZero, Container[] containers) { List results = new(); Mapping mapping; bool? isWrongYear; Item[] filteredItems; DateTime minimumDateTime; List distinctCheck = new(); MappingFromItem mappingFromItem; MappingFromPerson mappingFromPerson; string deterministicHashCodeKeyDisplay; MappingFromLocation mappingFromLocation; foreach (Container container in containers) { if (!container.Items.Any()) continue; if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero)) continue; filteredItems = (from l in container.Items where l.ImageFileHolder is not null && (l.Abandoned is null || !l.Abandoned.Value) && l.ValidImageFormatExtension && !_Configuration.IgnoreExtensions.Contains(l.ImageFileHolder.ExtensionLowered) select l).ToArray(); if (!filteredItems.Any()) continue; foreach (Item item in filteredItems) { if (item.Property?.Id is null || item.ImageFileHolder is null || item.ResizedFileHolder is null) continue; if (!item.Faces.Any()) continue; foreach (Face face in item.Faces) { if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) continue; if (distinctCheck.Contains(item.Property.Id.Value)) continue; minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property); (isWrongYear, _) = item.Property.IsWrongYear(item.ImageFileHolder.FullName, minimumDateTime); mappingFromItem = new(item.Property.Id.Value, item.ImageFileHolder, isWrongYear, minimumDateTime, item.ResizedFileHolder); mappingFromPerson = new(approximateYears: null, by: null, displayDirectoryName: string.Empty, personBirthday: null, segmentB: string.Empty); deterministicHashCodeKeyDisplay = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location.NormalizedPixelPercentage.Value); mappingFromLocation = new(face.Location.Confidence, deterministicHashCodeKeyDisplay, face.Location.NormalizedPixelPercentage.Value); mapping = new(mappingFromItem, mappingFromLocation, mappingFromPerson); face.SetMapping(mapping); results.Add(face); } } } return results; } private Item[] GetIdSortedFilteredItems(string argZero, Container[] containers) { Item[] results; List collection = new(); foreach (Container container in containers) { if (!container.Items.Any()) continue; if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero)) continue; collection.AddRange(from l in container.Items where l.ImageFileHolder is not null && (l.Abandoned is null || !l.Abandoned.Value) && l.ValidImageFormatExtension && !_Configuration.IgnoreExtensions.Contains(l.ImageFileHolder.ExtensionLowered) select l); } results = (from l in collection orderby l.Property?.Id is not null, l.Property?.Id select l).ToArray(); return results; } private void DistanceThenMapLogic(string argZero, long ticks, Person[] people, Container[] containers, MapLogic? mapLogic, string dResultsFullGroupDirectory, string eResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, string zResultsFullGroupDirectory, string peopleDateGroupDirectory, string outputResolution) { E_Distance distance = new(); if (string.IsNullOrEmpty(eResultsFullGroupDirectory)) throw new NullReferenceException(nameof(eResultsFullGroupDirectory)); string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, "()"); string eDistanceContentDirectory = Path.Combine(eResultsFullGroupDirectory, "([])"); if (!Directory.Exists(eDistanceContentDirectory)) _ = Directory.CreateDirectory(eDistanceContentDirectory); Map.Models.Configuration configuration = new(_Configuration.FaceDistanceHiddenImageFactor, _Configuration.FaceDistancePermyriad, _Configuration.FaceDistanceMinimumConfidence, _Configuration.FaceDistanceTolerance, _Configuration.LocationDigits, _Configuration.LocationFactor, _Configuration.MapLogicSigma, _Configuration.MappingSaveFaceEncoding, _Configuration.MappingSaveMapped, _Configuration.MappingUseDeterministicHashCodeUnknownFaceKeyValuePairsForAddToMapping, _Configuration.MappingUseDeterministicHashCodeUnknownFaceKeyValuePairsForSaveMapping, _Configuration.PersonBirthdayFirstYear, _Configuration.PersonBirthdayFormat, _Configuration.PersonKeyFormat, _Configuration.SortingDaysDeltaTolerance, _Configuration.SortingFacesToSkipAfterSortBeforeLoad, _Configuration.SortingFacesToTakeAfterSortBeforeLoad, _Configuration.SortingMaximumPerFaceShouldBeHigh, _Configuration.SortingMaximumPerKey, _Configuration.SortingSigma); if (mapLogic is not null) mapLogic.Update(configuration); string eDistanceContentFileName = Path.Combine(eDistanceContentDirectory, $"{_Configuration.PropertyConfiguration.ResultAllInOne}.tvs"); List distinctFilteredFaces = SetMappingThenGetDistinctFilteredFacesWithMapping(argZero, containers); List selectedFilteredFaces = E_Distance.GetSelectedFilteredFaces(configuration, distinctFilteredFaces); E_Distance.SetFaceDistances(_AppSettings.MaxDegreeOfParallelism, ticks, selectedFilteredFaces); if (mapLogic is null) mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FilenameExtension, _Faces.FilenameExtension, _Faces.HiddenFilenameExtension, _FaceParts.FilenameExtension, ticks, people, peopleDateGroupDirectory, zResultsFullGroupDirectory, configuration, distinctFilteredFaces, distance); mapLogic.SetPersonTicks(distinctFilteredFaces); SortingContainer[] sortingContainers = E_Distance.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, configuration, ticks, mapLogic, selectedFilteredFaces); E_Distance.SaveFaceDistances(eDistanceContentFileName, sortingContainers); int totalNotMapped = mapLogic.AddToMapping(distinctFilteredFaces); if (totalNotMapped > 0) mapLogic.ForceSingleImageThenSaveMapping(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, dFacesContentDirectory, d2ResultsFullGroupDirectory, distinctFilteredFaces, sortingContainers, totalNotMapped); mapLogic.SaveNotMappedTicks(_Configuration.PropertyConfiguration); if (_Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution)) mapLogic.SaveShortcuts(_Configuration.JuliePhares, distinctFilteredFaces); } private void Search(Model? model, PredictorModel? predictorModel, string argZero, string propertyRoot, Person[] people) { int j; int f; int t; MapLogic? mapLogic; Container[] containers; A_Property propertyLogic; long ticks = DateTime.Now.Ticks; string aResultsFullGroupDirectory; string bResultsFullGroupDirectory; string cResultsFullGroupDirectory; string dResultsFullGroupDirectory; string eResultsFullGroupDirectory; string d2ResultsFullGroupDirectory; string zResultsFullGroupDirectory = GetMapLogicResultsFullGroupDirectory(model, predictorModel); string peopleDateGroupDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People)); if (!_FirstRun) { mapLogic = null; propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FilenameExtension, _Configuration.Reverse, model, predictorModel); } else { mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FilenameExtension, _Faces.FilenameExtension, _Faces.HiddenFilenameExtension, _FaceParts.FilenameExtension, ticks, people, peopleDateGroupDirectory, zResultsFullGroupDirectory); propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FilenameExtension, _Configuration.Reverse, model, predictorModel, mapLogic.IndicesFromNew, mapLogic.KeyValuePairs); } int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string message = $") Building Container(s) - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; using (ProgressBar progressBar = new(1, message, options)) { progressBar.Tick(); if (string.IsNullOrEmpty(_Configuration.PropertyConfiguration.RootDirectory)) (j, f, t, containers) = A_Property.Get(_Configuration.PropertyConfiguration, propertyLogic); else (j, f, t, containers) = Property.Models.Stateless.Container.GetContainers(_Configuration.PropertyConfiguration, _FirstRun, propertyLogic); } FullDoWork(argZero, model, predictorModel, propertyRoot, ticks, propertyLogic, t, containers); foreach (string outputResolution in _Configuration.OutputResolutions) { if (_FirstRun) break; (aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory) = GetResultsFullGroupDirectories(model, predictorModel, outputResolution); if (_ArgZeroIsConfigurationRootDirectory && _Configuration.SaveResizedSubfiles && outputResolution == _Configuration.OutputResolutions[0] && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution) && _Exceptions.Count == 0) { DistanceThenMapLogic(argZero, ticks, people, containers, mapLogic, dResultsFullGroupDirectory, eResultsFullGroupDirectory, d2ResultsFullGroupDirectory, zResultsFullGroupDirectory, peopleDateGroupDirectory, outputResolution); if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Any()) break; if (_FileKeyValuePairs.Any()) _Random.Random(_Configuration.PropertyConfiguration, _Configuration.OutputResolutions[0], _FileKeyValuePairs); if (_IsEnvironment.Development) continue; G2_Identify identify = new(_Configuration); List identifiedCollection = identify.GetIdentifiedCollection(_Configuration.PropertyConfiguration, _IsEnvironment, _People); _People.WriteAllText(_Configuration.PropertyConfiguration, _Configuration.OutputResolutions[0], identifiedCollection); identify.WriteAllText(_Configuration.PropertyConfiguration, _Configuration.OutputResolutions[0], identifiedCollection); if (_Configuration.LoadOrCreateThenSaveIndex && _FilePropertiesKeyValuePairs.Any()) _Index.SetIndex(_Configuration.PropertyConfiguration, model, predictorModel, _Configuration.OutputResolutions[0], _FilePropertiesKeyValuePairs); } _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(aResultsFullGroupDirectory, "{}")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(bResultsFullGroupDirectory, "{}")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(cResultsFullGroupDirectory, "{}")); if (_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution)) _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(dResultsFullGroupDirectory, "[]")); if (_Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)) _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(eResultsFullGroupDirectory, "[]")); if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(d2ResultsFullGroupDirectory, "[]")); } } internal void RenameQueue(Model? model, PredictorModel? predictorModel) => _Rename.RenameQueue(_Configuration.PropertyConfiguration, model, predictorModel); }