diff --git a/Compare/Compare.cs b/Compare/Compare.cs index 0b2bd84..34061f7 100644 --- a/Compare/Compare.cs +++ b/Compare/Compare.cs @@ -53,8 +53,8 @@ public class Compare Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration); Verify(configuration); bool reverse = false; - Model model = Model.Hog; - PredictorModel predictorModel = PredictorModel.Large; + Model? model = null; + PredictorModel? predictorModel = null; if (propertyConfiguration.PopulatePropertyId is null) throw new Exception($"{nameof(propertyConfiguration.PopulatePropertyId)} is null!"); foreach (string spelling in configuration.Spelling) @@ -750,7 +750,7 @@ public class Compare } } - private void ThirdPassToMove(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, PropertyLogic propertyLogic, List propertyHolderCollections, string aPropertyContentCollectionDirectory) + private void ThirdPassToMove(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, PropertyLogic propertyLogic, List propertyHolderCollections, string aPropertyContentCollectionDirectory) { if (_Log is null) throw new Exception($"{nameof(_Log)} is null!"); @@ -828,7 +828,7 @@ public class Compare } } - private void FourthPassCreateWindowsShortcuts(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, PropertyLogic propertyLogic, List propertyHolderCollections, bool saveToCollection, bool keepAll) + private void FourthPassCreateWindowsShortcuts(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, PropertyLogic propertyLogic, List propertyHolderCollections, bool saveToCollection, bool keepAll) { if (_Log is null) throw new Exception($"{nameof(_Log)} is null!"); diff --git a/Date-Group/DateGroup.cs b/Date-Group/DateGroup.cs index 3c632cd..d86526b 100644 --- a/Date-Group/DateGroup.cs +++ b/Date-Group/DateGroup.cs @@ -42,8 +42,8 @@ public class DateGroup Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration); Verify(configuration); bool reverse = false; - Model model = Model.Hog; - PredictorModel predictorModel = PredictorModel.Large; + Model? model = null; + PredictorModel? predictorModel = null; _Configuration = configuration; if (configuration.ByHash is null) throw new Exception($"{nameof(configuration.ByHash)} is null!"); diff --git a/FaceRecognitionDotNet/FaceRecognition.cs b/FaceRecognitionDotNet/FaceRecognition.cs index 1e6a806..1b6d06d 100644 --- a/FaceRecognitionDotNet/FaceRecognition.cs +++ b/FaceRecognitionDotNet/FaceRecognition.cs @@ -329,7 +329,7 @@ public sealed class FaceRecognition : DisposableObject /// The enumerable collection of euclidean distance for comparison face. If 0, faces are completely equal. /// or is null. /// is disposed. Or contains disposed object. - public static IEnumerable FaceDistances(IEnumerable faceEncodings, FaceEncoding faceToCompare) + public static List FaceDistances(IEnumerable faceEncodings, FaceEncoding faceToCompare) { if (faceEncodings == null) throw new ArgumentNullException(nameof(faceEncodings)); @@ -366,7 +366,7 @@ public sealed class FaceRecognition : DisposableObject /// contains no elements. /// or this object or custom face landmark detector is disposed. /// is not supported. - public IEnumerable FaceEncodings(Image image, + public List FaceEncodings(Image image, IEnumerable? knownFaceLocation = null, int numJitters = 1, PredictorModel predictorModel = PredictorModel.Small, @@ -385,7 +385,7 @@ public sealed class FaceRecognition : DisposableObject IEnumerable? rawLandmarks = RawFaceLandmarks(image, knownFaceLocation, predictorModel, model); - List? results = new(); + List results = new(); foreach (FullObjectDetection? landmark in rawLandmarks) { FaceEncoding? ret = new(FaceRecognitionModelV1.ComputeFaceDescriptor(_FaceEncoder, image, landmark, numJitters)); @@ -408,7 +408,7 @@ public sealed class FaceRecognition : DisposableObject /// contains no elements. /// or this object or custom face landmark detector is disposed. /// The custom face landmark detector is not ready. - public IEnumerable>> FaceLandmark(Image faceImage, + public List>> FaceLandmark(Image faceImage, IEnumerable? faceLocations = null, PredictorModel predictorModel = PredictorModel.Large, Model model = Model.Hog) @@ -435,7 +435,7 @@ public sealed class FaceRecognition : DisposableObject IEnumerable? landmarkTuples = landmarks.Select(landmark => Enumerable.Range(0, (int)landmark.Parts) .Select(index => new FacePoint(index, landmark.GetPart((uint)index).X, landmark.GetPart((uint)index).Y)).ToArray()); - List>>? results = new(); + List>> results = new(); try { @@ -491,7 +491,7 @@ public sealed class FaceRecognition : DisposableObject landmark.Dispose(); } - return results.ToArray(); + return results; } /// @@ -503,7 +503,7 @@ public sealed class FaceRecognition : DisposableObject /// An enumerable collection of face location correspond to all faces in specified image. /// is null. /// or this object is disposed. - public IEnumerable FaceLocations(Image image, int numberOfTimesToUpsample = 1, Model model = Model.Hog) + public List FaceLocations(Image image, int numberOfTimesToUpsample = 1, Model model = Model.Hog) { if (image == null) throw new ArgumentNullException(nameof(image)); @@ -511,7 +511,7 @@ public sealed class FaceRecognition : DisposableObject image.ThrowIfDisposed(); ThrowIfDisposed(); - List? results = new(); + List results = new(); foreach (MModRect? face in RawFaceLocations(image, numberOfTimesToUpsample, model)) { Location? ret = TrimBound(face.Rect, image.Width, image.Height); diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index 85fec26..1720aa2 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -52,7 +52,7 @@ public class DlibDotNet Property.Models.Configuration.Verify(propertyConfiguration); Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration); Verify(configuration); - (Model model, PredictorModel predictorModel) = GetTuple(args, propertyConfiguration, configuration); + VerifyExtra(args, propertyConfiguration, configuration); _Configuration = configuration; _Index = new G_Index(configuration); _Random = new F_Random(configuration); @@ -84,13 +84,8 @@ public class DlibDotNet _ArgZeroIsConfigurationRootDirectory = propertyConfiguration.RootDirectory == argZero; (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters) = C_Resize.GetTuple(configuration.OutputExtension, configuration.OutputQuality.Value); _Resize = new C_Resize(configuration.ForceResizeLastWriteTimeToCreationTime.Value, configuration.OverrideForResizeImages.Value, configuration.PropertiesChangedForResize.Value, configuration.ValidResolutions, imageCodecInfo, encoderParameters); - 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")) - }; + _Log.Information(configuration.ModelDirectory); + (Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(configuration); _Faces = new D_Face(configuration, argZero, model, modelParameter, predictorModel); if (configuration.SkipSearch is null) throw new Exception($"{nameof(configuration.SkipSearch)} is null!"); @@ -149,37 +144,12 @@ public class DlibDotNet #pragma warning disable CA1416 #pragma warning restore CA1416 - private (Model Model, PredictorModel PredictorModel) GetTuple(List args, Property.Models.Configuration propertyConfiguration, Models.Configuration configuration) + private static (Model model, PredictorModel predictorModel, ModelParameter modelParameter) GetModel(Models.Configuration configuration) { - if (_Log is null) - throw new Exception($"{nameof(_Log)} is null!"); - (Model Model, PredictorModel PredictorModel) result; + (Model, PredictorModel, ModelParameter) result; Array array; Model? model = null; - string[] sourceDirectoryNames; PredictorModel? predictorModel = null; - if (!args.Any()) - sourceDirectoryNames = Array.Empty(); - else - { - 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(' '); - if (segments.Length < 2 || segments[^1].Length != 4 || (segments[^1][..2] != "19" && segments[^1][..2] != "20")) - throw new Exception("root subdirectory must have a year at the end or directory name needs to be added to the exclude list!"); - } - } - } - _Log.Information(configuration.ModelDirectory); - 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!"); array = Enum.GetValues(typeof(Model)); foreach (Model check in array) { @@ -204,7 +174,14 @@ public class DlibDotNet if (predictorModel is null) throw new Exception("Destination directory must have Predictor Model name!"); predictorModel = predictorModel.Value; - result = new(model.Value, 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; } @@ -300,6 +277,32 @@ public class DlibDotNet throw new Exception($"{nameof(configuration.DistanceFactor)} and {nameof(configuration.LocationConfidenceFactor)} must add up to 10!"); } + private void VerifyExtra(List args, Property.Models.Configuration propertyConfiguration, Models.Configuration configuration) + { + string[] sourceDirectoryNames; + if (!args.Any()) + sourceDirectoryNames = Array.Empty(); + else + { + 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(' '); + if (segments.Length < 2 || segments[^1].Length != 4 || (segments[^1][..2] != "19" && segments[^1][..2] != "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!"); + } + private void FullParallelForWork(PropertyLogic propertyLogic, object @lock, string outputResolution, List> sourceDirectoryChanges, List propertyFileInfoCollection, List propertyCollection, List>> metadataCollections, List> resizeKeyValuePairs, List> imageFaceCollections, string sourceDirectory, int index, PropertyHolder propertyHolder) { if (propertyHolder.ImageFileInfo is null) @@ -325,6 +328,7 @@ public class DlibDotNet { sourceDirectoryChanges.Add(new Tuple(nameof(A_Property), propertyHolder.ImageFileInfo.LastWriteTime)); property = propertyLogic.GetProperty(propertyLogic.AngleBracketCollection[0], propertyHolder, subFileTuples, parseExceptions); + propertyHolder.Update(property); } else { @@ -332,25 +336,24 @@ public class DlibDotNet if (propertyHolder.Changed.HasValue && propertyHolder.Changed.Value) sourceDirectoryChanges.Add(new Tuple(nameof(A_Property), propertyHolder.ImageFileInfo.LastWriteTime)); } - string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(propertyHolder.ImageFileInfo.FullName); - (int metadataGroups, metadataCollection) = _Metadata.GetMetadataCollection(subFileTuples, parseExceptions, propertyHolder.ImageFileInfo.FullName, propertyHolder.RelativePath, fileNameWithoutExtension); + (int metadataGroups, metadataCollection) = _Metadata.GetMetadataCollection(subFileTuples, parseExceptions, propertyHolder); if (_AppSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(B_Metadata.GetMetadataCollection)); FileInfo resizedFileInfo = new(Path.Combine(_Resize.AngleBracketCollection[0].Replace("<>", "()"), Path.GetFileName(propertyHolder.ImageFileInfo.FullName))); propertyHolder.SetResizedFileInfo(resizedFileInfo); - imageResizeKeyValuePairs = _Resize.GetResizeKeyValuePairs(subFileTuples, parseExceptions, original, metadataCollection, property, propertyHolder.ImageFileInfo.FullName, propertyHolder.RelativePath, fileNameWithoutExtension); + imageResizeKeyValuePairs = _Resize.GetResizeKeyValuePairs(subFileTuples, parseExceptions, original, metadataCollection, property, propertyHolder); if (_AppSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(C_Resize.GetResizeKeyValuePairs)); if (_Configuration.SaveResizedSubfiles.Value) { - _Resize.SaveResizedSubfile(outputResolution, subFileTuples, propertyHolder.ImageFileInfo.FullName, original, property, imageResizeKeyValuePairs, resizedFileInfo); + _Resize.SaveResizedSubfile(outputResolution, subFileTuples, propertyHolder, original, property, imageResizeKeyValuePairs); if (_AppSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(C_Resize.SaveResizedSubfile)); resizedFileInfo.Refresh(); } else if (outputResolution == _Configuration.OutputResolutions[0] && false) { - byte[] bytes = _Resize.GetResizedBytes(outputResolution, subFileTuples, propertyHolder.ImageFileInfo.FullName, property, imageResizeKeyValuePairs); + byte[] bytes = _Resize.GetResizedBytes(outputResolution, subFileTuples, propertyHolder, property, imageResizeKeyValuePairs); if (_AppSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(C_Resize.GetResizedBytes)); string path = Path.Combine(resizedFileInfo.DirectoryName, Path.GetFileNameWithoutExtension(resizedFileInfo.Name)); @@ -364,15 +367,15 @@ public class DlibDotNet int outputResolutionWidth = outputResolutionCollection[0]; int outputResolutionHeight = outputResolutionCollection[1]; int outputResolutionOrientation = outputResolutionCollection[2]; - faceCollection = _Faces.GetFaces(_Configuration.PropertyConfiguration, outputResolution, subFileTuples, parseExceptions, propertyHolder.RelativePath, fileNameWithoutExtension, property, resizedFileInfo, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation); + faceCollection = _Faces.GetFaces(_Configuration.PropertyConfiguration, outputResolution, subFileTuples, parseExceptions, propertyHolder, property, resizedFileInfo, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation); if (_AppSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(D_Face.GetFaces)); - _Faces.SaveFaces(_Configuration.PropertyConfiguration, subFileTuples, parseExceptions, propertyHolder.RelativePath, fileNameWithoutExtension, resizedFileInfo, faceCollection); + _Faces.SaveFaces(_Configuration.PropertyConfiguration, subFileTuples, parseExceptions, propertyHolder, faceCollection); if (_AppSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(D_Face.SaveFaces)); if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) { - _FaceLandmarks.SaveFaceLandmarkImages(subFileTuples, parseExceptions, propertyHolder.RelativePath, fileNameWithoutExtension, resizedFileInfo, faceCollection); + _FaceLandmarks.SaveFaceLandmarkImages(subFileTuples, parseExceptions, propertyHolder, faceCollection); if (_AppSettings.MaxDegreeOfParallelism.Value < 2) ticks = LogDelta(ticks, nameof(D2_FaceLandmarks.SaveFaceLandmarkImages)); } @@ -551,7 +554,7 @@ public class DlibDotNet } } - private void FullDoWork(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string argZero, Dictionary> peopleCollection, PropertyLogic propertyLogic, List propertyHolderCollections) + private void FullDoWork(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string argZero, Dictionary> peopleCollection, PropertyLogic propertyLogic, List propertyHolderCollections) { if (_Log is null) throw new Exception($"{nameof(_Log)} is null!"); @@ -745,7 +748,7 @@ public class DlibDotNet return result; } - private void Search(Property.Models.Configuration configuration, bool reverse, Model model, PredictorModel predictorModel, string argZero, Person[] people) + private void Search(Property.Models.Configuration configuration, bool reverse, Model? model, PredictorModel? predictorModel, string argZero, Person[] people) { PropertyLogic propertyLogic = GetPropertyLogic(); Dictionary> peopleCollection = A2_People.Convert(people); @@ -753,6 +756,6 @@ public class DlibDotNet FullDoWork(configuration, model, predictorModel, argZero, peopleCollection, propertyLogic, propertyHolderCollections); } - internal void RenameQueue(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel) => _Rename.RenameQueue(configuration, model, predictorModel); + internal void RenameQueue(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel) => _Rename.RenameQueue(configuration, model, predictorModel); } \ No newline at end of file diff --git a/Instance/Models/_D2_FaceLandmark.cs b/Instance/Models/_D2_FaceLandmark.cs index 95d560d..5908e66 100644 --- a/Instance/Models/_D2_FaceLandmark.cs +++ b/Instance/Models/_D2_FaceLandmark.cs @@ -107,8 +107,10 @@ internal class D2_FaceLandmarks #pragma warning restore CA1416 - internal void SaveFaceLandmarkImages(List> subFileTuples, List parseExceptions, string relativePath, string fileNameWithoutExtension, FileInfo resizedFileInfo, List faceCollections) + internal void SaveFaceLandmarkImages(List> subFileTuples, List parseExceptions, PropertyHolder propertyHolder, List faceCollections) { + if (propertyHolder.ResizedFileInfo is null) + throw new Exception($"{propertyHolder.ResizedFileInfo} is null!"); FileInfo fileInfo; bool check = false; string parentCheck; @@ -116,7 +118,7 @@ internal class D2_FaceLandmarks FileInfo rotatedFileInfo; long ticks = DateTime.Now.Ticks; List imageFiles = new(); - string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), fileNameWithoutExtension); + string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), propertyHolder.ImageFileNameWithoutExtension); string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) }; List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); if (!Directory.Exists(facesDirectory)) @@ -128,7 +130,7 @@ internal class D2_FaceLandmarks imageFiles.Add(Array.Empty()); continue; } - fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{i} - {fileNameWithoutExtension}.png")); + fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{i} - {propertyHolder.ImageFileNameWithoutExtension}.png")); if (!fileInfo.Exists) { if (fileInfo.Directory?.Parent is null) @@ -155,7 +157,7 @@ internal class D2_FaceLandmarks check = true; } if (check) - SaveFaceLandmarkImages(faceCollections, imageFiles, pointSize, resizedFileInfo); + SaveFaceLandmarkImages(faceCollections, imageFiles, pointSize, propertyHolder.ResizedFileInfo); } } \ No newline at end of file diff --git a/Instance/Models/_D_Face.cs b/Instance/Models/_D_Face.cs index 4e7b1b7..2918a8a 100644 --- a/Instance/Models/_D_Face.cs +++ b/Instance/Models/_D_Face.cs @@ -249,14 +249,14 @@ public class D_Face : Shared.Models.Properties.IFace, IFace } } - private List GetFaces(FileInfo resizedFileInfo, string relativePath, string fileNameWithoutExtension, A_Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, string facesDirectory) + private List GetFaces(FileInfo resizedFileInfo, PropertyHolder propertyHolder, A_Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, string facesDirectory) { List results = new(); if (_Configuration.PaddingLoops is null) throw new Exception(); if (_Configuration.NumJitters is null) throw new Exception(); - Location[] locations; + List locations; const int numberOfTimesToUpSample = 1; FaceRecognitionDotNet.Image? unknownImage = null; if (resizedFileInfo.Exists) @@ -266,13 +266,13 @@ public class D_Face : Shared.Models.Properties.IFace, IFace catch (Exception) { } } if (unknownImage is null) - results.Add(new D_Face(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, relativePath, i: null, location: null)); + results.Add(new D_Face(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, propertyHolder.RelativePath, i: null, location: null)); else { FaceRecognition faceRecognition = FaceRecognition.Create(_ModelParameter); - locations = faceRecognition.FaceLocations(unknownImage, numberOfTimesToUpSample, _Model).ToArray(); + locations = faceRecognition.FaceLocations(unknownImage, numberOfTimesToUpSample, _Model); if (!locations.Any()) - results.Add(new D_Face(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, relativePath, i: null, location: null)); + results.Add(new D_Face(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, propertyHolder.RelativePath, i: null, location: null)); else { double? α; @@ -295,11 +295,11 @@ public class D_Face : Shared.Models.Properties.IFace, IFace Shared.Models.FaceEncoding faceEncoding; FaceRecognitionDotNet.Image? knownImage; FaceRecognitionDotNet.Image? rotatedImage; - FaceRecognitionDotNet.FaceEncoding[] faceEncodings; - IDictionary>[] faceLandmarks; + List faceEncodings; + List>> faceLandmarks; using Bitmap source = unknownImage.ToBitmap(); padding = (int)((source.Width + source.Height) / 2 * .01); - for (int i = 0; i < locations.Length; i++) + for (int i = 0; i < locations.Count; i++) { for (int p = 0; p <= _Configuration.PaddingLoops.Value; p++) { @@ -308,7 +308,7 @@ public class D_Face : Shared.Models.Properties.IFace, IFace locations[i].Left - (padding * p), locations[i].Right + (padding * p), locations[i].Top - (padding * p)); - face = new D_Face(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, relativePath, i, location); + face = new D_Face(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, propertyHolder.RelativePath, i, location); width = location.Right - location.Left; height = location.Bottom - location.Top; rectangle = new Rectangle(location.Left, location.Top, width, height); @@ -322,11 +322,11 @@ public class D_Face : Shared.Models.Properties.IFace, IFace { if (knownImage is null || knownImage.IsDisposed) throw new Exception($"{nameof(knownImage)} is null"); - faceLandmarks = faceRecognition.FaceLandmark(knownImage, faceLocations: null, _PredictorModel, _Model).ToArray(); + faceLandmarks = faceRecognition.FaceLandmark(knownImage, faceLocations: null, _PredictorModel, _Model); } - if (faceLandmarks.Length == 0 && p < _Configuration.PaddingLoops.Value) + if (faceLandmarks.Count == 0 && p < _Configuration.PaddingLoops.Value) continue; - else if (faceLandmarks.Length != 1) + else if (faceLandmarks.Count != 1) continue; foreach (KeyValuePair> keyValuePair in faceLandmarks[0]) face.FaceLandmarks.Add(keyValuePair.Key.ToString(), keyValuePair.Value.ToArray()); @@ -346,17 +346,17 @@ public class D_Face : Shared.Models.Properties.IFace, IFace { if (rotatedImage is null || rotatedImage.IsDisposed) throw new Exception($"{nameof(rotatedImage)} is null"); - faceEncodings = faceRecognition.FaceEncodings(rotatedImage, knownFaceLocation: null, _Configuration.NumJitters.Value, _PredictorModel, _Model).ToArray(); + faceEncodings = faceRecognition.FaceEncodings(rotatedImage, knownFaceLocation: null, _Configuration.NumJitters.Value, _PredictorModel, _Model); } - if (faceEncodings.Length == 0 && p < _Configuration.PaddingLoops.Value) + if (faceEncodings.Count == 0 && p < _Configuration.PaddingLoops.Value) continue; - else if (faceEncodings.Length != 1) + else if (faceEncodings.Count != 1) continue; rawEncoding = faceEncodings[0].GetRawEncoding(); faceEncoding = new(rawEncoding, faceEncodings[0].Size); face.Update(α, faceEncoding, populated: true); } - faceFile = Path.Combine(facesDirectory, $"{i} - {fileNameWithoutExtension}.png"); + faceFile = Path.Combine(facesDirectory, $"{i} - {propertyHolder.ImageFileNameWithoutExtension}.png"); preRotated.Save(faceFile, System.Drawing.Imaging.ImageFormat.Png); results.Add(face); } @@ -370,7 +370,7 @@ public class D_Face : Shared.Models.Properties.IFace, IFace locations[i].Left, locations[i].Right, locations[i].Top); - face = new D_Face(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, relativePath, i, location); + face = new D_Face(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, propertyHolder.RelativePath, i, location); results.Add(face); } } @@ -392,7 +392,7 @@ public class D_Face : Shared.Models.Properties.IFace, IFace _Populated = populated; } - internal List GetFaces(Property.Models.Configuration configuration, string outputResolution, List> subFileTuples, List parseExceptions, string relativePath, string fileNameWithoutExtension, A_Property property, FileInfo resizedFileInfo, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation) + internal List GetFaces(Property.Models.Configuration configuration, string outputResolution, List> subFileTuples, List parseExceptions, PropertyHolder propertyHolder, A_Property property, FileInfo resizedFileInfo, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation) { List? results; if (_Configuration.PropertiesChangedForFaces is null) @@ -401,9 +401,9 @@ public class D_Face : Shared.Models.Properties.IFace, IFace D_Face face; bool checkForOutputResolutionChange = false; string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) }; - string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), fileNameWithoutExtension); + string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), propertyHolder.ImageFileNameWithoutExtension); List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); - FileInfo fileInfo = new(Path.Combine(AngleBracketCollection[0].Replace("<>", "[]"), $"{fileNameWithoutExtension}.json")); + FileInfo fileInfo = new(Path.Combine(AngleBracketCollection[0].Replace("<>", "[]"), $"{propertyHolder.ImageFileNameWithoutExtension}.json")); if (!fileInfo.Exists) { if (fileInfo.Directory?.Parent is null) @@ -453,7 +453,7 @@ public class D_Face : Shared.Models.Properties.IFace, IFace } else if (results is null) { - results = GetFaces(resizedFileInfo, relativePath, fileNameWithoutExtension, property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, facesDirectory); + results = GetFaces(resizedFileInfo, propertyHolder, property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, facesDirectory); json = JsonSerializer.Serialize(results, _WriteIndentedJsonSerializerOptions); if (Property.Models.Stateless.IPath.WriteAllText(fileInfo.FullName, json, compareBeforeWrite: true)) subFileTuples.Add(new Tuple(nameof(D_Face), DateTime.Now)); @@ -461,16 +461,18 @@ public class D_Face : Shared.Models.Properties.IFace, IFace return results; } - internal void SaveFaces(Property.Models.Configuration configuration, List> subFileTuples, List parseExceptions, string relativePath, string fileNameWithoutExtension, FileInfo resizedFileInfo, List faceCollection) + internal void SaveFaces(Property.Models.Configuration configuration, List> subFileTuples, List parseExceptions, PropertyHolder propertyHolder, List faceCollection) { if (_Configuration.OverrideForFaceImages is null) throw new Exception(); + if (propertyHolder.ResizedFileInfo is null) + throw new Exception($"{propertyHolder.ResizedFileInfo} is null!"); FileInfo fileInfo; bool check = false; string parentCheck; List imageFiles = new(); string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) }; - string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), fileNameWithoutExtension); + string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), propertyHolder.ImageFileNameWithoutExtension); List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); bool facesDirectoryExisted = Directory.Exists(facesDirectory); if (!facesDirectoryExisted) @@ -482,7 +484,7 @@ public class D_Face : Shared.Models.Properties.IFace, IFace imageFiles.Add(string.Empty); continue; } - fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{i} - {fileNameWithoutExtension}.png")); + fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{i} - {propertyHolder.ImageFileNameWithoutExtension}.png")); if (!fileInfo.Exists) { if (fileInfo.Directory?.Parent is null) @@ -500,10 +502,10 @@ public class D_Face : Shared.Models.Properties.IFace, IFace check = true; } if (check) - SaveFaces(faceCollection, resizedFileInfo, imageFiles); + SaveFaces(faceCollection, propertyHolder.ResizedFileInfo, imageFiles); } - internal static List<(PropertyHolder, (string, D_Face?, (string, string, string, string))[])> GetCollection(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, PropertyLogic propertyLogic, Dictionary> peopleCollection, string outputResolution, PropertyHolder[] filteredPropertyHolderCollection, List> faceCollections) + internal static List<(PropertyHolder, (string, D_Face?, (string, string, string, string))[])> GetCollection(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, PropertyLogic propertyLogic, Dictionary> peopleCollection, string outputResolution, PropertyHolder[] filteredPropertyHolderCollection, List> faceCollections) { List<(PropertyHolder, (string, D_Face?, (string, string, string, string))[])> results = new(); string[] keys; @@ -577,7 +579,10 @@ public class D_Face : Shared.Models.Properties.IFace, IFace } } directory = Path.Combine(dFacesContentDirectory, "Shortcuts", personKey, subDirectoryName); - copyDirectory = Path.Combine(dFacesContentDirectory, "Images", personKey, subDirectoryName); + if (faceCollection[0].FaceEncoding is not null) + copyDirectory = Path.Combine(dFacesContentDirectory, "Images", personKey, subDirectoryName); + else + copyDirectory = Path.Combine(dFacesContentDirectory, "ImagesBut", personKey, subDirectoryName); copyFileName = Path.Combine(copyDirectory, $"{propertyHolder.Property.Id.Value}{propertyHolder.ResizedFileInfo.Extension}"); } } diff --git a/Instance/Models/_E2_Navigate.cs b/Instance/Models/_E2_Navigate.cs index 085c4e7..4724136 100644 --- a/Instance/Models/_E2_Navigate.cs +++ b/Instance/Models/_E2_Navigate.cs @@ -35,7 +35,7 @@ internal class E2_Navigate return result; } - private void DisplayTags(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string outputResolution, string[] directories, Dictionary directoryKeyValuePairs, string[] files, Dictionary fileKeyValuePairs) + private void DisplayTags(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution, string[] directories, Dictionary directoryKeyValuePairs, string[] files, Dictionary fileKeyValuePairs) { if (_Log is null) throw new Exception($"{nameof(_Log)} is null!"); @@ -68,7 +68,7 @@ internal class E2_Navigate } } - private void DisplayFaces(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string outputResolution, string selectedFileFullName) + private void DisplayFaces(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution, string selectedFileFullName) { if (_Log is null) throw new Exception($"{nameof(_Log)} is null!"); @@ -91,7 +91,7 @@ internal class E2_Navigate // } } - private string Rename(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string subSourceDirectory) + private string Rename(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string subSourceDirectory) { string result; if (_Log is null) @@ -132,7 +132,7 @@ internal class E2_Navigate return result; } - internal void Navigate(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string outputResolution) + internal void Navigate(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution) { if (_Log is null) throw new Exception($"{nameof(_Log)} is null!"); diff --git a/Instance/Models/_E3_Rename.cs b/Instance/Models/_E3_Rename.cs index a18e91a..632d786 100644 --- a/Instance/Models/_E3_Rename.cs +++ b/Instance/Models/_E3_Rename.cs @@ -29,7 +29,7 @@ internal class E3_Rename return result; } - internal string[] GetDirectoryRenameCollection(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string relativePath, string newDirectoryName, bool jsonFiles4InfoAny) + internal string[] GetDirectoryRenameCollection(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string relativePath, string newDirectoryName, bool jsonFiles4InfoAny) { List results = new(); bool add; @@ -111,7 +111,7 @@ internal class E3_Rename return results.ToArray(); } - internal List GetDirectoryRenameCollections(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string relativePath, string newDirectoryName, bool jsonFiles4InfoAny) + internal List GetDirectoryRenameCollections(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string relativePath, string newDirectoryName, bool jsonFiles4InfoAny) { List results = new(); if (_Configuration?.PropertyConfiguration is null) @@ -227,7 +227,7 @@ internal class E3_Rename return results; } - internal void DirectoryRename(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string relativePath, string newDirectoryName) + internal void DirectoryRename(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string relativePath, string newDirectoryName) { if (_Configuration?.PropertyConfiguration is null) throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!"); @@ -315,7 +315,7 @@ internal class E3_Rename } } - internal void RenameQueue(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel) + internal void RenameQueue(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel) { string[] lines; string[] segments; diff --git a/Instance/Models/_E_Distance.cs b/Instance/Models/_E_Distance.cs index bbc7015..06d3953 100644 --- a/Instance/Models/_E_Distance.cs +++ b/Instance/Models/_E_Distance.cs @@ -72,7 +72,7 @@ internal class E_Distance return results; } - private List GetValues(List> faceCollections, List locationIndicesCollection, double[] faceDistances) + private List GetValues(List> faceCollections, List locationIndicesCollection, List faceDistances) { List results = new(); if (_Configuration.LocationConfidenceFactor is null) @@ -81,7 +81,7 @@ internal class E_Distance throw new Exception(); D_Face face; int[] locationIndices; - for (int d = 0; d < faceDistances.Length; d++) + for (int d = 0; d < faceDistances.Count; d++) { locationIndices = locationIndicesCollection[d]; face = faceCollections[locationIndices[0]][locationIndices[1]]; @@ -150,7 +150,7 @@ internal class E_Distance else { string tvsFile; - double[] faceDistances; + List faceDistances; List indicesAndValues; for (int j = 0; j < faceEncodingCollections.Count; j++) { @@ -158,7 +158,7 @@ internal class E_Distance continue; tvsFile = Path.Combine(tvsDirectory, $"{j} - {fileNameWithoutExtension}.tvs"); jsonFile = Path.Combine(jsonDirectory, $"{j} - {fileNameWithoutExtension}.json"); - faceDistances = FaceRecognition.FaceDistances(faceEncodingCollection, faceEncodingCollections[j]).ToArray(); + faceDistances = FaceRecognition.FaceDistances(faceEncodingCollection, faceEncodingCollections[j]); indicesAndValues = GetValues(faceCollections, locationIndicesCollection, faceDistances); orderedFaceCollection = GetOrderedFaceCollection(faceCollections, locationIndicesCollection, indicesAndValues); text = GetText(fileNameWithoutExtension, faceCollections, locationIndicesCollection, indicesAndValues); @@ -194,7 +194,7 @@ internal class E_Distance } } - internal void LoadOrCreateThenSaveDistanceResultsForOutputResolutions(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string sourceDirectory, string outputResolution, List> sourceDirectoryChanges, PropertyHolder[] filteredPropertyHolderCollection, List> faceCollections) + internal void LoadOrCreateThenSaveDistanceResultsForOutputResolutions(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string sourceDirectory, string outputResolution, List> sourceDirectoryChanges, PropertyHolder[] filteredPropertyHolderCollection, List> faceCollections) { if (_Configuration.CheckJsonForDistanceResults is null) throw new Exception(); @@ -270,7 +270,7 @@ internal class E_Distance _ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(directoryInfoCollection[0].Replace("<>", "()")); } - private List<(string, List>)> GetFiles(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string outputResolution) + private List<(string, List>)> GetFiles(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution) { string json; List>? facesKeyValuePairCollection; @@ -325,7 +325,7 @@ internal class E_Distance return result; } - private void Save(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string outputResolution, string eDistanceCollectionDirectory, int k, string relativePath, Shared.Models.Face face, List> faceAndFaceDistanceCollection) + private void Save(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution, string eDistanceCollectionDirectory, int k, string relativePath, Shared.Models.Face face, List> faceAndFaceDistanceCollection) { if (string.IsNullOrEmpty(eDistanceCollectionDirectory)) eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); @@ -347,7 +347,7 @@ internal class E_Distance return result; } - internal void LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string outputResolution) + internal void LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution) { if (_Log is null) throw new Exception($"{nameof(_Log)} is null!"); @@ -431,7 +431,7 @@ internal class E_Distance return results; } - internal static void SaveGroupedFaceEncodings(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string argZero, Dictionary> peopleCollection, string outputResolution, List propertyHolderCollections) + internal static void SaveGroupedFaceEncodings(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string argZero, Dictionary> peopleCollection, string outputResolution, List propertyHolderCollections) { string json; string checkFile; diff --git a/Instance/Models/_G_Index.cs b/Instance/Models/_G_Index.cs index c582993..bcb2848 100644 --- a/Instance/Models/_G_Index.cs +++ b/Instance/Models/_G_Index.cs @@ -104,7 +104,7 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex } } - private void WriteGroup(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string outputResolution, List>> indexInfoTuples) + private void WriteGroup(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution, List>> indexInfoTuples) { string json; G_Index[] indices; @@ -119,7 +119,7 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex } } - private void AppendTSV(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string outputResolution, Dictionary>> filePropertiesKeyValuePairs) + private void AppendTSV(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution, Dictionary>> filePropertiesKeyValuePairs) { A_Property property; DateTime?[] dateTimes; @@ -142,7 +142,7 @@ public class G_Index : Shared.Models.Properties.IIndex, IIndex } } - internal void SetIndex(Property.Models.Configuration configuration, Model model, PredictorModel predictorModel, string outputResolution, Dictionary>> filePropertiesKeyValuePairs) + internal void SetIndex(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution, Dictionary>> filePropertiesKeyValuePairs) { if (_Configuration.PropertiesChangedForIndex is null) throw new Exception(); diff --git a/Metadata/Models/B_Metadata.cs b/Metadata/Models/B_Metadata.cs index 8ecf0f7..1910154 100644 --- a/Metadata/Models/B_Metadata.cs +++ b/Metadata/Models/B_Metadata.cs @@ -78,14 +78,16 @@ public class B_Metadata return results; } - public (int, List>) GetMetadataCollection(List> subFileTuples, List parseExceptions, string subFile, string relativePath, string fileNameWithoutExtension) + public (int, List>) GetMetadataCollection(List> subFileTuples, List parseExceptions, Property.Models.PropertyHolder propertyHolder) { List> results = new(); + if (propertyHolder.ImageFileInfo is null) + throw new Exception($"{propertyHolder.ImageFileInfo} is null!"); Dictionary>>? dictionary; string json = string.Empty; string[] changesFrom = Array.Empty(); List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); - FileInfo fileInfo = new(Path.Combine(AngleBracketCollection[0].Replace("<>", "{}"), string.Concat(fileNameWithoutExtension, ".json"))); + FileInfo fileInfo = new(Path.Combine(AngleBracketCollection[0].Replace("<>", "{}"), string.Concat(propertyHolder.ImageFileNameWithoutExtension, ".json"))); if (!fileInfo.Exists) { if (fileInfo.Directory?.Parent is null) @@ -133,7 +135,7 @@ public class B_Metadata } if (dictionary is null || !dictionary.Any()) { - dictionary = GetMetadataCollection(subFile); + dictionary = GetMetadataCollection(propertyHolder.ImageFileInfo.FullName); json = JsonSerializer.Serialize(dictionary, _WriteIndentedJsonSerializerOptions); if (Property.Models.Stateless.IPath.WriteAllText(fileInfo.FullName, json, compareBeforeWrite: true)) { diff --git a/Not-Copy-Copy/Not-Copy-Copy.cs b/Not-Copy-Copy/Not-Copy-Copy.cs index 9bd2bfd..8c2f6ba 100644 --- a/Not-Copy-Copy/Not-Copy-Copy.cs +++ b/Not-Copy-Copy/Not-Copy-Copy.cs @@ -39,8 +39,8 @@ public class NotCopyCopy Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration); Verify(configuration); bool reverse = false; - Model model = Model.Hog; - PredictorModel predictorModel = PredictorModel.Large; + Model? model = null; + PredictorModel? predictorModel = null; _Configuration = configuration; if (propertyConfiguration.PopulatePropertyId is null) throw new Exception($"{nameof(propertyConfiguration.PopulatePropertyId)} is null!"); diff --git a/Property/Models/PropertyHolder.cs b/Property/Models/PropertyHolder.cs index 45ed659..f0c4f08 100644 --- a/Property/Models/PropertyHolder.cs +++ b/Property/Models/PropertyHolder.cs @@ -7,8 +7,8 @@ public class PropertyHolder protected readonly bool? _Abandoned; protected readonly bool? _Changed; - protected object? _Face; - protected FileInfo? _ImageFileInfo; + protected readonly FileInfo? _ImageFileInfo; + protected readonly string _ImageFileNameWithoutExtension; protected readonly int _G; protected DateTime? _MinimumDateTime; protected bool? _Moved; @@ -24,8 +24,8 @@ public class PropertyHolder protected bool? _WrongYear; public bool? Abandoned => _Abandoned; public bool? Changed => _Changed; - public object? Face => _Face; public FileInfo? ImageFileInfo => _ImageFileInfo; + public string ImageFileNameWithoutExtension => _ImageFileNameWithoutExtension; public int G => _G; public DateTime? MinimumDateTime => _MinimumDateTime; public bool? Moved => _Moved; @@ -47,6 +47,7 @@ public class PropertyHolder _RelativePath = string.Empty; _SourceDirectory = string.Empty; _SourceDirectoryFile = string.Empty; + _ImageFileNameWithoutExtension = string.Empty; _R = -1; } @@ -68,6 +69,10 @@ public class PropertyHolder _ValidImageFormatExtension = validImageFormatExtension; _WrongYear = wrongYear; _MinimumDateTime = Stateless.A_Property.GetMinimumDateTime(property); + if (imageFileInfo is null) + _ImageFileNameWithoutExtension = string.Empty; + else + _ImageFileNameWithoutExtension = Path.GetFileNameWithoutExtension(imageFileInfo.FullName); if (imageFileInfo is not null && imageFileInfo.Extension is ".json") throw new ArgumentException("Can not be a *.json file!"); if (!sourceDirectoryFile.EndsWith(".json") && !sourceDirectoryFile.EndsWith(".old")) @@ -82,10 +87,14 @@ public class PropertyHolder public void SetResizedFileInfo(FileInfo fileInfo) => _ResizedFileInfo = fileInfo; - internal void Update(A_Property property) => _Property = property; - public bool Any() => (_Abandoned.HasValue && _Abandoned.Value) || (_Changed.HasValue && _Changed.Value) || (_Moved.HasValue && _Moved.Value) || (_NoJson.HasValue && _NoJson.Value); public void AddNamed(string directory, string personKey, object face) => _Named.Add(new(directory, personKey, face)); + public void Update(A_Property property) + { + _Property = property; + _MinimumDateTime = Stateless.A_Property.GetMinimumDateTime(property); + } + } \ No newline at end of file diff --git a/Property/Models/PropertyLogic.cs b/Property/Models/PropertyLogic.cs index 3aa666f..9f3d452 100644 --- a/Property/Models/PropertyLogic.cs +++ b/Property/Models/PropertyLogic.cs @@ -336,7 +336,7 @@ public class PropertyLogic #pragma warning restore CA1416 - private A_Property GetPropertyOfPrivate(string angleBracket, PropertyHolder propertyHolder, bool firstPass, List> filteredSourceDirectoryFileTuples, List parseExceptions, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions, string extensionLowered, string fileNameWithoutExtension) + private A_Property GetPropertyOfPrivate(string angleBracket, PropertyHolder propertyHolder, bool firstPass, List> filteredSourceDirectoryFileTuples, List parseExceptions, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions, string extensionLowered) { A_Property? result; if (_Configuration.ForcePropertyLastWriteTimeToCreationTime is null) @@ -351,8 +351,8 @@ public class PropertyLogic bool hasWrongYearProperty = false; string[] changesFrom = Array.Empty(); bool populateId = !firstPass && _Configuration.PopulatePropertyId.Value; - string without = Path.Combine(angleBracket.Replace("<>", "{}"), $"{fileNameWithoutExtension}.json"); - FileInfo fileInfo = new(Path.Combine(angleBracket.Replace("<>", "{}"), $"{fileNameWithoutExtension}{extensionLowered}.json")); + string without = Path.Combine(angleBracket.Replace("<>", "{}"), $"{propertyHolder.ImageFileNameWithoutExtension}.json"); + FileInfo fileInfo = new(Path.Combine(angleBracket.Replace("<>", "{}"), $"{propertyHolder.ImageFileNameWithoutExtension}{extensionLowered}.json")); if (isValidImageFormatExtension && File.Exists(without)) { File.Move(without, fileInfo.FullName); @@ -647,17 +647,16 @@ public class PropertyLogic List parseExceptions = new(); string extensionLowered = propertyHolder.ImageFileInfo.Extension.ToLower(); bool isValidMetadataExtensions = _Configuration.ValidMetadataExtensions.Contains(extensionLowered); - string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(propertyHolder.ImageFileInfo.FullName); bool isValidImageFormatExtension = _Configuration.ValidImageFormatExtensions.Contains(extensionLowered); lock (propertyHolder) propertyHolder.SetValidImageFormatExtension(isValidImageFormatExtension); bool isIgnoreExtension = isValidImageFormatExtension && _Configuration.IgnoreExtensions.Contains(extensionLowered); - string filteredSourceDirectoryFileExtensionLowered = Path.Combine(sourceDirectory, $"{fileNameWithoutExtension}{extensionLowered}"); + string filteredSourceDirectoryFileExtensionLowered = Path.Combine(sourceDirectory, $"{propertyHolder.ImageFileNameWithoutExtension}{extensionLowered}"); if (isValidImageFormatExtension && propertyHolder.ImageFileInfo.FullName.Length == filteredSourceDirectoryFileExtensionLowered.Length && propertyHolder.ImageFileInfo.FullName != filteredSourceDirectoryFileExtensionLowered) File.Move(propertyHolder.ImageFileInfo.FullName, filteredSourceDirectoryFileExtensionLowered); if (propertyHolder.Changed is null || propertyHolder.Changed.Value || propertyHolder.Property is null) { - property = GetPropertyOfPrivate(angleBracket, propertyHolder, firstPass, filteredSourceDirectoryFileTuples, parseExceptions, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, extensionLowered, fileNameWithoutExtension); + property = GetPropertyOfPrivate(angleBracket, propertyHolder, firstPass, filteredSourceDirectoryFileTuples, parseExceptions, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, extensionLowered); lock (propertyHolder) propertyHolder.Update(property); } @@ -691,7 +690,7 @@ public class PropertyLogic }); } - private string SetAngleBracketCollectionAndGetZero(Configuration configuration, Model model, PredictorModel predictorModel, string sourceDirectory) + private string SetAngleBracketCollectionAndGetZero(Configuration configuration, Model? model, PredictorModel? predictorModel, string sourceDirectory) { string result; AngleBracketCollection.Clear(); @@ -711,7 +710,7 @@ public class PropertyLogic return result; } - public void ParallelWork(Configuration configuration, Model model, PredictorModel predictorModel, long ticks, List propertyHolderCollections, bool firstPass) + public void ParallelWork(Configuration configuration, Model? model, PredictorModel? predictorModel, long ticks, List propertyHolderCollections, bool firstPass) { if (_Log is null) throw new Exception($"{nameof(_Log)} is null!"); @@ -780,13 +779,12 @@ public class PropertyLogic string extensionLowered = propertyHolder.ImageFileInfo.Extension.ToLower(); bool isValidMetadataExtensions = _Configuration.ValidMetadataExtensions.Contains(extensionLowered); bool isValidImageFormatExtension = _Configuration.ValidImageFormatExtensions.Contains(extensionLowered); - string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(propertyHolder.ImageFileInfo.FullName); bool isIgnoreExtension = isValidImageFormatExtension && _Configuration.IgnoreExtensions.Contains(extensionLowered); - result = GetPropertyOfPrivate(angleBracket, propertyHolder, firstPass, filteredSourceDirectoryFileTuples, parseExceptions, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, extensionLowered, fileNameWithoutExtension); + result = GetPropertyOfPrivate(angleBracket, propertyHolder, firstPass, filteredSourceDirectoryFileTuples, parseExceptions, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, extensionLowered); return result; } - public (long Ticks, string FilteredSourceDirectoryFile, string PropertyDirectory, int PropertyId)[] GetPropertyIds(Configuration configuration, Model model, PredictorModel predictorModel, List groupCollection, bool saveToCollection) + public (long Ticks, string FilteredSourceDirectoryFile, string PropertyDirectory, int PropertyId)[] GetPropertyIds(Configuration configuration, Model? model, PredictorModel? predictorModel, List groupCollection, bool saveToCollection) { List<(long Ticks, string FilteredSourceDirectoryFile, string PropertyDirectory, int PropertyId)> results = new(); int level; diff --git a/Property/Models/Stateless/A_Property.cs b/Property/Models/Stateless/A_Property.cs index 64bde75..4d1be10 100644 --- a/Property/Models/Stateless/A_Property.cs +++ b/Property/Models/Stateless/A_Property.cs @@ -236,7 +236,7 @@ public static class A_Property results.Add(new(g, sourceDirectory, collection, r)); } - public static List Get(Models.Configuration configuration, bool reverse, Model model, PredictorModel predictorModel, PropertyLogic propertyLogic) + public static List Get(Models.Configuration configuration, bool reverse, Model? model, PredictorModel? predictorModel, PropertyLogic propertyLogic) { List results; string searchPattern = "*"; diff --git a/Property/Models/Stateless/IResult.cs b/Property/Models/Stateless/IResult.cs index c67ea15..6ca907a 100644 --- a/Property/Models/Stateless/IResult.cs +++ b/Property/Models/Stateless/IResult.cs @@ -17,10 +17,10 @@ public interface IResult string TestStatic_GetResultsDateGroupDirectory(Models.Configuration configuration, string description, string jsonGroup); static string GetResultsDateGroupDirectory(Models.Configuration configuration, string description, string jsonGroup) => Result.GetResultsDateGroupDirectory(configuration, description, jsonGroup); - string TestStatic_GetResultsFullGroupDirectory(Models.Configuration configuration, Model model, PredictorModel predictorModel, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel); - static string GetResultsFullGroupDirectory(Models.Configuration configuration, Model model, PredictorModel predictorModel, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel) => Result.GetResultsFullGroupDirectory(configuration, model, predictorModel, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel); + string TestStatic_GetResultsFullGroupDirectory(Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel); + static string GetResultsFullGroupDirectory(Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel) => Result.GetResultsFullGroupDirectory(configuration, model, predictorModel, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel); List TestStatic_GetDirectoryInfoCollection(Models.Configuration configuration, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription); - static List GetDirectoryInfoCollection(Models.Configuration configuration, Model model, PredictorModel predictorModel, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription) => Result.GetDirectoryInfoCollection(configuration, model, predictorModel, sourceDirectory, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel, contentDescription, singletonDescription, collectionDescription); + static List GetDirectoryInfoCollection(Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription) => Result.GetDirectoryInfoCollection(configuration, model, predictorModel, sourceDirectory, description, outputResolution, includeResizeGroup, includeModel, includePredictorModel, contentDescription, singletonDescription, collectionDescription); } \ No newline at end of file diff --git a/Property/Models/Stateless/Result.cs b/Property/Models/Stateless/Result.cs index dc5b33c..abae4d6 100644 --- a/Property/Models/Stateless/Result.cs +++ b/Property/Models/Stateless/Result.cs @@ -35,14 +35,24 @@ internal class Result return result; } - internal static string GetResultsFullGroupDirectory(Models.Configuration configuration, Model model, PredictorModel predictorModel, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel) + internal static string GetResultsFullGroupDirectory(Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel) { string result = GetResultsDateGroupDirectory(configuration, description); if (includeResizeGroup) result = Path.Combine(result, outputResolution); if (includeModel && includePredictorModel) { - string dateGroupDirectory = string.Concat(outputResolution.Replace(" ", string.Empty), " - ", model, " - ", predictorModel.ToString()); + string modelName; + string predictorModelName; + if (model is null) + modelName = Model.Hog.ToString(); + else + modelName = model.Value.ToString(); + if (predictorModel is null) + predictorModelName = PredictorModel.Large.ToString(); + else + predictorModelName = predictorModel.Value.ToString(); + string dateGroupDirectory = string.Concat(outputResolution.Replace(" ", string.Empty), " - ", modelName, " - ", predictorModelName); result = Path.Combine(result, dateGroupDirectory); } else if (includeModel) @@ -54,7 +64,7 @@ internal class Result return result; } - internal static List GetDirectoryInfoCollection(Models.Configuration configuration, Model model, PredictorModel predictorModel, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription) + internal static List GetDirectoryInfoCollection(Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string sourceDirectory, string description, string outputResolution, bool includeResizeGroup, bool includeModel, bool includePredictorModel, string contentDescription, string singletonDescription, string collectionDescription) { List results = new(); string result = string.Empty; diff --git a/Resize/Models/_C_Resize.cs b/Resize/Models/_C_Resize.cs index cd000e3..4c55769 100644 --- a/Resize/Models/_C_Resize.cs +++ b/Resize/Models/_C_Resize.cs @@ -284,22 +284,29 @@ public class C_Resize return results; } - public byte[] GetResizedBytes(string outputResolution, List> subFileTuples, string subFile, A_Property property, Dictionary imageResizes) + public byte[] GetResizedBytes(string outputResolution, List> subFileTuples, PropertyHolder propertyHolder, A_Property property, Dictionary imageResizes) { byte[] results; + if (propertyHolder.ImageFileInfo is null) + throw new Exception($"{propertyHolder.ImageFileInfo} is null!"); if (!imageResizes.ContainsKey(outputResolution)) throw new Exception(); int[] resize = imageResizes[outputResolution]; int outputResolutionWidth = resize[_OutputResolutionWidthIndex]; int outputResolutionHeight = resize[_OutputResolutionHeightIndex]; int outputResolutionOrientation = resize[_OutputResolutionOrientationIndex]; - results = SaveResizedSubfile(subFile, property, resize, fileInfo: null); + results = SaveResizedSubfile(propertyHolder.ImageFileInfo.FullName, property, resize, fileInfo: null); subFileTuples.Add(new Tuple(nameof(C_Resize), DateTime.Now)); return results; } - public void SaveResizedSubfile(string outputResolution, List> subFileTuples, string subFile, string original, A_Property property, Dictionary imageResizes, FileInfo fileInfo) + public void SaveResizedSubfile(string outputResolution, List> subFileTuples, PropertyHolder propertyHolder, string original, A_Property property, Dictionary imageResizes) { + if (propertyHolder.ImageFileInfo is null) + throw new Exception($"{propertyHolder.ImageFileInfo} is null!"); + if (propertyHolder.ResizedFileInfo is null) + throw new Exception($"{propertyHolder.ResizedFileInfo} is null!"); + FileInfo fileInfo = propertyHolder.ResizedFileInfo; if (!imageResizes.ContainsKey(outputResolution)) throw new Exception(); if (!fileInfo.Exists) @@ -322,7 +329,7 @@ public class C_Resize { if (!fileInfo.Exists) { - File.Copy(subFile, fileInfo.FullName); + File.Copy(propertyHolder.ImageFileInfo.FullName, fileInfo.FullName); subFileTuples.Add(new Tuple(nameof(C_Resize), DateTime.Now)); } } @@ -339,7 +346,7 @@ public class C_Resize check = true; if (check) { - _ = SaveResizedSubfile(subFile, property, resize, fileInfo); + _ = SaveResizedSubfile(propertyHolder.ImageFileInfo.FullName, property, resize, fileInfo); subFileTuples.Add(new Tuple(nameof(C_Resize), DateTime.Now)); } } @@ -414,13 +421,13 @@ public class C_Resize return results; } - public Dictionary GetResizeKeyValuePairs(List> subFileTuples, List parseExceptions, string original, List> metadataCollection, A_Property property, string subFile, string relativePath, string fileNameWithoutExtension) + public Dictionary GetResizeKeyValuePairs(List> subFileTuples, List parseExceptions, string original, List> metadataCollection, A_Property property, PropertyHolder propertyHolder) { Dictionary results; string json; string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata) }; List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); - FileInfo fileInfo = new(Path.Combine(AngleBracketCollection[0].Replace("<>", "{}"), string.Concat(fileNameWithoutExtension, ".json"))); + FileInfo fileInfo = new(Path.Combine(AngleBracketCollection[0].Replace("<>", "{}"), string.Concat(propertyHolder.ImageFileNameWithoutExtension, ".json"))); if (!fileInfo.Exists) { if (fileInfo.Directory?.Parent is null) diff --git a/Tests/Models/Configuration.cs b/Tests/Models/Configuration.cs index 7963e6c..79f8fca 100644 --- a/Tests/Models/Configuration.cs +++ b/Tests/Models/Configuration.cs @@ -43,7 +43,7 @@ public class Configuration protected readonly string[] _SaveFaceLandmarkForOutputResolutions; protected readonly bool? _SaveFullYearOfRandomFiles; protected readonly bool? _SaveResizedSubfiles; - protected readonly string _SaveShortcutsForOutputResolutions; + protected readonly string[] _SaveShortcutsForOutputResolutions; protected readonly bool? _SkipSearch; protected readonly bool? _TestDistanceResults; protected readonly string[] _ValidResolutions; @@ -84,13 +84,13 @@ public class Configuration public string[] SaveFaceLandmarkForOutputResolutions => _SaveFaceLandmarkForOutputResolutions; public bool? SaveFullYearOfRandomFiles => _SaveFullYearOfRandomFiles; public bool? SaveResizedSubfiles => _SaveResizedSubfiles; - public string SaveShortcutsForOutputResolutions => _SaveShortcutsForOutputResolutions; + public string[] SaveShortcutsForOutputResolutions => _SaveShortcutsForOutputResolutions; public bool? SkipSearch => _SkipSearch; public bool? TestDistanceResults => _TestDistanceResults; public string[] ValidResolutions => _ValidResolutions; [JsonConstructor] - public Configuration(bool? checkJsonForDistanceResults, int? crossDirectoryMaxItemsInDistanceCollection, int? distanceFactor, bool? forceMetadataLastWriteTimeToCreationTime, bool? forceResizeLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRelativePaths, string[] juliePhares, string[] loadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions, bool? loadOrCreateThenSaveIndex, int? locationConfidenceFactor, int? mappedMaxIndex, int? maxItemsInDistanceCollection, string[] mixedYearRelativePaths, string modelDirectory, string modelName, int? numJitters, string outputExtension, int? outputQuality, string[] outputResolutions, bool? overrideForFaceImages, bool? overrideForFaceLandmarkImages, bool? overrideForResizeImages, int? paddingLoops, string predictorModelName, bool? propertiesChangedForDistance, bool? propertiesChangedForFaces, bool? propertiesChangedForIndex, bool? propertiesChangedForMetadata, bool? propertiesChangedForResize, Property.Models.Configuration? propertyConfiguration, bool? reverse, string[] saveFaceLandmarkForOutputResolutions, bool? saveFullYearOfRandomFiles, bool? saveResizedSubfiles, string saveShortcutsForOutputResolutions, bool? skipSearch, bool? testDistanceResults, string[] validResolutions) + public Configuration(bool? checkJsonForDistanceResults, int? crossDirectoryMaxItemsInDistanceCollection, int? distanceFactor, bool? forceMetadataLastWriteTimeToCreationTime, bool? forceResizeLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRelativePaths, string[] juliePhares, string[] loadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions, bool? loadOrCreateThenSaveIndex, int? locationConfidenceFactor, int? mappedMaxIndex, int? maxItemsInDistanceCollection, string[] mixedYearRelativePaths, string modelDirectory, string modelName, int? numJitters, string outputExtension, int? outputQuality, string[] outputResolutions, bool? overrideForFaceImages, bool? overrideForFaceLandmarkImages, bool? overrideForResizeImages, int? paddingLoops, string predictorModelName, bool? propertiesChangedForDistance, bool? propertiesChangedForFaces, bool? propertiesChangedForIndex, bool? propertiesChangedForMetadata, bool? propertiesChangedForResize, Property.Models.Configuration? propertyConfiguration, bool? reverse, string[] saveFaceLandmarkForOutputResolutions, bool? saveFullYearOfRandomFiles, bool? saveResizedSubfiles, string[] saveShortcutsForOutputResolutions, bool? skipSearch, bool? testDistanceResults, string[] validResolutions) { _CheckJsonForDistanceResults = checkJsonForDistanceResults; _CrossDirectoryMaxItemsInDistanceCollection = crossDirectoryMaxItemsInDistanceCollection; diff --git a/Tests/UnitTestResize.cs b/Tests/UnitTestResize.cs index 1759eee..9a86f12 100644 --- a/Tests/UnitTestResize.cs +++ b/Tests/UnitTestResize.cs @@ -104,14 +104,14 @@ public class UnitTestResize throw new Exception($"{nameof(_Configuration.PropertiesChangedForResize)} is null!"); int g = 1; int r = 1; - Model model = Model.Hog; + Model? model = null; string original = "Original"; List parseExceptions = new(); Property.Models.A_Property? property = null; Property.Models.PropertyHolder propertyHolder; Dictionary imageResizeKeyValuePairs; List> subFileTuples = new(); - PredictorModel predictorModel = PredictorModel.Large; + PredictorModel? predictorModel = null; List> metadataCollection; int length = _PropertyConfiguration.RootDirectory.Length; string outputResolution = _Configuration.OutputResolutions[0]; @@ -162,14 +162,14 @@ public class UnitTestResize string relativePath = Property.Models.Stateless.IPath.GetRelativePath(fileInfo.FullName, length); sourceDirectory = Path.Combine(aPropertySingletonDirectory, sourceDirectoryName); propertyHolder = new(g, sourceDirectory, sourceDirectoryFile, relativePath, r, fileInfo, property, false, false, null, null, null); - if (propertyHolder.ImageFileInfo is null) - throw new Exception($"{nameof(propertyHolder.ImageFileInfo)} is null!"); - string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(propertyHolder.ImageFileInfo.FullName); + Assert.IsNotNull(propertyHolder.ImageFileInfo); property = propertyLogic.GetProperty(propertyLogic.AngleBracketCollection[0], propertyHolder, subFileTuples, parseExceptions); - (int _, metadataCollection) = metadata.GetMetadataCollection(subFileTuples, parseExceptions, propertyHolder.ImageFileInfo.FullName, propertyHolder.RelativePath, fileNameWithoutExtension); - imageResizeKeyValuePairs = resize.GetResizeKeyValuePairs(subFileTuples, parseExceptions, original, metadataCollection, property, propertyHolder.ImageFileInfo.FullName, propertyHolder.RelativePath, fileNameWithoutExtension); + (int _, metadataCollection) = metadata.GetMetadataCollection(subFileTuples, parseExceptions, propertyHolder); + imageResizeKeyValuePairs = resize.GetResizeKeyValuePairs(subFileTuples, parseExceptions, original, metadataCollection, property, propertyHolder); FileInfo resizedFileInfo = new(Path.Combine(resize.AngleBracketCollection[0].Replace("<>", "()"), Path.GetFileName(propertyHolder.ImageFileInfo.FullName))); - resize.SaveResizedSubfile(outputResolution, subFileTuples, propertyHolder.ImageFileInfo.FullName, original, property, imageResizeKeyValuePairs, resizedFileInfo); + propertyHolder.SetResizedFileInfo(resizedFileInfo); + resize.SaveResizedSubfile(outputResolution, subFileTuples, propertyHolder, original, property, imageResizeKeyValuePairs); + resizedFileInfo.Refresh(); } } \ No newline at end of file