Get Unable to Match Count and Rename Matches
This commit is contained in:
@ -10,30 +10,53 @@ namespace View_by_Distance.Distance.Models;
|
||||
public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
{
|
||||
|
||||
public static void SaveFaceDistances(Property.Models.Configuration propertyConfiguration, string eResultsFullGroupDirectory, SortingContainer[] sortingContainers)
|
||||
private readonly Serilog.ILogger? _Log;
|
||||
private readonly string _ResultAllInOne;
|
||||
private readonly int _FaceDistancePermyriad;
|
||||
private readonly double _FaceDistanceTolerance;
|
||||
private readonly int _SortingDaysDeltaTolerance;
|
||||
private readonly bool _DistanceMoveUnableToMatch;
|
||||
private readonly int _DistancePixelDistanceTolerance;
|
||||
private readonly double _FaceDistanceMinimumConfidence;
|
||||
private readonly int _SortingMaximumPerFaceShouldBeHigh;
|
||||
|
||||
public E_Distance(bool distanceMoveUnableToMatch, int distancePixelDistanceTolerance, double faceDistanceMinimumConfidence, int faceDistancePermyriad, double faceDistanceTolerance, string resultAllInOne, int sortingDaysDeltaTolerance, int sortingMaximumPerFaceShouldBeHigh)
|
||||
{
|
||||
string eDistanceContentCollectionDirectory = Path.Combine(eResultsFullGroupDirectory, "([])");
|
||||
_ResultAllInOne = resultAllInOne;
|
||||
_Log = Serilog.Log.ForContext<E_Distance>();
|
||||
_FaceDistancePermyriad = faceDistancePermyriad;
|
||||
_FaceDistanceTolerance = faceDistanceTolerance;
|
||||
_DistanceMoveUnableToMatch = distanceMoveUnableToMatch;
|
||||
_SortingDaysDeltaTolerance = sortingDaysDeltaTolerance;
|
||||
_FaceDistanceMinimumConfidence = faceDistanceMinimumConfidence;
|
||||
_DistancePixelDistanceTolerance = distancePixelDistanceTolerance;
|
||||
_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 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
|
||||
string eDistanceContentFileName = Path.Combine(eDistanceContentCollectionDirectory, $"{propertyConfiguration.ResultAllInOne}.tvs");
|
||||
string eDistanceContentFileName = Path.Combine(eDistanceContentCollectionDirectory, $"{configuration.ResultAllInOne}.tvs");
|
||||
File.WriteAllLines(eDistanceContentFileName, results);
|
||||
}
|
||||
|
||||
private static List<Sorting> GetSortingCollection(Configuration configuration, MapLogic mapLogic, List<FaceDistance> faceDistanceEncodings, int faceDistanceContainersLength, int i, FaceDistance faceDistanceEncoding)
|
||||
private 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 < configuration.FaceDistanceTolerance select true).Any();
|
||||
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);
|
||||
return results;
|
||||
}
|
||||
|
||||
private static List<SortingContainer> GetSortingContainers(Configuration configuration, Face face, FaceDistance faceDistanceEncoding, List<Sorting> sortingCollection)
|
||||
private List<SortingContainer> GetSortingContainers(Face face, FaceDistance faceDistanceEncoding, List<Sorting> sortingCollection)
|
||||
{
|
||||
List<SortingContainer> results = new();
|
||||
SortingContainer sortingContainer;
|
||||
@ -42,11 +65,11 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
{
|
||||
if (face.Mapping is null || faceDistanceEncoding.NormalizedPixelPercentage is null)
|
||||
throw new NotSupportedException();
|
||||
if (face.Mapping.MappingFromLocation.Confidence < configuration.FaceDistanceMinimumConfidence || sorting.DistancePermyriad > configuration.FaceDistancePermyriad || sorting.DaysDelta > configuration.SortingDaysDeltaTolerance)
|
||||
if (face.Mapping.MappingFromLocation.Confidence < _FaceDistanceMinimumConfidence || sorting.DistancePermyriad > _FaceDistancePermyriad || sorting.DaysDelta > _SortingDaysDeltaTolerance)
|
||||
continue;
|
||||
sortingContainer = new(face, sorting);
|
||||
results.Add(sortingContainer);
|
||||
if (results.Count >= configuration.SortingMaximumPerFaceShouldBeHigh)
|
||||
if (results.Count >= _SortingMaximumPerFaceShouldBeHigh)
|
||||
break;
|
||||
}
|
||||
return results;
|
||||
@ -64,7 +87,16 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
return faceDistanceEncodings;
|
||||
}
|
||||
|
||||
private static FaceDistanceContainer[] GetFaceDistanceContainers(List<Face> selectedFilteredFaces)
|
||||
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[] selectedFilteredFaces)
|
||||
{
|
||||
FaceDistanceContainer[] results;
|
||||
FaceDistance faceDistance;
|
||||
@ -80,23 +112,22 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
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!");
|
||||
results = GetOrderedFaceDistanceContainers(collection);
|
||||
return results;
|
||||
}
|
||||
|
||||
public static SortingContainer[] SetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, Configuration configuration, long ticks, MapLogic mapLogic, List<Face> selectedFilteredFaces)
|
||||
public SortingContainer[] SetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, long ticks, MapLogic mapLogic, Face[] selectedFilteredFaces)
|
||||
{
|
||||
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(selectedFilteredFaces);
|
||||
FaceDistanceContainer[] faceDistanceContainers = GetOrderedFaceDistanceContainers(selectedFilteredFaces);
|
||||
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 };
|
||||
selectedFilteredFaces.Clear();
|
||||
foreach (Face face in selectedFilteredFaces)
|
||||
face.ClearFaceDistance();
|
||||
using ProgressBar progressBar = new(faceDistanceContainers.Length, message, options);
|
||||
_ = Parallel.For(0, faceDistanceContainers.Length, parallelOptions, (i, state) =>
|
||||
{
|
||||
@ -105,8 +136,8 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
if (face.Mapping is null)
|
||||
throw new NotSupportedException();
|
||||
FaceDistance faceDistanceEncoding = faceDistanceContainers[i].FaceDistance;
|
||||
List<Sorting> sortingCollection = GetSortingCollection(configuration, mapLogic, faceDistanceEncodings, faceDistanceContainers.Length, i, faceDistanceEncoding);
|
||||
List<SortingContainer> sortingContainers = GetSortingContainers(configuration, face, faceDistanceEncoding, sortingCollection);
|
||||
List<Sorting> sortingCollection = GetSortingCollection(mapLogic, faceDistanceEncodings, faceDistanceContainers.Length, i, faceDistanceEncoding);
|
||||
List<SortingContainer> sortingContainers = GetSortingContainers(face, faceDistanceEncoding, sortingCollection);
|
||||
lock (collection)
|
||||
collection.AddRange(sortingContainers);
|
||||
lock (face)
|
||||
@ -116,49 +147,73 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
return results;
|
||||
}
|
||||
|
||||
public static List<Face> GetSelectedFilteredFaces(List<Face> distinctFilteredFaces)
|
||||
public static Face[] GetSelectedFilteredFaces(List<Face> distinctFilteredFaces)
|
||||
{
|
||||
List<Face> results;
|
||||
Face[] orderedFilteredFaces = (from l in distinctFilteredFaces orderby l.Mapping is not null, l.Mapping?.MappingFromItem.MinimumDateTime descending select l).ToArray();
|
||||
results = orderedFilteredFaces.ToList();
|
||||
Face[] results = (from l in distinctFilteredFaces orderby l.Mapping is not null, l.Mapping?.MappingFromItem.MinimumDateTime descending select l).ToArray();
|
||||
return results;
|
||||
}
|
||||
|
||||
public static void SetFaceDistances(int maxDegreeOfParallelism, long ticks, List<Face> selectedFilteredFaces)
|
||||
public static void SetFaceDistances(int maxDegreeOfParallelism, long ticks, Face[] selectedFilteredFaces)
|
||||
{
|
||||
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
||||
string message = $") {selectedFilteredFaces.Count:000} Load Face Encoding - {totalSeconds} total second(s)";
|
||||
string message = $") {selectedFilteredFaces.Length:000} Load Face Encoding - {totalSeconds} total second(s)";
|
||||
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||
using ProgressBar progressBar = new(selectedFilteredFaces.Count, message, options);
|
||||
_ = Parallel.For(0, selectedFilteredFaces.Count, parallelOptions, (i, state) =>
|
||||
using ProgressBar progressBar = new(selectedFilteredFaces.Length, message, options);
|
||||
_ = Parallel.For(0, selectedFilteredFaces.Length, parallelOptions, (i, state) =>
|
||||
{
|
||||
progressBar.Tick();
|
||||
FaceDistance faceDistance;
|
||||
Face face = selectedFilteredFaces[i];
|
||||
FaceRecognitionDotNet.FaceEncoding faceEncoding;
|
||||
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 = new(face.Mapping.MappingFromLocation.Confidence, faceEncoding, face.Mapping.MappingFromItem.Id, face.Mapping.MappingFromItem.IsWrongYear, face.Mapping.MappingFromItem.MinimumDateTime, face.Mapping.MappingFromLocation.NormalizedPixelPercentage);
|
||||
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.FaceDistanceAdd(faceDistance);
|
||||
face.SetFaceDistance(faceDistance);
|
||||
});
|
||||
}
|
||||
|
||||
List<Face> Shared.Models.Methods.IFaceDistance.GetMatchingFaces(double faceDistanceTolerance, string checkFile, List<Face> faces)
|
||||
private static FaceDistanceContainer[] GetOrderedFaceDistanceContainers(MappingFromItem mappingFromItem, List<Face> faces)
|
||||
{
|
||||
List<Face> results = new();
|
||||
FaceDistanceContainer[] results;
|
||||
FaceDistance faceDistance;
|
||||
int normalizedPixelPercentage;
|
||||
FaceDistanceContainer faceDistanceContainer;
|
||||
List<FaceDistanceContainer> collection = new();
|
||||
foreach (Face face in faces)
|
||||
{
|
||||
if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null)
|
||||
throw new NotSupportedException();
|
||||
normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution);
|
||||
if (face.FaceDistance?.Encoding is not null && face.FaceDistance.Encoding is FaceRecognitionDotNet.FaceEncoding faceEncoding)
|
||||
faceDistance = new(face.Location.Confidence, faceEncoding, mappingFromItem.Id, mappingFromItem.IsWrongYear, mappingFromItem.MinimumDateTime, normalizedPixelPercentage);
|
||||
else
|
||||
{
|
||||
faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
|
||||
faceDistance = new(face.Location.Confidence, faceEncoding, mappingFromItem.Id, mappingFromItem.IsWrongYear, mappingFromItem.MinimumDateTime, normalizedPixelPercentage);
|
||||
lock (faces)
|
||||
face.SetFaceDistance(faceDistance);
|
||||
}
|
||||
faceDistanceContainer = new(face, faceDistance);
|
||||
collection.Add(faceDistanceContainer);
|
||||
}
|
||||
results = GetOrderedFaceDistanceContainers(collection);
|
||||
return results;
|
||||
}
|
||||
|
||||
private static List<(Face Face, double Length)> GetValues(double faceDistanceTolerance, MappingFromItem mappingFromItem, List<Face> faces, string json)
|
||||
{
|
||||
List<(Face Face, double Length)> results = new();
|
||||
Face face;
|
||||
FaceDistance faceDistanceLength;
|
||||
string json = File.ReadAllText(checkFile);
|
||||
List<(Face Face, double Length)> collection = new();
|
||||
Shared.Models.FaceEncoding? modelsFaceEncoding = JsonSerializer.Deserialize<Shared.Models.FaceEncoding>(json);
|
||||
if (modelsFaceEncoding is null)
|
||||
throw new NotSupportedException();
|
||||
FaceRecognitionDotNet.FaceEncoding faceRecognitionDotNetFaceEncoding = FaceRecognition.LoadFaceEncoding(modelsFaceEncoding.RawEncoding);
|
||||
FaceDistance faceDistanceEncoding = new(faceRecognitionDotNetFaceEncoding);
|
||||
FaceDistanceContainer[] faceDistanceContainers = GetFaceDistanceContainers(faces);
|
||||
FaceDistanceContainer[] faceDistanceContainers = GetOrderedFaceDistanceContainers(mappingFromItem, faces);
|
||||
int faceDistanceContainersLength = faceDistanceContainers.Length;
|
||||
if (faceDistanceContainersLength != faces.Count)
|
||||
throw new NotSupportedException();
|
||||
@ -172,12 +227,19 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
{
|
||||
face = faces[i];
|
||||
faceDistanceLength = faceDistanceLengths[i];
|
||||
if (face.Mapping is null || faceDistanceLength.Length is null)
|
||||
if (faceDistanceLength.Length is null)
|
||||
throw new NotSupportedException();
|
||||
if (faceDistanceLength.Length.Value > faceDistanceTolerance)
|
||||
continue;
|
||||
collection.Add(new(face, faceDistanceLength.Length.Value));
|
||||
results.Add(new(face, faceDistanceLength.Length.Value));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static List<Face> GetMatchingFaces(double faceDistanceTolerance, MappingFromItem mappingFromItem, List<Face> faces, string json)
|
||||
{
|
||||
List<Face> results = new();
|
||||
List<(Face Face, double Length)> collection = GetValues(faceDistanceTolerance, mappingFromItem, faces, json);
|
||||
if (collection.Any())
|
||||
{
|
||||
collection = (from l in collection orderby l.Length select l).ToList();
|
||||
@ -237,4 +299,320 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
}
|
||||
}
|
||||
|
||||
private void MoveUnableToMatch(string eDistanceContentDirectory, string file)
|
||||
{
|
||||
bool result;
|
||||
string? fileName = Path.GetFileName(file);
|
||||
string? directoryName = Path.GetDirectoryName(file);
|
||||
if (fileName is null || directoryName is null)
|
||||
result = false;
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(directoryName) || string.IsNullOrEmpty(directoryName) || !directoryName.Contains(eDistanceContentDirectory))
|
||||
result = false;
|
||||
else
|
||||
{
|
||||
List<string> directoryNames = new();
|
||||
string? checkDirectoryName = directoryName;
|
||||
for (int i = 0; i < int.MaxValue; i++)
|
||||
{
|
||||
if (string.IsNullOrEmpty(checkDirectoryName))
|
||||
continue;
|
||||
directoryNames.Add(Path.GetFileName(checkDirectoryName));
|
||||
checkDirectoryName = Path.GetDirectoryName(checkDirectoryName);
|
||||
if (string.IsNullOrEmpty(checkDirectoryName))
|
||||
continue;
|
||||
if (checkDirectoryName == eDistanceContentDirectory)
|
||||
break;
|
||||
}
|
||||
if (string.IsNullOrEmpty(checkDirectoryName) || !directoryNames.Any() || !long.TryParse(directoryNames[^1][1..^1], out long directoryTicks))
|
||||
{
|
||||
result = false;
|
||||
File.Delete(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
checkDirectoryName = Path.Combine(checkDirectoryName, $"({directoryTicks}{_FaceDistanceTolerance.ToString()[1..]})");
|
||||
for (int i = directoryNames.Count - 1 - 1; i > -1; i--)
|
||||
checkDirectoryName = Path.Combine(checkDirectoryName, directoryNames[i]);
|
||||
if (!Directory.Exists(checkDirectoryName))
|
||||
_ = Directory.CreateDirectory(checkDirectoryName);
|
||||
File.Move(file, Path.Combine(checkDirectoryName, fileName));
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result)
|
||||
{ }
|
||||
}
|
||||
|
||||
public static string? GetFaceEncoding(string file)
|
||||
{
|
||||
string? result;
|
||||
List<string> results = new();
|
||||
const string comment = "Comment: ";
|
||||
if (File.Exists(file))
|
||||
{
|
||||
IReadOnlyList<MetadataExtractor.Directory> directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(file);
|
||||
foreach (MetadataExtractor.Directory directory in directories)
|
||||
{
|
||||
if (directory.Name != "PNG-tEXt")
|
||||
continue;
|
||||
foreach (MetadataExtractor.Tag tag in directory.Tags)
|
||||
{
|
||||
if (tag.Name != "Textual Data" || string.IsNullOrEmpty(tag.Description))
|
||||
continue;
|
||||
if (!tag.Description.StartsWith(comment))
|
||||
continue;
|
||||
results.Add(tag.Description);
|
||||
}
|
||||
}
|
||||
}
|
||||
result = results.Any() ? results[0][comment.Length..] : null;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Face[] GetMatchingFaces(int pixelDistanceTolerance, List<Face> faces)
|
||||
{
|
||||
Face[] results;
|
||||
int? x;
|
||||
int? y;
|
||||
double distance;
|
||||
double center = 2f;
|
||||
double xCenterValue;
|
||||
double yCenterValue;
|
||||
string normalizedPixelPercentagePadded;
|
||||
List<(double Order, Face Face)> collection = new();
|
||||
foreach (Face face in faces)
|
||||
{
|
||||
if (face.Location is null || face.OutputResolution is null || face.Mapping is null)
|
||||
throw new NotSupportedException();
|
||||
xCenterValue = (face.Location.Left + face.Location.Right) / center;
|
||||
yCenterValue = (face.Location.Top + face.Location.Bottom) / center;
|
||||
if (xCenterValue < face.Location.Left || xCenterValue > face.Location.Right)
|
||||
throw new Exception();
|
||||
if (yCenterValue < face.Location.Top || yCenterValue > face.Location.Bottom)
|
||||
throw new Exception();
|
||||
normalizedPixelPercentagePadded = Shared.Models.Stateless.Methods.ILocation.GetLeftPadded(Shared.Models.Stateless.ILocation.Digits, face.Mapping.MappingFromLocation.NormalizedPixelPercentage);
|
||||
(x, y) = Shared.Models.Stateless.Methods.ILocation.GetXY(Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution.Width, face.OutputResolution.Height, normalizedPixelPercentagePadded);
|
||||
if (x is null || y is null)
|
||||
throw new NotSupportedException();
|
||||
distance = Math.Sqrt(Math.Pow(xCenterValue - x.Value, 2) + Math.Pow(yCenterValue - y.Value, 2));
|
||||
collection.Add(new(distance, face));
|
||||
}
|
||||
results = (from l in collection orderby l.Order where l.Order < pixelDistanceTolerance select l.Face).ToArray();
|
||||
if (results.Any())
|
||||
{
|
||||
if (results.Any())
|
||||
{ }
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static string[] GetMatchingDuplicates(string[] mappedFaceFiles, List<string> duplicateMappedFaceFiles, string mappedFaceFile)
|
||||
{
|
||||
string[] results;
|
||||
string checkFile;
|
||||
FileInfo fileInfo = new(mappedFaceFile);
|
||||
List<(long Length, string FullName)> collection = new();
|
||||
if (fileInfo.Exists)
|
||||
collection.Add(new(fileInfo.Length, fileInfo.FullName));
|
||||
string fileName = Path.GetFileName(mappedFaceFile);
|
||||
foreach (string file in mappedFaceFiles)
|
||||
{
|
||||
if (duplicateMappedFaceFiles.Contains(file))
|
||||
continue;
|
||||
if (file == mappedFaceFile || !file.EndsWith(fileName))
|
||||
continue;
|
||||
fileInfo = new(file);
|
||||
if (!fileInfo.Exists)
|
||||
continue;
|
||||
collection.Add(new(fileInfo.Length, fileInfo.FullName));
|
||||
}
|
||||
collection = collection.OrderBy(l => l.Length).ToList();
|
||||
for (int i = 0; i < collection.Count - 1; i++)
|
||||
{
|
||||
checkFile = string.Concat(collection[i].FullName, ".dup");
|
||||
if (File.Exists(checkFile))
|
||||
continue;
|
||||
File.Move(collection[i].FullName, checkFile);
|
||||
}
|
||||
results = (from l in collection select l.FullName).ToArray();
|
||||
return results;
|
||||
}
|
||||
|
||||
private static List<Face> GetMatchingFaces(List<Face> faces, string? json)
|
||||
{
|
||||
List<Face> results = new();
|
||||
string check;
|
||||
foreach (Face face in faces)
|
||||
{
|
||||
if (json is null || face.FaceEncoding is null)
|
||||
continue;
|
||||
if (!json.Contains(face.FaceEncoding.RawEncoding[0].ToString()))
|
||||
continue;
|
||||
check = JsonSerializer.Serialize(face.FaceEncoding);
|
||||
if (check != json)
|
||||
continue;
|
||||
results.Add(face);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static FileInfo? CheckFileThenGetFileInfo(string facesFileNameExtension, Item item, string mappedFaceDirectory, string mappedFaceFile, List<Face> checkFaces)
|
||||
{
|
||||
FileInfo? result = null;
|
||||
string checkFile;
|
||||
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}");
|
||||
if (checkFile == mappedFaceFile)
|
||||
continue;
|
||||
result = new FileInfo(checkFile);
|
||||
if (!result.Exists)
|
||||
continue;
|
||||
File.Delete(result.FullName);
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public (int, int) GetUnableToMatchCountAndRenameMatches(string facesFileNameExtension, string eDistanceContentDirectory, List<string[]> duplicateMappedFaceFilesCollection, Item item, List<Face> faces, string[] mappedFaceFiles)
|
||||
{
|
||||
int result = 0;
|
||||
int? id;
|
||||
string? json;
|
||||
bool debugCheck;
|
||||
int renamed = 0;
|
||||
bool? isWrongYear;
|
||||
FileInfo? fileInfo;
|
||||
DateTime minimumDateTime;
|
||||
string? mappedFaceDirectory;
|
||||
List<Face> checkFaces = new();
|
||||
List<int> debugChecks = new();
|
||||
int? normalizedPixelPercentage;
|
||||
MappingFromItem mappingFromItem;
|
||||
int normalizedPixelPercentageLoop;
|
||||
List<int> normalizedPixelPercentages;
|
||||
List<string> duplicateMappedFaceFiles = new();
|
||||
Dictionary<int, List<int>> idToNormalizedPixelPercentages = new();
|
||||
foreach (string mappedFaceFile in mappedFaceFiles)
|
||||
{
|
||||
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(
|
||||
Shared.Models.Stateless.ILocation.Digits,
|
||||
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;
|
||||
minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
|
||||
(isWrongYear, _) = item.Property.IsWrongYear(item.ImageFileHolder.FullName, minimumDateTime);
|
||||
mappingFromItem = new(item.Property.Id.Value, item.ImageFileHolder, isWrongYear, minimumDateTime, item.ResizedFileHolder);
|
||||
json = null;
|
||||
debugCheck = false;
|
||||
checkFaces.Clear();
|
||||
debugChecks.Clear();
|
||||
if (!idToNormalizedPixelPercentages.ContainsKey(id.Value))
|
||||
idToNormalizedPixelPercentages.Add(id.Value, new());
|
||||
normalizedPixelPercentages = idToNormalizedPixelPercentages[id.Value];
|
||||
foreach (Face face in faces)
|
||||
{
|
||||
if (face.Location is null || face.OutputResolution is null)
|
||||
throw new NotSupportedException();
|
||||
normalizedPixelPercentageLoop = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(face.Location, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, face.OutputResolution);
|
||||
debugChecks.Add(normalizedPixelPercentageLoop);
|
||||
if (normalizedPixelPercentage.Value != normalizedPixelPercentageLoop)
|
||||
continue;
|
||||
if (normalizedPixelPercentages.Contains(normalizedPixelPercentageLoop))
|
||||
{
|
||||
duplicateMappedFaceFiles.AddRange(GetMatchingDuplicates(mappedFaceFiles, duplicateMappedFaceFiles, mappedFaceFile));
|
||||
continue;
|
||||
}
|
||||
debugCheck = true;
|
||||
checkFaces.Add(face);
|
||||
if (!debugCheck)
|
||||
debugChecks.Add(normalizedPixelPercentageLoop);
|
||||
}
|
||||
if (checkFaces.Count != 1)
|
||||
{
|
||||
checkFaces.Clear();
|
||||
json = GetFaceEncoding(mappedFaceFile);
|
||||
if (json is null)
|
||||
{
|
||||
result++;
|
||||
if (_DistanceMoveUnableToMatch)
|
||||
MoveUnableToMatch(eDistanceContentDirectory, mappedFaceFile);
|
||||
continue;
|
||||
}
|
||||
checkFaces.AddRange(GetMatchingFaces(faces, json));
|
||||
}
|
||||
if (checkFaces.Count != 1 && !string.IsNullOrEmpty(json))
|
||||
{
|
||||
checkFaces.Clear();
|
||||
if (json is null)
|
||||
{
|
||||
result++;
|
||||
if (_DistanceMoveUnableToMatch)
|
||||
MoveUnableToMatch(eDistanceContentDirectory, mappedFaceFile);
|
||||
continue;
|
||||
}
|
||||
checkFaces.AddRange(GetMatchingFaces(_FaceDistanceTolerance, mappingFromItem, faces, json));
|
||||
}
|
||||
if (checkFaces.Count != 1 && _DistancePixelDistanceTolerance > 0)
|
||||
{
|
||||
checkFaces.Clear();
|
||||
checkFaces.AddRange(GetMatchingFaces(_DistancePixelDistanceTolerance, faces));
|
||||
}
|
||||
if (!checkFaces.Any() && faces.Count == 1)
|
||||
checkFaces.AddRange(faces);
|
||||
if (!checkFaces.Any())
|
||||
{
|
||||
result++;
|
||||
if (_DistanceMoveUnableToMatch)
|
||||
MoveUnableToMatch(eDistanceContentDirectory, mappedFaceFile);
|
||||
continue;
|
||||
}
|
||||
if (checkFaces.Count != 1)
|
||||
{
|
||||
result++;
|
||||
if (_DistanceMoveUnableToMatch)
|
||||
MoveUnableToMatch(eDistanceContentDirectory, mappedFaceFile);
|
||||
continue;
|
||||
}
|
||||
normalizedPixelPercentages.Add(normalizedPixelPercentage.Value);
|
||||
fileInfo = CheckFileThenGetFileInfo(facesFileNameExtension, item, mappedFaceDirectory, mappedFaceFile, checkFaces);
|
||||
if (fileInfo is null)
|
||||
continue;
|
||||
File.Move(mappedFaceFile, fileInfo.FullName);
|
||||
renamed++;
|
||||
}
|
||||
if (duplicateMappedFaceFiles.Any())
|
||||
{
|
||||
lock (duplicateMappedFaceFilesCollection)
|
||||
duplicateMappedFaceFilesCollection.Add(duplicateMappedFaceFiles.ToArray());
|
||||
}
|
||||
return new(result, renamed);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user