From d789f295c687dabbcddd5e20ab863e4f38042c34 Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Sat, 24 Sep 2022 21:41:50 -0700 Subject: [PATCH] Forgot pad left --- .vscode/launch.json | 29 +- Distance/Models/_E_Distance.cs | 364 +++++++++--------- Face/Models/_D_Face.cs | 2 - Instance/DlibDotNet.cs | 32 +- Instance/Models/_G2_Identify.cs | 2 +- Map/Models/MapLogic.cs | 2 +- Map/Models/Stateless/MapLogic.cs | 5 +- Shared/Models/Stateless/Methods/IMapping.cs | 26 +- .../Stateless/Methods/IPersonContainer.cs | 8 +- Shared/Models/Stateless/Methods/Location.cs | 11 +- Shared/Models/Stateless/Methods/Mapping.cs | 13 +- .../Stateless/Methods/PersonContainer.cs | 26 +- Tests/UnitTestCalculations.cs | 30 ++ 13 files changed, 303 insertions(+), 247 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index a25ed2f..0cd8986 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -53,4 +53,31 @@ // Notes at 9/18/2022 10:29 PM // (637987913910140924) 9/14/2022 10:29 PM - 113 *.jpg && 109 *.json // (637989361172096980) 9/16/2022 02:41 PM - 094 *.jpg && 026 *.json -// All including (637991052364021796) 9/18/2022 1:40 PM - 17435 *.jpg && 16237 *.json = 93.128763980499% with int match only \ No newline at end of file +// All including (637991052364021796) 9/18/2022 1:40 PM - 17435 *.jpg && 16237 *.json = 93.128763980499% with int match only +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/49158951_2264915190186558_112485584324263936_n.jpg?_nc_cat=106&ccb=1-7&_nc_sid=84a396&_nc_ohc=Q78znguHVeMAX88OKg9&_nc_ht=scontent-lax3-2.xx&oh=00_AT_gJFk9xytYuXp9p5smDm0mMDXzsPnFS_EfKEbiL3KYqg&oe=63523F37 +// https://scontent-lax3-1.xx.fbcdn.net/v/t39.30808-6/290625560_10217841255422109_3297482250419620718_n.jpg?_nc_cat=104&ccb=1-7&_nc_sid=730e14&_nc_ohc=O3ybqwDLK9AAX_V0FGP&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-1.xx&oh=00_AT-9rtBghXU7lAGkOy4KPHbV9Kyj8DGm-BGtUabWgQJbOg&oe=63335209 +// https://scontent-lax3-1.xx.fbcdn.net/v/t39.30808-6/243093116_10216723829287154_8982585928017225043_n.jpg?_nc_cat=104&ccb=1-7&_nc_sid=730e14&_nc_ohc=TW6UDC8v9egAX-_YcWf&_nc_ht=scontent-lax3-1.xx&oh=00_AT8rE2JOfkJINSsA5imGVBDbXNDvxx1_uZn0sLM-6ITDUw&oe=633238A9 +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.18169-9/281249_1450445399251_3598212_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=cdbe9c&_nc_ohc=ihKT3xtvWXoAX-kiat-&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-1.xx&oh=00_AT9cmbHu00fc0-aR-k6MP7T_cja6geiAkobbvU4pdfG6KQ&oe=63527F21 +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.18169-9/62557_157063120990498_3918482_n.jpg?_nc_cat=110&ccb=1-7&_nc_sid=de6eea&_nc_ohc=lV8bmtAes-0AX8Uk9pG&_nc_ht=scontent-lax3-1.xx&oh=00_AT-ieBL8wIZ4gQmRWAvTWDu9wBzAsPV5s4c82MvOs6oU5g&oe=6355846B +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.18169-9/166577_1634651034600_6777460_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=cdbe9c&_nc_ohc=nEZ0RR0cqn4AX-wA-VH&_nc_ht=scontent-lax3-1.xx&oh=00_AT_ig2HUMDQl1fhXY0Inm0QWC3i2__rPUAWYF2Wqx-pkew&oe=635290D6 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/97107804_10223189072017432_5088375698351980544_n.jpg?_nc_cat=101&ccb=1-7&_nc_sid=09cbfe&_nc_ohc=t0rqlgAAd_0AX-ANM1H&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-2.xx&oh=00_AT_hqG2piNkASRB5z94qeY8q7hy90ku9Dka4enL4wsAnTg&oe=6354CD8A +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/121491463_10159438417238072_1207001349879930424_n.jpg?_nc_cat=103&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=rZTiRaFTrCkAX_L4sVS&_nc_ht=scontent-lax3-2.xx&oh=00_AT_uKD2jeNUTwlyN5r6UXRK40aNNgRNCZrrJ9B-WW6tlag&oe=63522946 +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.6435-9/96370874_10158521458082578_8748970895894118400_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=qvIn4gTjvo0AX-dHnuq&_nc_ht=scontent-lax3-1.xx&oh=00_AT8R-D8AsjWKMlUxK-AimPNzxuNT06zQCS43ESdf1LEeoQ&oe=63562F54 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/96681856_10157495047223435_2857053180632498176_n.jpg?_nc_cat=103&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=UwF0qUGoG9QAX-S1LcI&_nc_ht=scontent-lax3-2.xx&oh=00_AT-5j0EiZB6HOOc2jGqGOll2zFoNTdDLKLfJztq0HYWagg&oe=6355A2A9 +// https://scontent-lax3-1.xx.fbcdn.net/v/t31.18172-8/26850365_1810492538961485_3240264679723665015_o.jpg?_nc_cat=110&ccb=1-7&_nc_sid=0debeb&_nc_ohc=WrJYsgu1eS4AX8kIsyM&_nc_ht=scontent-lax3-1.xx&oh=00_AT-fzFN40kYFjF2-uYL6KcgKPxgFkDZ5BcyIUVFdCTf2tg&oe=635485B7 +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.6435-9/67735718_10219770387799941_2254439277247070208_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=730e14&_nc_ohc=MD8haDYY7uIAX_dwTY4&_nc_ht=scontent-lax3-1.xx&oh=00_AT_zhJpjbWomrihWiSq35KFkmpBfEgbXCSNM68icaABxoA&oe=6355871D +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/59983603_2215207855225638_2271200674882519040_n.jpg?_nc_cat=111&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=-2zmPWdcy9IAX8KXJ_t&_nc_ht=scontent-lax3-2.xx&oh=00_AT_7N0yufGym-cuQfeMK6iceBNI7eEyaScRm3m3_4njTIQ&oe=6354C2B6 +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.6435-9/204501292_10222856568897395_8588510782161393042_n.jpg?_nc_cat=105&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=2gLdnkn19swAX_9mAG1&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-1.xx&oh=00_AT_ha5ncAI7ykhbgFNT1_4NWCvPGFWQLgdq6q20nZSIVQA&oe=63537D09 +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.6435-9/65945099_10217135244827869_3400689284598988800_n.jpg?_nc_cat=110&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=NHnhR9_7UTkAX8wpbxK&_nc_ht=scontent-lax3-1.xx&oh=00_AT_-Q-zUeDoD11B9TY_n_MWEimMiXCokB_5TojplmU6_Eg&oe=6355A2B8 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.18169-9/22055_581856018827_4131263_n.jpg?_nc_cat=107&ccb=1-7&_nc_sid=cdbe9c&_nc_ohc=zsqIe2xzpf0AX8lcyLV&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-2.xx&oh=00_AT_DzvUir_30cauAjp8eaSlYKVADdanzWo1NAQK7_b3M-w&oe=63548E83 +// https://scontent-lax3-1.xx.fbcdn.net/v/t31.18172-8/14525108_10202312892739292_8313619716862825541_o.jpg?_nc_cat=102&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=lZ4MpT6i_MIAX-3d-nV&_nc_ht=scontent-lax3-1.xx&oh=00_AT_9JoZdMdlNV71PdrkU7AmvFkkwqllEg9sVTvcGyzoESw&oe=6353993A +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/104325415_860091804515928_5960365004832843376_n.jpg?_nc_cat=106&ccb=1-7&_nc_sid=174925&_nc_ohc=y1AW-ld80OcAX_927wW&_nc_oc=AQluU8Pwuqxs9xBVYhQJ9ThWOh5vLIKvQdOQnCtZpN2-j-6d9PRMHWHR5aaFBkcJicA&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-2.xx&oh=00_AT8vQwiLvz7cJU61FkIPLtcc8j8tlL2tC6zRlH1i20VUmQ&oe=6356EACE +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.6435-9/43565411_10217177505092918_6185540976904241152_n.jpg?_nc_cat=105&ccb=1-7&_nc_sid=730e14&_nc_ohc=yBls9BCXhdwAX_doX-2&_nc_ht=scontent-lax3-1.xx&oh=00_AT-PYyffphSxOeGM_3aC4oHSA4U9cEjm2OrappZ_jh6qIg&oe=6355895C +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.6435-9/48422692_10157144542022625_3324340889383337984_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=h_gtXGa5nSAAX-CB2E1&_nc_ht=scontent-lax3-1.xx&oh=00_AT8x7vZA5VN27hfoMPcQ39So-1COUnuNjDj4iz8d-cw6wQ&oe=6354B370 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/150153899_10208532293942419_1808101907825622971_n.jpg?_nc_cat=101&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=3NZWKCpJ0VYAX911uCo&_nc_ht=scontent-lax3-2.xx&oh=00_AT_NhKwagHEsPuQVSERZNQ2_6MOIG2UKG5r32c0fIPaeQA&oe=63552624 +// https://scontent-lax3-2.xx.fbcdn.net/v/t31.18172-8/13641143_10209202266801205_7525162492297688727_o.jpg?_nc_cat=106&ccb=1-7&_nc_sid=174925&_nc_ohc=AETs7fkfLacAX-q9cnO&_nc_ht=scontent-lax3-2.xx&oh=00_AT89DOYAP9GbNvEgmlI0z9VK9Z8uJttFQyuO-tfe5OGbFQ&oe=6355CF5D +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.18169-9/299875_2023116112081_1500929171_n.jpg?_nc_cat=103&ccb=1-7&_nc_sid=cdbe9c&_nc_ohc=bsY9uckSAQwAX-xxGaU&_nc_ht=scontent-lax3-2.xx&oh=00_AT8OStQmDU_7NLNrYLeNfoULcBA-onU1V3Z4bn35-ipzCQ&oe=63555339 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.18169-9/1544444_10203587296855592_4576811169900508598_n.jpg?_nc_cat=100&ccb=1-7&_nc_sid=730e14&_nc_ohc=pYUGNkoYGPcAX8X2gtw&_nc_ht=scontent-lax3-2.xx&oh=00_AT_thzQZyWPWDA8t1acXqEzifLMXxcPTUOgqWqmeuk3SfQ&oe=63566033 +// https://scontent-lax3-2.xx.fbcdn.net/v/t31.18172-8/10887668_10205175511939476_7644367668075304275_o.jpg?_nc_cat=100&ccb=1-7&_nc_sid=730e14&_nc_ohc=2T_utQvqkXYAX94o-WV&_nc_ht=scontent-lax3-2.xx&oh=00_AT8aSCQ4JVgRULd1RxRJ8DYqPtB9EyGY-May2QwwqKSqjQ&oe=6356B098 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/78675669_10102984650797787_175454688261439488_n.jpg?_nc_cat=101&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=7Plv_RW77xoAX9PiH9G&_nc_ht=scontent-lax3-2.xx&oh=00_AT-npzVNkTzAdYgQ4D1ltfyl8llC_xqOHJ9Mi8Vmh2khlw&oe=63571251 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/59569741_10214142910059142_9219208491263066112_n.jpg?_nc_cat=100&ccb=1-7&_nc_sid=730e14&_nc_ohc=F7GF2uCFljcAX8Skffr&_nc_ht=scontent-lax3-2.xx&oh=00_AT9e3f8x6hSmAcxQ5JDUvDPFEg0wcecKw175Qfj_WMwADQ&oe=635488AA diff --git a/Distance/Models/_E_Distance.cs b/Distance/Models/_E_Distance.cs index b27af1d..d586743 100644 --- a/Distance/Models/_E_Distance.cs +++ b/Distance/Models/_E_Distance.cs @@ -75,18 +75,6 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance return results; } - private static List GetFaceDistanceEncodings(FaceDistanceContainer[] faceDistanceContainers) - { - List faceDistanceEncodings = new(); - foreach (FaceDistanceContainer faceDistanceContainer in faceDistanceContainers) - { - if (faceDistanceContainer.FaceDistance.Encoding is null) - continue; - faceDistanceEncodings.Add(faceDistanceContainer.FaceDistance); - } - return faceDistanceEncodings; - } - private static FaceDistanceContainer[] GetOrderedFaceDistanceContainers(List collection) { FaceDistanceContainer[] results; @@ -116,6 +104,18 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance return results; } + private static List GetFaceDistanceEncodings(FaceDistanceContainer[] faceDistanceContainers) + { + List faceDistanceEncodings = new(); + foreach (FaceDistanceContainer faceDistanceContainer in faceDistanceContainers) + { + if (faceDistanceContainer.FaceDistance.Encoding is null) + continue; + faceDistanceEncodings.Add(faceDistanceContainer.FaceDistance); + } + return faceDistanceEncodings; + } + public SortingContainer[] SetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, long ticks, MapLogic mapLogic, Face[] selectedFilteredFaces) { SortingContainer[] results; @@ -175,79 +175,6 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance }); } - private static FaceDistanceContainer[] GetOrderedFaceDistanceContainers(MappingFromItem mappingFromItem, List faces) - { - FaceDistanceContainer[] results; - FaceDistance faceDistance; - int normalizedPixelPercentage; - FaceDistanceContainer faceDistanceContainer; - List collection = new(); - foreach (Face face in faces) - { - if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) - throw new NotSupportedException(); - normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution); - if (face.FaceDistance?.Encoding is not null && face.FaceDistance.Encoding is FaceRecognitionDotNet.FaceEncoding faceEncoding) - faceDistance = new(face.Location.Confidence, faceEncoding, mappingFromItem.Id, mappingFromItem.IsWrongYear, mappingFromItem.MinimumDateTime, normalizedPixelPercentage); - else - { - faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); - faceDistance = new(face.Location.Confidence, faceEncoding, mappingFromItem.Id, mappingFromItem.IsWrongYear, mappingFromItem.MinimumDateTime, normalizedPixelPercentage); - lock (faces) - face.SetFaceDistance(faceDistance); - } - faceDistanceContainer = new(face, faceDistance); - collection.Add(faceDistanceContainer); - } - results = GetOrderedFaceDistanceContainers(collection); - return results; - } - - private static List<(Face Face, double Length)> GetValues(double faceDistanceTolerance, MappingFromItem mappingFromItem, List faces, string json) - { - List<(Face Face, double Length)> results = new(); - Face face; - FaceDistance faceDistanceLength; - Shared.Models.FaceEncoding? modelsFaceEncoding = JsonSerializer.Deserialize(json); - if (modelsFaceEncoding is null) - throw new NotSupportedException(); - FaceRecognitionDotNet.FaceEncoding faceRecognitionDotNetFaceEncoding = FaceRecognition.LoadFaceEncoding(modelsFaceEncoding.RawEncoding); - FaceDistance faceDistanceEncoding = new(faceRecognitionDotNetFaceEncoding); - FaceDistanceContainer[] faceDistanceContainers = GetOrderedFaceDistanceContainers(mappingFromItem, faces); - int faceDistanceContainersLength = faceDistanceContainers.Length; - if (faceDistanceContainersLength != faces.Count) - throw new NotSupportedException(); - List faceDistanceEncodings = GetFaceDistanceEncodings(faceDistanceContainers); - if (faceDistanceEncodings.Count != faces.Count) - throw new NotSupportedException(); - List faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncoding); - if (faceDistanceLengths.Count != faceDistanceContainersLength) - throw new NotSupportedException(); - for (int i = 0; i < faces.Count; i++) - { - face = faces[i]; - faceDistanceLength = faceDistanceLengths[i]; - if (faceDistanceLength.Length is null) - throw new NotSupportedException(); - if (faceDistanceLength.Length.Value > faceDistanceTolerance) - continue; - results.Add(new(face, faceDistanceLength.Length.Value)); - } - return results; - } - - private static List GetMatchingFaces(double faceDistanceTolerance, MappingFromItem mappingFromItem, List faces, string json) - { - List results = new(); - List<(Face Face, double Length)> collection = GetValues(faceDistanceTolerance, mappingFromItem, faces, json); - if (collection.Any()) - { - collection = (from l in collection orderby l.Length select l).ToList(); - results.Add(collection[0].Face); - } - return results; - } - void Shared.Models.Methods.IFaceDistance.SavePossiblyNewPersonContainers(IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, string facesFileNameExtension, string a2PeopleSingletonDirectory, Dictionary personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer) { char @char; @@ -346,69 +273,6 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance { } } - public static string? GetFaceEncoding(string file) - { - string? result; - List results = new(); - const string comment = "Comment: "; - if (File.Exists(file)) - { - IReadOnlyList directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(file); - foreach (MetadataExtractor.Directory directory in directories) - { - if (directory.Name != "PNG-tEXt") - continue; - foreach (MetadataExtractor.Tag tag in directory.Tags) - { - if (tag.Name != "Textual Data" || string.IsNullOrEmpty(tag.Description)) - continue; - if (!tag.Description.StartsWith(comment)) - continue; - results.Add(tag.Description); - } - } - } - result = results.Any() ? results[0][comment.Length..] : null; - return result; - } - - private static Face[] GetMatchingFaces(int pixelDistanceTolerance, List faces) - { - Face[] results; - int? x; - int? y; - double distance; - double center = 2f; - double xCenterValue; - double yCenterValue; - string normalizedPixelPercentagePadded; - List<(double Order, Face Face)> collection = new(); - foreach (Face face in faces) - { - if (face.Location is null || face.OutputResolution is null || face.Mapping is null) - throw new NotSupportedException(); - xCenterValue = (face.Location.Left + face.Location.Right) / center; - yCenterValue = (face.Location.Top + face.Location.Bottom) / center; - if (xCenterValue < face.Location.Left || xCenterValue > face.Location.Right) - throw new Exception(); - if (yCenterValue < face.Location.Top || yCenterValue > face.Location.Bottom) - throw new Exception(); - normalizedPixelPercentagePadded = Shared.Models.Stateless.Methods.ILocation.GetLeftPadded(Shared.Models.Stateless.ILocation.Digits, face.Mapping.MappingFromLocation.NormalizedPixelPercentage); - (x, y) = Shared.Models.Stateless.Methods.ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution.Width, face.OutputResolution.Height, normalizedPixelPercentagePadded); - if (x is null || y is null) - throw new NotSupportedException(); - distance = Math.Sqrt(Math.Pow(xCenterValue - x.Value, 2) + Math.Pow(yCenterValue - y.Value, 2)); - collection.Add(new(distance, face)); - } - results = (from l in collection orderby l.Order where l.Order < pixelDistanceTolerance select l.Face).ToArray(); - if (results.Any()) - { - if (results.Any()) - { } - } - return results; - } - private static string[] GetMatchingDuplicates(string[] mappedFaceFiles, List duplicateMappedFaceFiles, string mappedFaceFile) { string[] results; @@ -441,6 +305,141 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance return results; } + public static string? GetFaceEncoding(string file) + { + string? result; + List results = new(); + const string comment = "Comment: "; + if (File.Exists(file)) + { + IReadOnlyList directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(file); + foreach (MetadataExtractor.Directory directory in directories) + { + if (directory.Name != "PNG-tEXt") + continue; + foreach (MetadataExtractor.Tag tag in directory.Tags) + { + if (tag.Name != "Textual Data" || string.IsNullOrEmpty(tag.Description)) + continue; + if (!tag.Description.StartsWith(comment)) + continue; + results.Add(tag.Description); + } + } + } + result = results.Any() ? results[0][comment.Length..] : null; + return result; + } + + private static FaceDistanceContainer[] GetOrderedFaceDistanceContainers(MappingFromItem mappingFromItem, List faces) + { + FaceDistanceContainer[] results; + FaceDistance faceDistance; + int normalizedPixelPercentage; + FaceDistanceContainer faceDistanceContainer; + List collection = new(); + foreach (Face face in faces) + { + if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) + throw new NotSupportedException(); + normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution); + if (face.FaceDistance?.Encoding is not null && face.FaceDistance.Encoding is FaceRecognitionDotNet.FaceEncoding faceEncoding) + faceDistance = new(face.Location.Confidence, faceEncoding, mappingFromItem.Id, mappingFromItem.IsWrongYear, mappingFromItem.MinimumDateTime, normalizedPixelPercentage); + else + { + faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); + faceDistance = new(face.Location.Confidence, faceEncoding, mappingFromItem.Id, mappingFromItem.IsWrongYear, mappingFromItem.MinimumDateTime, normalizedPixelPercentage); + lock (faces) + face.SetFaceDistance(faceDistance); + } + faceDistanceContainer = new(face, faceDistance); + collection.Add(faceDistanceContainer); + } + results = GetOrderedFaceDistanceContainers(collection); + return results; + } + + private static List<(Face Face, double Length)> GetValues(double faceDistanceTolerance, MappingFromItem mappingFromItem, List faces, string json) + { + List<(Face Face, double Length)> results = new(); + Face face; + FaceDistance faceDistanceLength; + Shared.Models.FaceEncoding? modelsFaceEncoding = JsonSerializer.Deserialize(json); + if (modelsFaceEncoding is null) + throw new NotSupportedException(); + FaceRecognitionDotNet.FaceEncoding faceRecognitionDotNetFaceEncoding = FaceRecognition.LoadFaceEncoding(modelsFaceEncoding.RawEncoding); + FaceDistance faceDistanceEncoding = new(faceRecognitionDotNetFaceEncoding); + FaceDistanceContainer[] faceDistanceContainers = GetOrderedFaceDistanceContainers(mappingFromItem, faces); + int faceDistanceContainersLength = faceDistanceContainers.Length; + if (faceDistanceContainersLength != faces.Count) + throw new NotSupportedException(); + List faceDistanceEncodings = GetFaceDistanceEncodings(faceDistanceContainers); + if (faceDistanceEncodings.Count != faces.Count) + throw new NotSupportedException(); + List faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncoding); + if (faceDistanceLengths.Count != faceDistanceContainersLength) + throw new NotSupportedException(); + for (int i = 0; i < faces.Count; i++) + { + face = faces[i]; + faceDistanceLength = faceDistanceLengths[i]; + if (faceDistanceLength.Length is null) + throw new NotSupportedException(); + if (faceDistanceLength.Length.Value > faceDistanceTolerance) + continue; + results.Add(new(face, faceDistanceLength.Length.Value)); + } + return results; + } + + private static Face[] GetMatchingFaces(double faceDistanceTolerance, MappingFromItem mappingFromItem, List faces, string json) + { + Face[] results; + List<(Face Face, double Length)> collection = GetValues(faceDistanceTolerance, mappingFromItem, faces, json); + if (!collection.Any()) + results = Array.Empty(); + else + results = (from l in collection orderby l.Length select l.Face).Take(1).ToArray(); + return results; + } + + private static Face[] GetMatchingFaces(int pixelDistanceTolerance, List faces) + { + Face[] results; + int? x; + int? y; + double distance; + double center = 2f; + double xCenterValue; + double yCenterValue; + int normalizedPixelPercentage; + string normalizedPixelPercentagePadded; + List<(double Order, Face Face)> collection = new(); + foreach (Face face in faces) + { + if (face.Location is null || face.OutputResolution is null) + throw new NotSupportedException(); + xCenterValue = (face.Location.Left + face.Location.Right) / center; + yCenterValue = (face.Location.Top + face.Location.Bottom) / center; + if (xCenterValue < face.Location.Left || xCenterValue > face.Location.Right) + throw new Exception(); + if (yCenterValue < face.Location.Top || yCenterValue > face.Location.Bottom) + throw new Exception(); + normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution); + normalizedPixelPercentagePadded = Shared.Models.Stateless.Methods.ILocation.GetLeftPadded(Shared.Models.Stateless.ILocation.Digits, normalizedPixelPercentage); + (x, y) = Shared.Models.Stateless.Methods.ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution.Width, face.OutputResolution.Height, normalizedPixelPercentagePadded); + if (x is null || y is null) + throw new NotSupportedException(); + distance = Math.Sqrt(Math.Pow(xCenterValue - x.Value, 2) + Math.Pow(yCenterValue - y.Value, 2)); + collection.Add(new(distance, face)); + } + if (!collection.Any()) + results = Array.Empty(); + else + results = (from l in collection orderby l.Order where l.Order < pixelDistanceTolerance select l.Face).Take(1).ToArray(); + return results; + } + private static List GetMatchingFaces(List faces, string? json) { List results = new(); @@ -485,12 +484,37 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance return result; } - public (int, int) GetUnableToMatchCountAndRenameMatches(string facesFileNameExtension, string eDistanceContentDirectory, List duplicateMappedFaceFilesCollection, Item item, List faces, string[] mappedFaceFiles) + private static List GetMatchingFaces(List faces, string[] mappedFaceFiles, List debugChecks, int normalizedPixelPercentageValue, List normalizedPixelPercentages, List duplicateMappedFaceFiles, string mappedFaceFile) + { + List results = new(); + bool check; + int normalizedPixelPercentage; + foreach (Face face in faces) + { + if (face.Location is null || face.OutputResolution is null) + throw new NotSupportedException(); + normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution); + debugChecks.Add(normalizedPixelPercentage); + if (normalizedPixelPercentage != normalizedPixelPercentageValue) + continue; + if (normalizedPixelPercentages.Contains(normalizedPixelPercentage)) + { + duplicateMappedFaceFiles.AddRange(GetMatchingDuplicates(mappedFaceFiles, duplicateMappedFaceFiles, mappedFaceFile)); + continue; + } + check = true; + results.Add(face); + if (!check) + debugChecks.Add(normalizedPixelPercentage); + } + return results; + } + + public (int, int, int) GetUnableToMatchCountAndRenameMatches(string facesFileNameExtension, string eDistanceContentDirectory, Item item, List faces, string[] mappedFaceFiles) { int result = 0; int? id; string? json; - bool debugCheck; int renamed = 0; bool? isWrongYear; FileInfo? fileInfo; @@ -500,7 +524,6 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance List debugChecks = new(); int? normalizedPixelPercentage; MappingFromItem mappingFromItem; - int normalizedPixelPercentageLoop; List normalizedPixelPercentages; List duplicateMappedFaceFiles = new(); Dictionary> idToNormalizedPixelPercentages = new(); @@ -513,10 +536,7 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance throw new NotSupportedException(); if (duplicateMappedFaceFiles.Contains(mappedFaceFile)) continue; - (id, normalizedPixelPercentage, _) = Shared.Models.Stateless.Methods.IMapping.GetReversedDeterministicHashCodeKey( - Shared.Models.Stateless.ILocation.Digits, - facesFileNameExtension, - mappedFaceFile); + (id, normalizedPixelPercentage, _) = Shared.Models.Stateless.Methods.IMapping.GetReversedDeterministicHashCodeKey(facesFileNameExtension, mappedFaceFile); if (id is null || normalizedPixelPercentage is null) { result++; @@ -526,34 +546,18 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance continue; if (item.Property?.Id is null || item.ImageFileHolder is null || item.ResizedFileHolder is null) continue; + if (faces.Any(l => l.FaceEncoding is null || l.Location is null || l.OutputResolution is null)) + continue; minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property); (isWrongYear, _) = item.Property.IsWrongYear(item.ImageFileHolder.FullName, minimumDateTime); mappingFromItem = new(item.Property.Id.Value, item.ImageFileHolder, isWrongYear, minimumDateTime, item.ResizedFileHolder); json = null; - debugCheck = false; checkFaces.Clear(); debugChecks.Clear(); if (!idToNormalizedPixelPercentages.ContainsKey(id.Value)) idToNormalizedPixelPercentages.Add(id.Value, new()); normalizedPixelPercentages = idToNormalizedPixelPercentages[id.Value]; - foreach (Face face in faces) - { - if (face.Location is null || face.OutputResolution is null) - throw new NotSupportedException(); - normalizedPixelPercentageLoop = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution); - debugChecks.Add(normalizedPixelPercentageLoop); - if (normalizedPixelPercentage.Value != normalizedPixelPercentageLoop) - continue; - if (normalizedPixelPercentages.Contains(normalizedPixelPercentageLoop)) - { - duplicateMappedFaceFiles.AddRange(GetMatchingDuplicates(mappedFaceFiles, duplicateMappedFaceFiles, mappedFaceFile)); - continue; - } - debugCheck = true; - checkFaces.Add(face); - if (!debugCheck) - debugChecks.Add(normalizedPixelPercentageLoop); - } + checkFaces.AddRange(GetMatchingFaces(faces, mappedFaceFiles, debugChecks, normalizedPixelPercentage.Value, normalizedPixelPercentages, duplicateMappedFaceFiles, mappedFaceFile)); if (checkFaces.Count != 1) { checkFaces.Clear(); @@ -571,12 +575,7 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance { checkFaces.Clear(); if (json is null) - { - result++; - if (_DistanceMoveUnableToMatch) - MoveUnableToMatch(eDistanceContentDirectory, mappedFaceFile); - continue; - } + throw new NotSupportedException(); checkFaces.AddRange(GetMatchingFaces(_FaceDistanceTolerance, mappingFromItem, faces, json)); } if (checkFaces.Count != 1 && _DistancePixelDistanceTolerance > 0) @@ -609,10 +608,9 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance } if (duplicateMappedFaceFiles.Any()) { - lock (duplicateMappedFaceFilesCollection) - duplicateMappedFaceFilesCollection.Add(duplicateMappedFaceFiles.ToArray()); + duplicateMappedFaceFiles.Sort(); } - return new(result, renamed); + return new(result, duplicateMappedFaceFiles.Count, renamed); } } \ No newline at end of file diff --git a/Face/Models/_D_Face.cs b/Face/Models/_D_Face.cs index 963f28a..e562a83 100644 --- a/Face/Models/_D_Face.cs +++ b/Face/Models/_D_Face.cs @@ -126,7 +126,6 @@ public class D_Face private void SaveFaces(FileHolder resizedFileHolder, List<(Shared.Models.Face, FileInfo?, string)> collection) { - int pixel; int width; int height; string json; @@ -149,7 +148,6 @@ public class D_Face width = location.Right - location.Left; height = location.Bottom - location.Top; json = JsonSerializer.Serialize(face.FaceEncoding); - pixel = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(face.Location, ILocation.Digits, ILocation.Factor, face.OutputResolution); rectangle = new Rectangle(location.Left, location.Top, width, height); using (bitmap = new(width, height)) { diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index a4462da..990c83a 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -131,7 +131,6 @@ public partial class DlibDotNet Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory); personContainers = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers( storage, - configuration.LocationDigits, configuration.PersonBirthdayFormat, _Faces.FileNameExtension); } @@ -349,7 +348,7 @@ public partial class DlibDotNet return result; } - private void FullParallelForWork(A_Property propertyLogic, string[] mappedFaceFiles, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string eDistanceContentDirectory, List> sourceDirectoryChanges, List propertyFileHolderCollection, List propertyCollection, List>> metadataCollections, List> resizeKeyValuePairs, List?> imageFaceCollections, List duplicateMappedFaceFilesCollection, Container container, int index, Item item) + private void FullParallelForWork(A_Property propertyLogic, string[] mappedFaceFiles, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string eDistanceContentDirectory, List> sourceDirectoryChanges, List propertyFileHolderCollection, List propertyCollection, List>> metadataCollections, List> resizeKeyValuePairs, List?> imageFaceCollections, Container container, int index, Item item) { if (item.ImageFileHolder is null) throw new NullReferenceException(nameof(item.ImageFileHolder)); @@ -425,7 +424,7 @@ public partial class DlibDotNet _Faces.SaveFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, item, faces); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(D_Face.SaveFaces)); - _ = _Distance.GetUnableToMatchCountAndRenameMatches(_Faces.FileNameExtension, eDistanceContentDirectory, duplicateMappedFaceFilesCollection, item, faces, mappedFaceFiles); + _ = _Distance.GetUnableToMatchCountAndRenameMatches(_Faces.FileNameExtension, eDistanceContentDirectory, item, faces, mappedFaceFiles); if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) { throw new NotImplementedException(); @@ -448,7 +447,23 @@ public partial class DlibDotNet } } - private int FullParallelWork(int maxDegreeOfParallelism, A_Property propertyLogic, string[] mappedFaceFiles, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string eDistanceContentDirectory, List> sourceDirectoryChanges, List propertyFileHolderCollection, List propertyCollection, List>> metadataCollection, List> resizeKeyValuePairs, List?> imageFaceCollections, List duplicateMappedFaceFilesCollection, Container container, Item[] filteredItems, string message) + private int FullParallelWork(int maxDegreeOfParallelism, + A_Property propertyLogic, + string[] mappedFaceFiles, + string outputResolution, + string bResultsFullGroupDirectory, + string cResultsFullGroupDirectory, + string dResultsFullGroupDirectory, + string eDistanceContentDirectory, + List> sourceDirectoryChanges, + List propertyFileHolderCollection, + List propertyCollection, + List>> metadataCollection, + List> resizeKeyValuePairs, + List?> imageFaceCollections, + Container container, + Item[] filteredItems, + string message) { if (_Log is null) throw new NullReferenceException(nameof(_Log)); @@ -488,7 +503,6 @@ public partial class DlibDotNet metadataCollection, resizeKeyValuePairs, imageFaceCollections, - duplicateMappedFaceFilesCollection, container, index: i, filteredItems[i]); @@ -751,7 +765,6 @@ public partial class DlibDotNet int containersLength = containers.Length; Shared.Models.Property[] propertyCollection; List propertyFileHolderCollection = new(); - List duplicateMappedFaceFilesCollection = new(); List> resizeKeyValuePairs = new(); List> sourceDirectoryChanges = new(); List?> imageFaceCollections = new(); @@ -762,7 +775,6 @@ public partial class DlibDotNet { total = 0; _FileKeyValuePairs.Clear(); - duplicateMappedFaceFilesCollection.Clear(); _FilePropertiesKeyValuePairs.Clear(); (aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory) = GetResultsFullGroupDirectories(model, predictorModel, outputResolution); for (int i = 0; i < containers.Length; i++) @@ -799,7 +811,6 @@ public partial class DlibDotNet metadataCollection, resizeKeyValuePairs, imageFaceCollections, - duplicateMappedFaceFilesCollection, container, filteredItems, message); @@ -836,11 +847,6 @@ public partial class DlibDotNet // break; total += container.Items.Count; } - foreach (string[] duplicateMappedFaceFiles in duplicateMappedFaceFilesCollection) - { - foreach (string duplicateMappedFaceFile in duplicateMappedFaceFiles) - _Log.Information(duplicateMappedFaceFile); - } } } diff --git a/Instance/Models/_G2_Identify.cs b/Instance/Models/_G2_Identify.cs index cf7a4d9..e1413ae 100644 --- a/Instance/Models/_G2_Identify.cs +++ b/Instance/Models/_G2_Identify.cs @@ -94,7 +94,7 @@ public class G2_Identify : Shared.Models.Properties.IIdentify, IIdentify if (rootResultsDirectory is null) throw new Exception(); Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory); - PersonContainer[] personContainers = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers(storage, _Configuration.LocationDigits, _Configuration.PersonBirthdayFormat, facesFileNameExtension); + PersonContainer[] personContainers = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers(storage, _Configuration.PersonBirthdayFormat, facesFileNameExtension); string[] peopleBirthDates = (from l in personContainers select Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, l.Person.Birthday)).ToArray(); Dictionary sourceKeyValuePairs = JsonSerializer.Deserialize>(json); foreach (KeyValuePair keyValuePair in sourceKeyValuePairs) diff --git a/Map/Models/MapLogic.cs b/Map/Models/MapLogic.cs index 7c96690..fc5f1ae 100644 --- a/Map/Models/MapLogic.cs +++ b/Map/Models/MapLogic.cs @@ -723,7 +723,7 @@ public class MapLogic { if (!personDisplayDirectoryAllFile.EndsWith(_FacesFileNameExtension)) continue; - (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(Shared.Models.Stateless.ILocation.Digits, _FacesFileNameExtension, personDisplayDirectoryAllFile); + (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(_FacesFileNameExtension, personDisplayDirectoryAllFile); if (id is null || normalizedPixelPercentage is null) continue; if (_IdThenNormalizedPixelPercentageToPersonContainers.TryGetValue(id.Value, out keyValuePairs)) diff --git a/Map/Models/Stateless/MapLogic.cs b/Map/Models/Stateless/MapLogic.cs index ccb32ae..7acf27e 100644 --- a/Map/Models/Stateless/MapLogic.cs +++ b/Map/Models/Stateless/MapLogic.cs @@ -46,7 +46,7 @@ internal abstract class MapLogic { if (!personDisplayDirectoryAllFile.EndsWith(facesFileNameExtension)) continue; - (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(Shared.Models.Stateless.ILocation.Digits, facesFileNameExtension, personDisplayDirectoryAllFile); + (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(facesFileNameExtension, personDisplayDirectoryAllFile); if (id is null || normalizedPixelPercentage is null) continue; if (!skipCollection.ContainsKey(id.Value)) @@ -148,7 +148,7 @@ internal abstract class MapLogic { if (file.EndsWith(".lnk") || file.EndsWith(".json")) continue; - (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(Shared.Models.Stateless.ILocation.Digits, facesFileNameExtension, file); + (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(facesFileNameExtension, file); if (id is null || normalizedPixelPercentage is null) continue; results.Add(new(personKeyFormatted, personDisplayDirectoryNames, file)); @@ -348,7 +348,6 @@ internal abstract class MapLogic { progressBar.Tick(); (id, normalizedPixelPercentage, faces) = IMapping.GetReversedDeterministicHashCodeKey( - Shared.Models.Stateless.ILocation.Digits, facesFileNameExtension, idToFacesAny, idToFaces, diff --git a/Shared/Models/Stateless/Methods/IMapping.cs b/Shared/Models/Stateless/Methods/IMapping.cs index 49475b7..63d2c3c 100644 --- a/Shared/Models/Stateless/Methods/IMapping.cs +++ b/Shared/Models/Stateless/Methods/IMapping.cs @@ -3,24 +3,24 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; public interface IMapping { // ... - (string?, string?, string?, bool?) TestStatic_GetSegments(int locationDigits, string facesFileNameExtension, string fileName) - => GetSegments(locationDigits, facesFileNameExtension, fileName); - static (string?, string?, string?, bool?) GetSegments(int locationDigits, string facesFileNameExtension, string fileName) - => Mapping.GetSegments(locationDigits, facesFileNameExtension, fileName); + (string?, string?, string?, bool?) TestStatic_GetSegments(string facesFileNameExtension, string fileName) + => GetSegments(facesFileNameExtension, fileName); + static (string?, string?, string?, bool?) GetSegments(string facesFileNameExtension, string fileName) + => Mapping.GetSegments(facesFileNameExtension, fileName); string TestStatic_GetDeterministicHashCodeKey(int id, Models.Location location, int locationDigits, int locationFactor, OutputResolution outputResolution) => GetDeterministicHashCodeKey(id, location, locationDigits, locationFactor, outputResolution); static string GetDeterministicHashCodeKey(int id, Models.Location location, int locationDigits, int locationFactor, OutputResolution outputResolution) - => $"{id}.{ILocation.GetNormalizedPixelPercentage(location, locationDigits, locationFactor, outputResolution)}"; + => $"{id}.{ILocation.GetLeftPadded(locationDigits, ILocation.GetNormalizedPixelPercentage(location, locationDigits, locationFactor, outputResolution))}"; - (int?, int?, List?) TestStatic_GetReversedDeterministicHashCodeKey(int locationDigits, string facesFileNameExtension, string file) => - GetReversedDeterministicHashCodeKey(locationDigits, facesFileNameExtension, file); - static (int?, int?, List?) GetReversedDeterministicHashCodeKey(int locationDigits, string facesFileNameExtension, string file) => - Mapping.GetReversedDeterministicHashCodeKey(locationDigits, facesFileNameExtension, false, new(), file); + (int?, int?, List?) TestStatic_GetReversedDeterministicHashCodeKey(string facesFileNameExtension, string file) => + GetReversedDeterministicHashCodeKey(facesFileNameExtension, file); + static (int?, int?, List?) GetReversedDeterministicHashCodeKey(string facesFileNameExtension, string file) => + Mapping.GetReversedDeterministicHashCodeKey(facesFileNameExtension, false, new(), file); - (int?, int?, List?) TestStatic_GetReversedDeterministicHashCodeKey(int locationDigits, string facesFileNameExtension, bool idToFacesAny, Dictionary> idToFaces, string file) => - GetReversedDeterministicHashCodeKey(locationDigits, facesFileNameExtension, idToFacesAny, idToFaces, file); - static (int?, int?, List?) GetReversedDeterministicHashCodeKey(int locationDigits, string facesFileNameExtension, bool idToFacesAny, Dictionary> idToFaces, string file) => - Mapping.GetReversedDeterministicHashCodeKey(locationDigits, facesFileNameExtension, idToFacesAny, idToFaces, file); + (int?, int?, List?) TestStatic_GetReversedDeterministicHashCodeKey(string facesFileNameExtension, bool idToFacesAny, Dictionary> idToFaces, string file) => + GetReversedDeterministicHashCodeKey(facesFileNameExtension, idToFacesAny, idToFaces, file); + static (int?, int?, List?) GetReversedDeterministicHashCodeKey(string facesFileNameExtension, bool idToFacesAny, Dictionary> idToFaces, string file) => + Mapping.GetReversedDeterministicHashCodeKey(facesFileNameExtension, idToFacesAny, idToFaces, file); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IPersonContainer.cs b/Shared/Models/Stateless/Methods/IPersonContainer.cs index 7cb58e8..bcb3a1f 100644 --- a/Shared/Models/Stateless/Methods/IPersonContainer.cs +++ b/Shared/Models/Stateless/Methods/IPersonContainer.cs @@ -5,9 +5,9 @@ public interface IPersonContainer // ... - Models.PersonContainer[] TestStatic_GetPersonContainers(Properties.IStorage storage, int locationDigits, string personBirthdayFormat, string facesFileNameExtension) => - GetPersonContainers(storage, locationDigits, personBirthdayFormat, facesFileNameExtension); - static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, int locationDigits, string personBirthdayFormat, string facesFileNameExtension) => - PersonContainer.GetPersonContainers(storage, locationDigits, personBirthdayFormat, facesFileNameExtension); + Models.PersonContainer[] TestStatic_GetPersonContainers(Properties.IStorage storage, string personBirthdayFormat, string facesFileNameExtension) => + GetPersonContainers(storage, personBirthdayFormat, facesFileNameExtension); + static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, string personBirthdayFormat, string facesFileNameExtension) => + PersonContainer.GetPersonContainers(storage, personBirthdayFormat, facesFileNameExtension); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/Location.cs b/Shared/Models/Stateless/Methods/Location.cs index 1739dfd..8f2d824 100644 --- a/Shared/Models/Stateless/Methods/Location.cs +++ b/Shared/Models/Stateless/Methods/Location.cs @@ -52,9 +52,9 @@ internal abstract class Location { int result; Check(bottom, height, left, right, top, width, zCount); + long check; int checksum; decimal center = 2m; - string xCenterPadded; string yCenterPadded; decimal factor = locationFactor; // int.MaxPercentage = 21 4748 3647; @@ -73,15 +73,14 @@ internal abstract class Location decimal yCenterPercentageFactored = yCenterValue / height * factor; int xCenterRounded = (int)Math.Round(xCenterPercentageFactored, 0); int yCenterRounded = (int)Math.Round(yCenterPercentageFactored, 0); - if (xCenterRounded != factor) - xCenterPadded = ILocation.GetLeftPadded(length, xCenterRounded); - else - xCenterPadded = ILocation.GetLeftPadded(length, xCenterRounded - 1); if (yCenterRounded != factor) yCenterPadded = ILocation.GetLeftPadded(length, yCenterRounded); else yCenterPadded = ILocation.GetLeftPadded(length, yCenterRounded - 1); - long check = long.Parse(string.Concat(xCenterPadded, yCenterPadded, checksum)); + if (xCenterRounded != factor) + check = long.Parse(string.Concat(xCenterRounded, yCenterPadded, checksum)); + else + check = long.Parse(string.Concat(xCenterRounded - 1, yCenterPadded, checksum)); if (check > int.MaxValue) throw new Exception(); result = (int)check; diff --git a/Shared/Models/Stateless/Methods/Mapping.cs b/Shared/Models/Stateless/Methods/Mapping.cs index 012f29e..857e8fe 100644 --- a/Shared/Models/Stateless/Methods/Mapping.cs +++ b/Shared/Models/Stateless/Methods/Mapping.cs @@ -3,7 +3,7 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; internal abstract class Mapping { - internal static (string?, string?, string?, bool?) GetSegments(int locationDigits, string facesFileNameExtension, string fileName) + internal static (string?, string?, string?, bool?) GetSegments(string facesFileNameExtension, string fileName) { string[] segments = fileName.Split('.'); string? id; @@ -21,18 +21,18 @@ internal abstract class Mapping { id = segments[0]; extensionLowered = $".{segments[2]}"; + normalizedPixelPercentage = segments[1]; needsFacesFileNameExtension = segments.Length == 3; - normalizedPixelPercentage = segments[1].Length == locationDigits ? segments[1] : null; } return new(id, normalizedPixelPercentage, extensionLowered, needsFacesFileNameExtension); } - private static (int?, int?, List?) GetReversedDeterministicHashCodeKeysFromSegments(int locationDigits, string facesFileNameExtension, bool idToFacesAny, Dictionary> idToFaces, string fileName) + private static (int?, int?, List?) GetReversedDeterministicHashCodeKeysFromSegments(string facesFileNameExtension, bool idToFacesAny, Dictionary> idToFaces, string fileName) { int? id; List? faces; int? normalizedPixelPercentage; - (string? Id, string? NormalizedPixelPercentage, string? ExtensionLowered, bool? Check) segments = GetSegments(locationDigits, facesFileNameExtension, fileName); + (string? Id, string? NormalizedPixelPercentage, string? ExtensionLowered, bool? Check) segments = GetSegments(facesFileNameExtension, fileName); if (string.IsNullOrEmpty(segments.Id) || string.IsNullOrEmpty(segments.NormalizedPixelPercentage) || string.IsNullOrEmpty(segments.ExtensionLowered) || segments.Check is null) { id = null; @@ -48,7 +48,7 @@ internal abstract class Mapping else { id = idValue; - normalizedPixelPercentage = segments.NormalizedPixelPercentage.Length == locationDigits ? normalizedPixelPercentageValue : null; + normalizedPixelPercentage = normalizedPixelPercentageValue; if (!idToFacesAny || !idToFaces.ContainsKey(idValue)) faces = null; else @@ -57,7 +57,7 @@ internal abstract class Mapping return new(id, normalizedPixelPercentage, faces); } - internal static (int?, int?, List?) GetReversedDeterministicHashCodeKey(int locationDigits, string facesFileNameExtension, bool idToFacesAny, Dictionary> idToFaces, string file) + internal static (int?, int?, List?) GetReversedDeterministicHashCodeKey(string facesFileNameExtension, bool idToFacesAny, Dictionary> idToFaces, string file) { int? id; List? faces; @@ -71,7 +71,6 @@ internal abstract class Mapping } else (id, normalizedPixelPercentage, faces) = GetReversedDeterministicHashCodeKeysFromSegments( - locationDigits, facesFileNameExtension, idToFacesAny, idToFaces, diff --git a/Shared/Models/Stateless/Methods/PersonContainer.cs b/Shared/Models/Stateless/Methods/PersonContainer.cs index 03f28ff..5aaa99e 100644 --- a/Shared/Models/Stateless/Methods/PersonContainer.cs +++ b/Shared/Models/Stateless/Methods/PersonContainer.cs @@ -3,7 +3,7 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; internal abstract class PersonContainer { - private static string[] GetFiles(int locationDigits, string facesFileNameExtension, string personDisplayDirectory) + private static string[] GetFiles(string facesFileNameExtension, string personDisplayDirectory) { string[] results = Directory.GetFiles(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly); int? id; @@ -14,7 +14,7 @@ internal abstract class PersonContainer { if (personDisplayDirectoryAllFile.EndsWith(".lnk")) continue; - (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(locationDigits, facesFileNameExtension, personDisplayDirectoryAllFile); + (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(facesFileNameExtension, personDisplayDirectoryAllFile); if (id is not null && normalizedPixelPercentage is not null && !personDisplayDirectoryAllFile.EndsWith(".json")) continue; checkDirectory = Path.GetDirectoryName(personDisplayDirectoryAllFile); @@ -33,7 +33,7 @@ internal abstract class PersonContainer return results; } - private static List<(long?, Models.PersonContainer)> GetPersonContainersCollections(int locationDigits, string personBirthdayFormat, string facesFileNameExtension, char[] chars, string personDisplayDirectory, string personDisplayDirectoryName, string[] personKeyDirectories, int? approximateYears, List collections) + private static List<(long?, Models.PersonContainer)> GetPersonContainersCollections(string personBirthdayFormat, string facesFileNameExtension, char[] chars, string personDisplayDirectory, string personDisplayDirectoryName, string[] personKeyDirectories, int? approximateYears, List collections) { List<(long?, Models.PersonContainer)> results = new(); long personKey; @@ -44,7 +44,7 @@ internal abstract class PersonContainer Models.PersonBirthday? personBirthday; Models.PersonContainer personContainer; Models.PersonBirthday[] personBirthdays = collections.OrderByDescending(l => l.Value).ToArray(); - string[] personDisplayDirectoryAllFiles = GetFiles(locationDigits, facesFileNameExtension, personDisplayDirectory); + string[] personDisplayDirectoryAllFiles = GetFiles(facesFileNameExtension, personDisplayDirectory); foreach (string personKeyDirectory in personKeyDirectories) { personKeyFormatted = Path.GetFileName(personKeyDirectory); @@ -60,15 +60,15 @@ internal abstract class PersonContainer return results; } - private static Models.PersonContainer GetPersonContainer(int locationDigits, string facesFileNameExtension, string personDisplayDirectory, string personDisplayDirectoryName, int? approximateYears) + private static Models.PersonContainer GetPersonContainer(string facesFileNameExtension, string personDisplayDirectory, string personDisplayDirectoryName, int? approximateYears) { Models.PersonContainer result; - string[] personDisplayDirectoryAllFiles = GetFiles(locationDigits, facesFileNameExtension, personDisplayDirectory); + string[] personDisplayDirectoryAllFiles = GetFiles(facesFileNameExtension, personDisplayDirectory); result = new(approximateYears, personDisplayDirectoryAllFiles, personDisplayDirectoryName); return result; } - private static List<(long?, Models.PersonContainer)> GetPersonContainersGroup(int locationDigits, string personBirthdayFormat, string facesFileNameExtension, char[] chars, string[] personDisplayDirectories) + private static List<(long?, Models.PersonContainer)> GetPersonContainersGroup(string personBirthdayFormat, string facesFileNameExtension, char[] chars, string[] personDisplayDirectories) { List<(long?, Models.PersonContainer)> results = new(); int? approximateYears; @@ -85,17 +85,17 @@ internal abstract class PersonContainer personKeyDirectories = Directory.GetDirectories(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly); collections = PersonBirthday.GetPersonBirthdays(personBirthdayFormat, personKeyDirectories, personDisplayDirectory); if (collections.Any()) - results.AddRange(GetPersonContainersCollections(locationDigits, personBirthdayFormat, facesFileNameExtension, chars, personDisplayDirectory, personDisplayDirectoryName, personKeyDirectories, approximateYears, collections)); + results.AddRange(GetPersonContainersCollections(personBirthdayFormat, facesFileNameExtension, chars, personDisplayDirectory, personDisplayDirectoryName, personKeyDirectories, approximateYears, collections)); else { - personContainer = GetPersonContainer(locationDigits, facesFileNameExtension, personDisplayDirectory, personDisplayDirectoryName, approximateYears); + personContainer = GetPersonContainer(facesFileNameExtension, personDisplayDirectory, personDisplayDirectoryName, approximateYears); results.Add(new(null, personContainer)); } } return results; } - private static Models.PersonContainer[] GetPersonContainersGroups(int locationDigits, string personBirthdayFormat, string facesFileNameExtension, char[] chars, string[] groupDirectories) + private static Models.PersonContainer[] GetPersonContainersGroups(string personBirthdayFormat, string facesFileNameExtension, char[] chars, string[] groupDirectories) { Models.PersonContainer[] results; const int zero = 0; @@ -109,14 +109,14 @@ internal abstract class PersonContainer if (!chars.Contains(groupDirectoryName[zero])) continue; personDisplayDirectories = Directory.GetDirectories(groupDirectory, "*", SearchOption.TopDirectoryOnly); - collection = GetPersonContainersGroup(locationDigits, personBirthdayFormat, facesFileNameExtension, chars, personDisplayDirectories); + collection = GetPersonContainersGroup(personBirthdayFormat, facesFileNameExtension, chars, personDisplayDirectories); personContainers.AddRange(collection); } results = (from l in personContainers orderby l.PersonKey is not null, l.PersonKey select l.PersonContainer).ToArray(); return results; } - internal static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, int locationDigits, string personBirthdayFormat, string facesFileNameExtension) + internal static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, string personBirthdayFormat, string facesFileNameExtension) { Models.PersonContainer[] results; char[] chars = IAge.GetChars(); @@ -134,7 +134,7 @@ internal abstract class PersonContainer if (!groupDirectories.Any()) results = Array.Empty(); else - results = GetPersonContainersGroups(locationDigits, personBirthdayFormat, facesFileNameExtension, chars, groupDirectories); + results = GetPersonContainersGroups(personBirthdayFormat, facesFileNameExtension, chars, groupDirectories); return results; } diff --git a/Tests/UnitTestCalculations.cs b/Tests/UnitTestCalculations.cs index 2b7adde..56115cf 100644 --- a/Tests/UnitTestCalculations.cs +++ b/Tests/UnitTestCalculations.cs @@ -370,6 +370,36 @@ public class UnitTestCalculations Assert.IsTrue(y.HasValue && y.Value == 641); } + [TestMethod] + public void TestGetPixelPercentageF() + { + int? x, y; + int normalizedPixelPercentage; + int bottom, height, left, right, top, width; + string normalizedPixelPercentagePadded; + width = 2048; + height = 1365; + normalizedPixelPercentagePadded = "617214031"; + (x, y) = ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, width, height, normalizedPixelPercentagePadded); + if (x is null || y is null) + throw new Exception(); + Assert.IsTrue(x.Value == 1264); + Assert.IsTrue(y.Value == 192); + left = x.Value; + right = x.Value; + top = y.Value; + bottom = y.Value; + normalizedPixelPercentage = ILocation.GetNormalizedPixelPercentage(bottom, height, left, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, right, top, width); + Assert.IsTrue(normalizedPixelPercentage == 617214071); + double x1, x2, y1, y2; + x1 = x.Value; + x2 = x.Value; + y1 = y.Value; + y2 = y.Value - 3; + double distance = Math.Sqrt(Math.Pow(x1 - x2, 2) + Math.Pow(y1 - y2, 2)); + Assert.IsTrue(distance == 3); + } + [TestMethod] public void TestGetDistance() {