From a145a8911254970bb3de9a55e7f0f49753fffa8a Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Sun, 25 Sep 2022 20:17:19 -0700 Subject: [PATCH] Published - Added Mapping shortcut, added leveled limits, container bug fix, --- .vscode/launch.json | 28 ++++ Distance/Models/_E_Distance.cs | 159 +++++++++++------- Face/Models/_D_Face.cs | 46 ++---- Instance/DlibDotNet.cs | 127 ++++++-------- Map/Models/MapLogic.cs | 173 +++++++++++++++----- Map/Models/Stateless/MapLogic.cs | 25 ++- Map/Models/Stateless/Methods/IMapLogic.cs | 4 +- Property/Models/Stateless/Container.cs | 14 +- Shared/Models/Face.cs | 4 - Shared/Models/Mapping.cs | 4 +- Shared/Models/Properties/IMapping.cs | 1 + Shared/Models/SortingContainer.cs | 3 +- Shared/Models/Stateless/Methods/IAge.cs | 2 +- Shared/Models/Stateless/Methods/IItem.cs | 8 +- Shared/Models/Stateless/Methods/ISorting.cs | 8 +- Shared/Models/Stateless/Methods/Item.cs | 24 ++- Shared/Models/Stateless/Methods/Sorting.cs | 48 ++---- 17 files changed, 416 insertions(+), 262 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 0cd8986..1e8dcb9 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -81,3 +81,31 @@ // 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 +// https://scontent-lax3-2.xx.fbcdn.net/v/t39.30808-6/290559432_10209959340897099_842876274165104077_n.jpg?_nc_cat=111&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=Vgxc93JsPBEAX8zrKaq&_nc_ht=scontent-lax3-2.xx&oh=00_AT-pPGd4o-t7kSeY4XKOTDeOzfg6wXOMBdY6rldQyrKQmw&oe=6335398E +// https://scontent-lax3-1.xx.fbcdn.net/v/t39.30808-6/308587069_10210153867920153_6202104893656263114_n.jpg?stp=cp6_dst-jpg&_nc_cat=104&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=SKB2FSdXFQEAX_v1t5g&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-1.xx&oh=00_AT_E1y9uQ27O5_FAyAeRJ0XotEyBEXytkM2iDCGvldSxLw&oe=633549B9 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/67309987_10214298629206292_6820175905885782016_n.jpg?_nc_cat=106&ccb=1-7&_nc_sid=730e14&_nc_ohc=BTQEZF_dwRwAX-cxNEm&_nc_ht=scontent-lax3-2.xx&oh=00_AT8_z-JOBPmskVsJ0S9bOYgcYngpVrMjhVrfFk3r06Wj8Q&oe=635473AE +// https://scontent-lax3-1.xx.fbcdn.net/v/t39.30808-6/263710427_1324163581376203_7502850514450466967_n.jpg?_nc_cat=110&ccb=1-7&_nc_sid=e3f864&_nc_ohc=2KB9VISs3y0AX-PiYUd&_nc_ht=scontent-lax3-1.xx&oh=00_AT_WaHBBSAR2-1dDEdpufugFf4eBttyGfIIflCwvCu_76g&oe=6334DBC3 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/67181620_114720179834180_3651229536021905408_n.jpg?_nc_cat=101&ccb=1-7&_nc_sid=09cbfe&_nc_ohc=CYF8Qyy506MAX-GBXV_&_nc_ht=scontent-lax3-2.xx&oh=00_AT_dFZiY42lloSfdiqNgSBlDpS9eGIEu85hhG5KIQD7DwA&oe=6354B320 +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.6435-9/68383564_10217654576270105_5209606295652401152_n.jpg?_nc_cat=109&ccb=1-7&_nc_sid=730e14&_nc_ohc=phqcunpNs5EAX-d33kB&_nc_ht=scontent-lax3-1.xx&oh=00_AT9n5kFQnIPSXUzNAMb19Wpue1YA-bHFpSCE-_tOXD8Gnw&oe=635615C2 +// https://scontent-lax3-2.xx.fbcdn.net/v/t39.30808-6/285466259_7423531907720135_1229107015631332741_n.jpg?_nc_cat=111&ccb=1-7&_nc_sid=09cbfe&_nc_ohc=z85uLRC706sAX_H3_Ht&_nc_ht=scontent-lax3-2.xx&oh=00_AT-_wJpeYhqcdivdF4SbBO3B6M082qGD3qdGAPDmVP6nAA&oe=6334B2ED +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.6435-9/32919393_10214483292069982_3789509822047584256_n.jpg?_nc_cat=105&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=oJzHahluIDYAX-5-UGl&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-1.xx&oh=00_AT9e7dHUoseqwf6qF39NHEnPzal6NzQgyCwio6SvzUZTUQ&oe=63575682 +// https://scontent-lax3-1.xx.fbcdn.net/v/t31.18172-8/22256636_1931521070438917_6414682443902494017_o.jpg?_nc_cat=102&ccb=1-7&_nc_sid=cdbe9c&_nc_ohc=bf99qSpRJOQAX_stzg5&_nc_ht=scontent-lax3-1.xx&oh=00_AT-eoWkn2Gaqj8BGasgNOycRzf3AiQE2GqHtKC28_-vFug&oe=63586C84 +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.18169-9/600876_10151927436713567_876993105_n.jpg?_nc_cat=110&ccb=1-7&_nc_sid=cdbe9c&_nc_ohc=dcNCC6RNOooAX985ENZ&_nc_ht=scontent-lax3-1.xx&oh=00_AT-9Q999B_sWiS-yPP48gVdrheH0bY-DAiOKmkExbnW5Rw&oe=6355ED8A +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.6435-9/35235266_10213962597433782_6655457381733892096_n.jpg?_nc_cat=110&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=uxfDliBhPHUAX_JXJNU&_nc_ht=scontent-lax3-1.xx&oh=00_AT9zGc-8QqaAHItoDqGzKAMEYOU0fEQz_ld1R_CGxPokug&oe=63565840 +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.6435-9/161932468_10159007128985149_3980438021322511452_n.jpg?_nc_cat=104&ccb=1-7&_nc_sid=09cbfe&_nc_ohc=6dCTPFwvFPcAX8ogdv8&_nc_ht=scontent-lax3-1.xx&oh=00_AT8pspicXFXgj-MOKzkTyp_ZpuboruYwyM-MMNwro_m9JA&oe=63564482 +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.6435-9/91250196_10215323899906785_1298078522899693568_n.jpg?_nc_cat=110&ccb=1-7&_nc_sid=730e14&_nc_ohc=CSXhKF_1hqsAX9qlbvP&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-1.xx&oh=00_AT-JZSnju_3XqWV6w9rSSUmuo2oIaCig5pn7JmrvFbBfGw&oe=6354B339 +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.18169-9/428510_490436967638912_1438526428_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=ba80b0&_nc_ohc=s0ZgvdtWwOsAX87AD-I&_nc_ht=scontent-lax3-1.xx&oh=00_AT-gv7QKuJhEjRPbmQr5hLG163-EQXcx6FJ8aHCcPTfEXw&oe=63563591 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/50312617_10161338488075048_5525340242208358400_n.jpg?_nc_cat=101&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=NcQcK_z6t9kAX9-On7t&_nc_ht=scontent-lax3-2.xx&oh=00_AT_WYrFNqGwzuSssGPBRmhpqGlyf1k2ulbdKakrs4xAHBg&oe=635832DB +// https://scontent-lax3-2.xx.fbcdn.net/v/t39.30808-6/247966826_10200232179385908_1907223790607385605_n.jpg?_nc_cat=106&ccb=1-7&_nc_sid=09cbfe&_nc_ohc=Xn0j5rxLaCQAX8OD7k4&_nc_ht=scontent-lax3-2.xx&oh=00_AT_bVVWAuaGYpIcBOCbAtn_xyS2Rqu--uKs06-FKOfjuzg&oe=633583B8 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/57840024_10161651547530207_1744748790901899264_n.jpg?_nc_cat=107&ccb=1-7&_nc_sid=730e14&_nc_ohc=TKg3rTiXkYUAX-V8NO5&_nc_ht=scontent-lax3-2.xx&oh=00_AT-Mepp0iN8-mHhyKRHj-R5yBOu2wZGtQeApkSoZTzM3mg&oe=6356A1D2 +// https://scontent-lax3-2.xx.fbcdn.net/v/t39.30808-6/269876615_612483726673361_2182050585964176784_n.jpg?_nc_cat=106&ccb=1-7&_nc_sid=174925&_nc_ohc=9QJt0X_FDlEAX_Okew3&_nc_ht=scontent-lax3-2.xx&oh=00_AT_Yq8OflcYUA39JsmM__UxFYi8YASqsrRYx-T1Qn2NPSw&oe=6336391B +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/126332086_10224303272989365_2242003924983097751_n.jpg?_nc_cat=111&ccb=1-7&_nc_sid=09cbfe&_nc_ohc=zpX0nadZ9XMAX8m1Kk1&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-2.xx&oh=00_AT9c_dq-TLiNxgeqmp9Pwnqp9xjUIG3_ijxmiAW4MPYBKw&oe=63578DD6 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/74624149_10215957575592842_7757392320252608512_n.jpg?_nc_cat=103&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=22WGGAPeTdAAX87greQ&_nc_ht=scontent-lax3-2.xx&oh=00_AT9J2qV9zBMEPuqsibA-87pjTBg3e3hVwHb211GO7lJicQ&oe=6355F050 +// https://scontent-lax3-1.xx.fbcdn.net/v/t31.18172-8/10649011_812346452173040_8035951943727654673_o.jpg?_nc_cat=104&ccb=1-7&_nc_sid=84a396&_nc_ohc=aDP-7N5XOgMAX9eflUn&_nc_ht=scontent-lax3-1.xx&oh=00_AT_mCAWB-OTJ32F1W90m-bPWu9GmjvFr-j1VdAQmkdNtXg&oe=63565628 +// https://scontent-lax3-2.xx.fbcdn.net/v/t39.30808-6/289655024_10228170790084748_4126077972169573791_n.jpg?_nc_cat=101&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=NeX9XD5pcwMAX9UBHLe&_nc_ht=scontent-lax3-2.xx&oh=00_AT-Qh77ATMIGL6JnKHr9rIim3Ui_UU7XH_S02S7-iu21qg&oe=633700F0 +// https://scontent-lax3-2.xx.fbcdn.net/v/t39.30808-6/266998682_10227151119593623_456420668145746211_n.jpg?_nc_cat=101&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=vjNb4pBYn5YAX_gWfIx&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-2.xx&oh=00_AT_rv-lqoI2u7Y-FMU8G8Vfxo6QyA-tTEIMKRpRx9TxZPg&oe=63353CCC +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.6435-9/40093120_10217172129645111_2951374557987995648_n.jpg?_nc_cat=110&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=X1j0ykpT26oAX8kDzfQ&_nc_ht=scontent-lax3-1.xx&oh=00_AT-jst6eXb7F4NsSJRj4jOQvKqQOiiMP4K5iT8xq2t4dTg&oe=63588214 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/31870362_10216285257993874_8330563136197230592_n.jpg?_nc_cat=103&ccb=1-7&_nc_sid=84a396&_nc_ohc=8kJ5pbwsKDMAX9hIVFA&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-2.xx&oh=00_AT9vRjGUZdT7KasJ4Ndti2LHfrPaTcahl4ipT9BmdRZJeg&oe=6356737F +// https://scontent-lax3-2.xx.fbcdn.net/v/t39.30808-6/230074448_10103880528811228_6909448863476427135_n.jpg?_nc_cat=103&ccb=1-7&_nc_sid=0debeb&_nc_ohc=cUpp1Y_DO8MAX92tN_t&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-2.xx&oh=00_AT-K2_yEERUmvvjkjUKf7zwaV2Ofq1fHIQAtEkCt7I2Bhw&oe=63352B95 +// https://scontent-lax3-2.xx.fbcdn.net/v/t31.18172-8/13502600_10210212049485607_95598559411189791_o.jpg?_nc_cat=101&ccb=1-7&_nc_sid=cdbe9c&_nc_ohc=AEojM0a2X5cAX8kmHfZ&_nc_ht=scontent-lax3-2.xx&oh=00_AT-ZX7vIfwazh_zcDpFCLxwLgp90gERyBG2CtGxIClEnYA&oe=6355A9C7 +// https://scontent-lax3-2.xx.fbcdn.net/v/t31.18172-8/14195939_1314130471931770_9026437168267009241_o.jpg?_nc_cat=106&ccb=1-7&_nc_sid=730e14&_nc_ohc=f8owaBX7kMQAX8ioj3m&_nc_ht=scontent-lax3-2.xx&oh=00_AT8N8GR4GXmKa3w_dP952fl1_bx_s7CTz8qFtxaBK91S2w&oe=6355DBA1 diff --git a/Distance/Models/_E_Distance.cs b/Distance/Models/_E_Distance.cs index d586743..be23bc4 100644 --- a/Distance/Models/_E_Distance.cs +++ b/Distance/Models/_E_Distance.cs @@ -39,33 +39,101 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance if (!Directory.Exists(eDistanceContentCollectionDirectory)) _ = Directory.CreateDirectory(eDistanceContentCollectionDirectory); #pragma warning disable - string[] results = (from l in sortingContainers select string.Concat(l.Sorting.WithinRange, '\t', l.Sorting.DistancePermyriad, '\t', l.Sorting.DaysDelta, '\t', l.Sorting.Id, '\t', l.Sorting.NormalizedPixelPercentage, '\t', l.Sorting.Older, '\t', l.Face.Mapping.MappingFromItem.Id, '\t', l.Face.Mapping.MappingFromLocation.NormalizedPixelPercentage)).ToArray(); + string[] results = (from l in sortingContainers select l.ToString()).ToArray(); #pragma warning restore string eDistanceContentFileName = Path.Combine(eDistanceContentCollectionDirectory, $"{configuration.ResultAllInOne}.tvs"); File.WriteAllLines(eDistanceContentFileName, results); } - private List GetSortingCollection(MapLogic mapLogic, List faceDistanceEncodings, int faceDistanceContainersLength, int i, FaceDistance faceDistanceEncoding) + private static List GetSortingCollection(MapLogic mapLogic, List faceDistanceEncodings, int faceDistanceContainersLength, int i, FaceDistance faceDistanceEncoding) { List results; List faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncoding); if (faceDistanceLengths.Count != faceDistanceContainersLength) throw new NotSupportedException(); - bool anyLowerThanTolerance = (from l in faceDistanceLengths where l.Length is not null && l.Length.Value != 0 && l.Length.Value < _FaceDistanceTolerance select true).Any(); - results = mapLogic.GetSortingCollection(i, faceDistanceEncoding, faceDistanceLengths, anyLowerThanTolerance); + results = mapLogic.GetSortingCollection(i, faceDistanceEncoding, faceDistanceLengths); return results; } - private List GetSortingContainers(Face face, FaceDistance faceDistanceEncoding, List sortingCollection) + private List GetSortingContainers(Face face, FaceDistance faceDistanceEncoding, List sortingCollection, int? useFiltersCounter) { List results = new(); SortingContainer sortingContainer; Sorting[] collection = Shared.Models.Stateless.Methods.ISorting.Sort(sortingCollection); + double faceDistancePermyriad; + double sortingDaysDeltaTolerance; + double faceDistanceMinimumConfidence; + if (useFiltersCounter is null) + { + sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance; + faceDistancePermyriad = _FaceDistancePermyriad; + faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence; + } + else if (useFiltersCounter.Value == 1) + { + sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 1.5; + faceDistancePermyriad = _FaceDistancePermyriad; + faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence; + } + else if (useFiltersCounter.Value == 2) + { + sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance; + faceDistancePermyriad = _FaceDistancePermyriad * 1.5; + faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence; + } + else if (useFiltersCounter.Value == 3) + { + sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance; + faceDistancePermyriad = _FaceDistancePermyriad; + faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence * .5; + } + else if (useFiltersCounter.Value == 4) + { + sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 2; + faceDistancePermyriad = _FaceDistancePermyriad * 1.5; + faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence * .5; + } + else if (useFiltersCounter.Value == 5) + { + sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 1.5; + faceDistancePermyriad = _FaceDistancePermyriad * 2; + faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence * .5; + } + else if (useFiltersCounter.Value == 6) + { + sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 1.5; + faceDistancePermyriad = _FaceDistancePermyriad * 1.5; + faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence * .25; + } + else if (useFiltersCounter.Value == 7) + { + sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 2.5; + faceDistancePermyriad = _FaceDistancePermyriad * 2; + faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence * .25; + } + else if (useFiltersCounter.Value == 8) + { + sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 2; + faceDistancePermyriad = _FaceDistancePermyriad * 2.5; + faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence * .25; + } + else if (useFiltersCounter.Value == 9) + { + sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 2; + faceDistancePermyriad = _FaceDistancePermyriad * 2; + faceDistanceMinimumConfidence = 0; + } + else + { + sortingDaysDeltaTolerance = int.MaxValue; + faceDistancePermyriad = int.MaxValue; + faceDistanceMinimumConfidence = 0; + } foreach (Sorting sorting in collection) { if (face.Mapping is null || faceDistanceEncoding.NormalizedPixelPercentage is null) throw new NotSupportedException(); - if (face.Mapping.MappingFromLocation.Confidence < _FaceDistanceMinimumConfidence || sorting.DistancePermyriad > _FaceDistancePermyriad || sorting.DaysDelta > _SortingDaysDeltaTolerance) + if (sorting.DaysDelta > sortingDaysDeltaTolerance || sorting.DistancePermyriad > faceDistancePermyriad || face.Mapping.MappingFromLocation.Confidence < faceDistanceMinimumConfidence) continue; sortingContainer = new(face, sorting); results.Add(sortingContainer); @@ -116,7 +184,7 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance return faceDistanceEncodings; } - public SortingContainer[] SetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, long ticks, MapLogic mapLogic, Face[] selectedFilteredFaces) + public SortingContainer[] SetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, long ticks, MapLogic mapLogic, Face[] selectedFilteredFaces, int? useFiltersCounter) { SortingContainer[] results; List collection = new(); @@ -126,8 +194,6 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance List faceDistanceEncodings = GetFaceDistanceEncodings(faceDistanceContainers); string message = $") {faceDistanceContainers.Length:000} Get Sorting Containers Then Set Face Mapping Sorting Collection - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; - foreach (Face face in selectedFilteredFaces) - face.ClearFaceDistance(); using ProgressBar progressBar = new(faceDistanceContainers.Length, message, options); _ = Parallel.For(0, faceDistanceContainers.Length, parallelOptions, (i, state) => { @@ -136,14 +202,22 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance if (face.Mapping is null) throw new NotSupportedException(); FaceDistance faceDistanceEncoding = faceDistanceContainers[i].FaceDistance; + if (mapLogic.Used(faceDistanceEncoding)) + return; List sortingCollection = GetSortingCollection(mapLogic, faceDistanceEncodings, faceDistanceContainers.Length, i, faceDistanceEncoding); - List sortingContainers = GetSortingContainers(face, faceDistanceEncoding, sortingCollection); - lock (collection) - collection.AddRange(sortingContainers); - lock (face) - face.ReleaseFaceDistance(); + if (!sortingCollection.Any()) + return; + List sortingContainers = GetSortingContainers(face, faceDistanceEncoding, sortingCollection, useFiltersCounter); + if (sortingContainers.Any()) + { + lock (collection) + collection.AddRange(sortingContainers); + } }); - results = Shared.Models.Stateless.Methods.ISortingContainer.Sort(collection); + if (!collection.Any()) + results = Array.Empty(); + else + results = Shared.Models.Stateless.Methods.ISortingContainer.Sort(collection); return results; } @@ -458,21 +532,23 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance return results; } - private static FileInfo? CheckFileThenGetFileInfo(string facesFileNameExtension, Item item, string mappedFaceDirectory, string mappedFaceFile, List checkFaces) + private static FileInfo? CheckFileThenGetFileInfo(string facesFileNameExtension, MappingFromItem mappingFromItem, string mappedFaceFile, List checkFaces) { FileInfo? result = null; string checkFile; + string? mappedFaceDirectory; string deterministicHashCodeKey; foreach (Face face in checkFaces) { if (checkFaces.Count != 1) break; - if (item.Property?.Id is null || item.ImageFileHolder is null) - throw new NotSupportedException(); if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) throw new NotSupportedException(); - deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution); - checkFile = Path.Combine(mappedFaceDirectory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}{facesFileNameExtension}"); + mappedFaceDirectory = Path.GetDirectoryName(mappedFaceFile); + if (mappedFaceDirectory is null) + throw new NotSupportedException(); + deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(mappingFromItem.Id, face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution); + checkFile = Path.Combine(mappedFaceDirectory, $"{deterministicHashCodeKey}{mappingFromItem.ImageFileHolder.ExtensionLowered}{facesFileNameExtension}"); if (checkFile == mappedFaceFile) continue; result = new FileInfo(checkFile); @@ -510,54 +586,25 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance return results; } - public (int, int, int) GetUnableToMatchCountAndRenameMatches(string facesFileNameExtension, string eDistanceContentDirectory, Item item, List faces, string[] mappedFaceFiles) + public (int, int, int) GetUnableToMatchCountAndRenameMatches(string facesFileNameExtension, string eDistanceContentDirectory, MappingFromItem mappingFromItem, List faces, List<(string MappedFaceFile, int normalizedPixelPercentage)> collection) { int result = 0; - int? id; string? json; int renamed = 0; - bool? isWrongYear; FileInfo? fileInfo; - DateTime minimumDateTime; - string? mappedFaceDirectory; List checkFaces = new(); List debugChecks = new(); - int? normalizedPixelPercentage; - MappingFromItem mappingFromItem; - List normalizedPixelPercentages; + List normalizedPixelPercentages = new(); List duplicateMappedFaceFiles = new(); - Dictionary> idToNormalizedPixelPercentages = new(); - foreach (string mappedFaceFile in mappedFaceFiles) + string[] mappedFaceFiles = (from l in collection select l.MappedFaceFile).ToArray(); + foreach ((string mappedFaceFile, int normalizedPixelPercentage) in collection) { - mappedFaceDirectory = Path.GetDirectoryName(mappedFaceFile); - if (mappedFaceDirectory is null) - throw new NotSupportedException(); - if (item.Property?.Id is null) - throw new NotSupportedException(); if (duplicateMappedFaceFiles.Contains(mappedFaceFile)) continue; - (id, normalizedPixelPercentage, _) = Shared.Models.Stateless.Methods.IMapping.GetReversedDeterministicHashCodeKey(facesFileNameExtension, mappedFaceFile); - if (id is null || normalizedPixelPercentage is null) - { - result++; - continue; - } - if (id.Value != item.Property.Id.Value) - 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; checkFaces.Clear(); debugChecks.Clear(); - if (!idToNormalizedPixelPercentages.ContainsKey(id.Value)) - idToNormalizedPixelPercentages.Add(id.Value, new()); - normalizedPixelPercentages = idToNormalizedPixelPercentages[id.Value]; - checkFaces.AddRange(GetMatchingFaces(faces, mappedFaceFiles, debugChecks, normalizedPixelPercentage.Value, normalizedPixelPercentages, duplicateMappedFaceFiles, mappedFaceFile)); + checkFaces.AddRange(GetMatchingFaces(faces, mappedFaceFiles, debugChecks, normalizedPixelPercentage, normalizedPixelPercentages, duplicateMappedFaceFiles, mappedFaceFile)); if (checkFaces.Count != 1) { checkFaces.Clear(); @@ -599,8 +646,8 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance MoveUnableToMatch(eDistanceContentDirectory, mappedFaceFile); continue; } - normalizedPixelPercentages.Add(normalizedPixelPercentage.Value); - fileInfo = CheckFileThenGetFileInfo(facesFileNameExtension, item, mappedFaceDirectory, mappedFaceFile, checkFaces); + normalizedPixelPercentages.Add(normalizedPixelPercentage); + fileInfo = CheckFileThenGetFileInfo(facesFileNameExtension, mappingFromItem, mappedFaceFile, checkFaces); if (fileInfo is null) continue; File.Move(mappedFaceFile, fileInfo.FullName); diff --git a/Face/Models/_D_Face.cs b/Face/Models/_D_Face.cs index e562a83..59c157e 100644 --- a/Face/Models/_D_Face.cs +++ b/Face/Models/_D_Face.cs @@ -175,32 +175,28 @@ public class D_Face } } - private List GetFaces(Item item, Shared.Models.Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation) + private List GetFaces(Shared.Models.Property property, MappingFromItem mappingFromItem, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation) { List results = new(); - if (item.ImageFileHolder is null) - throw new NullReferenceException(nameof(item.ImageFileHolder)); - if (item.ResizedFileHolder is null) - throw new NullReferenceException(nameof(item.ResizedFileHolder)); FaceRecognitionDotNet.Image? unknownImage; - if (!item.ResizedFileHolder.Exists) + if (!mappingFromItem.ResizedFileHolder.Exists) unknownImage = null; else { try - { unknownImage = FaceRecognition.LoadImageFile(item.ResizedFileHolder.FullName); } + { unknownImage = FaceRecognition.LoadImageFile(mappingFromItem.ResizedFileHolder.FullName); } catch (Exception) { unknownImage = null; } } if (unknownImage is null) - results.Add(new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, item.RelativePath, location: null)); + results.Add(new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, mappingFromItem.RelativePath, location: null)); else { List<(Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary? FaceParts)> collection; FaceRecognition faceRecognition = new(_NumberOfTimesToUpsample, _NumberOfJitters, _PredictorModel, _Model, _ModelParameter); collection = faceRecognition.GetCollection(unknownImage, includeFaceEncoding: true, includeFaceParts: true); if (!collection.Any()) - results.Add(new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, item.RelativePath, location: null)); + results.Add(new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, mappingFromItem.RelativePath, location: null)); else { double[] rawEncoding; @@ -208,7 +204,7 @@ public class D_Face Shared.Models.FaceEncoding convertedFaceEncoding; foreach ((Location location, FaceRecognitionDotNet.FaceEncoding? faceEncoding, Dictionary? faceParts) in collection) { - face = new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, item.RelativePath, location); + face = new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, mappingFromItem.RelativePath, location); if (faceEncoding is not null) { rawEncoding = faceEncoding.GetRawEncoding(); @@ -230,20 +226,16 @@ public class D_Face #pragma warning restore CA1416 - public List GetFaces(string dResultsFullGroupDirectory, List> subFileTuples, List parseExceptions, Item item, Shared.Models.Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation) + public List GetFaces(string dResultsFullGroupDirectory, List> subFileTuples, List parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation) { List? results; - if (item.Property?.Id is null) - throw new NullReferenceException(nameof(item.Property.Id)); - if (item.ImageFileHolder is null) - throw new NullReferenceException(nameof(item.ImageFileHolder)); if (string.IsNullOrEmpty(dResultsFullGroupDirectory)) throw new NullReferenceException(nameof(dResultsFullGroupDirectory)); string json; string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) }; List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); - string usingRelativePath = Path.Combine(AngleBracketCollection[0].Replace("<>", "[]"), $"{item.ImageFileHolder.NameWithoutExtension}.json"); - string dCollectionFile = Path.Combine(dResultsFullGroupDirectory, "[]", _Configuration.ResultAllInOne, $"{item.Property.Id.Value}{item.ImageFileHolder.ExtensionLowered}.json"); + string usingRelativePath = Path.Combine(AngleBracketCollection[0].Replace("<>", "[]"), $"{mappingFromItem.ImageFileHolder.NameWithoutExtension}.json"); + string dCollectionFile = Path.Combine(dResultsFullGroupDirectory, "[]", _Configuration.ResultAllInOne, $"{mappingFromItem.Id}{mappingFromItem.ImageFileHolder.ExtensionLowered}.json"); FileInfo fileInfo = new(dCollectionFile); if (!fileInfo.Exists) { @@ -299,7 +291,7 @@ public class D_Face if (results is null || (_RetryImagesWithoutAFace && results.Count == 1 && results[0].FaceEncoding is null)) { bool wasNull = results is null; - results = GetFaces(item, property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation); + results = GetFaces(property, mappingFromItem, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation); if (wasNull || (!wasNull && results.Any(l => l.FaceEncoding is not null))) { json = JsonSerializer.Serialize(results, _WriteIndentedAndWhenWritingNull); @@ -325,31 +317,27 @@ public class D_Face return results; } - public void SaveFaces(string dResultsFullGroupDirectory, List> subFileTuples, List parseExceptions, Item item, List faces) + public void SaveFaces(string dResultsFullGroupDirectory, List> subFileTuples, List parseExceptions, MappingFromItem mappingFromItem, List faces) { - if (item.ImageFileHolder is null) - throw new NullReferenceException(nameof(item.ImageFileHolder)); - if (item.ResizedFileHolder is null) - throw new NullReferenceException(nameof(item.ResizedFileHolder)); FileInfo fileInfo; bool check = false; string parentCheck; string deterministicHashCodeKey; List<(Shared.Models.Face, FileInfo?, string)> collection = new(); string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) }; - string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension); + string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), mappingFromItem.ImageFileHolder.NameWithoutExtension); List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); if (!Directory.Exists(facesDirectory)) _ = Directory.CreateDirectory(facesDirectory); foreach (Shared.Models.Face face in faces) { - if (item.Property?.Id is null || face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) + if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) { collection.Add(new(face, null, string.Empty)); continue; } - deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location, ILocation.Digits, ILocation.Factor, face.OutputResolution); - fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}{_FileNameExtension}")); + deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(mappingFromItem.Id, face.Location, ILocation.Digits, ILocation.Factor, face.OutputResolution); + fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{mappingFromItem.ImageFileHolder.ExtensionLowered}{_FileNameExtension}")); if (!fileInfo.Exists) { if (fileInfo.Directory?.Parent is null) @@ -358,7 +346,7 @@ public class D_Face if (File.Exists(parentCheck)) File.Delete(parentCheck); } - collection.Add(new(face, fileInfo, Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}{_HiddenFileNameExtension}"))); + collection.Add(new(face, fileInfo, Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{mappingFromItem.ImageFileHolder.ExtensionLowered}{_HiddenFileNameExtension}"))); if (_OverrideForFaceImages) check = true; else if (!fileInfo.Exists) @@ -367,7 +355,7 @@ public class D_Face check = true; } if (check) - SaveFaces(item.ResizedFileHolder, collection); + SaveFaces(mappingFromItem.ResizedFileHolder, collection); } } \ No newline at end of file diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index 990c83a..91ac1e6 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -348,7 +348,22 @@ 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, Container container, int index, Item item) + private static MappingFromItem GetMappingFromItem(Item item) + { + MappingFromItem result; + bool? isWrongYear; + DateTime minimumDateTime; + if (item.Property?.Id is null) + throw new NotSupportedException(); + if (item.Property?.Id is null || item.ImageFileHolder is null || item.ResizedFileHolder is null) + throw new NotSupportedException(); + minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property); + (isWrongYear, _) = item.Property.IsWrongYear(item.ImageFileHolder.FullName, minimumDateTime); + result = new(item.Property.Id.Value, item.ImageFileHolder, isWrongYear, minimumDateTime, item.RelativePath, item.ResizedFileHolder); + return result; + } + + private void FullParallelForWork(A_Property propertyLogic, Dictionary> idToMappedFaceFilesCollection, 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)); @@ -378,22 +393,10 @@ public partial class DlibDotNet sourceDirectoryChanges.Add(new Tuple(nameof(A_Property), (from l in subFileTuples select l.Item2).Max())); } } - (int metadataGroups, metadataCollection) = _Metadata.GetMetadataCollection( - _Configuration.PropertyConfiguration, - bResultsFullGroupDirectory, - subFileTuples, - parseExceptions, - item); + (int metadataGroups, metadataCollection) = _Metadata.GetMetadataCollection(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, subFileTuples, parseExceptions, item); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(B_Metadata.GetMetadataCollection)); - imageResizeKeyValuePairs = _Resize.GetResizeKeyValuePairs( - _Configuration.PropertyConfiguration, - cResultsFullGroupDirectory, - subFileTuples, - parseExceptions, - original, - metadataCollection, - item); + imageResizeKeyValuePairs = _Resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, subFileTuples, parseExceptions, original, metadataCollection, item); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(C_Resize.GetResizeKeyValuePairs)); if (_Configuration.SaveResizedSubfiles) @@ -414,17 +417,21 @@ public partial class DlibDotNet faces = null; else { + MappingFromItem mappingFromItem = GetMappingFromItem(item); int[] outputResolutionCollection = imageResizeKeyValuePairs[outputResolution]; int outputResolutionWidth = outputResolutionCollection[0]; int outputResolutionHeight = outputResolutionCollection[1]; int outputResolutionOrientation = outputResolutionCollection[2]; - faces = _Faces.GetFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, item, property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation); + faces = _Faces.GetFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(D_Face.GetFaces)); - _Faces.SaveFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, item, faces); + _Faces.SaveFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, mappingFromItem, faces); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(D_Face.SaveFaces)); - _ = _Distance.GetUnableToMatchCountAndRenameMatches(_Faces.FileNameExtension, eDistanceContentDirectory, item, faces, mappedFaceFiles); + if (item.Property?.Id is not null + && faces.Any(l => l.FaceEncoding is not null && l.Location is not null && l.OutputResolution is not null) + && idToMappedFaceFilesCollection.TryGetValue(item.Property.Id.Value, out List<(string, int)>? collection)) + _ = _Distance.GetUnableToMatchCountAndRenameMatches(_Faces.FileNameExtension, eDistanceContentDirectory, mappingFromItem, faces, collection); if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) { throw new NotImplementedException(); @@ -449,7 +456,7 @@ public partial class DlibDotNet private int FullParallelWork(int maxDegreeOfParallelism, A_Property propertyLogic, - string[] mappedFaceFiles, + Dictionary> idToMappedFaceFilesCollection, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, @@ -491,7 +498,7 @@ public partial class DlibDotNet { FullParallelForWork( propertyLogic, - mappedFaceFiles, + idToMappedFaceFilesCollection, outputResolution, bResultsFullGroupDirectory, cResultsFullGroupDirectory, @@ -555,15 +562,7 @@ public partial class DlibDotNet } } - private void WriteGroup( - A_Property propertyLogic, - Shared.Models.Property[] propertyCollection, - List>> metadataCollection, - List> resizeKeyValuePairs, - List?> imageFaceCollections, - string outputResolution, - Container container, - Item[] filteredItems) + private void WriteGroup(A_Property propertyLogic, Shared.Models.Property[] propertyCollection, List>> metadataCollection, List> resizeKeyValuePairs, List?> imageFaceCollections, string outputResolution, Container container, Item[] filteredItems) { Item item; string key; @@ -686,14 +685,7 @@ public partial class DlibDotNet return new(aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory); } - private void SetAngleBracketCollections( - A_Property propertyLogic, - string outputResolution, - Container container, - string aResultsFullGroupDirectory, - string bResultsFullGroupDirectory, - string cResultsFullGroupDirectory, - string dResultsFullGroupDirectory) + private void SetAngleBracketCollections(A_Property propertyLogic, string outputResolution, Container container, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory) { _Faces.AngleBracketCollection.Clear(); _Resize.AngleBracketCollection.Clear(); @@ -748,7 +740,7 @@ public partial class DlibDotNet return results.ToArray(); } - private void FullDoWork(string argZero, Model? model, PredictorModel? predictorModel, string propertyRoot, long ticks, A_Property propertyLogic, int t, Container[] containers, string eDistanceContentDirectory, string[] mappedFaceFiles) + private void FullDoWork(string argZero, Model? model, PredictorModel? predictorModel, string propertyRoot, long ticks, A_Property propertyLogic, int t, Container[] containers, string eDistanceContentDirectory, Dictionary> idToMappedFaceFilesCollection) { if (_Log is null) throw new NullReferenceException(nameof(_Log)); @@ -799,7 +791,7 @@ public partial class DlibDotNet exceptionCount = FullParallelWork( maxDegreeOfParallelism, propertyLogic, - mappedFaceFiles, + idToMappedFaceFilesCollection, outputResolution, bResultsFullGroupDirectory, cResultsFullGroupDirectory, @@ -875,17 +867,17 @@ public partial class DlibDotNet { if (item.Property?.Id is null || item.ImageFileHolder is null || item.ResizedFileHolder is null) continue; - if (!item.Faces.Any()) + if (!item.Faces.Any(l => l.FaceEncoding is not null && l.Location is not null && l.OutputResolution is not 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.RelativePath, item.ResizedFileHolder); foreach (Shared.Models.Face face in item.Faces) { if (face.RelativePath != item.RelativePath) break; if (face.FaceEncoding is null || face.Location is null || face.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); mappingFromPerson = new(approximateYears: null, by: null, displayDirectoryName: string.Empty, personBirthday: null, segmentB: string.Empty); normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution); deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution); @@ -899,14 +891,10 @@ public partial class DlibDotNet return results; } - private void DistanceThenMapLogic( - string argZero, - long ticks, - PersonContainer[] personContainers, - Container[] containers, - string dResultsFullGroupDirectory, - string outputResolution) + private void DistanceThenMapLogic(string argZero, long ticks, PersonContainer[] personContainers, Container[] containers, string dResultsFullGroupDirectory, string outputResolution) { + int? useFiltersCounter = null; + SortingContainer[] sortingContainers; string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, "()"); List distinctFilteredFaces = SetMappingThenGetDistinctFilteredFacesWithMapping(argZero, containers); Shared.Models.Face[] selectedFilteredFaces = E_Distance.GetSelectedFilteredFaces(distinctFilteredFaces); @@ -927,20 +915,20 @@ public partial class DlibDotNet eDistanceContentDirectory, distinctFilteredFaces, _Distance); - SortingContainer[] sortingContainers = _Distance.SetFaceMappingSortingCollectionThenGetSortingContainers( - _AppSettings.MaxDegreeOfParallelism, - ticks, - mapLogic, - selectedFilteredFaces); + sortingContainers = _Distance.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, ticks, mapLogic, selectedFilteredFaces, useFiltersCounter); + if (!sortingContainers.Any()) + { + for (useFiltersCounter = 1; useFiltersCounter < 11; useFiltersCounter++) + { + sortingContainers = _Distance.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, ticks, mapLogic, selectedFilteredFaces, useFiltersCounter); + if (sortingContainers.Any()) + break; + } + } E_Distance.SaveFaceDistances(_Configuration.PropertyConfiguration, sortingContainers); int totalNotMapped = mapLogic.AddToMapping(distinctFilteredFaces); if (totalNotMapped > 0) - mapLogic.ForceSingleImageThenSaveMapping( - dFacesContentDirectory, - d2FacePartsContentDirectory, - distinctFilteredFaces, - sortingContainers, - totalNotMapped); + mapLogic.ForceSingleImageThenSaveMapping(dFacesContentDirectory, d2FacePartsContentDirectory, distinctFilteredFaces, sortingContainers, useFiltersCounter, totalNotMapped); mapLogic.CopyManualFiles(dFacesContentDirectory, distinctFilteredFaces); if (_MapConfiguration.MappingSaveNotMapped) mapLogic.SaveNotMappedTicks(); @@ -1025,12 +1013,7 @@ public partial class DlibDotNet string cResultsFullGroupDirectory; string dResultsFullGroupDirectory; string eDistanceContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(E_Distance), "()"); - string[] mappedFaceFiles = Map.Models.Stateless.Methods.IMapLogic.DeleteEmptyDirectoriesAndGetMappedFaceFiles( - _MapConfiguration, - _Faces.FileNameExtension, - ticks, - eDistanceContentDirectory, - personContainers); + Dictionary> idToMappedFaceFilesCollection = Map.Models.Stateless.Methods.IMapLogic.DeleteEmptyDirectoriesAndGetMappedFaceFiles(_MapConfiguration, _Faces.FileNameExtension, ticks, eDistanceContentDirectory, personContainers); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string message = $") Building Container(s) - {totalSeconds} total second(s)"; A_Property propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, model, predictorModel); @@ -1055,15 +1038,9 @@ public partial class DlibDotNet _Configuration.PropertyConfiguration, nameof(A_Property), create: false); - propertyLogic = new( - _AppSettings.MaxDegreeOfParallelism, - _Configuration.PropertyConfiguration, - _Resize.FileNameExtension, - _Configuration.Reverse, - model, - predictorModel); + propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, model, predictorModel); } - FullDoWork(argZero, model, predictorModel, propertyRoot, ticks, propertyLogic, t, containers, eDistanceContentDirectory, mappedFaceFiles); + FullDoWork(argZero, model, predictorModel, propertyRoot, ticks, propertyLogic, t, containers, eDistanceContentDirectory, idToMappedFaceFilesCollection); foreach (string outputResolution in _Configuration.OutputResolutions) { if (_FirstRun || container is not null) diff --git a/Map/Models/MapLogic.cs b/Map/Models/MapLogic.cs index fc5f1ae..d58cc49 100644 --- a/Map/Models/MapLogic.cs +++ b/Map/Models/MapLogic.cs @@ -127,7 +127,27 @@ public class MapLogic return results; } - public List GetSortingCollection(int i, FaceDistance faceDistanceEncoding, List faceDistanceLengths, bool anyLowerThanTolerance) + public bool Used(FaceDistance faceDistanceEncoding) + { + bool result = false; + if (faceDistanceEncoding.NormalizedPixelPercentage is null) + throw new NotSupportedException(); + List? normalizedPixelPercentages; + Dictionary? normalizedPixelPercentageToPersonContainers; + if (_SkipCollection.TryGetValue(faceDistanceEncoding.Id, out normalizedPixelPercentages)) + { + if (normalizedPixelPercentages.Contains(faceDistanceEncoding.NormalizedPixelPercentage.Value)) + result = true; + } + if (!result && _IdThenNormalizedPixelPercentageToPersonContainers.TryGetValue(faceDistanceEncoding.Id, out normalizedPixelPercentageToPersonContainers)) + { + if (normalizedPixelPercentageToPersonContainers.ContainsKey(faceDistanceEncoding.NormalizedPixelPercentage.Value)) + result = true; + } + return result; + } + + public List GetSortingCollection(int i, FaceDistance faceDistanceEncoding, List faceDistanceLengths) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); @@ -135,33 +155,35 @@ public class MapLogic Sorting sorting; FaceDistance faceDistanceLength; List? normalizedPixelPercentages; - Dictionary? keyValuePairs; + Dictionary? normalizedPixelPercentageToPersonContainers; List<(long lcl, long minimum, long maximum, long ucl)> personKeysRangesCollection; for (int j = 0; j < faceDistanceLengths.Count; j++) { - if (j == i) - continue; - faceDistanceLength = faceDistanceLengths[j]; - if (faceDistanceEncoding.NormalizedPixelPercentage is null || faceDistanceLength.NormalizedPixelPercentage is null || faceDistanceLength.Length is null) + if (faceDistanceEncoding.NormalizedPixelPercentage is null) throw new NotSupportedException(); - if (faceDistanceLength.Length == 0) + if (j == i) continue; if (_SkipCollection.TryGetValue(faceDistanceEncoding.Id, out normalizedPixelPercentages)) { if (normalizedPixelPercentages.Contains(faceDistanceEncoding.NormalizedPixelPercentage.Value)) continue; } - if (_IdThenNormalizedPixelPercentageToPersonContainers.TryGetValue(faceDistanceEncoding.Id, out keyValuePairs)) + if (_IdThenNormalizedPixelPercentageToPersonContainers.TryGetValue(faceDistanceEncoding.Id, out normalizedPixelPercentageToPersonContainers)) { - if (keyValuePairs.ContainsKey(faceDistanceEncoding.NormalizedPixelPercentage.Value)) + if (normalizedPixelPercentageToPersonContainers.ContainsKey(faceDistanceEncoding.NormalizedPixelPercentage.Value)) continue; } - if (!_IdThenNormalizedPixelPercentageToPersonContainers.TryGetValue(faceDistanceLength.Id, out keyValuePairs)) + faceDistanceLength = faceDistanceLengths[j]; + if (faceDistanceLength.NormalizedPixelPercentage is null || faceDistanceLength.Length is null) + throw new NotSupportedException(); + if (faceDistanceLength.Length == 0) continue; - if (!keyValuePairs.ContainsKey(faceDistanceLength.NormalizedPixelPercentage.Value)) + if (!_IdThenNormalizedPixelPercentageToPersonContainers.TryGetValue(faceDistanceLength.Id, out normalizedPixelPercentageToPersonContainers)) continue; - personKeysRangesCollection = GetPersonKeysRangesCollection(keyValuePairs[faceDistanceLength.NormalizedPixelPercentage.Value]); - sorting = ISorting.Get(_Configuration.FaceDistancePermyriad, _Configuration.FaceDistanceTolerance, faceDistanceEncoding, faceDistanceLength, anyLowerThanTolerance, personKeysRangesCollection); + if (!normalizedPixelPercentageToPersonContainers.ContainsKey(faceDistanceLength.NormalizedPixelPercentage.Value)) + continue; + personKeysRangesCollection = GetPersonKeysRangesCollection(normalizedPixelPercentageToPersonContainers[faceDistanceLength.NormalizedPixelPercentage.Value]); + sorting = ISorting.Get(_Configuration.FaceDistancePermyriad, _Configuration.FaceDistanceTolerance, faceDistanceEncoding, faceDistanceLength, personKeysRangesCollection); if (sorting.DistancePermyriad == 0) continue; if (sorting.Id == faceDistanceEncoding.Id) @@ -299,14 +321,14 @@ public class MapLogic return result; } - private void SaveContainers(List saveContainers) + private void SaveContainers(int totalNotMapped, int updated, List saveContainers) { string checkFile; string sourceFile; WindowsShortcut windowsShortcut; string[] directories = (from l in saveContainers select l.Directory).Distinct().ToArray(); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - _Ticks).TotalSeconds); - string message = $") {saveContainers.Count:000} save(s) - {totalSeconds} total second(s)"; + string message = $") {saveContainers.Count:000} save(s) - {totalNotMapped} Total not Mapped - {updated} Updated - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; foreach (string directory in directories) { @@ -379,8 +401,10 @@ public class MapLogic { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); + int updated = 0; string directory; const int zero = 0; + int totalNotMapped = 0; string personKeyFormatted; SaveContainer saveContainer; PersonBirthday personBirthday; @@ -396,7 +420,7 @@ public class MapLogic saveContainer = new(directory); saveContainers.Add(saveContainer); } - SaveContainers(saveContainers); + SaveContainers(totalNotMapped, updated, saveContainers); } public List<(Face, long?, (string, string, string, string))> GetCollection(List distinctFilteredFaces) @@ -485,41 +509,37 @@ public class MapLogic if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); int result = 0; - Dictionary> results = new(); string key; const int zero = 0; - HashSet hashSet; string mappingSegmentB; string personKeyFormatted; List checkCollection; PersonBirthday personBirthday; PersonContainer[] personContainers; const int by = Stateless.IMapLogic.Sorting; - Dictionary? keyValuePairs; + List normalizedPixelPercentageCollection; Dictionary> checkKeyValuePairs = new(); + Dictionary> idToNormalizedPixelPercentageCollection = new(); + Dictionary? normalizedPixelPercentageToPersonContainers; int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - _Ticks).TotalSeconds); string message = $") {sortingContainers.Length:000} Update From Sorting Container(s) - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; - foreach (KeyValuePair> keyValuePair in _IdThenNormalizedPixelPercentageToPersonContainers) - results.Add(keyValuePair.Key, (from l in keyValuePair.Value select l.Key).ToHashSet()); using ProgressBar progressBar = new(sortingContainers.Length, message, options); foreach (SortingContainer sortingContainer in sortingContainers) { progressBar.Tick(); if (sortingContainer.Face.Mapping is null) throw new NotSupportedException(); - if (!_IdThenNormalizedPixelPercentageToPersonContainers.TryGetValue(sortingContainer.Sorting.Id, out keyValuePairs)) + if (!_IdThenNormalizedPixelPercentageToPersonContainers.TryGetValue(sortingContainer.Sorting.Id, out normalizedPixelPercentageToPersonContainers)) throw new NotSupportedException(); - if (!results.ContainsKey(sortingContainer.Face.Mapping.MappingFromItem.Id)) - results.Add(sortingContainer.Face.Mapping.MappingFromItem.Id, new()); - hashSet = results[sortingContainer.Face.Mapping.MappingFromItem.Id]; - if (hashSet.Contains(sortingContainer.Face.Mapping.MappingFromLocation.NormalizedPixelPercentage)) - continue; - if (!keyValuePairs.ContainsKey(sortingContainer.Sorting.NormalizedPixelPercentage)) + if (!normalizedPixelPercentageToPersonContainers.ContainsKey(sortingContainer.Sorting.NormalizedPixelPercentage)) throw new NotSupportedException(); - personContainers = keyValuePairs[sortingContainer.Sorting.NormalizedPixelPercentage]; - if (sortingContainer.Face.Mapping.MappingFromLocation.Confidence < _Configuration.FaceDistanceMinimumConfidence || sortingContainer.Sorting.DistancePermyriad > _Configuration.FaceDistancePermyriad || sortingContainer.Sorting.DaysDelta > _Configuration.SortingDaysDeltaTolerance) + if (!idToNormalizedPixelPercentageCollection.ContainsKey(sortingContainer.Face.Mapping.MappingFromItem.Id)) + idToNormalizedPixelPercentageCollection.Add(sortingContainer.Face.Mapping.MappingFromItem.Id, new()); + normalizedPixelPercentageCollection = idToNormalizedPixelPercentageCollection[sortingContainer.Face.Mapping.MappingFromItem.Id]; + if (normalizedPixelPercentageCollection.Contains(sortingContainer.Face.Mapping.MappingFromLocation.NormalizedPixelPercentage)) continue; + personContainers = normalizedPixelPercentageToPersonContainers[sortingContainer.Sorting.NormalizedPixelPercentage]; foreach (PersonContainer personContainer in personContainers) { if (personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any()) @@ -533,7 +553,7 @@ public class MapLogic checkCollection = checkKeyValuePairs[key]; if (checkCollection.Count > _Configuration.SortingMaximumPerKey) continue; - _ = hashSet.Add(sortingContainer.Sorting.NormalizedPixelPercentage); + normalizedPixelPercentageCollection.Add(sortingContainer.Face.Mapping.MappingFromLocation.NormalizedPixelPercentage); sortingContainer.Face.Mapping.UpdateMappingFromPerson(personContainer.ApproximateYears, by, personContainer.DisplayDirectoryName, personBirthday, mappingSegmentB); checkCollection.Add(sortingContainer.Face.Mapping); result += 1; @@ -578,7 +598,7 @@ public class MapLogic } } - private List GetMappingSaveContainers(string dFacesContentDirectory, string d2FacePartsContentDirectory, List filteredFaces) + private List GetMappingSaveContainers(string dFacesContentDirectory, string d2FacePartsContentDirectory, List filteredFaces, int? useFiltersCounter) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); @@ -612,6 +632,8 @@ public class MapLogic personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, face.Mapping.MappingFromPerson.PersonBirthday); if (face.Mapping.MappingFromPerson.By is null) by = $"{nameof(Stateless.IMapLogic.Mapping)}Null"; + else if (useFiltersCounter.HasValue && face.Mapping.MappingFromPerson.By.Value == Stateless.IMapLogic.Sorting) + by = $"{nameof(Stateless.IMapLogic.Sorting)} Modified Filters - {useFiltersCounter.Value}"; else { if (face.Mapping.MappingFromPerson.By == Stateless.IMapLogic.Mapping && !_Configuration.MappingSaveMapped) @@ -650,22 +672,97 @@ public class MapLogic return results; } - public void ForceSingleImageThenSaveMapping(string dFacesContentDirectory, string d2FacePartsContentDirectory, List distinctFilteredFaces, SortingContainer[] sortingContainers, int totalNotMapped) + private static IEnumerable<(string, string)> GetCollection(string[] yearDirectories) { + foreach (string l in yearDirectories) + yield return new(l, Path.GetFileName(l)); + } + + private static void SaveMappingShortcuts(string mappingDirectory) + { + string? shortcutFileName; + string[] yearDirectories; + string personKeyFormatted; + string[] personNameDirectories; + WindowsShortcut windowsShortcut; + string personDisplayDirectoryName; + (string, string)[] yearDirectoryNameCheck; + List<(string, string)> yearDirectoryNames = new(); + string[] personKeyDirectories = Directory.GetDirectories(mappingDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string personKeyDirectory in personKeyDirectories) + { + windowsShortcut = new(); + shortcutFileName = null; + yearDirectoryNames.Clear(); + personKeyFormatted = Path.GetFileName(personKeyDirectory); + yearDirectories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly); + yearDirectoryNames.AddRange(GetCollection(yearDirectories)); + yearDirectoryNameCheck = (from l in yearDirectoryNames where l.Item2.Contains('^') select l).OrderByDescending(l => l.Item2).ToArray(); + if (!yearDirectoryNameCheck.Any()) + yearDirectoryNameCheck = (from l in yearDirectoryNames where l.Item2.Contains('~') select l).OrderByDescending(l => l.Item2).ToArray(); + if (!yearDirectoryNameCheck.Any()) + yearDirectoryNameCheck = (from l in yearDirectoryNames where l.Item2.Contains('=') select l).OrderByDescending(l => l.Item2).ToArray(); + if (!yearDirectoryNameCheck.Any()) + yearDirectoryNameCheck = (from l in yearDirectoryNames select l).OrderByDescending(l => l).ToArray(); + if (!yearDirectoryNameCheck.Any()) + continue; + foreach ((string yearDirectory, string yearDirectoryName) in yearDirectoryNameCheck) + { + personNameDirectories = Directory.GetDirectories(yearDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string personNameDirectory in personNameDirectories) + { + personDisplayDirectoryName = Path.GetFileName(personNameDirectory).Split('-')[0]; + if (personDisplayDirectoryName is null) + continue; + windowsShortcut.Path = yearDirectory; + windowsShortcut.Description = yearDirectoryName; + shortcutFileName = Path.Combine(mappingDirectory, $"{personDisplayDirectoryName} [{windowsShortcut.Description}].lnk"); + break; + } + if (shortcutFileName is not null) + { + if (!File.Exists(shortcutFileName)) + break; + } + } + if (shortcutFileName is null || windowsShortcut.Path is null || windowsShortcut.Description is null) + continue; + try + { + windowsShortcut.Save(shortcutFileName); + windowsShortcut.Dispose(); + } + catch (Exception) + { } + } + } + + public void ForceSingleImageThenSaveMapping(string dFacesContentDirectory, string d2FacePartsContentDirectory, List distinctFilteredFaces, SortingContainer[] sortingContainers, int? useFiltersCounter, int totalNotMapped) + { + if (_Configuration is null) + throw new NullReferenceException(nameof(_Configuration)); + int updated; List saveContainers; if (!sortingContainers.Any()) { + updated = 0; ForceSingleImage(distinctFilteredFaces); - saveContainers = GetMappingSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, distinctFilteredFaces); + saveContainers = GetMappingSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, distinctFilteredFaces, useFiltersCounter); } else { - int updated = UpdateFromSortingContainers(sortingContainers); - if (totalNotMapped - updated > 0) + updated = UpdateFromSortingContainers(sortingContainers); + if (useFiltersCounter is null && totalNotMapped - updated > 0) ForceSingleImage(distinctFilteredFaces); - saveContainers = GetMappingSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, distinctFilteredFaces); + saveContainers = GetMappingSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, distinctFilteredFaces, useFiltersCounter); + } + SaveContainers(totalNotMapped, updated, saveContainers); + if (_Configuration.MappingSaveMapped) + { + string mappingDirectory = Path.Combine(_EDistanceContentTicksDirectory, nameof(Stateless.IMapLogic.Mapping)); + if (Directory.Exists(mappingDirectory)) + SaveMappingShortcuts(mappingDirectory); } - SaveContainers(saveContainers); } private static Dictionary> GetKeyValuePairs(List distinctFilteredFaces) diff --git a/Map/Models/Stateless/MapLogic.cs b/Map/Models/Stateless/MapLogic.cs index 7acf27e..677fb1d 100644 --- a/Map/Models/Stateless/MapLogic.cs +++ b/Map/Models/Stateless/MapLogic.cs @@ -177,9 +177,26 @@ internal abstract class MapLogic return results; } - internal static string[] DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, string facesFileNameExtension, long ticks, string eDistanceContentDirectory, PersonContainer[] personContainers) + public static Dictionary> GetIdToCollection(string facesFileNameExtension, List<(string, string[], string)> collection) { - string[] results; + Dictionary> results = new(); + int? id; + int? normalizedPixelPercentage; + foreach ((string personKeyFormatted, string[] personDisplayDirectoryNames, string mappedFaceFile) in collection) + { + (id, normalizedPixelPercentage, _) = IMapping.GetReversedDeterministicHashCodeKey(facesFileNameExtension, mappedFaceFile); + if (id is null || normalizedPixelPercentage is null) + continue; + if (!results.ContainsKey(id.Value)) + results.Add(id.Value, new()); + results[id.Value].Add(new(mappedFaceFile, normalizedPixelPercentage.Value)); + } + return results; + } + + internal static Dictionary> DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, string facesFileNameExtension, long ticks, string eDistanceContentDirectory, PersonContainer[] personContainers) + { + Dictionary> results; string personKeyFormatted; List personKeyFormattedCollection = new(); _ = GetDistinctCollection(configuration, personContainers.ToList(), new()); @@ -196,13 +213,13 @@ internal abstract class MapLogic personKeyFormattedCollection.Add(personKeyFormatted); } } - List<(string PersonKeyFormatted, string[] PersonDisplayDirectoryNames, string File)> collection = DeleteEmptyDirectoriesAndGetCollection( + List<(string, string[], string)> collection = DeleteEmptyDirectoriesAndGetCollection( configuration, facesFileNameExtension, personKeyFormattedCollection, ticksDirectories, message); - results = (from l in collection select l.File).ToArray(); + results = GetIdToCollection(facesFileNameExtension, collection); return results; } diff --git a/Map/Models/Stateless/Methods/IMapLogic.cs b/Map/Models/Stateless/Methods/IMapLogic.cs index 626c4cb..ef7e5c3 100644 --- a/Map/Models/Stateless/Methods/IMapLogic.cs +++ b/Map/Models/Stateless/Methods/IMapLogic.cs @@ -3,9 +3,9 @@ namespace View_by_Distance.Map.Models.Stateless.Methods; public interface IMapLogic { // ... - string[] TestStatic_DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, string facesFileNameExtension, long ticks, string eDistanceContentDirectory, Shared.Models.PersonContainer[] personContainers) => + Dictionary> TestStatic_DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, string facesFileNameExtension, long ticks, string eDistanceContentDirectory, Shared.Models.PersonContainer[] personContainers) => DeleteEmptyDirectoriesAndGetMappedFaceFiles(configuration, facesFileNameExtension, ticks, eDistanceContentDirectory, personContainers); - static string[] DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, string facesFileNameExtension, long ticks, string eDistanceContentDirectory, Shared.Models.PersonContainer[] personContainers) => + static Dictionary> DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, string facesFileNameExtension, long ticks, string eDistanceContentDirectory, Shared.Models.PersonContainer[] personContainers) => MapLogic.DeleteEmptyDirectoriesAndGetMappedFaceFiles(configuration, facesFileNameExtension, ticks, eDistanceContentDirectory, personContainers); } \ No newline at end of file diff --git a/Property/Models/Stateless/Container.cs b/Property/Models/Stateless/Container.cs index 2604ec9..0278b4c 100644 --- a/Property/Models/Stateless/Container.cs +++ b/Property/Models/Stateless/Container.cs @@ -153,11 +153,9 @@ public class Container Shared.Models.Container[] results; Item item; int length; - int itemCount; int additional; string inferred; List items; - string[] existing; string keyWithJson; string relativePath; FileHolder keyFileHolder; @@ -256,18 +254,8 @@ public class Container } else { - additional = 0; container = keyValuePairs[sourceDirectory]; - itemCount = items.Count; - existing = (from l in container.Items select l.ImageFileHolder?.FullName).ToArray(); - for (int i = 0; i < itemCount; i++) - { - item = items[i]; - if (item.ImageFileHolder is null || existing.Contains(item.ImageFileHolder.FullName)) - continue; - additional += 1; - items.Add(item); - } + (items, additional) = Shared.Models.Stateless.Methods.IItem.GetMerged(container.Items, items); result += additional; container = new(container.G, items, container.SourceDirectory); keyValuePairs[sourceDirectory] = container; diff --git a/Shared/Models/Face.cs b/Shared/Models/Face.cs index 353f22b..7e2db58 100644 --- a/Shared/Models/Face.cs +++ b/Shared/Models/Face.cs @@ -66,12 +66,8 @@ public class Face : Properties.IFace public void SetFaceParts(Dictionary faceParts) => _FaceParts = faceParts; - public void ReleaseFaceDistance() => _FaceDistance = null; - public void SetMapping(Mapping mapping) => _Mapping = mapping; public void SetFaceDistance(FaceDistance? faceDistance) => _FaceDistance = faceDistance; - public void ClearFaceDistance() => _FaceDistance = null; - } \ No newline at end of file diff --git a/Shared/Models/Mapping.cs b/Shared/Models/Mapping.cs index fab93ee..3423e10 100644 --- a/Shared/Models/Mapping.cs +++ b/Shared/Models/Mapping.cs @@ -10,15 +10,17 @@ public class MappingFromItem : Properties.IMappingFromItem public FileHolder ImageFileHolder { init; get; } public bool? IsWrongYear { init; get; } public DateTime MinimumDateTime { init; get; } + public string RelativePath { init; get; } public FileHolder ResizedFileHolder { init; get; } [JsonConstructor] - public MappingFromItem(int id, FileHolder imageFileHolder, bool? isWrongYear, DateTime minimumDateTime, FileHolder resizedFileHolder) + public MappingFromItem(int id, FileHolder imageFileHolder, bool? isWrongYear, DateTime minimumDateTime, string relativePath, FileHolder resizedFileHolder) { Id = id; ImageFileHolder = imageFileHolder; IsWrongYear = isWrongYear; MinimumDateTime = minimumDateTime; + RelativePath = relativePath; ResizedFileHolder = resizedFileHolder; } diff --git a/Shared/Models/Properties/IMapping.cs b/Shared/Models/Properties/IMapping.cs index f426569..fea13d7 100644 --- a/Shared/Models/Properties/IMapping.cs +++ b/Shared/Models/Properties/IMapping.cs @@ -7,6 +7,7 @@ public interface IMappingFromItem public FileHolder ImageFileHolder { init; get; } public bool? IsWrongYear { init; get; } public DateTime MinimumDateTime { init; get; } + public string RelativePath { init; get; } public FileHolder ResizedFileHolder { init; get; } } diff --git a/Shared/Models/SortingContainer.cs b/Shared/Models/SortingContainer.cs index 1ac3181..1785ce7 100644 --- a/Shared/Models/SortingContainer.cs +++ b/Shared/Models/SortingContainer.cs @@ -1,4 +1,3 @@ -using System.Text.Json; using System.Text.Json.Serialization; namespace View_by_Distance.Shared.Models; @@ -18,7 +17,7 @@ public record class SortingContainer : Properties.ISortingContainer public override string ToString() { - string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + string result = string.Concat(Face.Mapping?.MappingFromItem.Id, '\t', Face.Mapping?.MappingFromLocation.NormalizedPixelPercentage, '\t', Sorting.Id, '\t', Sorting.NormalizedPixelPercentage, '\t', Sorting.Older, '\t', Sorting.WithinRange, '\t', Sorting.DistancePermyriad, '\t', Sorting.DaysDelta); return result; } diff --git a/Shared/Models/Stateless/Methods/IAge.cs b/Shared/Models/Stateless/Methods/IAge.cs index e3a7ec8..0d633f0 100644 --- a/Shared/Models/Stateless/Methods/IAge.cs +++ b/Shared/Models/Stateless/Methods/IAge.cs @@ -21,7 +21,7 @@ public interface IAge char[] TestStatic_GetChars() => GetChars(); static char[] GetChars() => - new char[] { '!', '^', '_', '~' }; + new char[] { '!', '^', '_', '~', '+' }; int? TestStatic_GetApproximateYears(string personDisplayDirectoryName, char[] chars) => GetApproximateYears(personDisplayDirectoryName, chars); diff --git a/Shared/Models/Stateless/Methods/IItem.cs b/Shared/Models/Stateless/Methods/IItem.cs index 48503c5..586871e 100644 --- a/Shared/Models/Stateless/Methods/IItem.cs +++ b/Shared/Models/Stateless/Methods/IItem.cs @@ -3,7 +3,13 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; public interface IItem { // ... - string TestStatic_GetWrongYearFlag(bool? isWrongYear); + string TestStatic_GetWrongYearFlag(bool? isWrongYear) => + GetWrongYearFlag(isWrongYear); static string GetWrongYearFlag(bool? isWrongYear) => isWrongYear is null ? "#" : isWrongYear.Value ? "~" : "="; + (List, int) TestStatic_GetMerged(List itemsA, List itemsB) => + GetMerged(itemsA, itemsB); + static (List, int) GetMerged(List itemsA, List itemsB) => + Item.GetMerged(itemsA, itemsB); + } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/ISorting.cs b/Shared/Models/Stateless/Methods/ISorting.cs index ba2d979..df7b2b7 100644 --- a/Shared/Models/Stateless/Methods/ISorting.cs +++ b/Shared/Models/Stateless/Methods/ISorting.cs @@ -8,9 +8,9 @@ public interface ISorting static Models.Sorting[] Sort(List collection) => (from l in collection orderby l.WithinRange, l.DistancePermyriad, l.DaysDelta select l).ToArray(); - Models.Sorting TestStatic_Get(int faceDistancePermyriad, double faceDistanceTolerance, Models.FaceDistance faceDistanceEncoding, Models.FaceDistance faceDistanceLength, bool anyLowerThanTolerance, List<(long lcl, long minimum, long maximum, long ucl)> personKeysRangesCollection) => - Get(faceDistancePermyriad, faceDistanceTolerance, faceDistanceEncoding, faceDistanceLength, anyLowerThanTolerance, personKeysRangesCollection); - static Models.Sorting Get(int faceDistancePermyriad, double faceDistanceTolerance, Models.FaceDistance faceDistanceEncoding, Models.FaceDistance faceDistanceLength, bool anyLowerThanTolerance, List<(long lcl, long minimum, long maximum, long ucl)> personKeysRangesCollection) => - Sorting.Get(faceDistancePermyriad, faceDistanceTolerance, faceDistanceEncoding, faceDistanceLength, anyLowerThanTolerance, personKeysRangesCollection); + Models.Sorting TestStatic_Get(int faceDistancePermyriad, double faceDistanceTolerance, Models.FaceDistance faceDistanceEncoding, Models.FaceDistance faceDistanceLength, List<(long lcl, long minimum, long maximum, long ucl)> personKeysRangesCollection) => + Get(faceDistancePermyriad, faceDistanceTolerance, faceDistanceEncoding, faceDistanceLength, personKeysRangesCollection); + static Models.Sorting Get(int faceDistancePermyriad, double faceDistanceTolerance, Models.FaceDistance faceDistanceEncoding, Models.FaceDistance faceDistanceLength, List<(long lcl, long minimum, long maximum, long ucl)> personKeysRangesCollection) => + Sorting.Get(faceDistancePermyriad, faceDistanceTolerance, faceDistanceEncoding, faceDistanceLength, personKeysRangesCollection); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/Item.cs b/Shared/Models/Stateless/Methods/Item.cs index aacc8b1..da3096b 100644 --- a/Shared/Models/Stateless/Methods/Item.cs +++ b/Shared/Models/Stateless/Methods/Item.cs @@ -3,6 +3,28 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; internal abstract class Item { - internal static double GetDefaultValue() => throw new Exception(); + internal static (List, int) GetMerged(List itemsA, List itemsB) + { + int result = 0; + List results = new(); + List collection = new(); + foreach (Models.Item item in itemsA) + { + if (item.ImageFileHolder is null) + continue; + results.Add(item); + collection.Add(item.ImageFileHolder.FullName); + } + foreach (Models.Item item in itemsB) + { + if (item.ImageFileHolder is null) + continue; + if (collection.Contains(item.ImageFileHolder.FullName)) + continue; + result++; + results.Add(item); + } + return new(results, result); + } } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/Sorting.cs b/Shared/Models/Stateless/Methods/Sorting.cs index 190b59e..e89cc55 100644 --- a/Shared/Models/Stateless/Methods/Sorting.cs +++ b/Shared/Models/Stateless/Methods/Sorting.cs @@ -3,45 +3,31 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; internal abstract class Sorting { - internal static Models.Sorting Get(int faceDistancePermyriad, double faceDistanceTolerance, Models.FaceDistance faceDistanceEncoding, Models.FaceDistance faceDistanceLength, bool anyLowerThanTolerance, List<(long lcl, long minimum, long maximum, long ucl)> personKeysRangesCollection) + internal static Models.Sorting Get(int faceDistancePermyriad, double faceDistanceTolerance, Models.FaceDistance faceDistanceEncoding, Models.FaceDistance faceDistanceLength, List<(long lcl, long minimum, long maximum, long ucl)> personKeysRangesCollection) { Models.Sorting result; if (faceDistanceLength.Length is null) throw new NotSupportedException(); if (faceDistanceLength.NormalizedPixelPercentage is null) throw new NotSupportedException(); - bool older; - int daysDelta; - int withinRange; - int distancePermyriad; - if (faceDistanceLength.Length.Value == 0 || (anyLowerThanTolerance && faceDistanceLength.Length.Value >= faceDistanceTolerance)) + if (faceDistanceEncoding.MinimumDateTime is null || faceDistanceLength.MinimumDateTime is null) + throw new NotSupportedException(); + List withinRanges = new(); + long ticks = faceDistanceEncoding.MinimumDateTime.Value.Ticks; + TimeSpan timeSpan = new(faceDistanceLength.MinimumDateTime.Value.Ticks - ticks); + bool older = timeSpan.TotalMilliseconds < 0; + int daysDelta = (int)Math.Round(Math.Abs(timeSpan.TotalDays), 0); + int distancePermyriad = (int)(faceDistanceLength.Length.Value / faceDistanceTolerance * faceDistancePermyriad); + foreach ((long lcl, long minimum, long maximum, long ucl) in personKeysRangesCollection) { - older = false; - daysDelta = 0; - withinRange = 0; - distancePermyriad = 0; - } - else - { - if (faceDistanceEncoding.MinimumDateTime is null || faceDistanceLength.MinimumDateTime is null) - throw new NotSupportedException(); - List withinRanges = new(); - long ticks = faceDistanceEncoding.MinimumDateTime.Value.Ticks; - TimeSpan timeSpan = new(faceDistanceLength.MinimumDateTime.Value.Ticks - ticks); - older = timeSpan.TotalMilliseconds < 0; - daysDelta = (int)Math.Round(Math.Abs(timeSpan.TotalDays), 0); - distancePermyriad = (int)(faceDistanceLength.Length.Value / faceDistanceTolerance * faceDistancePermyriad); - foreach ((long lcl, long minimum, long maximum, long ucl) in personKeysRangesCollection) - { - if (ticks > minimum && ticks < maximum) - withinRanges.Add(0); - else if (ticks > lcl && ticks < ucl) - withinRanges.Add(1); - else - withinRanges.Add(2); - } - withinRange = withinRanges.Max(); + if (ticks > minimum && ticks < maximum) + withinRanges.Add(0); + else if (ticks > lcl && ticks < ucl) + withinRanges.Add(1); + else + withinRanges.Add(2); } + int withinRange = withinRanges.Max(); result = new(daysDelta, distancePermyriad, faceDistanceLength.Id, faceDistanceLength.NormalizedPixelPercentage.Value, older, withinRange); return result; }