From e532c3ef1e89ccfa4a5a0abd46223695f266de7f Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Sun, 20 Oct 2024 17:49:11 -0700 Subject: [PATCH] FaceFile for D2 --- Face/Models/_D_Face.cs | 14 +- FaceParts/Models/_D2_FaceParts.cs | 350 ++++++++++++------ Instance/DlibDotNet.cs | 32 +- Instance/Models/Binder/Configuration.cs | 6 +- Instance/Models/Configuration.cs | 2 +- Resize/Models/_C_Resize.cs | 4 +- Shared/Models/FaceEncoding.cs | 26 +- Shared/Models/FaceFile.cs | 16 +- Shared/Models/FacePoint.cs | 45 +-- Shared/Models/Location.cs | 8 +- Shared/Models/OutputResolution.cs | 31 +- Shared/Models/Properties/IFaceEncoding.cs | 12 +- Shared/Models/Properties/IOutputResolution.cs | 14 +- Shared/Models/Stateless/Methods/IProperty.cs | 5 + Shared/Models/Stateless/Methods/Property.cs | 16 + Tests/Models/Binder/Configuration.cs | 6 +- Tests/Models/Configuration.cs | 2 +- .../Models/Binder/Configuration.cs | 6 +- .../Models/Configuration.cs | 2 +- 19 files changed, 334 insertions(+), 263 deletions(-) diff --git a/Face/Models/_D_Face.cs b/Face/Models/_D_Face.cs index c6df1bc..844036d 100644 --- a/Face/Models/_D_Face.cs +++ b/Face/Models/_D_Face.cs @@ -193,11 +193,13 @@ public class D_Face : IFaceD rectangle = new Rectangle(location.Left, location.Top, width, height); faceFile = new(face.Mapping?.MappingFromLocation?.AreaPermyriad, face.Mapping?.MappingFromLocation?.ConfidencePercent, - face.DateTime, geoLocation?.ToDmsString(), + face.DateTime, + null, face.FaceParts, face.Location, maker, + null, model, face.OutputResolution); faceFileJson = JsonSerializer.Serialize(faceFile, FaceFileGenerationContext.Default.FaceFile); @@ -293,11 +295,9 @@ public class D_Face : IFaceD #pragma warning restore CA1416 - public List GetFaces(string outputResolution, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, FilePath filePath, List> subFileTuples, List parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary outputResolutionToResize, List? mappingFromPhotoPrismCollection) + public List GetFaces(string outputResolution, string cResultsFullGroupDirectory, FilePath filePath, List> subFileTuples, List parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary outputResolutionToResize, List? mappingFromPhotoPrismCollection) { List? results; - if (string.IsNullOrEmpty(dResultsFullGroupDirectory)) - throw new NullReferenceException(nameof(dResultsFullGroupDirectory)); string? json; List locations; string[] changesFrom = [nameof(A_Property), nameof(B_Metadata), nameof(C_Resize)]; @@ -366,7 +366,7 @@ public class D_Face : IFaceD return results; } - public List<(Shared.Models.Face, FileHolder?, string, bool)> SaveFaces(string f, string dResultsFullGroupDirectory, FilePath filePath, List> subFileTuples, List parseExceptions, MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List faces) + public List<(Shared.Models.Face, FileHolder?, string, bool)> SaveFaces(FilePath filePath, List> subFileTuples, List parseExceptions, MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List faces) { List<(Shared.Models.Face, FileHolder?, string, bool Save)> results = []; bool save; @@ -453,11 +453,13 @@ public class D_Face : IFaceD MetadataExtractor.GeoLocation? geoLocation = IMetadata.GeoLocation(exifDirectory); FaceFile faceFile = new(face.Mapping?.MappingFromLocation?.AreaPermyriad, face.Mapping?.MappingFromLocation?.ConfidencePercent, - face.DateTime, geoLocation?.ToDmsString(), + face.DateTime, + null, face.FaceParts, face.Location, maker, + null, model, face.OutputResolution); string faceFileJson = JsonSerializer.Serialize(faceFile, FaceFileGenerationContext.Default.FaceFile); diff --git a/FaceParts/Models/_D2_FaceParts.cs b/FaceParts/Models/_D2_FaceParts.cs index 6b60154..93bb2d3 100644 --- a/FaceParts/Models/_D2_FaceParts.cs +++ b/FaceParts/Models/_D2_FaceParts.cs @@ -2,9 +2,12 @@ using System.Collections.ObjectModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; +using System.Reflection; +using System.Text; using System.Text.Json; using View_by_Distance.Face.Models; using View_by_Distance.Metadata.Models; +using View_by_Distance.Metadata.Models.Stateless.Methods; using View_by_Distance.Property.Models; using View_by_Distance.Property.Models.Stateless; using View_by_Distance.Resize.Models; @@ -25,9 +28,9 @@ public class D2_FaceParts private readonly ImageCodecInfo _ImageCodecInfo; private readonly bool _CheckDFaceAndUpWriteDates; + private readonly ConstructorInfo _ConstructorInfo; private readonly bool _OverrideForFaceLandmarkImages; private readonly EncoderParameters _EncoderParameters; - private readonly List _AngleBracketCollection; private readonly Dictionary _FileGroups; private readonly IPropertyConfiguration _PropertyConfiguration; @@ -37,10 +40,11 @@ public class D2_FaceParts _ImageCodecInfo = imageCodecInfo; _EncoderParameters = encoderParameters; _FileNameExtension = filenameExtension; - _AngleBracketCollection = []; _PropertyConfiguration = propertyConfiguration; _CheckDFaceAndUpWriteDates = checkDFaceAndUpWriteDates; _OverrideForFaceLandmarkImages = overrideForFaceLandmarkImages; + ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, [], null) ?? throw new Exception(); + _ConstructorInfo = constructorInfo; } public override string ToString() @@ -57,41 +61,6 @@ public class D2_FaceParts _FileGroups.Add(keyValuePair.Key, keyValuePair.Value); } - public void SetAngleBracketCollection(IPropertyConfiguration propertyConfiguration, string d2ResultsFullGroupDirectory, string sourceDirectory) - { - _AngleBracketCollection.Clear(); - _AngleBracketCollection.AddRange(IResult.GetDirectoryInfoCollection(propertyConfiguration, - sourceDirectory, - d2ResultsFullGroupDirectory, - contentDescription: "n gif file(s) for each face found", - singletonDescription: string.Empty, - collectionDescription: string.Empty, - converted: true)); - } - - public string GetFacePartsDirectory(IPropertyConfiguration propertyConfiguration, string dResultsFullGroupDirectory, Item item, bool includeNameWithoutExtension) - { - string result; - bool angleBracketCollectionAny = _AngleBracketCollection.Count != 0; - if (!angleBracketCollectionAny) - { - if (item.FilePath.DirectoryName is null) - throw new NullReferenceException(nameof(item.FilePath.DirectoryName)); - SetAngleBracketCollection(propertyConfiguration, dResultsFullGroupDirectory, item.FilePath.DirectoryName); - } - if (includeNameWithoutExtension) - result = Path.Combine(_AngleBracketCollection[0].Replace("<>", _PropertyConfiguration.ResultContent), item.FilePath.NameWithoutExtension); - else - { - result = _AngleBracketCollection[0].Replace("<>", $"[{_PropertyConfiguration.ResultContent}]"); - if (!Directory.Exists(result)) - _ = Directory.CreateDirectory(result); - } - if (!angleBracketCollectionAny) - _AngleBracketCollection.Clear(); - return result; - } - private static void GetPointBounds(PointF[] points, out float xMinimum, out float xMaximum, out float yMinimum, out float yMaximum) { xMinimum = points[0].X; @@ -183,73 +152,234 @@ public class D2_FaceParts return result; } - private void SaveFaceParts(int pointSize, FileHolder resizedFileHolder, bool saveRotated, List<(Shared.Models.Face, string, string)> collection) + private void SaveRotated(MappingFromItem mappingFromItem, List<(Shared.Models.Face, string, string)> collection) + { + double? α; + Bitmap rotated; + foreach ((Shared.Models.Face face, string _, string rotatedFileName) in collection) + { + if (face.FaceParts is null) + continue; + (_, α) = Shared.Models.Stateless.Methods.IFace.GetEyeα(face.FaceParts); + if (α is null) + continue; + using Image image = Image.FromFile(mappingFromItem.ResizedFileHolder.FullName); + rotated = RotateBitmap(image, (float)α.Value); + if (rotated is not null) + { + rotated.Save(rotatedFileName, _ImageCodecInfo, _EncoderParameters); + rotated.Dispose(); + } + } + } + + private string GetSeasonABDirectory(string d2ResultsFullGroupDirectory, MappingFromItem mappingFromItem) + { + string result; + string minimumDateYear = mappingFromItem.MinimumDateTime.ToString("yyyy"); + DateTime dateTime = mappingFromItem.DateTimeOriginal is null ? mappingFromItem.MinimumDateTime : mappingFromItem.DateTimeOriginal.Value; + (int _, string seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeasonAB(dateTime.DayOfYear); + string year = mappingFromItem.DateTimeOriginal is null ? $"{minimumDateYear[1..]}{minimumDateYear[0]}" : mappingFromItem.DateTimeOriginal.Value.ToString("yyyy"); + result = Path.Combine(d2ResultsFullGroupDirectory, $"[{_PropertyConfiguration.ResultContent}]", $"{year} {seasonName}"); + if (!Directory.Exists(result)) + _ = Directory.CreateDirectory(result); + return result; + } + + private void SaveImage(MappingFromItem mappingFromItem, string directory, Image image, List faceFiles) + { + short type = 2; + string faceFileJson; + PropertyItem? propertyItem; + const int artist = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagArtist; // 315 + string fileName = Path.Combine(directory, $"{mappingFromItem.FilePath.Name}{_FileNameExtension}"); + try + { + foreach (int propertyId in image.PropertyIdList) + { + if (propertyId == MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagOrientation) + continue; + image.RemovePropertyItem(propertyId); + } + faceFileJson = JsonSerializer.Serialize(faceFiles.ToArray(), FaceFileCollectionGenerationContext.Default.FaceFileArray); + propertyItem = IProperty.GetPropertyItem(_ConstructorInfo, artist, type, faceFileJson); + image.SetPropertyItem(propertyItem); + image.Save(fileName, _ImageCodecInfo, _EncoderParameters); + } + catch (Exception ex) + { + if (ex is not null && !string.IsNullOrEmpty(fileName) && File.Exists(fileName)) + File.Delete(fileName); + faceFileJson = JsonSerializer.Serialize(faceFiles.ToArray(), FaceFileCollectionGenerationContext.Default.FaceFileArray); + if (!string.IsNullOrEmpty(faceFileJson)) + File.WriteAllText($"{fileName}.json", faceFileJson); + } + } + + private void SaveAllFaceParts(string d2ResultsFullGroupDirectory, MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List faces) { int x; int y; - double? α; - int width; - int height; - Bitmap rotated; - foreach ((Shared.Models.Face face, string fileName, string rotatedFileName) in collection) + Pen pen; + int pointSize; + FaceFile faceFile; + bool? isDefaultName; + List personKeys = []; + List faceFiles = []; + StringBuilder stringBuilder = new(); + MappingFromPerson? mappingFromPerson; + string? maker = IMetadata.GetMaker(exifDirectory); + string? model = IMetadata.GetModel(exifDirectory); + MetadataExtractor.GeoLocation? geoLocation = IMetadata.GeoLocation(exifDirectory); + string directory = GetSeasonABDirectory(d2ResultsFullGroupDirectory, mappingFromItem); + using Image image = Image.FromFile(mappingFromItem.ResizedFileHolder.FullName); + using Graphics graphics = Graphics.FromImage(image); + foreach (Shared.Models.Face face in faces) { - if (face.FaceEncoding is null) + if (face.Location is null || face.FaceEncoding is null || face.FaceParts is null || face.FaceParts.Count == 0) continue; + mappingFromPerson = face.Mapping?.MappingFromPerson; + pen = mappingFromPerson is null ? Pens.Red : Pens.GreenYellow; + isDefaultName = mappingFromPerson is null ? null : Shared.Models.Stateless.Methods.IPerson.IsDefaultName(mappingFromPerson); + if (mappingFromPerson is not null && isDefaultName is not null && !isDefaultName.Value) + personKeys.Add(mappingFromPerson.PersonKey); + faceFile = new(face.Mapping?.MappingFromLocation?.AreaPermyriad, + face.Mapping?.MappingFromLocation?.ConfidencePercent, + geoLocation?.ToDmsString(), + face.DateTime, + face.FaceEncoding, + face.FaceParts, + face.Location, + maker, + mappingFromPerson, + model, + face.OutputResolution); + faceFiles.Add(faceFile); + pointSize = GetPointSize(face.FaceParts, defaultPointSize: 2); + foreach ((FacePart facePart, FacePoint[] facePoints) in face.FaceParts) + { + foreach (FacePoint facePoint in facePoints) + graphics.DrawEllipse(pen, facePoint.X - pointSize, facePoint.Y - pointSize, pointSize * 2, pointSize * 2); + if (facePart == FacePart.Chin) + continue; + if (facePoints.Length < 3) + continue; + x = (int)(from l in facePoints select l.X).Average(); + y = (int)(from l in facePoints select l.Y).Average(); + graphics.DrawEllipse(Pens.Purple, x - pointSize, y - pointSize, pointSize * 2, pointSize * 2); + } + } + _ = graphics.Save(); + SaveImage(mappingFromItem, directory, image, faceFiles); + } + + private void SaveImage(string fileName, Image image, FaceFile faceFile) + { + short type = 2; + string faceFileJson; + PropertyItem? propertyItem; + const int artist = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagArtist; // 315 + try + { + foreach (int propertyId in image.PropertyIdList) + { + if (propertyId == MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagOrientation) + continue; + image.RemovePropertyItem(propertyId); + } + faceFileJson = JsonSerializer.Serialize(faceFile, FaceFileGenerationContext.Default.FaceFile); + propertyItem = IProperty.GetPropertyItem(_ConstructorInfo, artist, type, faceFileJson); + image.SetPropertyItem(propertyItem); + image.Save(fileName, _ImageCodecInfo, _EncoderParameters); + } + catch (Exception ex) + { + if (ex is not null && !string.IsNullOrEmpty(fileName) && File.Exists(fileName)) + File.Delete(fileName); + faceFileJson = JsonSerializer.Serialize(faceFile, FaceFileGenerationContext.Default.FaceFile); + if (!string.IsNullOrEmpty(faceFileJson)) + File.WriteAllText($"{fileName}.json", faceFileJson); + } + } + + private void SaveFaceParts(MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List<(Shared.Models.Face, string, string)> collection) + { + int x; + int y; + Pen pen; + int pointSize; + FaceFile faceFile; + MappingFromPerson? mappingFromPerson; + string? maker = IMetadata.GetMaker(exifDirectory); + string? model = IMetadata.GetModel(exifDirectory); + MetadataExtractor.GeoLocation? geoLocation = IMetadata.GeoLocation(exifDirectory); + foreach ((Shared.Models.Face face, string fileName, string _) in collection) + { try { - using (Image image = Image.FromFile(resizedFileHolder.FullName)) + if (face.Location is null || face.FaceEncoding is null || face.FaceParts is null || face.FaceParts.Count == 0) + continue; + using Image image = Image.FromFile(mappingFromItem.ResizedFileHolder.FullName); + mappingFromPerson = face.Mapping?.MappingFromPerson; + pen = mappingFromPerson is null ? Pens.Red : Pens.GreenYellow; + faceFile = new(face.Mapping?.MappingFromLocation?.AreaPermyriad, + face.Mapping?.MappingFromLocation?.ConfidencePercent, + geoLocation?.ToDmsString(), + face.DateTime, + face.FaceEncoding, + face.FaceParts, + face.Location, + maker, + mappingFromPerson, + model, + face.OutputResolution); + using Graphics graphics = Graphics.FromImage(image); + pointSize = GetPointSize(face.FaceParts, defaultPointSize: 2); + foreach ((FacePart facePart, FacePoint[] facePoints) in face.FaceParts) { - using Graphics graphic = Graphics.FromImage(image); - if (face.FaceParts is null || face.FaceParts.Count == 0) - { - if (face.Location is null) - continue; - width = face.Location.Right - face.Location.Left; - height = face.Location.Bottom - face.Location.Top; - graphic.DrawEllipse(Pens.Red, face.Location.Left, face.Location.Top, width, height); - } - else - { - foreach ((FacePart facePart, FacePoint[] facePoints) in face.FaceParts) - { - foreach (FacePoint facePoint in facePoints) - graphic.DrawEllipse(Pens.GreenYellow, facePoint.X - pointSize, facePoint.Y - pointSize, pointSize * 2, pointSize * 2); - if (facePart == FacePart.Chin) - continue; - if (facePoints.Length < 3) - continue; - x = (int)(from l in facePoints select l.X).Average(); - y = (int)(from l in facePoints select l.Y).Average(); - graphic.DrawEllipse(Pens.Purple, x - pointSize, y - pointSize, pointSize * 2, pointSize * 2); - } - } - image.Save(fileName, _ImageCodecInfo, _EncoderParameters); - } - if (saveRotated && face.FaceParts is not null) - { - (_, α) = Shared.Models.Stateless.Methods.IFace.GetEyeα(face.FaceParts); - if (α is null) + foreach (FacePoint facePoint in facePoints) + graphics.DrawEllipse(pen, facePoint.X - pointSize, facePoint.Y - pointSize, pointSize * 2, pointSize * 2); + if (facePart == FacePart.Chin) continue; - using Image image = Image.FromFile(resizedFileHolder.FullName); - rotated = RotateBitmap(image, (float)α.Value); - if (rotated is not null) - { - rotated.Save(rotatedFileName, _ImageCodecInfo, _EncoderParameters); - rotated.Dispose(); - } + if (facePoints.Length < 3) + continue; + x = (int)(from l in facePoints select l.X).Average(); + y = (int)(from l in facePoints select l.Y).Average(); + graphics.DrawEllipse(Pens.Purple, x - pointSize, y - pointSize, pointSize * 2, pointSize * 2); } + _ = graphics.Save(); + SaveImage(fileName, image, faceFile); + } + catch (Exception) + { + if (File.Exists(fileName)) + File.Delete(fileName); } - catch (Exception) { } } } + private int GetPointSize(Dictionary faceParts, int defaultPointSize) + { + int result; + FacePoint[]? facePoints; + if (faceParts.TryGetValue(FacePart.LeftEye, out facePoints)) + result = (int)Math.Ceiling((facePoints.Max(l => l.X) - facePoints.Min(l => l.X)) * .05); + else + { + if (faceParts.TryGetValue(FacePart.RightEye, out facePoints)) + result = (int)Math.Ceiling((facePoints.Max(l => l.X) - facePoints.Min(l => l.X)) * .05); + else + result = defaultPointSize; + } + return result; + } + #pragma warning restore CA1416 - public void SaveFaceLandmarkImages(Configuration configuration, FilePath filePath, List> subFileTuples, List parseExceptions, MappingFromItem mappingFromItem, List faces, bool saveRotated) + public void SaveFaceLandmarkImages(Configuration configuration, string d2ResultsFullGroupDirectory, FilePath filePath, List> subFileTuples, List parseExceptions, MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List faces, bool saveRotated) { FileInfo fileInfo; bool check = false; - const int pointSize = 2; FileInfo rotatedFileInfo; DateTime? dateTime = null; long ticks = DateTime.Now.Ticks; @@ -296,37 +426,12 @@ public class D2_FaceParts { if (!directoryExists) _ = Directory.CreateDirectory(directory); - SaveFaceParts(pointSize, mappingFromItem.ResizedFileHolder, saveRotated, collection); + SaveFaceParts(mappingFromItem, exifDirectory, collection); + if (saveRotated) + SaveRotated(mappingFromItem, collection); } } -#pragma warning disable CA1416 - - private void SaveFaceLandmarkImage(MappingFromItem mappingFromItem, List<(Shared.Models.Face, FileHolder?, string, bool)> faceCollection, string fileName) - { - Pen pen; - using Image image = Image.FromFile(mappingFromItem.ResizedFileHolder.FullName); - using Graphics graphic = Graphics.FromImage(image); - foreach ((Shared.Models.Face face, FileHolder? _, string _, bool _) in faceCollection) - { - if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null || face.FaceParts is null || face.FaceParts.Count == 0) - continue; - pen = face.Mapping?.MappingFromPerson is null ? Pens.Red : Pens.GreenYellow; - try - { - foreach ((FacePart facePart, FacePoint[] facePoints) in face.FaceParts) - { - for (int i = 0; i < facePoints.Length - 1; i++) - graphic.DrawLine(pen, new Point(facePoints[i].X, facePoints[i].Y), new Point(facePoints[i + 1].X, facePoints[i + 1].Y)); - } - } - catch (Exception) { } - } - image.Save(fileName, _ImageCodecInfo, _EncoderParameters); - } - -#pragma warning restore CA1416 - private static bool GetNotMapped(string facePartsCollectionDirectory, List<(Shared.Models.Face Face, FileHolder?, string, bool)> faceCollection) { bool results = false; @@ -360,19 +465,18 @@ public class D2_FaceParts return results; } - public void CopyFacesAndSaveFaceLandmarkImage(string facePartsCollectionDirectory, MappingFromItem mappingFromItem, List<(Shared.Models.Face Face, FileHolder?, string, bool)> faceCollection) + public void SaveFaceLandmarkImages(string d2ResultsFullGroupDirectory, MappingFromItem mappingFromItem, ExifDirectory exifDirectory, List faces) { - bool hasNotMapped = GetNotMapped(facePartsCollectionDirectory, faceCollection); - string fileName = Path.Combine(facePartsCollectionDirectory, $"{mappingFromItem.FilePath.Name}{_FileNameExtension}"); - bool save = faceCollection.Any(l => l.Face.FaceEncoding is not null && l.Face.Location is not null && l.Face.OutputResolution is not null && l.Face.FaceParts is not null && l.Face.FaceParts.Count != 0); - FileInfo fileInfo = new(fileName); - if (save && (!fileInfo.Exists || new TimeSpan(DateTime.Now.Ticks - fileInfo.LastWriteTime.Ticks).TotalDays > 10)) + bool any = false; + foreach (Shared.Models.Face face in faces) { - SaveFaceLandmarkImage(mappingFromItem, faceCollection, fileName); - fileInfo.Refresh(); + if (face.Location is null || face.FaceEncoding is null || face.FaceParts is null || face.FaceParts.Count == 0) + continue; + if (!any) + any = true; } - if (!hasNotMapped && !fileInfo.Attributes.HasFlag(FileAttributes.Hidden) && (fileInfo.Exists || save)) - File.SetAttributes(fileName, FileAttributes.Hidden); + if (any) + SaveAllFaceParts(d2ResultsFullGroupDirectory, mappingFromItem, exifDirectory, faces); } } \ No newline at end of file diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index d9fab14..7dd490b 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -88,7 +88,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable _Logger?.LogInformation(configuration.ModelDirectory); { (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetPngLowQuality(); - (ImageCodecInfo hiddenImageCodecInfo, EncoderParameters hiddenEncoderParameters, string hiddenFileNameExtension) = C_Resize.GetGifLowQuality(); + (ImageCodecInfo hiddenImageCodecInfo, EncoderParameters hiddenEncoderParameters, string hiddenFileNameExtension) = C_Resize.GetJpegLowQuality(); _Faces = new D_Face( argZero, configuration.PropertyConfiguration, @@ -110,7 +110,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable configuration.RectangleIntersectMinimums); } { - (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetGifLowQuality(); + (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetJpegLowQuality(); _FaceParts = new D2_FaceParts(_Configuration.PropertyConfiguration, imageCodecInfo, encoderParameters, filenameExtension, configuration.CheckDFaceAndUpWriteDates, configuration.OverrideForFaceLandmarkImages); } _DistanceLimits = new(_Configuration.FaceAreaPermyriad, _Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeDistanceTolerance, _Configuration.RangeFaceAreaPermyriadTolerance, _Configuration.RangeFaceConfidence, _Configuration.SortingMaximumPerFaceShouldBeHigh); @@ -204,6 +204,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable 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 ((from l in configuration.SaveFaceLandmarkForOutputResolutionsV2 where !configuration.ValidResolutions.Contains(l) select false).Any()) + throw new Exception($"One or more {nameof(configuration.SaveFaceLandmarkForOutputResolutionsV2)} are not in the ValidResolutions list!"); if (string.IsNullOrEmpty(configuration.ModelName)) throw new NullReferenceException(nameof(configuration.ModelName)); if (string.IsNullOrEmpty(configuration.OutputExtension)) @@ -630,7 +632,6 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable outputResolution, outputResolutionHasNumber, cResultsFullGroupDirectory, - dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, sourceDirectoryChanges, fileNameToCollection, @@ -1020,11 +1021,10 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable MappingFromFilterPre mappingFromFilterPre; MappingFromFilterPost mappingFromFilterPost; bool? isFocusModel = GetIsFocusModel(item.Property); + ReadOnlyDictionary>? wholePercentagesToPersonContainers = mapLogic.GetWholePercentagesToPersonContainers(item.Property?.Id); long[] jLinkResolvedPersonKeys = _JLinkResolvedDirectories.Select(l => l.PersonKey).ToArray(); - ReadOnlyDictionary>? wholePercentagesToPersonContainers; foreach (Shared.Models.Face face in faces) { - wholePercentagesToPersonContainers = mapLogic.GetWholePercentagesToPersonContainers(item.Property?.Id); if (item.Property?.Id is null || face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) { canReMap = null; @@ -1105,12 +1105,12 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable int faceAreaPermyriad = 0; bool? isFocusModel = GetIsFocusModel(item.Property); long[] jLinkResolvedPersonKeys = _JLinkResolvedDirectories.Select(l => l.PersonKey).ToArray(); - ReadOnlyDictionary>? wholePercentagesToPersonContainers = mapLogic.GetWholePercentagesToPersonContainers(mappingFromItem.Id); int wholePercentRectangle = Shared.Models.Stateless.Methods.ILocation.GetWholePercentages(Shared.Models.Stateless.ILocation.Digits); string deterministicHashCodeKey = IMapping.GetDeterministicHashCodeKey(item.FilePath, Shared.Models.Stateless.ILocation.Digits); MappingFromLocation? mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, eyeα, eyeReview, wholePercentRectangle); bool? inSkipCollection = mapLogic.InSkipCollection(mappingFromItem.Id, mappingFromLocation); MappingFromFilterPre mappingFromFilterPre = new(inSkipCollection, isFocusModel, isFocusRelativePath); + ReadOnlyDictionary>? wholePercentagesToPersonContainers = mapLogic.GetWholePercentagesToPersonContainers(mappingFromItem.Id); bool? canReMap = Map.Models.Stateless.Methods.IMapLogic.CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation); bool? isFocusPerson = mapLogic.IsFocusPerson(_Configuration.SkipPersonWithMoreThen, jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation); MappingFromFilterPost mappingFromFilterPost = new(canReMap, inSkipCollection, isFocusPerson); @@ -1125,7 +1125,6 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable string outputResolution, bool outputResolutionHasNumber, string cResultsFullGroupDirectory, - string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, List> sourceDirectoryChanges, Dictionary> fileNameToCollection, @@ -1133,8 +1132,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable int index, Item item, DateTime[] containerDateTimes, - bool? isFocusRelativePath, - string facePartsCollectionDirectory) + bool? isFocusRelativePath) { int result = 0; List faces; @@ -1245,11 +1243,9 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable if (!fileNameToCollection.TryGetValue(mappingFromItem.Id, out mappingFromPhotoPrismCollection)) mappingFromPhotoPrismCollection = null; bool move = _Configuration.DistanceMoveUnableToMatch || _Configuration.DistanceRenameToMatch && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution); - faces = _Faces.GetFaces(outputResolution, cResultsFullGroupDirectory, dResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionToResize, mappingFromPhotoPrismCollection); + faces = _Faces.GetFaces(outputResolution, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionToResize, mappingFromPhotoPrismCollection); result = GetNotMappedCountAndUpdateMappingFromPersonThenSetMapping(mapLogic, item, isFocusRelativePath, mappingFromItem, mappingFromPhotoPrismCollection, faces); - List<(Shared.Models.Face, FileHolder?, string, bool Saved)> faceCollection = _Faces.SaveFaces(_FaceParts.FileNameExtension, dResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, mappingFromItem, exifDirectory, faces); - if (_Configuration.CopyFacesAndSaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) - _FaceParts.CopyFacesAndSaveFaceLandmarkImage(facePartsCollectionDirectory, mappingFromItem, faceCollection); + List<(Shared.Models.Face, FileHolder?, string, bool Saved)> faceCollection = _Faces.SaveFaces(item.FilePath, subFileTuples, parseExceptions, mappingFromItem, exifDirectory, faces); if (move && faceCollection.All(l => !l.Saved)) { ReadOnlyCollection locationContainers = mapLogic.GetLocationContainers(item); @@ -1266,8 +1262,10 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable { bool saveRotated = false; string sourceDirectorySegment = Property.Models.Stateless.IResult.GetRelativePath(_Configuration.PropertyConfiguration, container.SourceDirectory); - _FaceParts.SaveFaceLandmarkImages(_Configuration.PropertyConfiguration, item.FilePath, subFileTuples, parseExceptions, mappingFromItem, faces, saveRotated); + _FaceParts.SaveFaceLandmarkImages(_Configuration.PropertyConfiguration, d2ResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, mappingFromItem, exifDirectory, faces, saveRotated); } + if (_Configuration.SaveFaceLandmarkForOutputResolutionsV2.Contains(outputResolution)) + _FaceParts.SaveFaceLandmarkImages(d2ResultsFullGroupDirectory, mappingFromItem, exifDirectory, faces); } lock (sourceDirectoryChanges) { @@ -1284,7 +1282,6 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable string outputResolution, bool outputResolutionHasNumber, string cResultsFullGroupDirectory, - string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, List> sourceDirectoryChanges, Dictionary> fileNameToCollection, @@ -1299,7 +1296,6 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; string focusRelativePath = Path.GetFullPath(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, _Configuration.FocusDirectory)); bool? isFocusRelativePath = string.IsNullOrEmpty(_Configuration.FocusDirectory) ? null : container.SourceDirectory.StartsWith(focusRelativePath); - string facePartsCollectionDirectory = _Configuration.CopyFacesAndSaveFaceLandmarkForOutputResolutions.Contains(outputResolution) ? _FaceParts.GetFacePartsDirectory(_Configuration.PropertyConfiguration, d2ResultsFullGroupDirectory, item: filteredItems.First(), includeNameWithoutExtension: false) : string.Empty; bool anyPropertiesChangedForX = _Configuration.PropertyConfiguration.PropertiesChangedForProperty || _Configuration.PropertiesChangedForDistance || _Configuration.PropertiesChangedForFaces || _Configuration.PropertiesChangedForIndex || _Configuration.PropertiesChangedForMetadata || _Configuration.PropertiesChangedForResize; using ProgressBar progressBar = new(filteredItems.Count, message, options); _ = Parallel.For(0, filteredItems.Count, parallelOptions, (i, state) => @@ -1312,7 +1308,6 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable outputResolution, outputResolutionHasNumber, cResultsFullGroupDirectory, - dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, sourceDirectoryChanges, fileNameToCollection, @@ -1320,8 +1315,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable index: i, filteredItems[i], containerDateTimes, - isFocusRelativePath, - facePartsCollectionDirectory); + isFocusRelativePath); if (!anyPropertiesChangedForX && (i == 0 || sourceDirectoryChanges.Count > 0)) progressBar.Tick(); } diff --git a/Instance/Models/Binder/Configuration.cs b/Instance/Models/Binder/Configuration.cs index aaaeb65..8c03e89 100644 --- a/Instance/Models/Binder/Configuration.cs +++ b/Instance/Models/Binder/Configuration.cs @@ -9,7 +9,6 @@ public class Configuration public bool? CheckDFaceAndUpWriteDates { get; set; } public bool? CheckJsonForDistanceResults { get; set; } - public string[]? CopyFacesAndSaveFaceLandmarkForOutputResolutions { get; set; } public int? CrossDirectoryMaxItemsInDistanceCollection { get; set; } public bool? DeletePossibleDuplicates { get; set; } public int? DistanceFactor { get; set; } @@ -77,6 +76,7 @@ public class Configuration public string[]? SaveBlurHashForOutputResolutions { get; set; } public string[]? SaveFaceDistancesForOutputResolutions { get; set; } public string[]? SaveFaceLandmarkForOutputResolutions { get; set; } + public string[]? SaveFaceLandmarkForOutputResolutionsV2 { get; set; } public string[]? SaveFilteredOriginalImagesFromJLinksForOutputResolutions { get; set; } public bool? SaveFullYearOfRandomFiles { get; set; } public bool? SaveIndividually { get; set; } @@ -129,7 +129,6 @@ public class Configuration if (configuration.CheckDFaceAndUpWriteDates is null) throw new NullReferenceException(nameof(configuration.CheckDFaceAndUpWriteDates)); if (configuration?.CheckDFaceAndUpWriteDates is null) throw new NullReferenceException(nameof(configuration.CheckDFaceAndUpWriteDates)); if (configuration?.CheckJsonForDistanceResults is null) throw new NullReferenceException(nameof(configuration.CheckJsonForDistanceResults)); - // if (configuration?.CopyFacesAndSaveFaceLandmarkForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.CopyFacesAndSaveFaceLandmarkForOutputResolutions)); if (configuration?.CrossDirectoryMaxItemsInDistanceCollection is null) throw new NullReferenceException(nameof(configuration.CrossDirectoryMaxItemsInDistanceCollection)); if (configuration?.DeletePossibleDuplicates is null) throw new NullReferenceException(nameof(configuration.DeletePossibleDuplicates)); if (configuration?.DistanceFactor is null) throw new NullReferenceException(nameof(configuration.DistanceFactor)); @@ -197,6 +196,7 @@ public class Configuration // if (configuration?.SaveBlurHashForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveBlurHashForOutputResolutions)); // if (configuration?.SaveFaceDistancesForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveFaceDistancesForOutputResolutions)); // if (configuration?.SaveFaceLandmarkForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveFaceLandmarkForOutputResolutions)); + // if (configuration?.SaveFaceLandmarkForOutputResolutionsV2 is null) throw new NullReferenceException(nameof(configuration.SaveFaceLandmarkForOutputResolutionsV2)); // if (configuration?.SaveFilteredOriginalImagesFromJLinksForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveFilteredOriginalImagesFromJLinksForOutputResolutions)); if (configuration?.SaveFullYearOfRandomFiles is null) throw new NullReferenceException(nameof(configuration.SaveFullYearOfRandomFiles)); if (configuration?.SaveIndividually is null) throw new NullReferenceException(nameof(configuration.SaveIndividually)); @@ -221,7 +221,6 @@ public class Configuration result = new(propertyConfiguration, configuration.CheckDFaceAndUpWriteDates.Value, configuration.CheckJsonForDistanceResults.Value, - configuration.CopyFacesAndSaveFaceLandmarkForOutputResolutions ?? [], configuration.CrossDirectoryMaxItemsInDistanceCollection.Value, configuration.DeletePossibleDuplicates.Value, configuration.DistanceFactor.Value, @@ -289,6 +288,7 @@ public class Configuration configuration.SaveBlurHashForOutputResolutions ?? [], configuration.SaveFaceDistancesForOutputResolutions ?? [], configuration.SaveFaceLandmarkForOutputResolutions ?? [], + configuration.SaveFaceLandmarkForOutputResolutionsV2 ?? [], configuration.SaveFilteredOriginalImagesFromJLinksForOutputResolutions ?? [], configuration.SaveFullYearOfRandomFiles.Value, configuration.SaveIndividually.Value, diff --git a/Instance/Models/Configuration.cs b/Instance/Models/Configuration.cs index 642e9bc..45ff305 100644 --- a/Instance/Models/Configuration.cs +++ b/Instance/Models/Configuration.cs @@ -3,7 +3,6 @@ namespace View_by_Distance.Instance.Models; public record Configuration(Property.Models.Configuration PropertyConfiguration, bool CheckDFaceAndUpWriteDates, bool CheckJsonForDistanceResults, - string[] CopyFacesAndSaveFaceLandmarkForOutputResolutions, int CrossDirectoryMaxItemsInDistanceCollection, bool DeletePossibleDuplicates, int DistanceFactor, @@ -71,6 +70,7 @@ public record Configuration(Property.Models.Configuration PropertyConfiguration, string[] SaveBlurHashForOutputResolutions, string[] SaveFaceDistancesForOutputResolutions, string[] SaveFaceLandmarkForOutputResolutions, + string[] SaveFaceLandmarkForOutputResolutionsV2, string[] SaveFilteredOriginalImagesFromJLinksForOutputResolutions, bool SaveFullYearOfRandomFiles, bool SaveIndividually, diff --git a/Resize/Models/_C_Resize.cs b/Resize/Models/_C_Resize.cs index a5f879b..4cc2d35 100644 --- a/Resize/Models/_C_Resize.cs +++ b/Resize/Models/_C_Resize.cs @@ -94,10 +94,10 @@ public class C_Resize #pragma warning disable CA1416 - public static (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) GetGifLowQuality() + public static (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) GetJpegLowQuality() { (ImageCodecInfo, EncoderParameters, string) result; - ImageFormat imageFormat = ImageFormat.Gif; + ImageFormat imageFormat = ImageFormat.Jpeg; ImageCodecInfo imageCodecInfo = (from l in ImageCodecInfo.GetImageEncoders() where l.FormatID == imageFormat.Guid select l).First(); EncoderParameters encoderParameters = new(1); encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 75L); diff --git a/Shared/Models/FaceEncoding.cs b/Shared/Models/FaceEncoding.cs index 482cfe2..e5c5360 100644 --- a/Shared/Models/FaceEncoding.cs +++ b/Shared/Models/FaceEncoding.cs @@ -1,27 +1,11 @@ -using System.Text.Json; using System.Text.Json.Serialization; namespace View_by_Distance.Shared.Models; -public class FaceEncoding : Properties.IFaceEncoding +public record FaceEncoding(double[] RawEncoding, int Size); + +[JsonSourceGenerationOptions(WriteIndented = false)] +[JsonSerializable(typeof(FaceEncoding))] +public partial class FaceEncodingGenerationContext : JsonSerializerContext { - - protected double[] _RawEncoding; - protected int _Size; - public double[] RawEncoding => _RawEncoding; - public int Size => _Size; - - [JsonConstructor] - public FaceEncoding(double[] rawEncoding, int size) - { - _RawEncoding = rawEncoding; - _Size = size; - } - - public override string ToString() - { - string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); - return result; - } - } \ No newline at end of file diff --git a/Shared/Models/FaceFile.cs b/Shared/Models/FaceFile.cs index ee46397..4f1a3ef 100644 --- a/Shared/Models/FaceFile.cs +++ b/Shared/Models/FaceFile.cs @@ -4,11 +4,13 @@ namespace View_by_Distance.Shared.Models; public record FaceFile(int? AreaPermyriad, int? ConfidencePercent, - DateTime DateTime, string? DMS, + DateTime DateTime, + FaceEncoding? FaceEncoding, Dictionary? FaceParts, Location? Location, string? Maker, + MappingFromPerson? MappingFromPerson, string? Model, OutputResolution? OutputResolution); @@ -16,4 +18,16 @@ public record FaceFile(int? AreaPermyriad, [JsonSerializable(typeof(FaceFile))] public partial class FaceFileGenerationContext : JsonSerializerContext { +} + +[JsonSourceGenerationOptions(WriteIndented = false, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)] +[JsonSerializable(typeof(FaceFile[]))] +public partial class FaceFileCollectionGenerationContext : JsonSerializerContext +{ +} + +[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)] +[JsonSerializable(typeof(FaceFile[]))] +public partial class FaceFileCollectionWriteIndentedGenerationContext : JsonSerializerContext +{ } \ No newline at end of file diff --git a/Shared/Models/FacePoint.cs b/Shared/Models/FacePoint.cs index a86e381..094577a 100644 --- a/Shared/Models/FacePoint.cs +++ b/Shared/Models/FacePoint.cs @@ -1,58 +1,35 @@ using System.Drawing; -using System.Text.Json; using System.Text.Json.Serialization; namespace View_by_Distance.Shared.Models; -public class FacePoint : Properties.IFacePoint +[method: JsonConstructor] +public class FacePoint(int index, int x, int y) : Properties.IFacePoint { + public int Index { get; } = index; + public int X { get; } = x; + public int Y { get; } = y; - protected int _Index; - protected int _X; - protected int _Y; - public int Index => _Index; - public int X => _X; - public int Y => _Y; - - private readonly Point _Point; - - [JsonConstructor] - public FacePoint(int index, int x, int y) - { - _Index = index; - _X = x; - _Y = y; - _Point = new(x, y); - } - - public FacePoint(Point point, int index) : - this(index, point.X, point.Y) - { } + private readonly Point _Point = new(x, y); public override bool Equals(object? obj) => obj is FacePoint point && Equals(point); - public override string ToString() - { - string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); - return result; - } - #pragma warning disable IDE0070 public override int GetHashCode() #pragma warning restore IDE0070 { int hashCode = 1861411795; - hashCode = hashCode * -1521134295 + _Point.GetHashCode(); - hashCode = hashCode * -1521134295 + _Index.GetHashCode(); + hashCode = (hashCode * -1521134295) + _Point.GetHashCode(); + hashCode = (hashCode * -1521134295) + Index.GetHashCode(); return hashCode; } public bool Equals(FacePoint? facePoint) { return facePoint is not null - && _X == facePoint.X - && _Y == facePoint.Y - && _Index == facePoint.Index; + && X == facePoint.X + && Y == facePoint.Y + && Index == facePoint.Index; } public static bool operator ==(FacePoint point1, FacePoint point2) => point1.Equals(point2); diff --git a/Shared/Models/Location.cs b/Shared/Models/Location.cs index 83ce666..bff202c 100644 --- a/Shared/Models/Location.cs +++ b/Shared/Models/Location.cs @@ -79,10 +79,10 @@ public class Location : Properties.ILocation, IEquatable #pragma warning restore IDE0070 { int hashCode = -773114317; - hashCode = hashCode * -1521134295 + Bottom.GetHashCode(); - hashCode = hashCode * -1521134295 + Left.GetHashCode(); - hashCode = hashCode * -1521134295 + Right.GetHashCode(); - hashCode = hashCode * -1521134295 + Top.GetHashCode(); + hashCode = (hashCode * -1521134295) + Bottom.GetHashCode(); + hashCode = (hashCode * -1521134295) + Left.GetHashCode(); + hashCode = (hashCode * -1521134295) + Right.GetHashCode(); + hashCode = (hashCode * -1521134295) + Top.GetHashCode(); return hashCode; } diff --git a/Shared/Models/OutputResolution.cs b/Shared/Models/OutputResolution.cs index cb4350a..4a8c65b 100644 --- a/Shared/Models/OutputResolution.cs +++ b/Shared/Models/OutputResolution.cs @@ -1,30 +1,5 @@ -using System.Text.Json; -using System.Text.Json.Serialization; - namespace View_by_Distance.Shared.Models; -public class OutputResolution : Properties.IOutputResolution -{ - - protected int _Height; - protected int _Orientation; - protected int _Width; - public int Height => _Height; - public int Orientation => _Orientation; - public int Width => _Width; - - [JsonConstructor] - public OutputResolution(int height, int orientation, int width) - { - _Height = height; - _Orientation = orientation; - _Width = width; - } - - public override string ToString() - { - string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); - return result; - } - -} \ No newline at end of file +public record OutputResolution(int Height, + int Orientation, + int Width); \ No newline at end of file diff --git a/Shared/Models/Properties/IFaceEncoding.cs b/Shared/Models/Properties/IFaceEncoding.cs index 5cd6707..9b61d47 100644 --- a/Shared/Models/Properties/IFaceEncoding.cs +++ b/Shared/Models/Properties/IFaceEncoding.cs @@ -1,9 +1,9 @@ -namespace View_by_Distance.Shared.Models.Properties; +// namespace View_by_Distance.Shared.Models.Properties; -public interface IFaceEncoding -{ +// public interface IFaceEncoding +// { - public double[] RawEncoding { get; } - public int Size { get; } +// public double[] RawEncoding { get; } +// public int Size { get; } -} \ No newline at end of file +// } \ No newline at end of file diff --git a/Shared/Models/Properties/IOutputResolution.cs b/Shared/Models/Properties/IOutputResolution.cs index ede782c..40a339c 100644 --- a/Shared/Models/Properties/IOutputResolution.cs +++ b/Shared/Models/Properties/IOutputResolution.cs @@ -1,10 +1,10 @@ -namespace View_by_Distance.Shared.Models.Properties; +// namespace View_by_Distance.Shared.Models.Properties; -public interface IOutputResolution -{ +// public interface IOutputResolution +// { - public int Height { get; } - public int Orientation { get; } - public int Width { get; } +// public int Height { get; } +// public int Orientation { get; } +// public int Width { get; } -} \ No newline at end of file +// } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IProperty.cs b/Shared/Models/Stateless/Methods/IProperty.cs index 47e96ef..c396364 100644 --- a/Shared/Models/Stateless/Methods/IProperty.cs +++ b/Shared/Models/Stateless/Methods/IProperty.cs @@ -18,6 +18,11 @@ public interface IProperty static (int Season, string seasonName) GetSeason(int dayOfYear) => Property.GetSeason(dayOfYear); + (int Season, string seasonName) TestStatic_GetSeasonAB(int dayOfYear) => + GetSeasonAB(dayOfYear); + static (int Season, string seasonName) GetSeasonAB(int dayOfYear) => + Property.GetSeasonAB(dayOfYear); + string TestStatic_GetDiffRootDirectory(string diffPropertyDirectory) => GetDiffRootDirectory(diffPropertyDirectory); static string GetDiffRootDirectory(string diffPropertyDirectory) => diff --git a/Shared/Models/Stateless/Methods/Property.cs b/Shared/Models/Stateless/Methods/Property.cs index 6cbb570..afdb516 100644 --- a/Shared/Models/Stateless/Methods/Property.cs +++ b/Shared/Models/Stateless/Methods/Property.cs @@ -16,6 +16,22 @@ internal abstract class Property return result; } + internal static (int Season, string seasonName) GetSeasonAB(int dayOfYear) + { + (int Season, string seasonName) result = dayOfYear switch + { + < 78 => new(0, "WinterA"), + < 124 => new(1, "SpringA"), + < 171 => new(1, "SpringB"), + < 217 => new(2, "SummerA"), + < 264 => new(2, "SummerB"), + < 309 => new(3, "FallA"), + < 354 => new(3, "FallB"), + _ => new(4, "WinterB") + }; + return result; + } + internal static (bool?, string[]) IsWrongYear(string[] segments, string year) { bool? result; diff --git a/Tests/Models/Binder/Configuration.cs b/Tests/Models/Binder/Configuration.cs index e003aa3..44f06ea 100644 --- a/Tests/Models/Binder/Configuration.cs +++ b/Tests/Models/Binder/Configuration.cs @@ -9,7 +9,6 @@ public class Configuration public bool? CheckDFaceAndUpWriteDates { get; set; } public bool? CheckJsonForDistanceResults { get; set; } - public string[]? CopyFacesAndSaveFaceLandmarkForOutputResolutions { get; set; } public int? CrossDirectoryMaxItemsInDistanceCollection { get; set; } public bool? DeletePossibleDuplicates { get; set; } public int? DistanceFactor { get; set; } @@ -72,6 +71,7 @@ public class Configuration public string[]? SaveBlurHashForOutputResolutions { get; set; } public string[]? SaveFaceDistancesForOutputResolutions { get; set; } public string[]? SaveFaceLandmarkForOutputResolutions { get; set; } + public string[]? SaveFaceLandmarkForOutputResolutionsV2 { get; set; } public string[]? SaveFilteredOriginalImagesFromJLinksForOutputResolutions { get; set; } public bool? SaveFullYearOfRandomFiles { get; set; } public bool? SaveIndividually { get; set; } @@ -123,7 +123,6 @@ public class Configuration if (configuration.CheckDFaceAndUpWriteDates is null) throw new NullReferenceException(nameof(configuration.CheckDFaceAndUpWriteDates)); if (configuration?.CheckDFaceAndUpWriteDates is null) throw new NullReferenceException(nameof(configuration.CheckDFaceAndUpWriteDates)); if (configuration?.CheckJsonForDistanceResults is null) throw new NullReferenceException(nameof(configuration.CheckJsonForDistanceResults)); - // if (configuration?.CopyFacesAndSaveFaceLandmarkForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.CopyFacesAndSaveFaceLandmarkForOutputResolutions)); if (configuration?.CrossDirectoryMaxItemsInDistanceCollection is null) throw new NullReferenceException(nameof(configuration.CrossDirectoryMaxItemsInDistanceCollection)); if (configuration?.DeletePossibleDuplicates is null) throw new NullReferenceException(nameof(configuration.DeletePossibleDuplicates)); if (configuration?.DistanceFactor is null) throw new NullReferenceException(nameof(configuration.DistanceFactor)); @@ -184,6 +183,7 @@ public class Configuration // if (configuration?.SaveBlurHashForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveBlurHashForOutputResolutions)); // if (configuration?.SaveFaceDistancesForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveFaceDistancesForOutputResolutions)); // if (configuration?.SaveFaceLandmarkForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveFaceLandmarkForOutputResolutions)); + // if (configuration?.SaveFaceLandmarkForOutputResolutionsV2 is null) throw new NullReferenceException(nameof(configuration.SaveFaceLandmarkForOutputResolutionsV2)); // if (configuration?.SaveFilteredOriginalImagesFromJLinksForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveFilteredOriginalImagesFromJLinksForOutputResolutions)); if (configuration?.SaveFullYearOfRandomFiles is null) throw new NullReferenceException(nameof(configuration.SaveFullYearOfRandomFiles)); if (configuration?.SaveIndividually is null) throw new NullReferenceException(nameof(configuration.SaveIndividually)); @@ -207,7 +207,6 @@ public class Configuration result = new(propertyConfiguration, configuration.CheckDFaceAndUpWriteDates.Value, configuration.CheckJsonForDistanceResults.Value, - configuration.CopyFacesAndSaveFaceLandmarkForOutputResolutions ?? [], configuration.CrossDirectoryMaxItemsInDistanceCollection.Value, configuration.DeletePossibleDuplicates.Value, configuration.DistanceFactor.Value, @@ -268,6 +267,7 @@ public class Configuration configuration.SaveBlurHashForOutputResolutions ?? [], configuration.SaveFaceDistancesForOutputResolutions ?? [], configuration.SaveFaceLandmarkForOutputResolutions ?? [], + configuration.SaveFaceLandmarkForOutputResolutionsV2 ?? [], configuration.SaveFilteredOriginalImagesFromJLinksForOutputResolutions ?? [], configuration.SaveIndividually.Value, configuration.SaveFullYearOfRandomFiles.Value, diff --git a/Tests/Models/Configuration.cs b/Tests/Models/Configuration.cs index 201381b..9a94207 100644 --- a/Tests/Models/Configuration.cs +++ b/Tests/Models/Configuration.cs @@ -3,7 +3,6 @@ namespace View_by_Distance.Tests.Models; public record Configuration(Property.Models.Configuration PropertyConfiguration, bool CheckDFaceAndUpWriteDates, bool CheckJsonForDistanceResults, - string[] CopyFacesAndSaveFaceLandmarkForOutputResolutions, int CrossDirectoryMaxItemsInDistanceCollection, bool DeletePossibleDuplicates, int DistanceFactor, @@ -64,6 +63,7 @@ public record Configuration(Property.Models.Configuration PropertyConfiguration, string[] SaveBlurHashForOutputResolutions, string[] SaveFaceDistancesForOutputResolutions, string[] SaveFaceLandmarkForOutputResolutions, + string[] SaveFaceLandmarkForOutputResolutionsV2, string[] SaveFilteredOriginalImagesFromJLinksForOutputResolutions, bool SaveIndividually, bool SaveFullYearOfRandomFiles, diff --git a/TestsWithFaceRecognitionDotNet/Models/Binder/Configuration.cs b/TestsWithFaceRecognitionDotNet/Models/Binder/Configuration.cs index b1e144e..3ec588b 100644 --- a/TestsWithFaceRecognitionDotNet/Models/Binder/Configuration.cs +++ b/TestsWithFaceRecognitionDotNet/Models/Binder/Configuration.cs @@ -9,7 +9,6 @@ public class Configuration public bool? CheckDFaceAndUpWriteDates { get; set; } public bool? CheckJsonForDistanceResults { get; set; } - public string[]? CopyFacesAndSaveFaceLandmarkForOutputResolutions { get; set; } public int? CrossDirectoryMaxItemsInDistanceCollection { get; set; } public bool? DeletePossibleDuplicates { get; set; } public int? DistanceFactor { get; set; } @@ -71,6 +70,7 @@ public class Configuration public string[]? SaveBlurHashForOutputResolutions { get; set; } public string[]? SaveFaceDistancesForOutputResolutions { get; set; } public string[]? SaveFaceLandmarkForOutputResolutions { get; set; } + public string[]? SaveFaceLandmarkForOutputResolutionsV2 { get; set; } public string[]? SaveFilteredOriginalImagesFromJLinksForOutputResolutions { get; set; } public bool? SaveFullYearOfRandomFiles { get; set; } public bool? SaveIndividually { get; set; } @@ -122,7 +122,6 @@ public class Configuration if (configuration.CheckDFaceAndUpWriteDates is null) throw new NullReferenceException(nameof(configuration.CheckDFaceAndUpWriteDates)); if (configuration?.CheckDFaceAndUpWriteDates is null) throw new NullReferenceException(nameof(configuration.CheckDFaceAndUpWriteDates)); if (configuration?.CheckJsonForDistanceResults is null) throw new NullReferenceException(nameof(configuration.CheckJsonForDistanceResults)); - // if (configuration?.CopyFacesAndSaveFaceLandmarkForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.CopyFacesAndSaveFaceLandmarkForOutputResolutions)); if (configuration?.CrossDirectoryMaxItemsInDistanceCollection is null) throw new NullReferenceException(nameof(configuration.CrossDirectoryMaxItemsInDistanceCollection)); if (configuration?.DeletePossibleDuplicates is null) throw new NullReferenceException(nameof(configuration.DeletePossibleDuplicates)); if (configuration?.DistanceFactor is null) throw new NullReferenceException(nameof(configuration.DistanceFactor)); @@ -182,6 +181,7 @@ public class Configuration // if (configuration?.SaveBlurHashForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveBlurHashForOutputResolutions)); // if (configuration?.SaveFaceDistancesForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveFaceDistancesForOutputResolutions)); // if (configuration?.SaveFaceLandmarkForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveFaceLandmarkForOutputResolutions)); + // if (configuration?.SaveFaceLandmarkForOutputResolutionsV2 is null) throw new NullReferenceException(nameof(configuration.SaveFaceLandmarkForOutputResolutionsV2)); // if (configuration?.SaveFilteredOriginalImagesFromJLinksForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveFilteredOriginalImagesFromJLinksForOutputResolutions)); if (configuration?.SaveFullYearOfRandomFiles is null) throw new NullReferenceException(nameof(configuration.SaveFullYearOfRandomFiles)); if (configuration?.SaveIndividually is null) throw new NullReferenceException(nameof(configuration.SaveIndividually)); @@ -205,7 +205,6 @@ public class Configuration result = new(propertyConfiguration, configuration.CheckDFaceAndUpWriteDates.Value, configuration.CheckJsonForDistanceResults.Value, - configuration.CopyFacesAndSaveFaceLandmarkForOutputResolutions ?? [], configuration.CrossDirectoryMaxItemsInDistanceCollection.Value, configuration.DeletePossibleDuplicates.Value, configuration.DistanceFactor.Value, @@ -265,6 +264,7 @@ public class Configuration configuration.SaveBlurHashForOutputResolutions ?? [], configuration.SaveFaceDistancesForOutputResolutions ?? [], configuration.SaveFaceLandmarkForOutputResolutions ?? [], + configuration.SaveFaceLandmarkForOutputResolutionsV2 ?? [], configuration.SaveFilteredOriginalImagesFromJLinksForOutputResolutions ?? [], configuration.SaveIndividually.Value, configuration.SaveFullYearOfRandomFiles.Value, diff --git a/TestsWithFaceRecognitionDotNet/Models/Configuration.cs b/TestsWithFaceRecognitionDotNet/Models/Configuration.cs index 74b7e4b..3074e95 100644 --- a/TestsWithFaceRecognitionDotNet/Models/Configuration.cs +++ b/TestsWithFaceRecognitionDotNet/Models/Configuration.cs @@ -3,7 +3,6 @@ namespace View_by_Distance.Tests.Models; public record Configuration(Property.Models.Configuration PropertyConfiguration, bool CheckDFaceAndUpWriteDates, bool CheckJsonForDistanceResults, - string[] CopyFacesAndSaveFaceLandmarkForOutputResolutions, int CrossDirectoryMaxItemsInDistanceCollection, bool DeletePossibleDuplicates, int DistanceFactor, @@ -63,6 +62,7 @@ public record Configuration(Property.Models.Configuration PropertyConfiguration, string[] SaveBlurHashForOutputResolutions, string[] SaveFaceDistancesForOutputResolutions, string[] SaveFaceLandmarkForOutputResolutions, + string[] SaveFaceLandmarkForOutputResolutionsV2, string[] SaveFilteredOriginalImagesFromJLinksForOutputResolutions, bool SaveIndividually, bool SaveFullYearOfRandomFiles,