142 lines
8.7 KiB
C#
142 lines
8.7 KiB
C#
using ShellProgressBar;
|
|
using View_by_Distance.FaceRecognitionDotNet;
|
|
using View_by_Distance.Map.Models;
|
|
using View_by_Distance.Shared.Models;
|
|
using View_by_Distance.Shared.Models.Stateless;
|
|
|
|
namespace View_by_Distance.Instance.Models;
|
|
|
|
internal class E_Distance
|
|
{
|
|
|
|
private static void SaveFaceDistances(string eDistanceContentFileName, SortingContainer[] sortingContainers)
|
|
{
|
|
#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();
|
|
#pragma warning restore
|
|
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();
|
|
bool anyLowerThanTolerance = (from l in faceDistanceLengths where l.Length is not null && l.Length.Value != 0 && l.Length.Value < IFaceDistance.Tolerance select true).Any();
|
|
results = mapLogic.GetSortingCollection(i, faceDistanceEncoding, faceDistanceLengths, anyLowerThanTolerance);
|
|
return results;
|
|
}
|
|
|
|
private static List<SortingContainer> GetSortingContainers(Face face, FaceDistance faceDistanceEncoding, List<Sorting> sortingCollection)
|
|
{
|
|
List<SortingContainer> results = new();
|
|
SortingContainer sortingContainer;
|
|
Sorting[] collection = Shared.Models.Stateless.Methods.ISorting.Sort(sortingCollection);
|
|
foreach (Sorting sorting in collection)
|
|
{
|
|
if (face.Mapping is null || faceDistanceEncoding.NormalizedPixelPercentage is null)
|
|
throw new NotSupportedException();
|
|
if (face.Mapping.MappingFromLocation.Confidence < IFaceDistance.MinimumConfidence || sorting.DistancePermyriad > IFaceDistance.Permyriad || sorting.DaysDelta > ISorting.DaysDeltaTolerance)
|
|
continue;
|
|
sortingContainer = new(face, sorting);
|
|
results.Add(sortingContainer);
|
|
if (results.Count >= ISorting.MaximumPerFaceShouldBeHigh)
|
|
break;
|
|
}
|
|
return results;
|
|
}
|
|
|
|
private static SortingContainer[] GetSortingContainersThenSetFaceMappingSortingCollection(int maxDegreeOfParallelism, long ticks, MapLogic mapLogic, string outputResolution, FaceDistanceContainer[] faceDistanceContainers)
|
|
{
|
|
SortingContainer[] results;
|
|
List<SortingContainer> collection = new();
|
|
List<FaceDistance> faceDistanceEncodings = new();
|
|
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
|
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
|
string message = $") {faceDistanceContainers.Length:000} faceDistanceContainer(s) - {totalSeconds} total second(s) - {outputResolution}";
|
|
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
|
foreach (FaceDistanceContainer faceDistanceContainer in faceDistanceContainers)
|
|
{
|
|
if (faceDistanceContainer.FaceDistance.Encoding is null)
|
|
continue;
|
|
faceDistanceEncodings.Add(faceDistanceContainer.FaceDistance);
|
|
}
|
|
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;
|
|
List<Sorting> sortingCollection = GetSortingCollection(mapLogic, faceDistanceEncodings, faceDistanceContainers.Length, i, faceDistanceEncoding);
|
|
List<SortingContainer> sortingContainers = GetSortingContainers(face, faceDistanceEncoding, sortingCollection);
|
|
lock (collection)
|
|
collection.AddRange(sortingContainers);
|
|
lock (face)
|
|
face.ReleaseFaceDistance();
|
|
});
|
|
results = Shared.Models.Stateless.Methods.ISortingContainer.Sort(collection);
|
|
return results;
|
|
}
|
|
|
|
private static FaceDistanceContainer[] GetFaceDistanceContainers(Face[] firstFilteredFaces)
|
|
{
|
|
FaceDistanceContainer[] results;
|
|
FaceDistance faceDistance;
|
|
FaceDistanceContainer faceDistanceContainer;
|
|
List<FaceDistanceContainer> collection = new();
|
|
foreach (Face face in firstFilteredFaces)
|
|
{
|
|
if (face.Mapping is null)
|
|
throw new NotSupportedException();
|
|
if (face.FaceDistance?.Encoding is not FaceRecognitionDotNet.FaceEncoding faceEncoding)
|
|
throw new NotSupportedException();
|
|
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 = (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 void SetFaceDistances(int maxDegreeOfParallelism, long ticks, string outputResolution, Face[] selectedFilteredFaces)
|
|
{
|
|
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
|
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
|
string message = $") {selectedFilteredFaces.Length:000} Load Face Encoding - {totalSeconds} total second(s) - {outputResolution}";
|
|
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = false };
|
|
using ProgressBar progressBar = new(selectedFilteredFaces.Length, message, options);
|
|
_ = Parallel.For(0, selectedFilteredFaces.Length, parallelOptions, (i, state) =>
|
|
{
|
|
FaceDistance faceDistance;
|
|
FaceRecognitionDotNet.FaceEncoding faceEncoding;
|
|
Face face = selectedFilteredFaces[i];
|
|
if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
|
|
throw new NotSupportedException();
|
|
if (face.Mapping is null)
|
|
throw new NotSupportedException();
|
|
faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
|
|
faceDistance = new(face.Location.Confidence, faceEncoding, face.Mapping.MappingFromItem.Id, face.Mapping.MappingFromItem.IsWrongYear, face.Mapping.MappingFromItem.MinimumDateTime, face.Location.NormalizedPixelPercentage.Value);
|
|
lock (face)
|
|
face.FaceDistanceAdd(faceDistance);
|
|
});
|
|
}
|
|
|
|
internal static SortingContainer[] SetPersonTicksAndSetFaceDistancesAndSetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, long ticks, MapLogic mapLogic, string outputResolution, string eDistanceContentFileName, List<Face> distinctFilteredFaces)
|
|
{
|
|
SortingContainer[] results;
|
|
Face[] orderedFilteredFaces = (from l in distinctFilteredFaces orderby l.Mapping is not null, l.Mapping?.MappingFromItem.MinimumDateTime descending select l).ToArray();
|
|
mapLogic.SetPersonTicks(outputResolution, orderedFilteredFaces);
|
|
Face[] selectedFilteredFaces = orderedFilteredFaces.Skip(ISorting.FacesToSkipAfterSortBeforeLoad).Take(ISorting.FacesToTakeAfterSortBeforeLoad).ToArray();
|
|
SetFaceDistances(maxDegreeOfParallelism, ticks, outputResolution, selectedFilteredFaces);
|
|
FaceDistanceContainer[] faceDistanceContainers = GetFaceDistanceContainers(selectedFilteredFaces);
|
|
results = GetSortingContainersThenSetFaceMappingSortingCollection(maxDegreeOfParallelism, ticks, mapLogic, outputResolution, faceDistanceContainers);
|
|
SaveFaceDistances(eDistanceContentFileName, results);
|
|
return results;
|
|
}
|
|
|
|
} |