diff --git a/Delete-By-Distinct/DeleteByDistinct.cs b/Delete-By-Distinct/DeleteByDistinct.cs index 067f87a..8197bd3 100644 --- a/Delete-By-Distinct/DeleteByDistinct.cs +++ b/Delete-By-Distinct/DeleteByDistinct.cs @@ -70,8 +70,8 @@ public class DeleteByDistinct // if (!fileTicksToNames.TryGetValue(fileInfo.LastWriteTime.Ticks, out fileNames)) // throw new Exception(); // } - checkDate = new DateTime(ticks); - // checkDate = new DateTime(fileInfo.LastWriteTime.Year, fileInfo.LastWriteTime.Month, fileInfo.LastWriteTime.Day); + // checkDate = new DateTime(ticks); + checkDate = new DateTime(fileInfo.LastWriteTime.Year, fileInfo.LastWriteTime.Month, fileInfo.LastWriteTime.Day); if (!fileTicksToNames.TryGetValue(checkDate.Ticks, out fileNames)) { fileTicksToNames.Add(checkDate.Ticks, new()); diff --git a/Drag-Drop/Form.cs b/Drag-Drop/Form.cs index 4d8b9b1..5aac3a4 100644 --- a/Drag-Drop/Form.cs +++ b/Drag-Drop/Form.cs @@ -181,7 +181,6 @@ public partial class Form : System.Windows.Forms.Form FileHolder fileHolder; bool isIgnoreExtension; string checkFileExtension; - bool skipOneAllAreNumbers; DateTime? minimumDateTime; const string jpg = ".jpg"; _InnerProgressBar.Step = 1; @@ -208,19 +207,15 @@ public partial class Form : System.Windows.Forms.Form continue; isValidImageFormatExtension = _Configuration.PropertyConfiguration.ValidImageFormatExtensions.Contains(fileHolder.ExtensionLowered); isIgnoreExtension = isValidImageFormatExtension && _Configuration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered); - if (fileHolder.NameWithoutExtension.Length > 4) + if (IProperty.NameWithoutExtensionIsIdFormat(fileHolder)) { - skipOneAllAreNumbers = fileHolder.NameWithoutExtension[1..].All(l => char.IsNumber(l)); - if ((skipOneAllAreNumbers && fileHolder.NameWithoutExtension[0] == '-') || (skipOneAllAreNumbers && char.IsNumber(fileHolder.NameWithoutExtension[0]))) + if (fileHolder.ExtensionLowered == jpeg) { - if (fileHolder.ExtensionLowered == jpeg) - { - if (File.Exists($"{fileHolder.FullName}.id")) - File.Move($"{fileHolder.FullName}.id", Path.Combine(fileHolder.DirectoryName, $"{fileHolder.NameWithoutExtension}{jpg}.id")); - File.Move(fileHolder.FullName, Path.Combine(fileHolder.DirectoryName, $"{fileHolder.NameWithoutExtension}{jpg}")); - } - continue; + if (File.Exists($"{fileHolder.FullName}.id")) + File.Move($"{fileHolder.FullName}.id", Path.Combine(fileHolder.DirectoryName, $"{fileHolder.NameWithoutExtension}{jpg}.id")); + File.Move(fileHolder.FullName, Path.Combine(fileHolder.DirectoryName, $"{fileHolder.NameWithoutExtension}{jpg}")); } + continue; } if (!isIgnoreExtension && isValidImageFormatExtension) extraLargeBitmapThumbnail = null; diff --git a/Face/Models/_D_Face.cs b/Face/Models/_D_Face.cs index 75a01f7..fe511aa 100644 --- a/Face/Models/_D_Face.cs +++ b/Face/Models/_D_Face.cs @@ -212,7 +212,7 @@ public class D_Face } } - private List GetFaces(Shared.Models.Property property, MappingFromItem mappingFromItem, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, List locations) + private List GetFaces(Shared.Models.Property property, MappingFromItem mappingFromItem, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, List? locations) { if (_Log is null) throw new NullReferenceException(nameof(_Log)); @@ -297,7 +297,7 @@ public class D_Face if (string.IsNullOrEmpty(dResultsFullGroupDirectory)) throw new NullReferenceException(nameof(dResultsFullGroupDirectory)); string json; - List locations = new(); + List? locations; string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) }; List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); string dCollectionFile = Path.Combine(dResultsFullGroupDirectory, "[]", _Configuration.ResultAllInOne, $"{mappingFromItem.Id}{mappingFromItem.ImageFileHolder.ExtensionLowered}.json"); @@ -334,18 +334,20 @@ public class D_Face parseExceptions.Add(nameof(D_Face)); } } - if (mappingFromPhotoPrismCollection is not null && results is not null) - locations.AddRange(Shared.Models.Stateless.Methods.ILocation.GetLocations(mappingFromPhotoPrismCollection, results)); - if (results is null || locations.Any()) + if (mappingFromPhotoPrismCollection is null || results is null) + locations = null; + else + locations = Shared.Models.Stateless.Methods.ILocation.GetLocations(mappingFromPhotoPrismCollection, results); + if (results is null || (locations is not null && locations.Any())) { results = GetFaces(property, mappingFromItem, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, locations); if (!results.Any()) File.Move(mappingFromItem.ResizedFileHolder.FullName, $"{mappingFromItem.ResizedFileHolder.FullName}.err"); else { - json = JsonSerializer.Serialize(results, _WriteIndentedAndWhenWritingNull); bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); + json = JsonSerializer.Serialize(results, _WriteIndentedAndWhenWritingNull); if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime)) { if (!_ForceFaceLastWriteTimeToCreationTime) diff --git a/FaceRecognitionDotNet/FaceRecognition.cs b/FaceRecognitionDotNet/FaceRecognition.cs index 1038539..46687ad 100644 --- a/FaceRecognitionDotNet/FaceRecognition.cs +++ b/FaceRecognitionDotNet/FaceRecognition.cs @@ -198,7 +198,7 @@ public class FaceRecognition : DisposableObject return results; } - public List<(Location, FaceEncoding?, Dictionary?)> GetCollection(Image image, List locations, bool includeFaceEncoding, bool includeFaceParts) + public List<(Location, FaceEncoding?, Dictionary?)> GetCollection(Image image, List? locations, bool includeFaceEncoding, bool includeFaceParts) { List<(Location, FaceEncoding?, Dictionary?)> results = new(); if (image is null) @@ -207,7 +207,10 @@ public class FaceRecognition : DisposableObject ThrowIfDisposed(); if (_PredictorModel == PredictorModel.Custom) throw new NotSupportedException("FaceRecognition.PredictorModel.Custom is not supported."); - locations.AddRange(GetLocations(image)); + if (locations is null) + locations = GetLocations(image); + else if (!locations.Any()) + locations.AddRange(GetLocations(image)); List fullObjectDetections = GetFullObjectDetections(image, locations); if (fullObjectDetections.Count != locations.Count) throw new Exception(); diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index b58bcf5..10acda8 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -302,6 +302,9 @@ public partial class DlibDotNet subFileTuples.Add(new Tuple(nameof(A_Property), item.SourceDirectoryFileHolder.LastWriteTime.Value)); else subFileTuples.Add(new Tuple(nameof(A_Property), new FileInfo(item.SourceDirectoryFileHolder.FullName).LastWriteTime)); + bool nameWithoutExtensionIsIdFormat = Shared.Models.Stateless.Methods.IProperty.NameWithoutExtensionIsIdFormat(item.ImageFileHolder); + if (nameWithoutExtensionIsIdFormat && item.ImageFileHolder.NameWithoutExtension != item.Property.Id.ToString()) + _Log.Information($"Name without extension is Id format but doesn't match id <{item.ImageFileHolder.FullName}>"); } else { @@ -1100,7 +1103,7 @@ public partial class DlibDotNet MapLogic? mapLogic = _Configuration.DistanceMoveUnableToMatch ? null : new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, ticks, _PersonContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory, mapLogicSupport); if (Directory.Exists(fPhotoPrismSingletonDirectory)) { - Dictionary> fileNameToCollection = F_PhotoPrism.GetFileNameToCollection(fPhotoPrismContentDirectory); + Dictionary> fileNameToCollection = F_PhotoPrism.GetFileNameToCollection(fPhotoPrismSingletonDirectory); foreach (KeyValuePair> keyValuePair in fileNameToCollection) _FileNameToCollection.Add(keyValuePair.Key, keyValuePair.Value); } diff --git a/Shared/Models/Stateless/Methods/IProperty.cs b/Shared/Models/Stateless/Methods/IProperty.cs index 3177ad7..30853e0 100644 --- a/Shared/Models/Stateless/Methods/IProperty.cs +++ b/Shared/Models/Stateless/Methods/IProperty.cs @@ -61,6 +61,11 @@ public interface IProperty static DateTime? GetDateTimeFromName(Models.FileHolder fileHolder) => Property.GetDateTimeFromName(fileHolder); + bool TestStatic_NameWithoutExtensionIsIdFormat(Models.FileHolder fileHolder) => + NameWithoutExtensionIsIdFormat(fileHolder); + static bool NameWithoutExtensionIsIdFormat(Models.FileHolder fileHolder) => + Property.NameWithoutExtensionIsIdFormat(fileHolder); + List TestStatic_GetDateTimes(Models.Property property) => GetDateTimes(property); static List GetDateTimes(Models.Property property) => diff --git a/Shared/Models/Stateless/Methods/Location.cs b/Shared/Models/Stateless/Methods/Location.cs index 4356d47..54966d7 100644 --- a/Shared/Models/Stateless/Methods/Location.cs +++ b/Shared/Models/Stateless/Methods/Location.cs @@ -206,10 +206,10 @@ internal abstract class Location return result; } - internal static Models.Location? GetLocation(Marker marker, Rectangle rectangle) + private static Models.Location? GetLocation(DatabaseFile databaseFile, Marker marker, Rectangle rectangle) { Models.Location? result; - bool verified = Check(rectangle.Bottom, rectangle.Height, rectangle.Left, rectangle.Right, rectangle.Top, rectangle.Width, zCount: 1, throwException: false); + bool verified = Check(rectangle.Bottom, databaseFile.FileHeight, rectangle.Left, rectangle.Right, rectangle.Top, databaseFile.FileWidth, zCount: 1, throwException: false); if (!verified) result = null; else @@ -224,45 +224,61 @@ internal abstract class Location if (rectangle is null) result = null; else - result = GetLocation(marker, rectangle.Value); + result = GetLocation(databaseFile, marker, rectangle.Value); return result; } internal static List GetLocations(List mappingFromPhotoPrismCollection, List faces) { List results = new(); - double percent; + bool any; + bool matches; Rectangle dlibRectangle; Rectangle? prismRectangle; Models.Location? location; Rectangle intersectRectangle; + Models.OutputResolution? outputResolution = null; foreach (Models.Face face in faces) { if (face.Location is null || face.OutputResolution is null) continue; - foreach (MappingFromPhotoPrism mappingFromPhotoPrism in mappingFromPhotoPrismCollection) + results.Add(face.Location); + outputResolution ??= face.OutputResolution; + } + int before = results.Count; + foreach (MappingFromPhotoPrism mappingFromPhotoPrism in mappingFromPhotoPrismCollection) + { + if (outputResolution is null) + break; + matches = Matches(outputResolution, mappingFromPhotoPrism.DatabaseFile); + if (!matches) + break; + foreach (Marker marker in mappingFromPhotoPrism.Markers) { - dlibRectangle = new(face.Location.Left, face.Location.Top, face.Location.Right - face.Location.Left, face.Location.Bottom - face.Location.Top); - foreach (Marker marker in mappingFromPhotoPrism.Markers) + any = false; + prismRectangle = GetRectangle(outputResolution, mappingFromPhotoPrism.DatabaseFile, marker); + if (prismRectangle is null) + break; + location = GetLocation(mappingFromPhotoPrism.DatabaseFile, marker, prismRectangle.Value); + if (location is null) + break; + foreach (Models.Face face in faces) { - prismRectangle = GetRectangle(face.OutputResolution, mappingFromPhotoPrism.DatabaseFile, marker); - if (prismRectangle is null) - { - location = new(1, 0, 0, 1, 0); - results.Add(location); - continue; - } - location = GetLocation(marker, prismRectangle.Value); - if (location is null) + if (face.Location is null || face.OutputResolution is null) continue; + dlibRectangle = new(face.Location.Left, face.Location.Top, face.Location.Right - face.Location.Left, face.Location.Bottom - face.Location.Top); intersectRectangle = Rectangle.Intersect(dlibRectangle, prismRectangle.Value); - percent = (double)intersectRectangle.Width * intersectRectangle.Height / (dlibRectangle.Width * dlibRectangle.Height); - if (percent > 0.000001) + if (intersectRectangle.Width == 0 && intersectRectangle.Height == 0) continue; - results.Add(location); + any = true; + break; } + if (!any) + results.Add(location); } } + if (before == results.Count) + results.Clear(); return results; } diff --git a/Shared/Models/Stateless/Methods/Property.cs b/Shared/Models/Stateless/Methods/Property.cs index f1005fc..dfd7410 100644 --- a/Shared/Models/Stateless/Methods/Property.cs +++ b/Shared/Models/Stateless/Methods/Property.cs @@ -330,6 +330,19 @@ internal abstract class Property return result; } + internal static bool NameWithoutExtensionIsIdFormat(Models.FileHolder fileHolder) + { + bool result; + if (fileHolder.NameWithoutExtension.Length < 5) + result = false; + else + { + bool skipOneAllAreNumbers = fileHolder.NameWithoutExtension[1..].All(l => char.IsNumber(l)); + result = (skipOneAllAreNumbers && fileHolder.NameWithoutExtension[0] == '-') || (skipOneAllAreNumbers && char.IsNumber(fileHolder.NameWithoutExtension[0])); + } + return result; + } + internal static List GetMetadataDateTimesByPattern(string dateTimeFormat, string sourceDirectoryFile) { List results = new();