E Distance split to Map Logic Support
This commit is contained in:
parent
5d257b0bec
commit
3899cf6b4c
300
Distance/Models/MapLogicSupport.cs
Normal file
300
Distance/Models/MapLogicSupport.cs
Normal file
@ -0,0 +1,300 @@
|
||||
using ShellProgressBar;
|
||||
using System.Text.Json;
|
||||
using View_by_Distance.FaceRecognitionDotNet;
|
||||
using View_by_Distance.Map.Models;
|
||||
using View_by_Distance.Shared.Models;
|
||||
using View_by_Distance.Shared.Models.Properties;
|
||||
|
||||
namespace View_by_Distance.Distance.Models;
|
||||
|
||||
public class MapLogicSupport : Shared.Models.Methods.IMapLogicSupport
|
||||
{
|
||||
|
||||
private readonly int _FaceDistancePermyriad;
|
||||
private readonly int _SortingDaysDeltaTolerance;
|
||||
private readonly double _FaceDistanceMinimumConfidence;
|
||||
private readonly int _FaceDistanceAreaPermilleTolerance;
|
||||
private readonly int _SortingMaximumPerFaceShouldBeHigh;
|
||||
|
||||
public MapLogicSupport(int faceDistanceAreaPermilleTolerance, double faceDistanceMinimumConfidence, int faceDistancePermyriad, int sortingDaysDeltaTolerance, int sortingMaximumPerFaceShouldBeHigh)
|
||||
{
|
||||
_FaceDistancePermyriad = faceDistancePermyriad;
|
||||
_SortingDaysDeltaTolerance = sortingDaysDeltaTolerance;
|
||||
_FaceDistanceMinimumConfidence = faceDistanceMinimumConfidence;
|
||||
_FaceDistanceAreaPermilleTolerance = faceDistanceAreaPermilleTolerance;
|
||||
_SortingMaximumPerFaceShouldBeHigh = sortingMaximumPerFaceShouldBeHigh;
|
||||
}
|
||||
|
||||
public static void SaveFaceDistances(Property.Models.Configuration configuration, SortingContainer[] sortingContainers)
|
||||
{
|
||||
string eDistanceContentCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(E_Distance), "([])");
|
||||
if (!Directory.Exists(eDistanceContentCollectionDirectory))
|
||||
_ = Directory.CreateDirectory(eDistanceContentCollectionDirectory);
|
||||
#pragma warning disable
|
||||
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<SortingContainer> GetSortingContainers(Face face, FaceDistance faceDistanceEncoding, List<Sorting> sortingCollection, int? useFiltersCounter)
|
||||
{
|
||||
List<SortingContainer> results = new();
|
||||
SortingContainer sortingContainer;
|
||||
Sorting[] collection = Shared.Models.Stateless.Methods.ISorting.Sort(sortingCollection);
|
||||
double faceDistancePermyriad;
|
||||
double sortingDaysDeltaTolerance;
|
||||
double faceDistanceMinimumConfidence;
|
||||
double faceDistanceAreaPermilleTolerance;
|
||||
if (useFiltersCounter is null)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence;
|
||||
}
|
||||
else if (useFiltersCounter.Value == 1)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 1.5;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence;
|
||||
}
|
||||
else if (useFiltersCounter.Value == 2)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad * 1.5;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence;
|
||||
}
|
||||
else if (useFiltersCounter.Value == 3)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence * .5;
|
||||
}
|
||||
else if (useFiltersCounter.Value == 4)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 2;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad * 1.5;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence * .5;
|
||||
}
|
||||
else if (useFiltersCounter.Value == 5)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 1.5;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad * 2;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence * .5;
|
||||
}
|
||||
else if (useFiltersCounter.Value == 6)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 1.5;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad * 1.5;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence * .25;
|
||||
}
|
||||
else if (useFiltersCounter.Value == 7)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 2.5;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad * 2;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence * .25;
|
||||
}
|
||||
else if (useFiltersCounter.Value == 8)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 2;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad * 2.5;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence * .25;
|
||||
}
|
||||
else if (useFiltersCounter.Value == 9)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 2;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad * 2;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sortingDaysDeltaTolerance = int.MaxValue;
|
||||
faceDistancePermyriad = int.MaxValue;
|
||||
faceDistanceAreaPermilleTolerance = 0;
|
||||
faceDistanceMinimumConfidence = 0;
|
||||
}
|
||||
foreach (Sorting sorting in collection)
|
||||
{
|
||||
if (face.Mapping is null || faceDistanceEncoding.NormalizedPixelPercentage is null)
|
||||
throw new NotSupportedException();
|
||||
if (sorting.DaysDelta > sortingDaysDeltaTolerance || sorting.DistancePermyriad > faceDistancePermyriad || face.Mapping.MappingFromLocation.Confidence < faceDistanceMinimumConfidence || face.Mapping.MappingFromLocation.AreaPermille < faceDistanceAreaPermilleTolerance)
|
||||
continue;
|
||||
sortingContainer = new(face.Mapping, sorting);
|
||||
results.Add(sortingContainer);
|
||||
if (results.Count >= _SortingMaximumPerFaceShouldBeHigh)
|
||||
break;
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static List<Sorting> GetSortingCollection(MapLogic mapLogic, List<FaceDistance> faceDistanceEncodings, int faceDistanceContainersLength, int i, FaceDistance faceDistanceEncoding)
|
||||
{
|
||||
List<Sorting> results;
|
||||
List<FaceDistance> faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncoding);
|
||||
if (faceDistanceLengths.Count != faceDistanceContainersLength)
|
||||
throw new NotSupportedException();
|
||||
results = mapLogic.GetSortingCollection(i, faceDistanceEncoding, faceDistanceLengths);
|
||||
return results;
|
||||
}
|
||||
|
||||
private static FaceDistanceContainer[] GetFaceDistanceContainers(Face[] distinctFilteredFaces)
|
||||
{
|
||||
FaceDistanceContainer[] results;
|
||||
FaceDistance faceDistance;
|
||||
FaceDistanceContainer faceDistanceContainer;
|
||||
List<FaceDistanceContainer> collection = new();
|
||||
foreach (Face face in distinctFilteredFaces)
|
||||
{
|
||||
if (face.Mapping is null)
|
||||
throw new NotSupportedException();
|
||||
if (face.FaceDistance?.Encoding is not FaceRecognitionDotNet.FaceEncoding faceEncoding)
|
||||
continue;
|
||||
faceDistance = new(face.Mapping.MappingFromLocation.Confidence, faceEncoding, face.Mapping.MappingFromItem.Id, face.Mapping.MappingFromItem.IsWrongYear, face.Mapping.MappingFromItem.MinimumDateTime, face.Mapping.MappingFromLocation.NormalizedPixelPercentage);
|
||||
faceDistanceContainer = new(face, faceDistance);
|
||||
collection.Add(faceDistanceContainer);
|
||||
}
|
||||
results = collection.ToArray();
|
||||
return results;
|
||||
}
|
||||
|
||||
private static List<FaceDistance> GetFaceDistanceEncodings(FaceDistanceContainer[] faceDistanceContainers)
|
||||
{
|
||||
List<FaceDistance> 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[] distinctFilteredFaces, int? useFiltersCounter)
|
||||
{
|
||||
SortingContainer[] results;
|
||||
List<SortingContainer> collection = new();
|
||||
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
||||
FaceDistanceContainer[] faceDistanceContainers = GetFaceDistanceContainers(distinctFilteredFaces);
|
||||
List<FaceDistance> 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 };
|
||||
using ProgressBar progressBar = new(faceDistanceContainers.Length, message, options);
|
||||
_ = Parallel.For(0, faceDistanceContainers.Length, parallelOptions, (i, state) =>
|
||||
{
|
||||
progressBar.Tick();
|
||||
Face face = faceDistanceContainers[i].Face;
|
||||
if (face.Mapping is null)
|
||||
throw new NotSupportedException();
|
||||
FaceDistance faceDistanceEncoding = faceDistanceContainers[i].FaceDistance;
|
||||
if (mapLogic.Used(faceDistanceEncoding))
|
||||
return;
|
||||
List<Sorting> sortingCollection = GetSortingCollection(mapLogic, faceDistanceEncodings, faceDistanceContainers.Length, i, faceDistanceEncoding);
|
||||
if (!sortingCollection.Any())
|
||||
return;
|
||||
List<SortingContainer> sortingContainers = GetSortingContainers(face, faceDistanceEncoding, sortingCollection, useFiltersCounter);
|
||||
if (sortingContainers.Any())
|
||||
{
|
||||
lock (collection)
|
||||
collection.AddRange(sortingContainers);
|
||||
}
|
||||
});
|
||||
if (!collection.Any())
|
||||
results = Array.Empty<SortingContainer>();
|
||||
else
|
||||
results = Shared.Models.Stateless.Methods.ISortingContainer.Sort(collection);
|
||||
return results;
|
||||
}
|
||||
|
||||
public static Mapping[] GetSelectedMappingCollection(Face[] distinctFilteredFaces)
|
||||
{
|
||||
Mapping[] results;
|
||||
IEnumerable<Mapping> collection = from l in distinctFilteredFaces orderby l.Mapping?.MappingFromItem.MinimumDateTime descending select l.Mapping;
|
||||
results = (from l in collection where l is not null select l).ToArray();
|
||||
return results;
|
||||
}
|
||||
|
||||
public static void SetFaceDistances(int maxDegreeOfParallelism, long ticks, Face[] distinctFilteredFaces)
|
||||
{
|
||||
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
||||
string message = $") {distinctFilteredFaces.Length:000} Load Face Encoding - {totalSeconds} total second(s)";
|
||||
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||
using ProgressBar progressBar = new(distinctFilteredFaces.Length, message, options);
|
||||
_ = Parallel.For(0, distinctFilteredFaces.Length, parallelOptions, (i, state) =>
|
||||
{
|
||||
Face face = distinctFilteredFaces[i];
|
||||
if (face.FaceEncoding is null || face.Mapping is null)
|
||||
throw new NotSupportedException();
|
||||
if (face.FaceDistance?.Encoding is not null && face.FaceDistance.Encoding is FaceRecognitionDotNet.FaceEncoding faceEncoding)
|
||||
return;
|
||||
progressBar.Tick();
|
||||
faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
|
||||
FaceDistance faceDistance = new(face.Mapping.MappingFromLocation.Confidence, faceEncoding, face.Mapping.MappingFromItem.Id, face.Mapping.MappingFromItem.IsWrongYear, face.Mapping.MappingFromItem.MinimumDateTime, face.Mapping.MappingFromLocation.NormalizedPixelPercentage);
|
||||
lock (face)
|
||||
face.SetFaceDistance(faceDistance);
|
||||
});
|
||||
}
|
||||
|
||||
void Shared.Models.Methods.IMapLogicSupport.SavePossiblyNewPersonContainers(IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, string facesFileNameExtension, string? a2PeopleSingletonDirectory, Dictionary<long, PersonContainer> personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer)
|
||||
{
|
||||
char @char;
|
||||
string json;
|
||||
string[] files;
|
||||
string checkFile;
|
||||
string[] segments;
|
||||
const int zero = 0;
|
||||
string personKeyFormatted;
|
||||
string personDisplayDirectory;
|
||||
PersonBirthday personBirthday;
|
||||
string personDisplayDirectoryName;
|
||||
string checkPersonDisplayDirectory;
|
||||
string checkPersonKeyFormattedDirectory;
|
||||
char[] chars = Shared.Models.Stateless.Methods.IAge.GetChars();
|
||||
JsonSerializerOptions jsonSerializerOptions = new() { WriteIndented = true };
|
||||
foreach ((string[] personDisplayDirectoryNames, PersonContainer personContainer) in possiblyNewPersonDisplayDirectoryNamesAndPersonContainer)
|
||||
{
|
||||
if (a2PeopleSingletonDirectory is null || personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any())
|
||||
continue;
|
||||
personBirthday = personContainer.Birthdays[zero];
|
||||
personDisplayDirectoryName = personDisplayDirectoryNames[^1];
|
||||
personDisplayDirectory = Path.Combine(personDisplayDirectoryNames);
|
||||
personKeyFormatted = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(personBirthdayFormat, personBirthday);
|
||||
segments = personDisplayDirectoryName.Split(chars);
|
||||
if (segments.Length != 2)
|
||||
@char = '_';
|
||||
else
|
||||
@char = personDisplayDirectoryName[segments[zero].Length];
|
||||
checkPersonDisplayDirectory = Path.Combine(a2PeopleSingletonDirectory, @char.ToString(), personDisplayDirectoryName);
|
||||
checkPersonKeyFormattedDirectory = Path.Combine(checkPersonDisplayDirectory, personKeyFormatted);
|
||||
if (Directory.Exists(checkPersonKeyFormattedDirectory))
|
||||
continue;
|
||||
_ = Directory.CreateDirectory(checkPersonKeyFormattedDirectory);
|
||||
checkFile = Path.Combine(checkPersonKeyFormattedDirectory, $"{personKeyFormatted}.json");
|
||||
json = JsonSerializer.Serialize(personContainer.Person, jsonSerializerOptions);
|
||||
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true);
|
||||
if (!Directory.Exists(personDisplayDirectory))
|
||||
continue;
|
||||
files = Directory.GetFiles(personDisplayDirectory, $"*{facesFileNameExtension}", SearchOption.TopDirectoryOnly);
|
||||
foreach (string file in files)
|
||||
{
|
||||
checkFile = Path.Combine(checkPersonDisplayDirectory, Path.GetFileName(file));
|
||||
if (File.Exists(checkFile))
|
||||
continue;
|
||||
File.Copy(files[0], checkFile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,333 +1,35 @@
|
||||
using ShellProgressBar;
|
||||
using System.Text.Json;
|
||||
using View_by_Distance.FaceRecognitionDotNet;
|
||||
using View_by_Distance.Map.Models;
|
||||
using View_by_Distance.Shared.Models;
|
||||
using View_by_Distance.Shared.Models.Properties;
|
||||
|
||||
namespace View_by_Distance.Distance.Models;
|
||||
|
||||
public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
public partial class E_Distance
|
||||
{
|
||||
|
||||
private readonly List<string> _Moved;
|
||||
private readonly List<double?> _Debug;
|
||||
private readonly List<string> _Renamed;
|
||||
private readonly Serilog.ILogger? _Log;
|
||||
private readonly string _ResultAllInOne;
|
||||
private readonly int _FaceDistancePermyriad;
|
||||
private readonly bool _DistanceRenameToMatch;
|
||||
private readonly double _FaceDistanceTolerance;
|
||||
private readonly int _SortingDaysDeltaTolerance;
|
||||
private readonly bool _DistanceMoveUnableToMatch;
|
||||
private readonly List<string> _AllMappedFaceFiles;
|
||||
private readonly int _DistancePixelDistanceTolerance;
|
||||
private readonly List<string> _AllMappedFaceFileNames;
|
||||
private readonly double _FaceDistanceMinimumConfidence;
|
||||
private readonly List<string> _DuplicateMappedFaceFiles;
|
||||
private readonly int _FaceDistanceAreaPermilleTolerance;
|
||||
private readonly int _SortingMaximumPerFaceShouldBeHigh;
|
||||
|
||||
public E_Distance(bool distanceMoveUnableToMatch, int distancePixelDistanceTolerance, bool distanceRenameToMatch, int faceDistanceAreaPermilleTolerance, double faceDistanceMinimumConfidence, int faceDistancePermyriad, double faceDistanceTolerance, string resultAllInOne, int sortingDaysDeltaTolerance, int sortingMaximumPerFaceShouldBeHigh)
|
||||
public E_Distance(bool distanceMoveUnableToMatch, int distancePixelDistanceTolerance, bool distanceRenameToMatch, double faceDistanceTolerance)
|
||||
{
|
||||
_Debug = new();
|
||||
_Moved = new();
|
||||
_Renamed = new();
|
||||
_AllMappedFaceFiles = new();
|
||||
_AllMappedFaceFileNames = new();
|
||||
_ResultAllInOne = resultAllInOne;
|
||||
_DuplicateMappedFaceFiles = new();
|
||||
_Log = Serilog.Log.ForContext<E_Distance>();
|
||||
_DistanceRenameToMatch = distanceRenameToMatch;
|
||||
_FaceDistancePermyriad = faceDistancePermyriad;
|
||||
_FaceDistanceTolerance = faceDistanceTolerance;
|
||||
_DistanceMoveUnableToMatch = distanceMoveUnableToMatch;
|
||||
_SortingDaysDeltaTolerance = sortingDaysDeltaTolerance;
|
||||
_FaceDistanceMinimumConfidence = faceDistanceMinimumConfidence;
|
||||
_DistancePixelDistanceTolerance = distancePixelDistanceTolerance;
|
||||
_FaceDistanceAreaPermilleTolerance = faceDistanceAreaPermilleTolerance;
|
||||
_SortingMaximumPerFaceShouldBeHigh = sortingMaximumPerFaceShouldBeHigh;
|
||||
}
|
||||
|
||||
public static void SaveFaceDistances(Property.Models.Configuration configuration, SortingContainer[] sortingContainers)
|
||||
{
|
||||
string eDistanceContentCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(E_Distance), "([])");
|
||||
if (!Directory.Exists(eDistanceContentCollectionDirectory))
|
||||
_ = Directory.CreateDirectory(eDistanceContentCollectionDirectory);
|
||||
#pragma warning disable
|
||||
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 static List<Sorting> GetSortingCollection(MapLogic mapLogic, List<FaceDistance> faceDistanceEncodings, int faceDistanceContainersLength, int i, FaceDistance faceDistanceEncoding)
|
||||
{
|
||||
List<Sorting> results;
|
||||
List<FaceDistance> faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncoding);
|
||||
if (faceDistanceLengths.Count != faceDistanceContainersLength)
|
||||
throw new NotSupportedException();
|
||||
results = mapLogic.GetSortingCollection(i, faceDistanceEncoding, faceDistanceLengths);
|
||||
return results;
|
||||
}
|
||||
|
||||
private List<SortingContainer> GetSortingContainers(Face face, FaceDistance faceDistanceEncoding, List<Sorting> sortingCollection, int? useFiltersCounter)
|
||||
{
|
||||
List<SortingContainer> results = new();
|
||||
SortingContainer sortingContainer;
|
||||
Sorting[] collection = Shared.Models.Stateless.Methods.ISorting.Sort(sortingCollection);
|
||||
double faceDistancePermyriad;
|
||||
double sortingDaysDeltaTolerance;
|
||||
double faceDistanceMinimumConfidence;
|
||||
double faceDistanceAreaPermilleTolerance;
|
||||
if (useFiltersCounter is null)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence;
|
||||
}
|
||||
else if (useFiltersCounter.Value == 1)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 1.5;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence;
|
||||
}
|
||||
else if (useFiltersCounter.Value == 2)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad * 1.5;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence;
|
||||
}
|
||||
else if (useFiltersCounter.Value == 3)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence * .5;
|
||||
}
|
||||
else if (useFiltersCounter.Value == 4)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 2;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad * 1.5;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence * .5;
|
||||
}
|
||||
else if (useFiltersCounter.Value == 5)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 1.5;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad * 2;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence * .5;
|
||||
}
|
||||
else if (useFiltersCounter.Value == 6)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 1.5;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad * 1.5;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence * .25;
|
||||
}
|
||||
else if (useFiltersCounter.Value == 7)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 2.5;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad * 2;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence * .25;
|
||||
}
|
||||
else if (useFiltersCounter.Value == 8)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 2;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad * 2.5;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = _FaceDistanceMinimumConfidence * .25;
|
||||
}
|
||||
else if (useFiltersCounter.Value == 9)
|
||||
{
|
||||
sortingDaysDeltaTolerance = _SortingDaysDeltaTolerance * 2;
|
||||
faceDistancePermyriad = _FaceDistancePermyriad * 2;
|
||||
faceDistanceAreaPermilleTolerance = _FaceDistanceAreaPermilleTolerance;
|
||||
faceDistanceMinimumConfidence = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sortingDaysDeltaTolerance = int.MaxValue;
|
||||
faceDistancePermyriad = int.MaxValue;
|
||||
faceDistanceAreaPermilleTolerance = 0;
|
||||
faceDistanceMinimumConfidence = 0;
|
||||
}
|
||||
foreach (Sorting sorting in collection)
|
||||
{
|
||||
if (face.Mapping is null || faceDistanceEncoding.NormalizedPixelPercentage is null)
|
||||
throw new NotSupportedException();
|
||||
if (sorting.DaysDelta > sortingDaysDeltaTolerance || sorting.DistancePermyriad > faceDistancePermyriad || face.Mapping.MappingFromLocation.Confidence < faceDistanceMinimumConfidence || face.Mapping.MappingFromLocation.AreaPermille < faceDistanceAreaPermilleTolerance)
|
||||
continue;
|
||||
sortingContainer = new(face.Mapping, sorting);
|
||||
results.Add(sortingContainer);
|
||||
if (results.Count >= _SortingMaximumPerFaceShouldBeHigh)
|
||||
break;
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static FaceDistanceContainer[] GetOrderedFaceDistanceContainers(List<FaceDistanceContainer> collection)
|
||||
{
|
||||
FaceDistanceContainer[] results;
|
||||
results = (from l in collection orderby l.FaceDistance.Encoding is not null select l).ToArray();
|
||||
if (results.Any() && results[0].FaceDistance.Encoding is null)
|
||||
throw new Exception("Sorting failed!");
|
||||
return results;
|
||||
}
|
||||
|
||||
private static FaceDistanceContainer[] GetOrderedFaceDistanceContainers(Face[] distinctFilteredFaces)
|
||||
{
|
||||
FaceDistanceContainer[] results;
|
||||
FaceDistance faceDistance;
|
||||
FaceDistanceContainer faceDistanceContainer;
|
||||
List<FaceDistanceContainer> collection = new();
|
||||
foreach (Face face in distinctFilteredFaces)
|
||||
{
|
||||
if (face.Mapping is null)
|
||||
throw new NotSupportedException();
|
||||
if (face.FaceDistance?.Encoding is not FaceRecognitionDotNet.FaceEncoding faceEncoding)
|
||||
continue;
|
||||
faceDistance = new(face.Mapping.MappingFromLocation.Confidence, faceEncoding, face.Mapping.MappingFromItem.Id, face.Mapping.MappingFromItem.IsWrongYear, face.Mapping.MappingFromItem.MinimumDateTime, face.Mapping.MappingFromLocation.NormalizedPixelPercentage);
|
||||
faceDistanceContainer = new(face, faceDistance);
|
||||
collection.Add(faceDistanceContainer);
|
||||
}
|
||||
results = GetOrderedFaceDistanceContainers(collection);
|
||||
return results;
|
||||
}
|
||||
|
||||
private static List<FaceDistance> GetFaceDistanceEncodings(FaceDistanceContainer[] faceDistanceContainers)
|
||||
{
|
||||
List<FaceDistance> 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[] distinctFilteredFaces, int? useFiltersCounter)
|
||||
{
|
||||
SortingContainer[] results;
|
||||
List<SortingContainer> collection = new();
|
||||
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
||||
FaceDistanceContainer[] faceDistanceContainers = GetOrderedFaceDistanceContainers(distinctFilteredFaces);
|
||||
List<FaceDistance> 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 };
|
||||
using ProgressBar progressBar = new(faceDistanceContainers.Length, message, options);
|
||||
_ = Parallel.For(0, faceDistanceContainers.Length, parallelOptions, (i, state) =>
|
||||
{
|
||||
progressBar.Tick();
|
||||
Face face = faceDistanceContainers[i].Face;
|
||||
if (face.Mapping is null)
|
||||
throw new NotSupportedException();
|
||||
FaceDistance faceDistanceEncoding = faceDistanceContainers[i].FaceDistance;
|
||||
if (mapLogic.Used(faceDistanceEncoding))
|
||||
return;
|
||||
List<Sorting> sortingCollection = GetSortingCollection(mapLogic, faceDistanceEncodings, faceDistanceContainers.Length, i, faceDistanceEncoding);
|
||||
if (!sortingCollection.Any())
|
||||
return;
|
||||
List<SortingContainer> sortingContainers = GetSortingContainers(face, faceDistanceEncoding, sortingCollection, useFiltersCounter);
|
||||
if (sortingContainers.Any())
|
||||
{
|
||||
lock (collection)
|
||||
collection.AddRange(sortingContainers);
|
||||
}
|
||||
});
|
||||
if (!collection.Any())
|
||||
results = Array.Empty<SortingContainer>();
|
||||
else
|
||||
results = Shared.Models.Stateless.Methods.ISortingContainer.Sort(collection);
|
||||
return results;
|
||||
}
|
||||
|
||||
public static Mapping[] GetSelectedMappingCollection(Face[] distinctFilteredFaces)
|
||||
{
|
||||
Mapping[] results;
|
||||
IEnumerable<Mapping> collection = from l in distinctFilteredFaces orderby l.Mapping?.MappingFromItem.MinimumDateTime descending select l.Mapping;
|
||||
results = (from l in collection where l is not null select l).ToArray();
|
||||
return results;
|
||||
}
|
||||
|
||||
public static void SetFaceDistances(int maxDegreeOfParallelism, long ticks, Face[] distinctFilteredFaces)
|
||||
{
|
||||
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
||||
string message = $") {distinctFilteredFaces.Length:000} Load Face Encoding - {totalSeconds} total second(s)";
|
||||
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||
using ProgressBar progressBar = new(distinctFilteredFaces.Length, message, options);
|
||||
_ = Parallel.For(0, distinctFilteredFaces.Length, parallelOptions, (i, state) =>
|
||||
{
|
||||
Face face = distinctFilteredFaces[i];
|
||||
if (face.FaceEncoding is null || face.Mapping is null)
|
||||
throw new NotSupportedException();
|
||||
if (face.FaceDistance?.Encoding is not null && face.FaceDistance.Encoding is FaceRecognitionDotNet.FaceEncoding faceEncoding)
|
||||
return;
|
||||
progressBar.Tick();
|
||||
faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
|
||||
FaceDistance faceDistance = new(face.Mapping.MappingFromLocation.Confidence, faceEncoding, face.Mapping.MappingFromItem.Id, face.Mapping.MappingFromItem.IsWrongYear, face.Mapping.MappingFromItem.MinimumDateTime, face.Mapping.MappingFromLocation.NormalizedPixelPercentage);
|
||||
lock (face)
|
||||
face.SetFaceDistance(faceDistance);
|
||||
});
|
||||
}
|
||||
|
||||
void Shared.Models.Methods.IFaceDistance.SavePossiblyNewPersonContainers(IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, string facesFileNameExtension, string? a2PeopleSingletonDirectory, Dictionary<long, PersonContainer> personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer)
|
||||
{
|
||||
char @char;
|
||||
string json;
|
||||
string[] files;
|
||||
string checkFile;
|
||||
string[] segments;
|
||||
const int zero = 0;
|
||||
string personKeyFormatted;
|
||||
string personDisplayDirectory;
|
||||
PersonBirthday personBirthday;
|
||||
string personDisplayDirectoryName;
|
||||
string checkPersonDisplayDirectory;
|
||||
string checkPersonKeyFormattedDirectory;
|
||||
char[] chars = Shared.Models.Stateless.Methods.IAge.GetChars();
|
||||
JsonSerializerOptions jsonSerializerOptions = new() { WriteIndented = true };
|
||||
foreach ((string[] personDisplayDirectoryNames, PersonContainer personContainer) in possiblyNewPersonDisplayDirectoryNamesAndPersonContainer)
|
||||
{
|
||||
if (a2PeopleSingletonDirectory is null || personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any())
|
||||
continue;
|
||||
personBirthday = personContainer.Birthdays[zero];
|
||||
personDisplayDirectoryName = personDisplayDirectoryNames[^1];
|
||||
personDisplayDirectory = Path.Combine(personDisplayDirectoryNames);
|
||||
personKeyFormatted = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(personBirthdayFormat, personBirthday);
|
||||
segments = personDisplayDirectoryName.Split(chars);
|
||||
if (segments.Length != 2)
|
||||
@char = '_';
|
||||
else
|
||||
@char = personDisplayDirectoryName[segments[zero].Length];
|
||||
checkPersonDisplayDirectory = Path.Combine(a2PeopleSingletonDirectory, @char.ToString(), personDisplayDirectoryName);
|
||||
checkPersonKeyFormattedDirectory = Path.Combine(checkPersonDisplayDirectory, personKeyFormatted);
|
||||
if (Directory.Exists(checkPersonKeyFormattedDirectory))
|
||||
continue;
|
||||
_ = Directory.CreateDirectory(checkPersonKeyFormattedDirectory);
|
||||
checkFile = Path.Combine(checkPersonKeyFormattedDirectory, $"{personKeyFormatted}.json");
|
||||
json = JsonSerializer.Serialize(personContainer.Person, jsonSerializerOptions);
|
||||
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true);
|
||||
if (!Directory.Exists(personDisplayDirectory))
|
||||
continue;
|
||||
files = Directory.GetFiles(personDisplayDirectory, $"*{facesFileNameExtension}", SearchOption.TopDirectoryOnly);
|
||||
foreach (string file in files)
|
||||
{
|
||||
checkFile = Path.Combine(checkPersonDisplayDirectory, Path.GetFileName(file));
|
||||
if (File.Exists(checkFile))
|
||||
continue;
|
||||
File.Copy(files[0], checkFile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MoveUnableToMatch(string eDistanceContentDirectory, string mappedFaceFile, string mappedFaceFileName)
|
||||
@ -428,14 +130,14 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
return result;
|
||||
}
|
||||
|
||||
private static FaceDistanceContainer[] GetOrderedFaceDistanceContainers(MappingFromItem mappingFromItem, List<Face> faces)
|
||||
private static FaceDistanceContainer[] GetFaceDistanceContainers(MappingFromItem mappingFromItem, Face[] filteredFaces)
|
||||
{
|
||||
FaceDistanceContainer[] results;
|
||||
FaceDistance faceDistance;
|
||||
int normalizedPixelPercentage;
|
||||
FaceDistanceContainer faceDistanceContainer;
|
||||
List<FaceDistanceContainer> collection = new();
|
||||
foreach (Face face in faces)
|
||||
foreach (Face face in filteredFaces)
|
||||
{
|
||||
if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null)
|
||||
throw new NotSupportedException();
|
||||
@ -446,17 +148,29 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
{
|
||||
faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
|
||||
faceDistance = new(face.Location.Confidence, faceEncoding, mappingFromItem.Id, mappingFromItem.IsWrongYear, mappingFromItem.MinimumDateTime, normalizedPixelPercentage);
|
||||
lock (faces)
|
||||
lock (filteredFaces)
|
||||
face.SetFaceDistance(faceDistance);
|
||||
}
|
||||
faceDistanceContainer = new(face, faceDistance);
|
||||
collection.Add(faceDistanceContainer);
|
||||
}
|
||||
results = GetOrderedFaceDistanceContainers(collection);
|
||||
results = collection.ToArray();
|
||||
return results;
|
||||
}
|
||||
|
||||
private static List<(Face Face, double? Length)> GetValues(MappingFromItem mappingFromItem, List<Face> faces, string json)
|
||||
private static List<FaceDistance> GetFaceDistanceEncodings(FaceDistanceContainer[] faceDistanceContainers)
|
||||
{
|
||||
List<FaceDistance> faceDistanceEncodings = new();
|
||||
foreach (FaceDistanceContainer faceDistanceContainer in faceDistanceContainers)
|
||||
{
|
||||
if (faceDistanceContainer.FaceDistance.Encoding is null)
|
||||
continue;
|
||||
faceDistanceEncodings.Add(faceDistanceContainer.FaceDistance);
|
||||
}
|
||||
return faceDistanceEncodings;
|
||||
}
|
||||
|
||||
private static List<(Face Face, double? Length)> GetValues(MappingFromItem mappingFromItem, Face[] filteredFaces, string json)
|
||||
{
|
||||
List<(Face Face, double? Length)> results = new();
|
||||
Face face;
|
||||
@ -466,19 +180,19 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
throw new NotSupportedException();
|
||||
FaceRecognitionDotNet.FaceEncoding faceRecognitionDotNetFaceEncoding = FaceRecognition.LoadFaceEncoding(modelsFaceEncoding.RawEncoding);
|
||||
FaceDistance faceDistanceEncoding = new(faceRecognitionDotNetFaceEncoding);
|
||||
FaceDistanceContainer[] faceDistanceContainers = GetOrderedFaceDistanceContainers(mappingFromItem, faces);
|
||||
FaceDistanceContainer[] faceDistanceContainers = GetFaceDistanceContainers(mappingFromItem, filteredFaces);
|
||||
int faceDistanceContainersLength = faceDistanceContainers.Length;
|
||||
if (faceDistanceContainersLength != faces.Count)
|
||||
if (faceDistanceContainersLength != filteredFaces.Length)
|
||||
throw new NotSupportedException();
|
||||
List<FaceDistance> faceDistanceEncodings = GetFaceDistanceEncodings(faceDistanceContainers);
|
||||
if (faceDistanceEncodings.Count != faces.Count)
|
||||
if (faceDistanceEncodings.Count != filteredFaces.Length)
|
||||
throw new NotSupportedException();
|
||||
List<FaceDistance> faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncoding);
|
||||
if (faceDistanceLengths.Count != faceDistanceContainersLength)
|
||||
throw new NotSupportedException();
|
||||
for (int i = 0; i < faces.Count; i++)
|
||||
for (int i = 0; i < filteredFaces.Length; i++)
|
||||
{
|
||||
face = faces[i];
|
||||
face = filteredFaces[i];
|
||||
faceDistanceLength = faceDistanceLengths[i];
|
||||
if (faceDistanceLength.Length is null)
|
||||
throw new NotSupportedException();
|
||||
@ -487,10 +201,10 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
return results;
|
||||
}
|
||||
|
||||
private (Face, double?)[] GetClosestFaceByDistanceIgnoringTolerance(MappingFromItem mappingFromItem, List<Face> faces, string json)
|
||||
private (Face, double?)[] GetClosestFaceByDistanceIgnoringTolerance(MappingFromItem mappingFromItem, Face[] filteredFaces, string json)
|
||||
{
|
||||
(Face, double?)[] results;
|
||||
List<(Face Face, double? Length)> collection = GetValues(mappingFromItem, faces, json);
|
||||
List<(Face Face, double? Length)> collection = GetValues(mappingFromItem, filteredFaces, json);
|
||||
results = (from l in collection orderby l.Length select l).Take(1).ToArray();
|
||||
(Face face, double? length) = results.First();
|
||||
lock (_Debug)
|
||||
@ -515,7 +229,7 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
return new(x, y);
|
||||
}
|
||||
|
||||
private (Face, double?)[] GetClosestFaceByPixel(List<Face> faces, int? x1, int? y1)
|
||||
private (Face, double?)[] GetClosestFaceByPixel(Face[] filteredFaces, int? x1, int? y1)
|
||||
{
|
||||
(Face, double?)[] results;
|
||||
int? x2;
|
||||
@ -526,7 +240,7 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
List<(Face Face, double? Order)> collection = new();
|
||||
if (x1 is null || y1 is null)
|
||||
throw new NotSupportedException();
|
||||
foreach (Face face in faces)
|
||||
foreach (Face face in filteredFaces)
|
||||
{
|
||||
if (face.Location is null || face.OutputResolution is null)
|
||||
throw new NotSupportedException();
|
||||
@ -542,25 +256,25 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
return results;
|
||||
}
|
||||
|
||||
private (Face, double?)[] GetClosestFaceByPixel(List<Face> faces, int normalizedPixelPercentage)
|
||||
private (Face, double?)[] GetClosestFaceByPixel(Face[] filteredFaces, int normalizedPixelPercentage)
|
||||
{
|
||||
if (!faces.Any())
|
||||
if (!filteredFaces.Any())
|
||||
throw new NotSupportedException();
|
||||
(Face, double?)[] results;
|
||||
const int zero = 0;
|
||||
OutputResolution? outputResolution = faces[zero].OutputResolution;
|
||||
OutputResolution? outputResolution = filteredFaces[zero].OutputResolution;
|
||||
(int? x1, int? y1) = GetXY(normalizedPixelPercentage, outputResolution);
|
||||
results = GetClosestFaceByPixel(faces, x1, y1);
|
||||
results = GetClosestFaceByPixel(filteredFaces, x1, y1);
|
||||
return results;
|
||||
}
|
||||
|
||||
private (Face, double?)[] GetClosestFaceByPixel(List<Face> faces, string json)
|
||||
private (Face, double?)[] GetClosestFaceByPixel(Face[] filteredFaces, string json)
|
||||
{
|
||||
if (!faces.Any())
|
||||
if (!filteredFaces.Any())
|
||||
throw new NotSupportedException();
|
||||
(Face, double?)[] results;
|
||||
const int zero = 0;
|
||||
OutputResolution? outputResolution = faces[zero].OutputResolution;
|
||||
OutputResolution? outputResolution = filteredFaces[zero].OutputResolution;
|
||||
if (outputResolution is null)
|
||||
throw new NullReferenceException(nameof(outputResolution));
|
||||
Location? location = JsonSerializer.Deserialize<Location>(json);
|
||||
@ -568,15 +282,15 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
throw new NullReferenceException(nameof(location));
|
||||
int normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, outputResolution);
|
||||
(int? x1, int? y1) = GetXY(normalizedPixelPercentage, outputResolution);
|
||||
results = GetClosestFaceByPixel(faces, x1, y1);
|
||||
results = GetClosestFaceByPixel(filteredFaces, x1, y1);
|
||||
return results;
|
||||
}
|
||||
|
||||
private static List<(Face, double?)> GetMatchingFacesByFaceEncoding(List<Face> faces, string? json)
|
||||
private static List<(Face, double?)> GetMatchingFacesByFaceEncoding(Face[] filteredFaces, string? json)
|
||||
{
|
||||
List<(Face, double?)> results = new();
|
||||
string check;
|
||||
foreach (Face face in faces)
|
||||
foreach (Face face in filteredFaces)
|
||||
{
|
||||
if (json is null || face.FaceEncoding is null)
|
||||
continue;
|
||||
@ -648,6 +362,9 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
FileInfo? fileInfo;
|
||||
string mappedFaceFileName;
|
||||
List<(Face, double?)> checkFaces = new();
|
||||
Face[] filteredFaces = (from l in faces where l.FaceEncoding is not null && l.Location is not null && l.OutputResolution is not null select l).ToArray();
|
||||
if (filteredFaces.Length != faces.Count)
|
||||
checkFaces.Clear();
|
||||
foreach ((string mappedFaceFile, int normalizedPixelPercentage) in collection)
|
||||
{
|
||||
mappedFaceFileName = Path.GetFileName(mappedFaceFile);
|
||||
@ -661,7 +378,7 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
MoveUnableToMatch(eDistanceContentDirectory, mappedFaceFile, mappedFaceFileName);
|
||||
continue;
|
||||
}
|
||||
checkFaces.AddRange(GetMatchingFacesByFaceEncoding(faces, json));
|
||||
checkFaces.AddRange(GetMatchingFacesByFaceEncoding(filteredFaces, json));
|
||||
if (checkFaces.Count == 1)
|
||||
_Debug.Add(0);
|
||||
if (checkFaces.Count != 1 && !string.IsNullOrEmpty(json))
|
||||
@ -669,16 +386,16 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
checkFaces.Clear();
|
||||
if (json is null)
|
||||
throw new NotSupportedException();
|
||||
checkFaces.AddRange(GetClosestFaceByDistanceIgnoringTolerance(mappingFromItem, faces, json));
|
||||
checkFaces.AddRange(GetClosestFaceByDistanceIgnoringTolerance(mappingFromItem, filteredFaces, json));
|
||||
}
|
||||
if (checkFaces.Count != 1 && _DistancePixelDistanceTolerance > 0)
|
||||
{
|
||||
checkFaces.Clear();
|
||||
json = GetFaceLocation(mappedFaceFile);
|
||||
if (json is not null)
|
||||
checkFaces.AddRange(GetClosestFaceByPixel(faces, json));
|
||||
checkFaces.AddRange(GetClosestFaceByPixel(filteredFaces, json));
|
||||
else
|
||||
checkFaces.AddRange(GetClosestFaceByPixel(faces, normalizedPixelPercentage));
|
||||
checkFaces.AddRange(GetClosestFaceByPixel(filteredFaces, normalizedPixelPercentage));
|
||||
throw new NotImplementedException("Without a tolerance this should not ever occur!");
|
||||
}
|
||||
if (!checkFaces.Any())
|
||||
|
@ -75,13 +75,7 @@ public partial class DlibDotNet
|
||||
configuration.DistanceMoveUnableToMatch,
|
||||
configuration.DistancePixelDistanceTolerance,
|
||||
configuration.DistanceRenameToMatch,
|
||||
configuration.FaceDistanceAreaPermilleTolerance,
|
||||
configuration.FaceDistanceMinimumConfidence,
|
||||
configuration.FaceDistancePermyriad,
|
||||
configuration.FaceDistanceTolerance,
|
||||
configuration.PropertyConfiguration.ResultAllInOne,
|
||||
configuration.SortingDaysDeltaTolerance,
|
||||
configuration.SortingMaximumPerFaceShouldBeHigh);
|
||||
configuration.FaceDistanceTolerance);
|
||||
if (configuration.IgnoreExtensions is null)
|
||||
throw new NullReferenceException(nameof(configuration.IgnoreExtensions));
|
||||
string propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(propertyConfiguration, nameof(A_Property), create: false);
|
||||
@ -422,7 +416,6 @@ public partial class DlibDotNet
|
||||
if (_AppSettings.MaxDegreeOfParallelism < 2)
|
||||
ticks = LogDelta(ticks, nameof(D_Face.SaveFaces));
|
||||
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.LookForMatchFacesAndPossiblyRename(_Faces.FileNameExtension, eDistanceContentDirectory, mappingFromItem, faces, collection);
|
||||
if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution))
|
||||
@ -924,13 +917,19 @@ public partial class DlibDotNet
|
||||
return results;
|
||||
}
|
||||
|
||||
private void DistanceThenMapLogic(string argZero, long ticks, PersonContainer[] personContainers, Container[] containers, string a2PeopleSingletonDirectory, string dResultsFullGroupDirectory, string d2FacePartsContentDirectory, string eDistanceContentDirectory, string outputResolution)
|
||||
private void MapLogic(string argZero, long ticks, PersonContainer[] personContainers, Container[] containers, string a2PeopleSingletonDirectory, string dResultsFullGroupDirectory, string d2FacePartsContentDirectory, string eDistanceContentDirectory, string outputResolution)
|
||||
{
|
||||
int? useFiltersCounter = null;
|
||||
SortingContainer[] sortingContainers;
|
||||
string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, "()");
|
||||
Shared.Models.Face[] distinctFilteredFaces = SetMappingThenGetDistinctFilteredFacesWithMapping(argZero, containers);
|
||||
Mapping[] mappingCollection = E_Distance.GetSelectedMappingCollection(distinctFilteredFaces);
|
||||
Mapping[] mappingCollection = MapLogicSupport.GetSelectedMappingCollection(distinctFilteredFaces);
|
||||
MapLogicSupport mapLogicSupport = new(
|
||||
_Configuration.FaceDistanceAreaPermilleTolerance,
|
||||
_Configuration.FaceDistanceMinimumConfidence,
|
||||
_Configuration.FaceDistancePermyriad,
|
||||
_Configuration.SortingDaysDeltaTolerance,
|
||||
_Configuration.SortingMaximumPerFaceShouldBeHigh);
|
||||
MapLogic mapLogic = new(
|
||||
_AppSettings.MaxDegreeOfParallelism,
|
||||
_Configuration.PropertyConfiguration,
|
||||
@ -940,24 +939,24 @@ public partial class DlibDotNet
|
||||
a2PeopleSingletonDirectory,
|
||||
eDistanceContentDirectory,
|
||||
mappingCollection,
|
||||
_Distance);
|
||||
mapLogicSupport);
|
||||
Dictionary<int, Dictionary<int, Mapping>> idToNormalizedPixelPercentageToMapping = GetIdToNormalizedPixelPercentageToFace(mappingCollection);
|
||||
mapLogic.CopyManualFiles(dFacesContentDirectory, idToNormalizedPixelPercentageToMapping);
|
||||
int totalNotMapped = mapLogic.AddToMapping(mappingCollection);
|
||||
if (_Configuration.MappingSaveMapped)
|
||||
mapLogic.SaveMapped(dFacesContentDirectory, d2FacePartsContentDirectory, mappingCollection, idToNormalizedPixelPercentageToMapping, totalNotMapped);
|
||||
E_Distance.SetFaceDistances(_AppSettings.MaxDegreeOfParallelism, ticks, distinctFilteredFaces);
|
||||
sortingContainers = _Distance.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, ticks, mapLogic, distinctFilteredFaces, useFiltersCounter);
|
||||
MapLogicSupport.SetFaceDistances(_AppSettings.MaxDegreeOfParallelism, ticks, distinctFilteredFaces);
|
||||
sortingContainers = mapLogicSupport.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, ticks, mapLogic, distinctFilteredFaces, useFiltersCounter);
|
||||
if (!sortingContainers.Any())
|
||||
{
|
||||
for (useFiltersCounter = 1; useFiltersCounter < 11; useFiltersCounter++)
|
||||
{
|
||||
sortingContainers = _Distance.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, ticks, mapLogic, distinctFilteredFaces, useFiltersCounter);
|
||||
sortingContainers = mapLogicSupport.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, ticks, mapLogic, distinctFilteredFaces, useFiltersCounter);
|
||||
if (sortingContainers.Any())
|
||||
break;
|
||||
}
|
||||
}
|
||||
E_Distance.SaveFaceDistances(_Configuration.PropertyConfiguration, sortingContainers);
|
||||
MapLogicSupport.SaveFaceDistances(_Configuration.PropertyConfiguration, sortingContainers);
|
||||
if (totalNotMapped > 0)
|
||||
mapLogic.ForceSingleImageThenSaveSorting(dFacesContentDirectory, d2FacePartsContentDirectory, mappingCollection, idToNormalizedPixelPercentageToMapping, sortingContainers, useFiltersCounter, totalNotMapped);
|
||||
if (_Configuration.MappingSaveNotMapped)
|
||||
@ -1090,7 +1089,7 @@ public partial class DlibDotNet
|
||||
{
|
||||
if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Any())
|
||||
break;
|
||||
DistanceThenMapLogic(argZero, ticks, personContainers, containers, a2PeopleSingletonDirectory, dResultsFullGroupDirectory, d2FacePartsContentDirectory, eDistanceContentDirectory, outputResolution);
|
||||
MapLogic(argZero, ticks, personContainers, containers, a2PeopleSingletonDirectory, dResultsFullGroupDirectory, d2FacePartsContentDirectory, eDistanceContentDirectory, outputResolution);
|
||||
if (_IsEnvironment.Development)
|
||||
continue;
|
||||
if (_FileKeyValuePairs.Any())
|
||||
|
@ -25,7 +25,7 @@ public class MapLogic
|
||||
private readonly Configuration? _Configuration;
|
||||
private readonly string _EDistanceContentTicksDirectory;
|
||||
|
||||
public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, long ticks, PersonContainer[] personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory, Mapping[] mappingCollection, Shared.Models.Methods.IFaceDistance? faceDistance)
|
||||
public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, long ticks, PersonContainer[] personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory, Mapping[] mappingCollection, Shared.Models.Methods.IMapLogicSupport? faceDistance)
|
||||
{
|
||||
_Ticks = ticks;
|
||||
_Configuration = configuration;
|
||||
|
@ -567,7 +567,7 @@ internal abstract class MapLogic
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Set(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, long ticks, List<PersonContainer> personContainers, string? a2PeopleContentDirectory, string eDistanceContentDirectory, Mapping[] mappingCollection, Shared.Models.Methods.IFaceDistance faceDistance, Dictionary<long, PersonContainer> personKeyToPersonContainer, Dictionary<long, (long LCL, long Minimum, long Maximum, long UCL)> personKeyToRanges, List<PersonContainer> notMappedPersonContainers, Dictionary<int, List<int>> skipCollection, Dictionary<int, Dictionary<int, PersonContainer[]>> idThenNormalizedPixelPercentageToPersonContainers)
|
||||
internal static void Set(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, long ticks, List<PersonContainer> personContainers, string? a2PeopleContentDirectory, string eDistanceContentDirectory, Mapping[] mappingCollection, Shared.Models.Methods.IMapLogicSupport faceDistance, Dictionary<long, PersonContainer> personKeyToPersonContainer, Dictionary<long, (long LCL, long Minimum, long Maximum, long UCL)> personKeyToRanges, List<PersonContainer> notMappedPersonContainers, Dictionary<int, List<int>> skipCollection, Dictionary<int, Dictionary<int, PersonContainer[]>> idThenNormalizedPixelPercentageToPersonContainers)
|
||||
{
|
||||
if (configuration is null)
|
||||
throw new NullReferenceException(nameof(configuration));
|
||||
|
@ -1,6 +1,6 @@
|
||||
namespace View_by_Distance.Shared.Models.Methods;
|
||||
|
||||
public interface IFaceDistance
|
||||
public interface IMapLogicSupport
|
||||
{
|
||||
|
||||
void SavePossiblyNewPersonContainers(Properties.IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, string facesFileNameExtension, string? a2PeopleContentDirectory, Dictionary<long, PersonContainer> personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer);
|
Loading…
x
Reference in New Issue
Block a user