Re-Write without checking mapped

This commit is contained in:
Mike Phares 2022-09-14 19:00:57 -07:00
parent 73de1070b8
commit ad28ab2d38
70 changed files with 1596 additions and 2342 deletions

View File

@ -18,9 +18,13 @@
"Greyscale", "Greyscale",
"jfif", "jfif",
"mmod", "mmod",
"Nicéphore",
"Niépce",
"nosj", "nosj",
"paramref", "paramref",
"permyriad",
"Phares", "Phares",
"Phgtv",
"RDHC", "RDHC",
"Rects", "Rects",
"resnet", "resnet",

View File

@ -413,22 +413,28 @@ public class FaceRecognition : DisposableObject
return null; return null;
} }
public static List<double> FaceDistances(IEnumerable<FaceEncoding> faceEncodings, FaceEncoding faceToCompare) public static List<FaceDistance> FaceDistances(List<FaceDistance> faceDistances, FaceDistance faceDistanceToCompare)
{ {
List<double>? results = new(); List<FaceDistance> results = new();
if (faceEncodings is null) if (faceDistances is null)
throw new NullReferenceException(nameof(faceEncodings)); throw new NullReferenceException(nameof(faceDistances));
if (faceToCompare is null) if (faceDistances.Count != 0)
throw new NullReferenceException(nameof(faceToCompare)); {
faceToCompare.ThrowIfDisposed(); double length;
FaceEncoding[] array = faceEncodings.ToArray(); FaceDistance result;
if (array.Any(encoding => encoding.IsDisposed)) if (faceDistanceToCompare is null || faceDistanceToCompare.Encoding is not FaceEncoding faceEncodingToCompare)
throw new ObjectDisposedException($"{nameof(faceEncodings)} contains disposed object."); throw new NullReferenceException(nameof(faceDistanceToCompare));
if (array.Length == 0) faceEncodingToCompare.ThrowIfDisposed();
return results; foreach (FaceDistance faceDistance in faceDistances)
foreach (FaceEncoding faceEncoding in array) {
using (Matrix<double> diff = faceEncoding.Encoding - faceToCompare.Encoding) if (faceDistance.Encoding is not FaceEncoding faceEncoding || faceEncoding.IsDisposed)
results.Add(DlibDotNet.Dlib.Length(diff)); throw new ObjectDisposedException($"{nameof(faceDistances)} contains disposed object.");
using (Matrix<double> diff = faceEncoding.Encoding - faceEncodingToCompare.Encoding)
length = DlibDotNet.Dlib.Length(diff);
result = new(faceDistance, length);
results.Add(result);
}
}
return results; return results;
} }

View File

@ -26,7 +26,6 @@ public partial class DlibDotNet
private readonly A2_People _People; private readonly A2_People _People;
private readonly E3_Rename _Rename; private readonly E3_Rename _Rename;
private readonly B_Metadata _Metadata; private readonly B_Metadata _Metadata;
private readonly E_Distance _Distance;
private readonly Serilog.ILogger? _Log; private readonly Serilog.ILogger? _Log;
private readonly D2_FaceParts _FaceParts; private readonly D2_FaceParts _FaceParts;
private readonly AppSettings _AppSettings; private readonly AppSettings _AppSettings;
@ -58,7 +57,6 @@ public partial class DlibDotNet
_Random = new F_Random(configuration); _Random = new F_Random(configuration);
_People = new A2_People(configuration); _People = new A2_People(configuration);
_Rename = new E3_Rename(configuration); _Rename = new E3_Rename(configuration);
_Distance = new E_Distance(configuration);
if (configuration.IgnoreExtensions is null) if (configuration.IgnoreExtensions is null)
throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); throw new NullReferenceException(nameof(configuration.IgnoreExtensions));
string propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(propertyConfiguration, nameof(A_Property), create: false); string propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(propertyConfiguration, nameof(A_Property), create: false);
@ -115,14 +113,6 @@ public partial class DlibDotNet
_Log.Information(message); _Log.Information(message);
if (_Exceptions.Count != 0) if (_Exceptions.Count != 0)
throw new Exception(message); throw new Exception(message);
if (!_FirstRun && configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions.Any())
{
long ticks = DateTime.Now.Ticks;
foreach (string outputResolution in configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions)
_Distance.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions(propertyConfiguration, model, predictorModel, outputResolution);
if (appSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(E_Distance.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions));
}
if (_FirstRun) if (_FirstRun)
_Log.Information("First run completed. Run again if wanted"); _Log.Information("First run completed. Run again if wanted");
} }
@ -210,8 +200,6 @@ public partial class DlibDotNet
throw new NullReferenceException($"{nameof(configuration.OutputResolutions)} must be a valid outputResolution!"); throw new NullReferenceException($"{nameof(configuration.OutputResolutions)} must be a valid outputResolution!");
if ((from l in configuration.OutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any()) if ((from l in configuration.OutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any())
throw new Exception($"One or more {nameof(configuration.OutputResolutions)} are not in the ValidResolutions list!"); throw new Exception($"One or more {nameof(configuration.OutputResolutions)} are not in the ValidResolutions list!");
if ((from l in configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any())
throw new Exception($"One or more {nameof(configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions)} are not in the ValidResolutions list!");
if ((from l in configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any()) if ((from l in configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any())
throw new Exception($"One or more {nameof(configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions)} are not in the ValidResolutions list!"); throw new Exception($"One or more {nameof(configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions)} are not in the ValidResolutions list!");
if ((from l in configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any()) if ((from l in configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any())
@ -262,14 +250,14 @@ public partial class DlibDotNet
throw new Exception("Input directory should be the source and not a resized directory!"); throw new Exception("Input directory should be the source and not a resized directory!");
} }
private void FullParallelForWork(A_Property propertyLogic, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, string eResultsFullGroupDirectory, List<Tuple<string, DateTime>> sourceDirectoryChanges, List<FileHolder?> propertyFileHolderCollection, List<Shared.Models.Property?> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollections, List<Dictionary<string, int[]>> resizeKeyValuePairs, List<List<Face>?> imageFaceCollections, List<bool> faceEncodingRequired, Container container, int index, Item item) private void FullParallelForWork(A_Property propertyLogic, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, List<Tuple<string, DateTime>> sourceDirectoryChanges, List<FileHolder?> propertyFileHolderCollection, List<Shared.Models.Property?> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollections, List<Dictionary<string, int[]>> resizeKeyValuePairs, List<List<Face>?> imageFaceCollections, Container container, int index, Item item)
{ {
if (item.ImageFileHolder is null) if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder)); throw new NullReferenceException(nameof(item.ImageFileHolder));
Shared.Models.Property property;
List<Face>? faceCollection; List<Face>? faceCollection;
string original = "Original"; string original = "Original";
FileHolder? resizedFileHolder; FileHolder? resizedFileHolder;
Shared.Models.Property property;
long ticks = DateTime.Now.Ticks; long ticks = DateTime.Now.Ticks;
DateTime dateTime = DateTime.Now; DateTime dateTime = DateTime.Now;
List<string> parseExceptions = new(); List<string> parseExceptions = new();
@ -332,12 +320,12 @@ public partial class DlibDotNet
{ {
bool saveRotated = _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution); bool saveRotated = _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution);
_FaceParts.SaveFaceLandmarkImages(d2ResultsFullGroupDirectory, container, subFileTuples, parseExceptions, item, faceCollection, saveRotated); string sourceDirectorySegment = Property.Models.Stateless.IResult.GetRelativePath(_Configuration.PropertyConfiguration, container.SourceDirectory);
string facesDirectory = Path.GetFullPath(Path.Combine($"{Path.Combine(d2ResultsFullGroupDirectory, "()")}{sourceDirectorySegment}", item.ImageFileHolder.NameWithoutExtension));
_FaceParts.SaveFaceLandmarkImages(facesDirectory, subFileTuples, parseExceptions, item, faceCollection, saveRotated);
if (_AppSettings.MaxDegreeOfParallelism < 2) if (_AppSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(D2_FaceParts.SaveFaceLandmarkImages)); ticks = LogDelta(ticks, nameof(D2_FaceParts.SaveFaceLandmarkImages));
} }
if (_Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution))
_Distance.GetFaceDistances(eResultsFullGroupDirectory, faceEncodingRequired, subFileTuples, parseExceptions, item, faceCollection);
} }
lock (sourceDirectoryChanges) lock (sourceDirectoryChanges)
{ {
@ -350,11 +338,11 @@ public partial class DlibDotNet
} }
} }
private int FullParallelWork(long ticks, A_Property propertyLogic, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, string eResultsFullGroupDirectory, List<Tuple<string, DateTime>> sourceDirectoryChanges, List<FileHolder?> propertyFileHolderCollection, List<Shared.Models.Property?> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollection, List<Dictionary<string, int[]>> resizeKeyValuePairs, List<List<Face>?> imageFaceCollections, List<bool> faceEncodingRequired, int containersCount, Container container, Item[] filteredItems) private int FullParallelWork(long ticks, A_Property propertyLogic, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, List<Tuple<string, DateTime>> sourceDirectoryChanges, List<FileHolder?> propertyFileHolderCollection, List<Shared.Models.Property?> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollection, List<Dictionary<string, int[]>> resizeKeyValuePairs, List<List<Face>?> imageFaceCollections, int containersCount, Container container, Item[] filteredItems)
{ {
int result = 0;
if (_Log is null) if (_Log is null)
throw new NullReferenceException(nameof(_Log)); throw new NullReferenceException(nameof(_Log));
int result = 0;
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism }; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism };
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
if (imageFaceCollections.Count != filteredItems.Length || metadataCollection.Count != filteredItems.Length || resizeKeyValuePairs.Count != filteredItems.Length || propertyCollection.Count != filteredItems.Length) if (imageFaceCollections.Count != filteredItems.Length || metadataCollection.Count != filteredItems.Length || resizeKeyValuePairs.Count != filteredItems.Length || propertyCollection.Count != filteredItems.Length)
@ -370,25 +358,23 @@ public partial class DlibDotNet
} }
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
string message = $"{container.R:000}.{container.G} / {containersCount:000}) {filteredItems.Length:000} file(s) - {totalSeconds} total second(s) - {outputResolution} - {container.SourceDirectory}"; string message = $"{container.R:000}.{container.G} / {containersCount:000}) {filteredItems.Length:000} file(s) - {totalSeconds} total second(s) - {outputResolution} - {container.SourceDirectory}";
using (ProgressBar progressBar = new(filteredItems.Length, message, options)) using ProgressBar progressBar = new(filteredItems.Length, message, options);
{ _ = Parallel.For(0, filteredItems.Length, parallelOptions, (i, state) =>
_ = Parallel.For(0, filteredItems.Length, parallelOptions, (i, state) => {
try
{ {
try FullParallelForWork(propertyLogic, outputResolution, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, sourceDirectoryChanges, propertyFileHolderCollection, propertyCollection, metadataCollection, resizeKeyValuePairs, imageFaceCollections, container, index: i, filteredItems[i]);
{ if (i == 0 || sourceDirectoryChanges.Any())
FullParallelForWork(propertyLogic, outputResolution, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory, sourceDirectoryChanges, propertyFileHolderCollection, propertyCollection, metadataCollection, resizeKeyValuePairs, imageFaceCollections, faceEncodingRequired, container, index: i, filteredItems[i]); progressBar.Tick();
if (i == 0 || sourceDirectoryChanges.Any()) }
progressBar.Tick(); catch (Exception ex)
} {
catch (Exception ex) result += 1;
{ _Log.Error(string.Concat(container.SourceDirectory, Environment.NewLine, ex.Message, Environment.NewLine, ex.StackTrace), ex);
result += 1; if (result == filteredItems.Length)
_Log.Error(string.Concat(container.SourceDirectory, Environment.NewLine, ex.Message, Environment.NewLine, ex.StackTrace), ex); throw new Exception(string.Concat("All in [", container.SourceDirectory, "] failed!"));
if (result == filteredItems.Length) }
throw new Exception(string.Concat("All in [", container.SourceDirectory, "] failed!")); });
}
});
}
return result; return result;
} }
@ -524,188 +510,64 @@ public partial class DlibDotNet
return new(aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory); return new(aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory);
} }
private void SetAngleBracketCollections(Property.Models.Configuration configuration, A_Property propertyLogic, string outputResolution, Container container, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string eResultsFullGroupDirectory, bool onlyE) private void SetAngleBracketCollections(Property.Models.Configuration configuration, A_Property propertyLogic, string outputResolution, Container container, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, string eResultsFullGroupDirectory)
{ {
_Faces.AngleBracketCollection.Clear(); _Faces.AngleBracketCollection.Clear();
_Resize.AngleBracketCollection.Clear(); _Resize.AngleBracketCollection.Clear();
_Metadata.AngleBracketCollection.Clear(); _Metadata.AngleBracketCollection.Clear();
_Distance.AngleBracketCollection.Clear();
propertyLogic.AngleBracketCollection.Clear(); propertyLogic.AngleBracketCollection.Clear();
if (!onlyE) propertyLogic.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration,
{ container.SourceDirectory,
propertyLogic.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, aResultsFullGroupDirectory,
contentDescription: string.Empty,
singletonDescription: "Properties for each image",
collectionDescription: string.Empty,
converted: false));
_Metadata.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration,
container.SourceDirectory,
bResultsFullGroupDirectory,
contentDescription: string.Empty,
singletonDescription: "Metadata as key value pairs",
collectionDescription: string.Empty,
converted: true));
_Resize.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration,
container.SourceDirectory,
cResultsFullGroupDirectory,
contentDescription: "Resized image",
singletonDescription: "Resize dimensions for each resolution",
collectionDescription: string.Empty,
converted: true));
if (_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution))
_Faces.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration,
container.SourceDirectory, container.SourceDirectory,
aResultsFullGroupDirectory, dResultsFullGroupDirectory,
contentDescription: string.Empty, contentDescription: "n png file(s) for each face found",
singletonDescription: "Properties for each image", singletonDescription: string.Empty,
collectionDescription: string.Empty, collectionDescription: "For each image a json file with all faces found",
converted: false));
_Metadata.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration,
container.SourceDirectory,
bResultsFullGroupDirectory,
contentDescription: string.Empty,
singletonDescription: "Metadata as key value pairs",
collectionDescription: string.Empty,
converted: true)); converted: true));
_Resize.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution))
_ = Property.Models.Stateless.IResult.GetDirectoryInfoCollection(
_Configuration.PropertyConfiguration,
container.SourceDirectory, container.SourceDirectory,
cResultsFullGroupDirectory, d2ResultsFullGroupDirectory,
contentDescription: "Resized image", contentDescription: "n x 2 gif file(s) for each face found",
singletonDescription: "Resize dimensions for each resolution", singletonDescription: string.Empty,
collectionDescription: string.Empty, collectionDescription: string.Empty,
converted: true)); converted: false);
if (_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution))
_Faces.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration,
container.SourceDirectory,
dResultsFullGroupDirectory,
contentDescription: "n png file(s) for each face found",
singletonDescription: string.Empty,
collectionDescription: "For each image a json file with all faces found",
converted: true));
}
if (_Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)) if (_Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution))
_Distance.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, _ = Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration,
container.SourceDirectory, container.SourceDirectory,
eResultsFullGroupDirectory, eResultsFullGroupDirectory,
contentDescription: string.Empty, contentDescription: string.Empty,
singletonDescription: "n json file(s) for each face found", singletonDescription: "n json file(s) for each face found",
collectionDescription: string.Empty, collectionDescription: string.Empty,
converted: true)); converted: true);
}
private (Sorting Sorting, FaceRecognitionDotNet.FaceEncoding FaceEncoding)[] GetValues(string argZero, Container[] containers)
{
(Sorting Sorting, FaceRecognitionDotNet.FaceEncoding FaceEncoding)[] results;
Sorting sorting;
Item[] filteredItems;
List<(Sorting Sorting, FaceRecognitionDotNet.FaceEncoding FaceEncoding)> collection = new();
foreach (Container container in containers)
{
if (!container.Items.Any())
continue;
if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
continue;
filteredItems = (from l in container.Items where l.ImageFileHolder is not null && (l.Abandoned is null || !l.Abandoned.Value) && l.ValidImageFormatExtension && !_Configuration.IgnoreExtensions.Contains(l.ImageFileHolder.ExtensionLowered) select l).ToArray();
if (!filteredItems.Any())
continue;
foreach (Item item in filteredItems)
{
if (item.Property?.Id is null || item.ImageFileHolder is null || item.ResizedFileHolder is null)
continue;
if (!item.Faces.Any())
continue;
foreach (Face face in item.Faces)
{
if (face.FaceEncoding is null || face.Location?.Confidence is null || face.Location?.NormalizedPixelPercentage is null)
continue;
if (!face.Tags.Any() || face.Tags[0] is not FaceRecognitionDotNet.FaceEncoding faceEncoding)
continue;
sorting = new(face.Location.Confidence, item.Property.Id.Value, face.Location.NormalizedPixelPercentage.Value);
collection.Add(new(sorting, faceEncoding));
face.Tags.Clear();
}
}
}
results = (from l in collection orderby l.FaceEncoding is not null, l.Sorting.Id select l).ToArray();
if (results.Any() && results[0].FaceEncoding is null)
throw new Exception("Sorting failed!");
return results;
}
private void SaveFaceNumbers(string eResultsFullGroupDirectory, Item item, (Sorting Sorting, FaceRecognitionDotNet.FaceEncoding FaceEncoding)[] inputCollection, List<FaceRecognitionDotNet.FaceEncoding> faceEncodings)
{
Sorting sorting;
List<double> doubles;
List<int[]> faceNumbers;
List<Sorting> sortingOutputCollection;
FaceRecognitionDotNet.FaceEncoding faceEncoding;
if (item.Property?.Id is null || item.ImageFileHolder is null || item.ResizedFileHolder is null)
throw new Exception();
foreach (Face face in item.Faces)
{
if (face.FaceEncoding is null || face.Location?.Confidence is null || face.Location?.NormalizedPixelPercentage is null)
continue;
sortingOutputCollection = new();
faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
doubles = FaceRecognition.FaceDistances(faceEncodings, faceEncoding);
for (int j = 0; j < doubles.Count; j++)
{
sorting = new(inputCollection[j].Sorting, doubles[j]);
lock (sortingOutputCollection)
sortingOutputCollection.Add(sorting);
}
faceNumbers = Shared.Models.Stateless.Methods.ISorting.GetFaceNumbers(sortingOutputCollection);
lock (face)
face.SetFaceNumbers(faceNumbers);
_Distance.SaveFaceNumbers(eResultsFullGroupDirectory, item, face, faceNumbers);
}
}
private void SaveFaceNumbers(string argZero, A_Property propertyLogic, string outputResolution, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string eResultsFullGroupDirectory, Container[] containers, (Sorting Sorting, FaceRecognitionDotNet.FaceEncoding FaceEncoding)[] collection)
{
if (collection.Any() && collection[0].FaceEncoding is null)
throw new Exception("Sorting failed!");
Item[] filteredItems;
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism };
foreach (Container container in containers)
{
if (!container.Items.Any())
continue;
if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
continue;
filteredItems = (from l in container.Items where l.ImageFileHolder is not null && (l.Abandoned is null || !l.Abandoned.Value) && l.ValidImageFormatExtension && !_Configuration.IgnoreExtensions.Contains(l.ImageFileHolder.ExtensionLowered) select l).ToArray();
if (!filteredItems.Any())
continue;
List<FaceRecognitionDotNet.FaceEncoding> faceEncodings = new();
foreach ((Sorting _, FaceRecognitionDotNet.FaceEncoding faceEncoding) in collection)
{
if (faceEncoding is null)
continue;
faceEncodings.Add(faceEncoding);
}
SetAngleBracketCollections(_Configuration.PropertyConfiguration, propertyLogic, outputResolution, container, aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, eResultsFullGroupDirectory, onlyE: true);
_ = Parallel.For(0, filteredItems.Length, parallelOptions, (i, state) => SaveFaceNumbers(eResultsFullGroupDirectory, filteredItems[i], collection, faceEncodings));
}
}
private static void SetFaceTags(Item item)
{
FaceRecognitionDotNet.FaceEncoding faceEncoding;
foreach (Face face in item.Faces)
{
if (face.FaceEncoding is null || face.Location?.Confidence is null || face.Location?.NormalizedPixelPercentage is null)
continue;
faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
lock (face.Tags)
face.Tags.Add(faceEncoding);
}
}
private void SetFaceTags(string argZero, List<bool> faceEncodingRequired, Container[] containers)
{
Item[] filteredItems;
faceEncodingRequired.Clear();
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism };
foreach (Container container in containers)
{
if (!container.Items.Any())
continue;
if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
continue;
filteredItems = (from l in container.Items where l.ImageFileHolder is not null && (l.Abandoned is null || !l.Abandoned.Value) && l.ValidImageFormatExtension && !_Configuration.IgnoreExtensions.Contains(l.ImageFileHolder.ExtensionLowered) select l).ToArray();
if (!filteredItems.Any())
continue;
_ = Parallel.For(0, filteredItems.Length, parallelOptions, (i, state) => SetFaceTags(filteredItems[i]));
}
} }
private void FullDoWork(string argZero, Model? model, PredictorModel? predictorModel, string propertyRoot, long ticks, MapLogic mapLogic, A_Property propertyLogic, Container[] containers) private void FullDoWork(string argZero, Model? model, PredictorModel? predictorModel, string propertyRoot, long ticks, MapLogic mapLogic, A_Property propertyLogic, Container[] containers)
{ {
if (_Log is null) if (_Log is null)
throw new NullReferenceException(nameof(_Log)); throw new NullReferenceException(nameof(_Log));
int[] ids;
bool needToSave;
int distinctCount;
int exceptionCount; int exceptionCount;
Item[] filteredItems; Item[] filteredItems;
string aResultsFullGroupDirectory; string aResultsFullGroupDirectory;
@ -714,7 +576,6 @@ public partial class DlibDotNet
string dResultsFullGroupDirectory; string dResultsFullGroupDirectory;
string eResultsFullGroupDirectory; string eResultsFullGroupDirectory;
string d2ResultsFullGroupDirectory; string d2ResultsFullGroupDirectory;
List<bool> faceEncodingRequired = new();
Shared.Models.Property[] propertyCollection; Shared.Models.Property[] propertyCollection;
List<List<Face>?> imageFaceCollections = new(); List<List<Face>?> imageFaceCollections = new();
List<FileHolder?> propertyFileHolderCollection = new(); List<FileHolder?> propertyFileHolderCollection = new();
@ -726,7 +587,6 @@ public partial class DlibDotNet
foreach (string outputResolution in _Configuration.OutputResolutions) foreach (string outputResolution in _Configuration.OutputResolutions)
{ {
_FileKeyValuePairs.Clear(); _FileKeyValuePairs.Clear();
faceEncodingRequired.Clear();
_FilePropertiesKeyValuePairs.Clear(); _FilePropertiesKeyValuePairs.Clear();
(aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory) = GetResultsFullGroupDirectories(_Configuration.PropertyConfiguration, model, predictorModel, outputResolution); (aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory) = GetResultsFullGroupDirectories(_Configuration.PropertyConfiguration, model, predictorModel, outputResolution);
foreach (Container container in containers) foreach (Container container in containers)
@ -744,14 +604,8 @@ public partial class DlibDotNet
sourceDirectoryChanges.Clear(); sourceDirectoryChanges.Clear();
nullablePropertyCollection.Clear(); nullablePropertyCollection.Clear();
propertyFileHolderCollection.Clear(); propertyFileHolderCollection.Clear();
SetAngleBracketCollections(_Configuration.PropertyConfiguration, propertyLogic, outputResolution, container, aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, eResultsFullGroupDirectory, onlyE: false); SetAngleBracketCollections(_Configuration.PropertyConfiguration, propertyLogic, outputResolution, container, aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory);
exceptionCount = FullParallelWork(ticks, propertyLogic, outputResolution, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory, sourceDirectoryChanges, propertyFileHolderCollection, nullablePropertyCollection, metadataCollection, resizeKeyValuePairs, imageFaceCollections, faceEncodingRequired, containers.Length, container, filteredItems); exceptionCount = FullParallelWork(ticks, propertyLogic, outputResolution, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, sourceDirectoryChanges, propertyFileHolderCollection, nullablePropertyCollection, metadataCollection, resizeKeyValuePairs, imageFaceCollections, containers.Length, container, filteredItems);
#pragma warning disable
ids = (from l in filteredItems where l.Property?.Id is not null select l.Property.Id.Value).ToArray();
#pragma warning restore
distinctCount = ids.Distinct().Count();
if (ids.Length != distinctCount)
_Log.Information($"{ids.Length} != {distinctCount} <{container.SourceDirectory}>");
if (metadataCollection.Count != filteredItems.Length || nullablePropertyCollection.Count != filteredItems.Length || resizeKeyValuePairs.Count != filteredItems.Length || imageFaceCollections.Count != filteredItems.Length) if (metadataCollection.Count != filteredItems.Length || nullablePropertyCollection.Count != filteredItems.Length || resizeKeyValuePairs.Count != filteredItems.Length || imageFaceCollections.Count != filteredItems.Length)
throw new Exception("Counts don't match!"); throw new Exception("Counts don't match!");
if (exceptionCount != 0) if (exceptionCount != 0)
@ -761,8 +615,6 @@ public partial class DlibDotNet
propertyCollection = (from l in nullablePropertyCollection where l is not null select l).ToArray(); propertyCollection = (from l in nullablePropertyCollection where l is not null select l).ToArray();
if (_ArgZeroIsConfigurationRootDirectory && exceptionCount == 0) if (_ArgZeroIsConfigurationRootDirectory && exceptionCount == 0)
WriteGroup(_Configuration.PropertyConfiguration, propertyLogic, propertyCollection, metadataCollection, resizeKeyValuePairs, imageFaceCollections, outputResolution, container, filteredItems); WriteGroup(_Configuration.PropertyConfiguration, propertyLogic, propertyCollection, metadataCollection, resizeKeyValuePairs, imageFaceCollections, outputResolution, container, filteredItems);
if (false && exceptionCount == 0 && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution))
_Distance.LoadOrCreateThenSaveDistanceResults(_Configuration.PropertyConfiguration, eResultsFullGroupDirectory, outputResolution, container, sourceDirectoryChanges, filteredItems);
if (Directory.GetFiles(propertyRoot, "*.txt", SearchOption.TopDirectoryOnly).Any()) if (Directory.GetFiles(propertyRoot, "*.txt", SearchOption.TopDirectoryOnly).Any())
{ {
for (int y = 0; y < int.MaxValue; y++) for (int y = 0; y < int.MaxValue; y++)
@ -786,79 +638,9 @@ public partial class DlibDotNet
// if (isSilent && container.SourceDirectory.EndsWith("Texas 2015")) //46#.4 // if (isSilent && container.SourceDirectory.EndsWith("Texas 2015")) //46#.4
// break; // break;
} }
if (_Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution))
{
needToSave = faceEncodingRequired.Any();
if (needToSave)
SetFaceTags(argZero, faceEncodingRequired, containers);
if (faceEncodingRequired.Any())
throw new Exception("Why!");
if (needToSave)
{
(Sorting Sorting, FaceRecognitionDotNet.FaceEncoding FaceEncoding)[] collection = GetValues(argZero, containers);
SaveFaceNumbers(argZero, propertyLogic, outputResolution, aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, eResultsFullGroupDirectory, containers, collection);
}
}
} }
} }
private static List<(string, int, Mapping, DateTime, bool?, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>)> Convert(Dictionary<string, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>> keyValuePairs)
{
List<(string, int, Mapping, DateTime, bool?, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>)> results = new();
MappingContainer mc;
foreach (KeyValuePair<string, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>> keyValuePair in keyValuePairs)
{
foreach ((FaceRecognitionDotNet.FaceEncoding _, MappingContainer mappingContainer) in keyValuePair.Value)
{
mc = mappingContainer;
results.Add(new(mc.Key, mc.Id, mc.Mapping, mc.MinimumDateTime, mc.IsWrongYear, keyValuePair.Value));
}
}
return results;
}
private static Dictionary<int, List<MappingContainer>> Strip(Dictionary<string, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>> keyValuePairs)
{
Dictionary<int, List<MappingContainer>> results = new();
foreach (KeyValuePair<string, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>> keyValuePair in keyValuePairs)
{
foreach ((FaceRecognitionDotNet.FaceEncoding _, MappingContainer mappingContainer) in keyValuePair.Value)
{
if (!results.ContainsKey(mappingContainer.Id))
results.Add(mappingContainer.Id, new());
results[mappingContainer.Id].Add(mappingContainer);
}
}
return results;
}
private void MapLogic(long ticks, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, MapLogic mapLogic, string outputResolution, Item[] items, int totalNotMapped)
{
mapLogic.UseKeyValuePairsSaveFaceEncoding(items);
if (_Configuration.SaveResizedSubfiles)
{
string dFacesContentDirectory;
dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, "()");
mapLogic.SaveNotMappedTicks();
_ = LogDeltaInMinutes(ticks, nameof(mapLogic.SaveNotMappedTicks));
Dictionary<string, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>> keyValuePairs = _Distance.ParallelWork(_AppSettings.MaxDegreeOfParallelism, ticks, mapLogic, items, totalNotMapped);
_ = LogDeltaInSeconds(ticks, nameof(E_Distance.ParallelWork));
Dictionary<int, List<MappingContainer>> strippedKeyValuePairs = Strip(keyValuePairs);
List<(string, int, Mapping, DateTime, bool?, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>)> collection = Convert(keyValuePairs);
mapLogic.SaveMapping(items, dFacesContentDirectory, d2ResultsFullGroupDirectory);
_ = LogDeltaInMinutes(ticks, nameof(mapLogic.SaveMapping));
E_Distance.AddToFaceDistance(_AppSettings.MaxDegreeOfParallelism, mapLogic, items, collection);
_ = LogDeltaInSeconds(ticks, nameof(_Distance.AddToFaceDistance));
mapLogic.AddToClosest(_AppSettings.MaxDegreeOfParallelism, items);
_ = LogDeltaInMinutes(ticks, nameof(mapLogic.AddToClosest));
mapLogic.SaveClosest(items, dFacesContentDirectory, d2ResultsFullGroupDirectory);
_ = LogDeltaInMinutes(ticks, nameof(mapLogic.SaveClosest));
mapLogic.SavePropertyHolders(items);
_ = LogDeltaInSeconds(ticks, nameof(mapLogic.SavePropertyHolders));
}
_ = LogDeltaInSeconds(ticks, nameof(MapLogic));
}
private string GetMapLogicResultsFullGroupDirectory(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel) private string GetMapLogicResultsFullGroupDirectory(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel)
{ {
const int zero = 0; const int zero = 0;
@ -868,6 +650,79 @@ public partial class DlibDotNet
return zResultsFullGroupDirectory; return zResultsFullGroupDirectory;
} }
private List<Face> SetMappingThenGetDistinctFilteredFacesWithMapping(string argZero, Container[] containers)
{
List<Face> results = new();
Mapping mapping;
bool? isWrongYear;
Item[] filteredItems;
DateTime minimumDateTime;
List<int> distinctCheck = new();
string deterministicHashCodeKeyDisplay;
MappingFromItem mappingFromItem;
MappingFromPerson mappingFromPerson;
MappingFromLocation mappingFromLocation;
foreach (Container container in containers)
{
if (!container.Items.Any())
continue;
if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
continue;
filteredItems = (from l in container.Items where l.ImageFileHolder is not null && (l.Abandoned is null || !l.Abandoned.Value) && l.ValidImageFormatExtension && !_Configuration.IgnoreExtensions.Contains(l.ImageFileHolder.ExtensionLowered) select l).ToArray();
if (!filteredItems.Any())
continue;
foreach (Item item in filteredItems)
{
if (item.Property?.Id is null || item.ImageFileHolder is null || item.ResizedFileHolder is null)
continue;
if (!item.Faces.Any())
continue;
foreach (Face face in item.Faces)
{
if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
continue;
if (distinctCheck.Contains(item.Property.Id.Value))
continue;
minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
(isWrongYear, _) = item.Property.IsWrongYear(item.ImageFileHolder.FullName, minimumDateTime);
mappingFromItem = new(item.Property.Id.Value, item.ImageFileHolder, isWrongYear, minimumDateTime, item.ResizedFileHolder);
mappingFromPerson = new(approximateYears: null, by: null, displayDirectoryName: string.Empty, personBirthday: null, segmentB: string.Empty);
deterministicHashCodeKeyDisplay = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKeyDisplay(item.Property.Id.Value, face.Location.NormalizedPixelPercentage.Value);
mappingFromLocation = new(face.Location.Confidence, deterministicHashCodeKeyDisplay, face.Location.NormalizedPixelPercentage.Value);
mapping = new(mappingFromItem, mappingFromLocation, mappingFromPerson);
face.SetMapping(mapping);
results.Add(face);
}
}
}
return results;
}
private Item[] GetIdSortedFilteredItems(string argZero, Container[] containers)
{
Item[] results;
List<Item> collection = new();
foreach (Container container in containers)
{
if (!container.Items.Any())
continue;
if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
continue;
collection.AddRange(from l in container.Items where l.ImageFileHolder is not null && (l.Abandoned is null || !l.Abandoned.Value) && l.ValidImageFormatExtension && !_Configuration.IgnoreExtensions.Contains(l.ImageFileHolder.ExtensionLowered) select l);
}
results = (from l in collection orderby l.Property?.Id is not null, l.Property?.Id select l).ToArray();
return results;
}
private void OldMapLogic(long ticks, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, MapLogic mapLogic, string outputResolution, Item[] filteredItems)
{
string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, "()");
if (_Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution))
mapLogic.SaveShortcuts(_Configuration.JuliePhares, filteredItems);
mapLogic.SavePropertyHolders(filteredItems);
_ = LogDeltaInSeconds(ticks, nameof(mapLogic.SavePropertyHolders));
}
private void Search(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string argZero, string propertyRoot, Person[] people) private void Search(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string argZero, string propertyRoot, Person[] people)
{ {
Container[] containers; Container[] containers;
@ -882,30 +737,36 @@ public partial class DlibDotNet
string peopleDateGroupDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A2_People)); string peopleDateGroupDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A2_People));
MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FilenameExtension, _Faces.FilenameExtension, _Faces.HiddenFilenameExtension, _FaceParts.FilenameExtension, ticks, people, peopleDateGroupDirectory, zResultsFullGroupDirectory); MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FilenameExtension, _Faces.FilenameExtension, _Faces.HiddenFilenameExtension, _FaceParts.FilenameExtension, ticks, people, peopleDateGroupDirectory, zResultsFullGroupDirectory);
A_Property propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FilenameExtension, _Configuration.Reverse, model, predictorModel, mapLogic.IndicesFromNew, mapLogic.KeyValuePairs); A_Property propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FilenameExtension, _Configuration.Reverse, model, predictorModel, mapLogic.IndicesFromNew, mapLogic.KeyValuePairs);
if (string.IsNullOrEmpty(configuration.RootDirectory)) int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
containers = A_Property.Get(configuration, propertyLogic); string message = $") Building Container(s) - {totalSeconds} total second(s)";
else ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
containers = Property.Models.Stateless.Container.GetContainers(configuration, _FirstRun, propertyLogic); using (ProgressBar progressBar = new(1, message, options))
{
if (string.IsNullOrEmpty(configuration.RootDirectory))
containers = A_Property.Get(configuration, propertyLogic);
else
containers = Property.Models.Stateless.Container.GetContainers(configuration, _FirstRun, propertyLogic);
}
FullDoWork(argZero, model, predictorModel, propertyRoot, ticks, mapLogic, propertyLogic, containers); FullDoWork(argZero, model, predictorModel, propertyRoot, ticks, mapLogic, propertyLogic, containers);
foreach (string outputResolution in _Configuration.OutputResolutions) foreach (string outputResolution in _Configuration.OutputResolutions)
{ {
if (_FirstRun) if (_FirstRun)
break; break;
(aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory) = GetResultsFullGroupDirectories(configuration, model, predictorModel, outputResolution); (aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory) = GetResultsFullGroupDirectories(configuration, model, predictorModel, outputResolution);
if (_ArgZeroIsConfigurationRootDirectory && _Exceptions.Count == 0 && outputResolution == _Configuration.OutputResolutions[0]) if (_ArgZeroIsConfigurationRootDirectory && _Configuration.SaveResizedSubfiles && outputResolution == _Configuration.OutputResolutions[0] && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution) && _Exceptions.Count == 0)
{ {
int totalNotMapped = 0; if (string.IsNullOrEmpty(eResultsFullGroupDirectory))
DateTime dateTime = new(ticks); throw new NullReferenceException(nameof(eResultsFullGroupDirectory));
List<(int Id, Item Item)> idAndItemCollection = new(); string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, "()");
foreach (Container container in containers) string eDistanceContentDirectory = Path.Combine(eResultsFullGroupDirectory, "([])");
{ if (!Directory.Exists(eDistanceContentDirectory))
totalNotMapped += mapLogic.AddToMapping(ticks, container.Items); _ = Directory.CreateDirectory(eDistanceContentDirectory);
Map.Models.MapLogic.AppendToItems(container.Items, idAndItemCollection); string eDistanceContentFileName = Path.Combine(eDistanceContentDirectory, $"{Property.Models.Stateless.IResult.AllInOne}.tvs");
if (_Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution)) List<Face> distinctFilteredFaces = SetMappingThenGetDistinctFilteredFacesWithMapping(argZero, containers);
mapLogic.SaveShortcuts(_Configuration.JuliePhares, container.Items); SortingContainer[] sortingContainers = E_Distance.SetPersonTicksAndSetFaceDistancesAndSetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, ticks, mapLogic, outputResolution, eDistanceContentFileName, distinctFilteredFaces);
} mapLogic.CommonWork(_AppSettings.MaxDegreeOfParallelism, dFacesContentDirectory, d2ResultsFullGroupDirectory, distinctFilteredFaces, sortingContainers);
Item[] items = (from l in idAndItemCollection orderby l.Id select l.Item).ToArray(); Item[] filteredItems = GetIdSortedFilteredItems(argZero, containers);
MapLogic(ticks, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, mapLogic, outputResolution, items, totalNotMapped); OldMapLogic(ticks, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, mapLogic, outputResolution, filteredItems);
if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Any()) if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Any())
break; break;
if (_FileKeyValuePairs.Any()) if (_FileKeyValuePairs.Any())
@ -926,8 +787,6 @@ public partial class DlibDotNet
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(dResultsFullGroupDirectory, "[]")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(dResultsFullGroupDirectory, "[]"));
if (_Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)) if (_Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution))
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(eResultsFullGroupDirectory, "[]")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(eResultsFullGroupDirectory, "[]"));
if (_Configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions.Contains(outputResolution))
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(eResultsFullGroupDirectory, "[]"));
if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution))
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(d2ResultsFullGroupDirectory, "[]")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(d2ResultsFullGroupDirectory, "[]"));
} }

View File

@ -19,7 +19,6 @@ public class Configuration
[Display(Name = "Ignore Extensions"), Required] public string[] IgnoreExtensions { get; set; } [Display(Name = "Ignore Extensions"), Required] public string[] IgnoreExtensions { get; set; }
[Display(Name = "Ignore Relative Paths"), Required] public string[] IgnoreRelativePaths { get; set; } [Display(Name = "Ignore Relative Paths"), Required] public string[] IgnoreRelativePaths { get; set; }
[Display(Name = "Julie Phares Copy Birthdays"), Required] public string[] JuliePhares { get; set; } [Display(Name = "Julie Phares Copy Birthdays"), Required] public string[] JuliePhares { get; set; }
[Display(Name = "Load Or Create Then Save Directory Distance Results"), Required] public string[] LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions { get; set; }
[Display(Name = "Load Or Create Then Save Distance Results"), Required] public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { get; set; } [Display(Name = "Load Or Create Then Save Distance Results"), Required] public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { get; set; }
[Display(Name = "Load Or Create Then Save Image Faces Results"), Required] public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; } [Display(Name = "Load Or Create Then Save Image Faces Results"), Required] public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; }
[Display(Name = "Load Or Create Then Save Index"), Required] public bool? LoadOrCreateThenSaveIndex { get; set; } [Display(Name = "Load Or Create Then Save Index"), Required] public bool? LoadOrCreateThenSaveIndex { get; set; }
@ -129,8 +128,6 @@ public class Configuration
throw new NullReferenceException(nameof(configuration.TestDistanceResults)); throw new NullReferenceException(nameof(configuration.TestDistanceResults));
if (configuration.ValidResolutions is null) if (configuration.ValidResolutions is null)
throw new NullReferenceException(nameof(configuration.ValidResolutions)); throw new NullReferenceException(nameof(configuration.ValidResolutions));
if (configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions is null)
configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions = Array.Empty<string>();
if (configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions is null) if (configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions is null)
configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions = Array.Empty<string>(); configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions = Array.Empty<string>();
if (configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions is null) if (configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions is null)
@ -149,7 +146,6 @@ public class Configuration
configuration.IgnoreExtensions, configuration.IgnoreExtensions,
configuration.IgnoreRelativePaths, configuration.IgnoreRelativePaths,
configuration.JuliePhares, configuration.JuliePhares,
configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions,
configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions, configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions,
configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions, configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions,
configuration.LoadOrCreateThenSaveIndex.Value, configuration.LoadOrCreateThenSaveIndex.Value,

View File

@ -18,7 +18,6 @@ public class Configuration
public string[] IgnoreExtensions { init; get; } public string[] IgnoreExtensions { init; get; }
public string[] IgnoreRelativePaths { init; get; } public string[] IgnoreRelativePaths { init; get; }
public string[] JuliePhares { init; get; } public string[] JuliePhares { init; get; }
public string[] LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions { init; get; }
public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { init; get; } public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { init; get; }
public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { init; get; } public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { init; get; }
public bool LoadOrCreateThenSaveIndex { init; get; } public bool LoadOrCreateThenSaveIndex { init; get; }
@ -53,7 +52,7 @@ public class Configuration
public string[] ValidResolutions { init; get; } public string[] ValidResolutions { init; get; }
[JsonConstructor] [JsonConstructor]
public Configuration(Property.Models.Configuration propertyConfiguration, bool checkJsonForDistanceResults, int crossDirectoryMaxItemsInDistanceCollection, int distanceFactor, bool forceFaceLastWriteTimeToCreationTime, bool forceMetadataLastWriteTimeToCreationTime, bool forceResizeLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRelativePaths, string[] juliePhares, string[] loadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions, bool loadOrCreateThenSaveIndex, int locationConfidenceFactor, int? mappedMaxIndex, int maxItemsInDistanceCollection, string[] mixedYearRelativePaths, string modelDirectory, string modelName, int numberOfJitters, int numberOfTimesToUpsample, string outputExtension, int outputQuality, string[] outputResolutions, bool overrideForFaceImages, bool overrideForFaceLandmarkImages, bool overrideForResizeImages, int paddingLoops, string predictorModelName, bool propertiesChangedForDistance, bool propertiesChangedForFaces, bool propertiesChangedForIndex, bool propertiesChangedForMetadata, bool propertiesChangedForResize, bool reverse, string[] saveFaceLandmarkForOutputResolutions, bool saveFullYearOfRandomFiles, bool saveResizedSubfiles, string[] saveShortcutsForOutputResolutions, bool skipSearch, bool testDistanceResults, string[] validResolutions) public Configuration(Property.Models.Configuration propertyConfiguration, bool checkJsonForDistanceResults, int crossDirectoryMaxItemsInDistanceCollection, int distanceFactor, bool forceFaceLastWriteTimeToCreationTime, bool forceMetadataLastWriteTimeToCreationTime, bool forceResizeLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRelativePaths, string[] juliePhares, string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions, bool loadOrCreateThenSaveIndex, int locationConfidenceFactor, int? mappedMaxIndex, int maxItemsInDistanceCollection, string[] mixedYearRelativePaths, string modelDirectory, string modelName, int numberOfJitters, int numberOfTimesToUpsample, string outputExtension, int outputQuality, string[] outputResolutions, bool overrideForFaceImages, bool overrideForFaceLandmarkImages, bool overrideForResizeImages, int paddingLoops, string predictorModelName, bool propertiesChangedForDistance, bool propertiesChangedForFaces, bool propertiesChangedForIndex, bool propertiesChangedForMetadata, bool propertiesChangedForResize, bool reverse, string[] saveFaceLandmarkForOutputResolutions, bool saveFullYearOfRandomFiles, bool saveResizedSubfiles, string[] saveShortcutsForOutputResolutions, bool skipSearch, bool testDistanceResults, string[] validResolutions)
{ {
_PropertyConfiguration = propertyConfiguration; _PropertyConfiguration = propertyConfiguration;
CheckJsonForDistanceResults = checkJsonForDistanceResults; CheckJsonForDistanceResults = checkJsonForDistanceResults;
@ -65,7 +64,6 @@ public class Configuration
IgnoreExtensions = ignoreExtensions; IgnoreExtensions = ignoreExtensions;
IgnoreRelativePaths = ignoreRelativePaths; IgnoreRelativePaths = ignoreRelativePaths;
JuliePhares = juliePhares; JuliePhares = juliePhares;
LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions = loadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions;
LoadOrCreateThenSaveDistanceResultsForOutputResolutions = loadOrCreateThenSaveDistanceResultsForOutputResolutions; LoadOrCreateThenSaveDistanceResultsForOutputResolutions = loadOrCreateThenSaveDistanceResultsForOutputResolutions;
LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = loadOrCreateThenSaveImageFacesResultsForOutputResolutions; LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = loadOrCreateThenSaveImageFacesResultsForOutputResolutions;
LoadOrCreateThenSaveIndex = loadOrCreateThenSaveIndex; LoadOrCreateThenSaveIndex = loadOrCreateThenSaveIndex;

View File

@ -118,7 +118,7 @@ internal class D2_FaceParts
#pragma warning restore CA1416 #pragma warning restore CA1416
internal void SaveFaceLandmarkImages(string d2ResultsFullGroupDirectory, Container container, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Item item, List<Face> faceCollection, bool saveRotated) internal void SaveFaceLandmarkImages(string facesDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Item item, List<Face> faceCollection, bool saveRotated)
{ {
if (item.ImageFileHolder is null) if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder)); throw new NullReferenceException(nameof(item.ImageFileHolder));
@ -130,33 +130,23 @@ internal class D2_FaceParts
const int pointSize = 2; const int pointSize = 2;
FileInfo rotatedFileInfo; FileInfo rotatedFileInfo;
DateTime? dateTime = null; DateTime? dateTime = null;
double deterministicHashCodeKey;
long ticks = DateTime.Now.Ticks; long ticks = DateTime.Now.Ticks;
bool updateDateWhenMatches = false; bool updateDateWhenMatches = false;
List<string> angleBracketCollection = new(); string deterministicHashCodeKeyDisplay;
List<(Face, string, string)> collection = new(); List<(Face, string, string)> collection = new();
angleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(
_Configuration.PropertyConfiguration,
container.SourceDirectory,
d2ResultsFullGroupDirectory,
contentDescription: "n x 2 gif file(s) for each face found",
singletonDescription: string.Empty,
collectionDescription: string.Empty,
converted: false));
string facesDirectory = Path.Combine(angleBracketCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension);
string[] changesFrom = new string[] { nameof(Property.Models.A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) }; string[] changesFrom = new string[] { nameof(Property.Models.A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) };
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
if (!Directory.Exists(facesDirectory)) if (!Directory.Exists(facesDirectory))
_ = Directory.CreateDirectory(facesDirectory); _ = Directory.CreateDirectory(facesDirectory);
foreach (Face face in faceCollection) foreach (Face face in faceCollection)
{ {
if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) if (item.Property?.Id is null || face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
{ {
collection.Add(new(face, string.Empty, string.Empty)); collection.Add(new(face, string.Empty, string.Empty));
continue; continue;
} }
deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item, face); deterministicHashCodeKeyDisplay = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKeyDisplay(item.Property.Id.Value, face.Location.NormalizedPixelPercentage.Value);
fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}{_FilenameExtension}")); fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKeyDisplay}{item.ImageFileHolder.ExtensionLowered}{_FilenameExtension}"));
if (!fileInfo.Exists) if (!fileInfo.Exists)
{ {
if (fileInfo.Directory?.Parent is null) if (fileInfo.Directory?.Parent is null)
@ -167,7 +157,7 @@ internal class D2_FaceParts
} }
if (string.IsNullOrEmpty(fileInfo.DirectoryName)) if (string.IsNullOrEmpty(fileInfo.DirectoryName))
continue; continue;
rotatedFileInfo = new FileInfo(Path.Combine(fileInfo.DirectoryName, $"{deterministicHashCodeKey} - R{item.ImageFileHolder.ExtensionLowered}{_FilenameExtension}")); rotatedFileInfo = new FileInfo(Path.Combine(fileInfo.DirectoryName, $"{deterministicHashCodeKeyDisplay} - R{item.ImageFileHolder.ExtensionLowered}{_FilenameExtension}"));
collection.Add(new(face, fileInfo.FullName, rotatedFileInfo.FullName)); collection.Add(new(face, fileInfo.FullName, rotatedFileInfo.FullName));
if (check) if (check)
continue; continue;

View File

@ -2,6 +2,7 @@ using System.Drawing;
using System.Drawing.Drawing2D; using System.Drawing.Drawing2D;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization;
using View_by_Distance.FaceRecognitionDotNet; using View_by_Distance.FaceRecognitionDotNet;
using View_by_Distance.Metadata.Models; using View_by_Distance.Metadata.Models;
using View_by_Distance.Property.Models; using View_by_Distance.Property.Models;
@ -35,7 +36,7 @@ public class D_Face
private readonly EncoderParameters _EncoderParameters; private readonly EncoderParameters _EncoderParameters;
private readonly ImageCodecInfo _HiddenImageCodecInfo; private readonly ImageCodecInfo _HiddenImageCodecInfo;
private readonly EncoderParameters _HiddenEncoderParameters; private readonly EncoderParameters _HiddenEncoderParameters;
private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions; private readonly JsonSerializerOptions _WriteIndentedAndWhenWritingNull;
internal D_Face(Configuration configuration, string argZero, Model model, ModelParameter modelParameter, PredictorModel predictorModel, ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension, ImageCodecInfo hiddenImageCodecInfo, EncoderParameters hiddenEncoderParameters, string hiddenFilenameExtension) internal D_Face(Configuration configuration, string argZero, Model model, ModelParameter modelParameter, PredictorModel predictorModel, ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension, ImageCodecInfo hiddenImageCodecInfo, EncoderParameters hiddenEncoderParameters, string hiddenFilenameExtension)
{ {
@ -52,7 +53,7 @@ public class D_Face
_HiddenImageCodecInfo = hiddenImageCodecInfo; _HiddenImageCodecInfo = hiddenImageCodecInfo;
_HiddenEncoderParameters = hiddenEncoderParameters; _HiddenEncoderParameters = hiddenEncoderParameters;
_HiddenFilenameExtension = hiddenFilenameExtension; _HiddenFilenameExtension = hiddenFilenameExtension;
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true }; _WriteIndentedAndWhenWritingNull = new JsonSerializerOptions { WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull };
} }
private static void GetPointBounds(PointF[] points, out float xMinimum, out float xMaximum, out float yMinimum, out float yMaximum) private static void GetPointBounds(PointF[] points, out float xMinimum, out float xMaximum, out float yMinimum, out float yMaximum)
@ -321,7 +322,7 @@ public class D_Face
if (results is null) if (results is null)
{ {
results = GetFaces(item, property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation); results = GetFaces(item, property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation);
json = JsonSerializer.Serialize(results, _WriteIndentedJsonSerializerOptions); json = JsonSerializer.Serialize(results, _WriteIndentedAndWhenWritingNull);
bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime;
DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max();
if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime)) if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime))
@ -334,7 +335,7 @@ public class D_Face
normalizedPixelPercentageDistinctCount = normalizedPixelPercentageCollection.Distinct().Count(); normalizedPixelPercentageDistinctCount = normalizedPixelPercentageCollection.Distinct().Count();
if (normalizedPixelPercentageDistinctCount != normalizedPixelPercentageCollection.Length) if (normalizedPixelPercentageDistinctCount != normalizedPixelPercentageCollection.Length)
throw new Exception($"Not distinct! <{fileInfo.FullName}>"); throw new Exception($"Not distinct! <{fileInfo.FullName}>");
json = JsonSerializer.Serialize(results, _WriteIndentedJsonSerializerOptions); json = JsonSerializer.Serialize(results, _WriteIndentedAndWhenWritingNull);
bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime;
DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max();
if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime)) if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime))
@ -356,7 +357,7 @@ public class D_Face
FileInfo fileInfo; FileInfo fileInfo;
bool check = false; bool check = false;
string parentCheck; string parentCheck;
double deterministicHashCodeKey; string deterministicHashCodeKeyDisplay;
List<(Face, FileInfo?, string)> collection = new(); List<(Face, FileInfo?, string)> collection = new();
string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) }; string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) };
string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension); string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension);
@ -366,13 +367,13 @@ public class D_Face
_ = Directory.CreateDirectory(facesDirectory); _ = Directory.CreateDirectory(facesDirectory);
foreach (Face face in faceCollection) foreach (Face face in faceCollection)
{ {
if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) if (item.Property?.Id is null || face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
{ {
collection.Add(new(face, null, string.Empty)); collection.Add(new(face, null, string.Empty));
continue; continue;
} }
deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item, face); deterministicHashCodeKeyDisplay = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKeyDisplay(item.Property.Id.Value, face.Location.NormalizedPixelPercentage.Value);
fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}{_FilenameExtension}")); fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKeyDisplay}{item.ImageFileHolder.ExtensionLowered}{_FilenameExtension}"));
if (!fileInfo.Exists) if (!fileInfo.Exists)
{ {
if (fileInfo.Directory?.Parent is null) if (fileInfo.Directory?.Parent is null)
@ -381,7 +382,7 @@ public class D_Face
if (File.Exists(parentCheck)) if (File.Exists(parentCheck))
File.Delete(parentCheck); File.Delete(parentCheck);
} }
collection.Add(new(face, fileInfo, Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}{_HiddenFilenameExtension}"))); collection.Add(new(face, fileInfo, Path.Combine(facesDirectory, $"{deterministicHashCodeKeyDisplay}{item.ImageFileHolder.ExtensionLowered}{_HiddenFilenameExtension}")));
if (_Configuration.OverrideForFaceImages) if (_Configuration.OverrideForFaceImages)
check = true; check = true;
else if (!fileInfo.Exists) else if (!fileInfo.Exists)

View File

@ -1,8 +1,6 @@
using System.Text.Json; using ShellProgressBar;
using View_by_Distance.FaceRecognitionDotNet; using View_by_Distance.FaceRecognitionDotNet;
using View_by_Distance.Metadata.Models; using View_by_Distance.Map.Models;
using View_by_Distance.Property.Models;
using View_by_Distance.Resize.Models;
using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Stateless; using View_by_Distance.Shared.Models.Stateless;
@ -11,764 +9,135 @@ namespace View_by_Distance.Instance.Models;
internal class E_Distance internal class E_Distance
{ {
internal List<string> AngleBracketCollection { get; } private static void SaveFaceDistances(string eDistanceContentFileName, SortingContainer[] sortingContainers)
private readonly Serilog.ILogger? _Log;
private readonly Configuration _Configuration;
private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions;
internal E_Distance(Configuration configuration)
{ {
_Configuration = configuration; #pragma warning disable
AngleBracketCollection = new List<string>(); 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();
_Log = Serilog.Log.ForContext<E_Distance>(); #pragma warning restore
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true }; File.WriteAllLines(eDistanceContentFileName, results);
} }
public override string ToString() private static List<Sorting> GetSortingCollection(MapLogic mapLogic, List<FaceDistance> faceDistanceEncodings, int faceDistanceContainersLength, int i, FaceDistance faceDistanceEncoding)
{ {
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); List<Sorting> results;
return result; List<FaceDistance> faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncoding);
} if (faceDistanceLengths.Count != faceDistanceContainersLength)
throw new NotSupportedException();
private static List<(DistanceHolder, FaceRecognitionDotNet.FaceEncoding?)> GetDistanceHolder(Item[] items, List<(string JSONDirectory, string TSVDirectory)> directories) 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);
List<(DistanceHolder, FaceRecognitionDotNet.FaceEncoding?)> results = new();
Item item;
const int zero = 0;
string tsvDirectory;
string jsonDirectory;
FaceRecognitionDotNet.FaceEncoding? faceEncoding;
if (items.Length != directories.Count)
throw new Exception();
for (int i = 0; i < items.Length; i++)
{
faceEncoding = null;
item = items[i];
if (item.ImageFileHolder is null || item.Property?.Id is null || !item.Faces.Any())
continue;
tsvDirectory = directories[i].TSVDirectory;
jsonDirectory = directories[i].JSONDirectory;
foreach (Face face in item.Faces)
{
if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
continue;
faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
results.Add(new(new(face, item.ImageFileHolder, item.Property.Id.Value, jsonDirectory, item.Faces[zero].Location, tsvDirectory), faceEncoding));
}
if (faceEncoding is null)
results.Add(new(new(item.Faces[zero], item.ImageFileHolder, item.Property.Id.Value, jsonDirectory, item.Faces[zero].Location, tsvDirectory), null));
}
return results; return results;
} }
private void WriteNoFaceCollection(bool updateDateWhenMatches, DateTime? updateToWhenMatches, List<Tuple<string, DateTime>> subFileTuples, List<DistanceHolder> distanceHolders) private static List<SortingContainer> GetSortingContainers(Face face, FaceDistance faceDistanceEncoding, List<Sorting> sortingCollection)
{ {
string json; List<SortingContainer> results = new();
string check; SortingContainer sortingContainer;
string jsonFile; Sorting[] collection = Shared.Models.Stateless.Methods.ISorting.Sort(sortingCollection);
const int zero = 0; foreach (Sorting sorting in collection)
DistanceHolder distanceHolder;
List<Tuple<Face, string>> tupleCollection;
for (int i = 0; i < distanceHolders.Count; i++)
{ {
distanceHolder = distanceHolders[i]; if (faceDistanceEncoding.NormalizedPixelPercentage is null)
if (distanceHolder.Face.Location?.NormalizedPixelPercentage is null) throw new NotSupportedException();
if (sorting.DistancePermyriad > IFaceDistance.Permyriad || sorting.DaysDelta > ISorting.DaysDeltaTolerance)
continue; continue;
check = Path.Combine(distanceHolder.JSONDirectory, $"{zero} - {distanceHolder.FileHolder.NameWithoutExtension}.json"); sortingContainer = new(face, sorting);
jsonFile = Path.Combine(distanceHolder.JSONDirectory, $"{distanceHolder.Id}.{zero}{distanceHolder.FileHolder.ExtensionLowered}.json"); results.Add(sortingContainer);
if (File.Exists(check)) if (results.Count >= ISorting.MaximumPerFaceShouldBeHigh)
File.Move(check, jsonFile);
tupleCollection = new() { new(distanceHolders[i].Face, string.Empty) };
for (int j = 0; j < distanceHolders.Count; j++)
{
if (j == i)
continue;
distanceHolder = distanceHolders[j];
tupleCollection.Add(new(distanceHolder.Face, string.Empty));
if (tupleCollection.Count > _Configuration.MaxItemsInDistanceCollection)
break;
}
json = JsonSerializer.Serialize(tupleCollection, _WriteIndentedJsonSerializerOptions);
if (Shared.Models.Stateless.Methods.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: updateToWhenMatches))
subFileTuples.Add(new Tuple<string, DateTime>(nameof(E_Distance), DateTime.Now));
}
}
private static List<FaceRecognitionDotNet.FaceEncoding> GetFaceEncodings((DistanceHolder, FaceRecognitionDotNet.FaceEncoding?)[] distanceHoldersAfterSort)
{
List<FaceRecognitionDotNet.FaceEncoding> results = new();
foreach ((DistanceHolder distanceHolder, FaceRecognitionDotNet.FaceEncoding? faceEncoding) in distanceHoldersAfterSort)
{
if (distanceHolder.Face.FaceEncoding is null || distanceHolder.Face.Location?.NormalizedPixelPercentage is null || faceEncoding is null)
continue;
results.Add(faceEncoding);
}
return results;
}
private void SaveDistanceResults(bool updateDateWhenMatches, DateTime? updateToWhenMatches, List<Tuple<string, DateTime>> subFileTuples, List<(DistanceHolder DistanceHolder, FaceRecognitionDotNet.FaceEncoding? _)> distanceHolders)
{
string json;
string check;
string jsonFile;
int locationIndex;
List<double> faceDistances;
DistanceHolder distanceHolder;
int normalizedPixelPercentage;
DistanceHolder[] sortedDistanceHolders;
List<Tuple<Face, string>> tupleCollection;
List<(int Index, double Distance)> collection;
FaceRecognitionDotNet.FaceEncoding? faceEncoding;
(DistanceHolder DistanceHolder, FaceRecognitionDotNet.FaceEncoding? FaceEncoding)[] distanceHoldersAfterSort =
distanceHolders.OrderByDescending(l => l.DistanceHolder.Face.FaceEncoding is not null && l.DistanceHolder.Face.Location?.NormalizedPixelPercentage is not null).ToArray();
List<FaceRecognitionDotNet.FaceEncoding> faceEncodings = GetFaceEncodings(distanceHoldersAfterSort);
for (int i = 0; i < distanceHoldersAfterSort.Length; i++)
{
faceEncoding = distanceHoldersAfterSort[i].FaceEncoding;
distanceHolder = distanceHoldersAfterSort[i].DistanceHolder;
collection = new();
tupleCollection = new();
distanceHolder.Sort = 0d;
if (distanceHolder.Face.LocationIndex is null)
locationIndex = 0;
else
locationIndex = distanceHolder.Face.LocationIndex.Value;
if (distanceHolder.Face.FaceEncoding is null || distanceHolder.Face.Location?.NormalizedPixelPercentage is null)
normalizedPixelPercentage = 0;
else
normalizedPixelPercentage = distanceHolder.Face.Location.NormalizedPixelPercentage.Value;
check = Path.Combine(distanceHolder.JSONDirectory, $"{locationIndex} - {distanceHolder.FileHolder.NameWithoutExtension}.json");
jsonFile = Path.Combine(distanceHolder.JSONDirectory, $"{distanceHolder.Id}.{normalizedPixelPercentage}{distanceHolder.FileHolder.ExtensionLowered}.json");
if (!Directory.Exists(distanceHolder.JSONDirectory))
_ = Directory.CreateDirectory(distanceHolder.JSONDirectory);
if (File.Exists(check))
File.Move(check, jsonFile);
if (faceEncodings.Count == 1)
faceDistances = new() { 0d };
else if (faceEncoding is null)
faceDistances = Enumerable.Repeat(9d, faceEncodings.Count).ToList();
else
faceDistances = FaceRecognition.FaceDistances(faceEncodings, faceEncoding);
if (distanceHolder.Face.FaceEncoding is not null && faceEncoding is not null && faceDistances[i] != 0d)
faceDistances[i] = 0d;
for (int d = 0; d < faceDistances.Count; d++)
collection.Add(new(d, faceDistances[d]));
collection = collection.OrderBy(l => l.Distance).ToList();
foreach ((int index, double distance) in collection)
{
distanceHolder = distanceHoldersAfterSort[index].DistanceHolder;
if (distanceHolder.Location is null)
continue;
distanceHolder.Sort = ((distance * _Configuration.DistanceFactor) + (distanceHolder.Location.Confidence * _Configuration.LocationConfidenceFactor)) / 10;
}
sortedDistanceHolders = (from l in distanceHoldersAfterSort orderby l.DistanceHolder.Sort select l.DistanceHolder).ToArray();
for (int j = 0; j < sortedDistanceHolders.Length; j++)
{
distanceHolder = sortedDistanceHolders[j];
tupleCollection.Add(new(distanceHoldersAfterSort[j].DistanceHolder.Face, string.Empty));
if (tupleCollection.Count > _Configuration.MaxItemsInDistanceCollection)
break;
}
json = JsonSerializer.Serialize(tupleCollection, _WriteIndentedJsonSerializerOptions);
if (Shared.Models.Stateless.Methods.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: updateToWhenMatches))
subFileTuples.Add(new Tuple<string, DateTime>(nameof(E_Distance), DateTime.Now));
}
}
internal void LoadOrCreateThenSaveDistanceResults(Property.Models.Configuration configuration, string eResultsFullGroupDirectory, string outputResolution, Container container, List<Tuple<string, DateTime>> sourceDirectoryChanges, Item[] filteredItems)
{
Item item;
string json;
bool check = false;
string parentCheck;
bool hasPopulatedFace;
string usingRelativePath;
DateTime? dateTime = null;
string dCollectionDirectory;
FileInfo[] fileInfoCollection;
bool updateDateWhenMatches = false;
System.IO.DirectoryInfo directoryInfo;
System.IO.DirectoryInfo tvsDirectoryInfo;
int?[] normalizedPixelPercentageCollection;
int normalizedPixelPercentageDistinctCount;
List<(string, string)> directories = new();
string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) };
List<DateTime> dateTimes = (from l in sourceDirectoryChanges where changesFrom.Contains(l.Item1) select l.Item2).ToList();
List<string> directoryInfoCollection = Property.Models.Stateless.IResult.GetDirectoryInfoCollection(
configuration,
container.SourceDirectory,
eResultsFullGroupDirectory,
contentDescription: ".tvs File",
singletonDescription: string.Empty,
collectionDescription: "n json file(s) for each face found (one to many)",
converted: true);
for (int i = 0; i < filteredItems.Length; i++)
{
item = filteredItems[i];
if (item.ImageFileHolder is null || item.Property?.Id is null)
continue;
hasPopulatedFace = (from l in item.Faces where l.FaceEncoding is not null && l.Location?.NormalizedPixelPercentage is not null select true).Any();
usingRelativePath = Path.Combine(directoryInfoCollection[0].Replace("<>", "[]"), item.ImageFileHolder.NameWithoutExtension);
dCollectionDirectory = Path.Combine(eResultsFullGroupDirectory, "[]", Property.Models.Stateless.IResult.AllInOne, $"{item.Property.Id.Value}{item.ImageFileHolder.ExtensionLowered}");
directoryInfo = new System.IO.DirectoryInfo(dCollectionDirectory);
if (!directoryInfo.Exists)
{
if (Directory.Exists(usingRelativePath))
{
Directory.Move(usingRelativePath, directoryInfo.FullName);
directoryInfo.Refresh();
}
if (!Directory.Exists(dCollectionDirectory))
{
if (directoryInfo.Parent?.Parent is null)
throw new Exception();
parentCheck = Path.Combine(directoryInfo.Parent.Parent.FullName, directoryInfo.Name);
if (Directory.Exists(parentCheck))
{
foreach (string file in Directory.GetFiles(parentCheck))
File.Delete(file);
Directory.Delete(parentCheck);
}
}
}
tvsDirectoryInfo = new System.IO.DirectoryInfo(Path.Combine(directoryInfoCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension));
directories.Add(new(directoryInfo.FullName, tvsDirectoryInfo.FullName));
if (directoryInfo.Exists && (!check || _Configuration.CheckJsonForDistanceResults))
{
json = string.Empty;
normalizedPixelPercentageCollection = Shared.Models.Stateless.Methods.IFace.GetInts(item.Faces);
normalizedPixelPercentageDistinctCount = normalizedPixelPercentageCollection.Distinct().Count();
if (normalizedPixelPercentageDistinctCount != normalizedPixelPercentageCollection.Length)
check = true;
fileInfoCollection = directoryInfo.GetFiles($"{item.Property.Id.Value}*.json", SearchOption.TopDirectoryOnly);
if (fileInfoCollection.Length < normalizedPixelPercentageDistinctCount)
check = true;
if (!check && _Configuration.CheckJsonForDistanceResults)
{
for (int j = 0; j < fileInfoCollection.Length; j++)
{
json = Shared.Models.Stateless.Methods.IIndex.GetJson(fileInfoCollection[j].FullName, fileInfoCollection[j]);
if (!_Configuration.PropertiesChangedForDistance && Shared.Models.Stateless.Methods.IFace.GetFace(fileInfoCollection[j].FullName) is null)
{
check = true;
break;
}
}
if (!check && string.IsNullOrEmpty(json))
check = true;
}
}
if (check)
continue;
if (_Configuration.PropertiesChangedForDistance)
check = true;
else if (hasPopulatedFace && !directoryInfo.Exists)
check = true;
else if (dateTimes.Any() && dateTimes.Max() > directoryInfo.LastWriteTime)
check = true;
if (check && !updateDateWhenMatches)
{
updateDateWhenMatches = dateTimes.Any() && directoryInfo.Exists && dateTimes.Max() > directoryInfo.LastWriteTime;
dateTime = !updateDateWhenMatches ? null : dateTimes.Max();
}
}
if (check)
{
DateTime? updateToWhenMatches = dateTime;
List<Tuple<string, DateTime>> subFileTuples = new();
List<(DistanceHolder, FaceRecognitionDotNet.FaceEncoding?)> distanceHolders = GetDistanceHolder(filteredItems, directories);
SaveDistanceResults(updateDateWhenMatches, updateToWhenMatches, subFileTuples, distanceHolders);
}
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(directoryInfoCollection[0].Replace("<>", "()"));
}
private List<(string, List<KeyValuePair<string, Face[]>>)> GetFiles(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution)
{
string json;
List<KeyValuePair<string, Face[]>>? facesKeyValuePairCollection;
List<(string, List<KeyValuePair<string, Face[]>>)> results = new();
string dFacesCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[[]]");
string[] dFacesCollectionFiles = Directory.GetFiles(dFacesCollectionDirectory, "*.json", SearchOption.TopDirectoryOnly);
foreach (string dFacesCollectionFile in dFacesCollectionFiles)
{
json = File.ReadAllText(dFacesCollectionFile);
facesKeyValuePairCollection = JsonSerializer.Deserialize<List<KeyValuePair<string, Face[]>>>(json);
if (facesKeyValuePairCollection is null)
continue;
results.Add(new(dFacesCollectionFile, facesKeyValuePairCollection));
}
return results;
}
private static List<(string, List<Face>, List<FaceRecognitionDotNet.FaceEncoding>)> GetMatches(List<(string, List<KeyValuePair<string, Face[]>>)> files)
{
List<(string, List<Face>, List<FaceRecognitionDotNet.FaceEncoding>)> results = new();
FaceRecognitionDotNet.FaceEncoding faceEncoding;
List<Face> faces;
List<FaceRecognitionDotNet.FaceEncoding> faceEncodings;
foreach ((string, List<KeyValuePair<string, Face[]>>) file in files)
{
faces = new();
faceEncodings = new();
foreach (KeyValuePair<string, Face[]> keyValuePair in file.Item2)
{
foreach (Face face in keyValuePair.Value)
{
if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
continue;
faces.Add(face);
faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
faceEncodings.Add(faceEncoding);
}
}
results.Add(new(file.Item1, faces, faceEncodings));
}
return results;
}
private static int GetIndex(double[] faceDistances)
{
int result;
List<double[]> faceDistancesWithIndex = new();
for (int y = 0; y < faceDistances.Length; y++)
faceDistancesWithIndex.Add(new double[] { faceDistances[y], y });
faceDistancesWithIndex = (from l in faceDistancesWithIndex orderby l[0] select l).ToList();
result = (int)faceDistancesWithIndex[0][1];
return result;
}
private void Save(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution, string eDistanceCollectionDirectory, int k, string relativePath, Face face, List<Tuple<Face, string>> faceAndFaceDistanceCollection)
{
if (string.IsNullOrEmpty(eDistanceCollectionDirectory))
eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]");
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(face.RelativePath);
string jsonDirectory = string.Concat(eDistanceCollectionDirectory, Path.Combine(relativePath, fileNameWithoutExtension));
if (!Directory.Exists(jsonDirectory))
_ = Directory.CreateDirectory(jsonDirectory);
string json = JsonSerializer.Serialize(faceAndFaceDistanceCollection, _WriteIndentedJsonSerializerOptions);
string jsonFile = Path.Combine(jsonDirectory, $"{k} - {fileNameWithoutExtension}.nosj");
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches: true, compareBeforeWrite: true);
}
private static Tuple<Face, double> Get(FaceRecognitionDotNet.FaceEncoding faceEncoding, (string, List<Face>, List<FaceRecognitionDotNet.FaceEncoding>) match)
{
Tuple<Face, double> result;
double[] faceDistances = FaceRecognition.FaceDistances(match.Item3, faceEncoding).ToArray();
int index = GetIndex(faceDistances);
result = new(match.Item2[index], faceDistances[index]);
return result;
}
internal void LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution)
{
if (_Log is null)
throw new NullReferenceException(nameof(_Log));
string? relativePath;
Face face;
ParallelOptions parallelOptions = new();
FaceRecognitionDotNet.FaceEncoding faceEncoding;
string eDistanceCollectionDirectory = string.Empty;
Tuple<Face, double> faceAndFaceDistance;
List<Tuple<Face, string>> faceAndFaceDistanceCollection;
List<(string, List<KeyValuePair<string, Face[]>>)> files = GetFiles(configuration, model, predictorModel, outputResolution);
List<(string, List<Face>, List<FaceRecognitionDotNet.FaceEncoding>)> matches = GetMatches(files);
if (files.Count != matches.Count)
throw new Exception();
int filesCount = files.Count;
for (int i = 0; i < filesCount; i++)
{
_Log.Debug(string.Concat("LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions - ", nameof(outputResolution), ' ', outputResolution, " - ", i, " of ", filesCount));
for (int j = 0; j < files[i].Item2.Count; j++)
{
if (!matches[i].Item2.Any())
continue;
for (int k = 0; k < files[i].Item2[j].Value.Length; k++)
{
face = files[i].Item2[j].Value[k];
if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
continue;
faceAndFaceDistanceCollection = new(matches.Count);
relativePath = Path.GetDirectoryName(face.RelativePath);
if (string.IsNullOrEmpty(relativePath))
continue;
if (face.FaceEncoding is null)
continue;
faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
_ = Parallel.For(0, matches.Count, parallelOptions, z =>
{
if (z != i && matches[z].Item2.Any())
{
faceAndFaceDistance = Get(faceEncoding, matches[z]);
// if (faceAndFaceDistance.Item2 < _Configuration.)
faceAndFaceDistanceCollection.Add(new(faceAndFaceDistance.Item1, faceAndFaceDistance.Item2.ToString("0.000")));
}
});
if (faceAndFaceDistanceCollection.Any())
{
faceAndFaceDistanceCollection = (from l in faceAndFaceDistanceCollection orderby l.Item2 select l).Take(_Configuration.CrossDirectoryMaxItemsInDistanceCollection).ToList();
Save(configuration, model, predictorModel, outputResolution, eDistanceCollectionDirectory, k, relativePath, face, faceAndFaceDistanceCollection);
}
}
}
}
}
internal void SaveFaceNumbers(string eResultsFullGroupDirectory, Item item, Face face, List<int[]> faceDistances)
{
if (item.Property?.Id is null)
throw new NullReferenceException(nameof(item.Property.Id));
if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder));
if (face.Location?.NormalizedPixelPercentage is null)
throw new NullReferenceException(nameof(face.Location.NormalizedPixelPercentage));
if (string.IsNullOrEmpty(eResultsFullGroupDirectory))
throw new NullReferenceException(nameof(eResultsFullGroupDirectory));
string json;
List<(Face, string, string)> collection = new();
string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) };
string eSingletonFile = Path.Combine(eResultsFullGroupDirectory, "{}", Property.Models.Stateless.IResult.AllInOne, $"{item.Property.Id.Value}.{face.Location.NormalizedPixelPercentage.Value}{item.ImageFileHolder.ExtensionLowered}.json");
FileInfo fileInfo = new(eSingletonFile);
json = JsonSerializer.Serialize(faceDistances, _WriteIndentedJsonSerializerOptions);
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
}
internal void GetFaceDistances(string eResultsFullGroupDirectory, List<bool> faceEncodingRequired, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Item item, List<Face> faceCollection)
{
List<int[]>? results;
if (item.Property?.Id is null)
throw new NullReferenceException(nameof(item.Property.Id));
if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder));
if (string.IsNullOrEmpty(eResultsFullGroupDirectory))
throw new NullReferenceException(nameof(eResultsFullGroupDirectory));
string json;
FileInfo fileInfo;
string eSingletonFile;
List<(Face, string, string)> collection = new();
string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) };
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
foreach (Face face in faceCollection)
{
results = null;
if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
continue;
eSingletonFile = Path.Combine(eResultsFullGroupDirectory, "{}", Property.Models.Stateless.IResult.AllInOne, $"{item.Property.Id.Value}.{face.Location.NormalizedPixelPercentage.Value}{item.ImageFileHolder.ExtensionLowered}.json");
fileInfo = new(eSingletonFile);
if (_Configuration.PropertiesChangedForDistance)
results = null;
else if (!fileInfo.Exists)
results = null;
else if (dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime)
results = null;
else
{
json = File.ReadAllText(fileInfo.FullName);
try
{
results = JsonSerializer.Deserialize<List<int[]>>(json);
if (results is null)
throw new NullReferenceException(nameof(results));
subFileTuples.Add(new Tuple<string, DateTime>(nameof(E_Distance), fileInfo.LastWriteTime));
lock (face)
face.SetFaceNumbers(results);
}
catch (Exception)
{
results = null;
parseExceptions.Add(nameof(E_Distance));
}
}
if (results is null && !faceEncodingRequired.Any())
faceEncodingRequired.Add(true);
}
}
public static double GetStandardDeviation(IEnumerable<double> values, double average)
{
double result = 0;
if (!values.Any())
throw new Exception("Collection must have at least one value!");
double sum = values.Sum(l => (l - average) * (l - average));
result = Math.Sqrt(sum / values.Count());
return result;
}
private static int GetSelectedIndex(int maxDegreeOfParallelism, Random random, List<FaceRecognitionDotNet.FaceEncoding> faceEncodings)
{
int? result;
int selectedIndex;
List<(int? Index, double? Sum)> faceDistanceCollections = new();
if (maxDegreeOfParallelism == 1)
{
double sum;
List<double> faceDistances;
for (int i = 0; i < faceEncodings.Count; i++)
{
faceDistances = FaceRecognition.FaceDistances(faceEncodings, faceEncodings[i]);
sum = faceDistances.Sum();
faceDistanceCollections.Add(new(i, sum));
}
}
else
{
for (int i = 0; i < faceEncodings.Count; i++)
faceDistanceCollections.Add(new(null, null));
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
_ = Parallel.For(0, faceEncodings.Count, parallelOptions, (i, state) =>
{
List<double> faceDistances = FaceRecognition.FaceDistances(faceEncodings, faceEncodings[i]);
double sum = faceDistances.Sum();
lock (faceDistanceCollections)
faceDistanceCollections[i] = new(i, sum);
});
}
faceDistanceCollections = faceDistanceCollections.OrderBy(l => l.Sum).ToList();
if (faceDistanceCollections.Count != faceEncodings.Count)
throw new Exception();
if (faceDistanceCollections.Count > 1000)
selectedIndex = random.Next(0, 36);
else if (faceDistanceCollections.Count > 500)
selectedIndex = random.Next(0, 31);
else if (faceDistanceCollections.Count > 200)
selectedIndex = random.Next(0, 26);
else if (faceDistanceCollections.Count > 100)
selectedIndex = random.Next(0, 21);
else if (faceDistanceCollections.Count > 50)
selectedIndex = random.Next(0, 16);
else if (faceDistanceCollections.Count > 25)
selectedIndex = random.Next(0, 11);
else if (faceDistanceCollections.Count > 10)
selectedIndex = random.Next(0, 6);
else if (faceDistanceCollections.Count > 5)
selectedIndex = random.Next(0, 3);
else
selectedIndex = 0;
result = faceDistanceCollections[selectedIndex].Index;
if (result is null)
throw new NullReferenceException(nameof(result));
return result.Value;
}
private static void SetFiltered(List<(FaceRecognitionDotNet.FaceEncoding FaceEncoding, MappingContainer MappingContainer)> collection)
{
double ucl;
bool check;
double average;
double[] doubles;
double standardDeviation;
double?[] nullableDoubles;
for (int i = 0; i < int.MaxValue; i++)
{
check = true;
nullableDoubles = (from l in collection where l.MappingContainer.Mapping.Filtered is not null && !l.MappingContainer.Mapping.Filtered.Value select l.MappingContainer.Distance).ToArray();
doubles = (from l in nullableDoubles where l.HasValue select l.Value).ToArray();
if (doubles.Length < 4)
break;
average = doubles.Average();
standardDeviation = GetStandardDeviation(doubles, average);
ucl = average + (standardDeviation * 3);
if (ucl > IClosest.Tolerance)
ucl = IClosest.Tolerance;
foreach ((FaceRecognitionDotNet.FaceEncoding _, MappingContainer mappingContainer) in collection)
{
if (mappingContainer.Mapping.Filtered is null || mappingContainer.Mapping.Filtered.Value || mappingContainer.Distance <= ucl)
continue;
if (check)
check = false;
mappingContainer.Mapping.SetFiltered();
}
if (check)
break; break;
} }
return results;
} }
private static FaceDistance GetFaceDistanceParallelFor(Face face, FaceRecognitionDotNet.FaceEncoding faceEncoding, Mapping mapping, DateTime minimumDateTime, bool? isWrongYear, string key, FaceRecognitionDotNet.FaceEncoding[] faceEncodings) private static SortingContainer[] GetSortingContainersThenSetFaceMappingSortingCollection(int maxDegreeOfParallelism, long ticks, MapLogic mapLogic, string outputResolution, FaceDistanceContainer[] faceDistanceContainers)
{ {
FaceDistance result; SortingContainer[] results;
if (face.Location?.NormalizedPixelPercentage is null) List<SortingContainer> collection = new();
throw new NullReferenceException(nameof(face.Location.NormalizedPixelPercentage)); List<FaceDistance> faceDistanceEncodings = new();
List<double> faceDistances = FaceRecognition.FaceDistances(faceEncodings, faceEncoding); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
result = new(faceDistances, isWrongYear, key, mapping, minimumDateTime); ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
return result; 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)
private static List<FaceDistance> GetFaceDistanceCollection(int maxDegreeOfParallelism, List<(string Key, int Id, Mapping Mapping, DateTime MinimumDateTime, bool? IsWrongYear, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>)> collection, Face face) {
{ if (faceDistanceContainer.FaceDistance.Encoding is null)
List<FaceDistance> results; continue;
if (face.FaceEncoding is null) faceDistanceEncodings.Add(faceDistanceContainer.FaceDistance);
throw new NullReferenceException(nameof(face.FaceEncoding)); }
FaceRecognitionDotNet.FaceEncoding faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); using ProgressBar progressBar = new(faceDistanceContainers.Length, message, options);
if (maxDegreeOfParallelism == 1) _ = 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) =>
{ {
results = new();
FaceDistance faceDistance; FaceDistance faceDistance;
List<double> faceDistances;
FaceRecognitionDotNet.FaceEncoding[] faceEncodings;
if (face.Location?.NormalizedPixelPercentage is null)
throw new NullReferenceException(nameof(face.Location.NormalizedPixelPercentage));
foreach ((string key, int id, Mapping mapping, DateTime minimumDateTime, bool? isWrongYear, List<(FaceRecognitionDotNet.FaceEncoding FaceEncoding, MappingContainer _)> faceEncodingContainers) in collection)
{
faceEncodings = (from l in faceEncodingContainers select l.FaceEncoding).ToArray();
faceDistances = FaceRecognition.FaceDistances(faceEncodings, faceEncoding);
faceDistance = new(faceDistances, isWrongYear, key, mapping, minimumDateTime);
results.Add(faceDistance);
if (results.Count > IFaceDistance.MaximumPer)
break;
}
}
else
{
results = new();
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
_ = Parallel.For(0, collection.Count, parallelOptions, (i, state) =>
{
(string key, int id, Mapping mapping, DateTime minimumDateTime, bool? isWrongYear, List<(FaceRecognitionDotNet.FaceEncoding FaceEncoding, MappingContainer _)> faceEncodingContainers) = collection[i];
FaceRecognitionDotNet.FaceEncoding[] faceEncodings = (from l in faceEncodingContainers select l.FaceEncoding).ToArray();
FaceDistance? closest = GetFaceDistanceParallelFor(face, faceEncoding, mapping, minimumDateTime, isWrongYear, key, faceEncodings);
if (closest is not null)
{
lock (results)
{
results.Add(closest);
if (results.Count > IFaceDistance.MaximumPer)
state.Break();
}
}
});
}
return results;
}
private static FaceRecognitionDotNet.FaceEncoding? GetFaceEncoding(Face face)
{
FaceRecognitionDotNet.FaceEncoding? result;
if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
result = null;
else
result = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
return result;
}
private static List<FaceRecognitionDotNet.FaceEncoding> GetFaceEncodingsOnly(int maxDegreeOfParallelism, List<MappingContainer> collection)
{
List<FaceRecognitionDotNet.FaceEncoding> results;
if (maxDegreeOfParallelism == 1)
{
results = new();
FaceRecognitionDotNet.FaceEncoding faceEncoding; FaceRecognitionDotNet.FaceEncoding faceEncoding;
foreach (MappingContainer mappingContainer in collection) Face face = selectedFilteredFaces[i];
{ if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
if (mappingContainer.Face?.FaceEncoding is null || mappingContainer.Face.Location?.NormalizedPixelPercentage is null) throw new NotSupportedException();
continue; if (face.Mapping is null)
faceEncoding = FaceRecognition.LoadFaceEncoding(mappingContainer.Face.FaceEncoding.RawEncoding); throw new NotSupportedException();
results.Add(faceEncoding); 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)
else face.FaceDistanceAdd(faceDistance);
{ });
results = new(); }
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
_ = Parallel.For(0, collection.Count, parallelOptions, (i, state) => internal static SortingContainer[] SetPersonTicksAndSetFaceDistancesAndSetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, long ticks, MapLogic mapLogic, string outputResolution, string eDistanceContentFileName, List<Face> distinctFilteredFaces)
{ {
Face? face = collection[i].Face; SortingContainer[] results;
if (face is null) Face[] orderedFilteredFaces = (from l in distinctFilteredFaces orderby l.Mapping is not null, l.Mapping?.MappingFromItem.MinimumDateTime descending select l).ToArray();
throw new Exception(); mapLogic.SetPersonTicks(outputResolution, orderedFilteredFaces);
FaceRecognitionDotNet.FaceEncoding? faceEncoding = GetFaceEncoding(face); Face[] selectedFilteredFaces = orderedFilteredFaces.Skip(ISorting.FacesToSkipAfterSortBeforeLoad).Take(ISorting.FacesToTakeAfterSortBeforeLoad).ToArray();
if (faceEncoding is not null) SetFaceDistances(maxDegreeOfParallelism, ticks, outputResolution, selectedFilteredFaces);
{ FaceDistanceContainer[] faceDistanceContainers = GetFaceDistanceContainers(selectedFilteredFaces);
lock (results) results = GetSortingContainersThenSetFaceMappingSortingCollection(maxDegreeOfParallelism, ticks, mapLogic, outputResolution, faceDistanceContainers);
results.Add(faceEncoding); if (results.Length < IFaceDistance.Permyriad)
} SaveFaceDistances(eDistanceContentFileName, results);
});
}
return results; return results;
} }
private static void SetNonFiltered(List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)> collection)
{
foreach ((FaceRecognitionDotNet.FaceEncoding _, MappingContainer mappingContainer) in collection)
{
if (mappingContainer.Mapping.Filtered is null)
mappingContainer.Mapping.SetFiltered(value: false);
}
}
private Dictionary<string, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>> GetThreeSigmaFaceEncodings(int maxDegreeOfParallelism, long ticks, Random random, Dictionary<string, List<MappingContainer>> keyValuePairs)
{
if (_Log is null)
throw new NullReferenceException(nameof(_Log));
Dictionary<string, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>> results = new();
int totalSeconds;
int selectedIndex;
List<double> faceDistances;
MappingContainer mappingContainer;
int keyValuePairsCount = keyValuePairs.Count;
FaceRecognitionDotNet.FaceEncoding faceEncoding;
List<FaceRecognitionDotNet.FaceEncoding> faceEncodings;
List<(FaceRecognitionDotNet.FaceEncoding FaceEncoding, MappingContainer MappingContainer)> collection;
foreach (KeyValuePair<string, List<MappingContainer>> keyValuePair in keyValuePairs)
{
collection = new();
faceEncodings = GetFaceEncodingsOnly(maxDegreeOfParallelism, keyValuePair.Value);
for (int i = 0; i < faceEncodings.Count; i++)
{
faceEncoding = faceEncodings[i];
mappingContainer = keyValuePair.Value[i];
collection.Add(new(faceEncoding, mappingContainer));
}
results.Add(keyValuePair.Key, collection);
if (faceEncodings.Count == 1)
selectedIndex = 0;
else
selectedIndex = GetSelectedIndex(maxDegreeOfParallelism, random, faceEncodings);
faceDistances = FaceRecognition.FaceDistances(faceEncodings, faceEncodings[selectedIndex]);
for (int i = 0; i < faceEncodings.Count; i++)
collection[i].MappingContainer.SetDistance(faceDistances[i]);
if (collection.Count > 3)
SetFiltered(collection);
SetNonFiltered(collection);
totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
_Log.Information($"{keyValuePairsCount:0000}) {totalSeconds} total second(s) - {keyValuePair.Key} - {collection[selectedIndex].MappingContainer.Mapping.DisplayDirectoryName}");
}
return results;
}
internal Dictionary<string, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>> ParallelWork(int maxDegreeOfParallelism, long ticks, Map.Models.MapLogic mapLogic, Item[] items, int totalNotMapped)
{
Dictionary<string, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>> results;
Random random = new((int)ticks);
mapLogic.ForceSingleImage(ticks, items, totalNotMapped, random);
Dictionary<string, List<MappingContainer>> keyValuePairs = Map.Models.Stateless.IMapLogic.GetKeyValuePairs(items);
results = GetThreeSigmaFaceEncodings(maxDegreeOfParallelism, ticks, random, keyValuePairs);
return results;
}
public static void AddToFaceDistance(int maxDegreeOfParallelism, Map.Models.MapLogic mapLogic, Item[] items, List<(string, int, Mapping, DateTime, bool?, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>)> collection)
{
Face face;
double deterministicHashCodeKey;
DateTime dateTime = DateTime.Now;
List<FaceDistance> faceDistances;
foreach (Item item in items)
{
if (item.Property?.Id is null || item.ImageFileHolder is null || item.ResizedFileHolder is null)
continue;
for (int i = 0; i < item.Faces.Count; i++)
{
face = item.Faces[i];
face.FaceDistances.Clear();
if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
continue;
if ((from l in item.Mapping where l.NormalizedPixelPercentage.HasValue && l.NormalizedPixelPercentage.Value == face.Location.NormalizedPixelPercentage.Value select true).Any())
continue;
deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item, face);
if (mapLogic.Skip(deterministicHashCodeKey))
continue;
faceDistances = GetFaceDistanceCollection(maxDegreeOfParallelism, collection, face);
face.FaceDistances.AddRange(faceDistances);
}
}
}
} }

View File

@ -152,9 +152,6 @@
"1976-01-05_00", "1976-01-05_00",
"1982-05-02_00" "1982-05-02_00"
], ],
"LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions": [
"1920 x 1080"
],
"LoadOrCreateThenSaveDistanceResultsForOutputResolutions": [ "LoadOrCreateThenSaveDistanceResultsForOutputResolutions": [
"1920 x 1080" "1920 x 1080"
], ],

File diff suppressed because it is too large Load Diff

View File

@ -3,12 +3,6 @@ namespace View_by_Distance.Map.Models.Stateless;
public interface IMapLogic public interface IMapLogic
{ // ... { // ...
(bool?, string[]) TestStatic_IsWrongYear(Shared.Models.Item item); const int Sigma = 3;
static (bool?, string[]) IsWrongYear(Shared.Models.Item item) =>
MapLogic.IsWrongYear(item);
Dictionary<string, List<Shared.Models.MappingContainer>> TestStatic_GetKeyValuePairs(Shared.Models.Item[] items);
static Dictionary<string, List<Shared.Models.MappingContainer>> GetKeyValuePairs(Shared.Models.Item[] items) =>
MapLogic.GetKeyValuePairs(items);
} }

View File

@ -1,84 +1,6 @@
using View_by_Distance.Shared.Models;
namespace View_by_Distance.Map.Models.Stateless; namespace View_by_Distance.Map.Models.Stateless;
internal abstract class MapLogic internal abstract class MapLogic
{ {
internal static string GetMappingSegmentB(long ticks, PersonBirthday personBirthday, int? approximateYears, DateTime minimumDateTime, bool? isWrongYear)
{
int years;
string result;
TimeSpan? timeSpan = Shared.Models.Stateless.Methods.IPersonBirthday.GetTimeSpan(minimumDateTime, isWrongYear, personBirthday);
if (timeSpan.HasValue && timeSpan.Value.Ticks < 0)
result = "!---";
else if (timeSpan.HasValue)
{
(years, _) = Shared.Models.Stateless.Methods.IPersonBirthday.GetAge(minimumDateTime, personBirthday);
result = $"^{years:000}";
}
else if (approximateYears.HasValue)
{
DateTime dateTime = new(ticks);
(years, _) = Shared.Models.Stateless.Methods.IAge.GetAge(minimumDateTime, dateTime.AddYears(-approximateYears.Value));
result = $"~{years:000}";
}
else
{
string isWrongYearFlag = Shared.Models.Stateless.Methods.IItem.GetWrongYearFlag(isWrongYear);
result = $"{isWrongYearFlag}{minimumDateTime:yyyy}";
}
return result;
}
internal static Dictionary<string, List<MappingContainer>> GetKeyValuePairs(Item[] items)
{
Dictionary<string, List<MappingContainer>> results = new();
string key;
bool? isWrongYear;
string personKeyFormatted;
DateTime minimumDateTime;
MappingContainer mappingContainer;
foreach (Item item in items)
{
if (item.Property?.Id is null || item.ImageFileHolder is null || item.ResizedFileHolder is null)
continue;
if (!item.Mapping.Any())
continue;
foreach (Face face in item.Faces)
{
if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
continue;
foreach (Mapping mapping in item.Mapping)
{
if (mapping.NormalizedPixelPercentage.HasValue && mapping.NormalizedPixelPercentage.Value != face.Location.NormalizedPixelPercentage.Value)
continue;
// if (named.NormalizedPixelPercentage is null && (Shared.Models.Stateless.INamed.OnlyUseNamedWithNormalizedPixelPercentagePopulatedForGetKeyValuePairs || item.Named.Count != 1 || item.Faces.Count != 1))
// continue;
minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
(isWrongYear, _) = item.Property.IsWrongYear(item.ImageFileHolder.FullName, minimumDateTime);
personKeyFormatted = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(mapping.PersonBirthday);
key = string.Concat(personKeyFormatted, mapping.SegmentB);
if (!results.ContainsKey(key))
results.Add(key, new());
mappingContainer = new(face, item.Property.Id.Value, isWrongYear, key, mapping, minimumDateTime);
results[key].Add(mappingContainer);
// if (named.NormalizedPixelPercentage is null)
// break;
}
}
}
return results;
}
internal static (bool?, string[]) IsWrongYear(Item item)
{
(bool?, string[]) result;
if (item.Property is null || item.ImageFileHolder is null)
throw new NullReferenceException();
DateTime? minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property);
result = item.Property.IsWrongYear(item.ImageFileHolder.FullName, minimumDateTime);
return result;
}
} }

View File

@ -0,0 +1,6 @@
namespace View_by_Distance.Map.Models.Stateless.Methods;
public interface IMapLogic
{ // ...
}

View File

@ -1,3 +1,4 @@
using ShellProgressBar;
using System.Globalization; using System.Globalization;
using System.Text.Json; using System.Text.Json;
using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models;
@ -7,11 +8,14 @@ namespace View_by_Distance.Map.Models.Stateless;
public class ByDeterministicHashCode public class ByDeterministicHashCode
{ {
private static void SetOther(string resizeFilenameExtension, Person[] people, string deterministicHashCodePeopleDirectory, List<double> skipCollection, List<(string, int?, PersonBirthday[], long)> peopleCollection) private static void SetOther(string resizeFilenameExtension, Person[] people, string deterministicHashCodePeopleDirectory, List<double> skipCollection, Dictionary<long, long> personKeyAliases, List<(string, int?, PersonBirthday[], long)> peopleCollection)
{ {
long ticks; long pK;
string json; string json;
long personKey;
PersonBirthday pB;
string[] segments; string[] segments;
const int zero = 0;
int? approximateYears; int? approximateYears;
string groupDirectoryName; string groupDirectoryName;
string personKeyFormatted; string personKeyFormatted;
@ -37,12 +41,12 @@ public class ByDeterministicHashCode
foreach (string groupDirectory in groupDirectories) foreach (string groupDirectory in groupDirectories)
{ {
groupDirectoryName = Path.GetFileName(groupDirectory); groupDirectoryName = Path.GetFileName(groupDirectory);
if (groupDirectoryName[0] == '!') if (groupDirectoryName[zero] == '!')
{ {
skipCollection.AddRange(from l in Directory.GetFiles(groupDirectory, $"*{resizeFilenameExtension}", SearchOption.AllDirectories) select double.Parse(Path.GetFileNameWithoutExtension(l))); skipCollection.AddRange(from l in Directory.GetFiles(groupDirectory, $"*{resizeFilenameExtension}", SearchOption.AllDirectories) select double.Parse(Path.GetFileNameWithoutExtension(l)));
continue; continue;
} }
else if (groupDirectoryName[0] is not '_' and not '~' and not '^') else if (groupDirectoryName[zero] is not '_' and not '~' and not '^')
continue; continue;
skipCollection.AddRange(from l in Directory.GetFiles(groupDirectory, $"*{resizeFilenameExtension}", SearchOption.AllDirectories) select double.Parse(Path.GetFileNameWithoutExtension(l))); skipCollection.AddRange(from l in Directory.GetFiles(groupDirectory, $"*{resizeFilenameExtension}", SearchOption.AllDirectories) select double.Parse(Path.GetFileNameWithoutExtension(l)));
personDisplayDirectories = Directory.GetDirectories(groupDirectory, "*", SearchOption.TopDirectoryOnly); personDisplayDirectories = Directory.GetDirectories(groupDirectory, "*", SearchOption.TopDirectoryOnly);
@ -52,12 +56,12 @@ public class ByDeterministicHashCode
personDisplayDirectoryName = Path.GetFileName(personDisplayDirectory); personDisplayDirectoryName = Path.GetFileName(personDisplayDirectory);
if (string.IsNullOrEmpty(personDisplayDirectoryName)) if (string.IsNullOrEmpty(personDisplayDirectoryName))
continue; continue;
if (groupDirectoryName[0] != '~') if (groupDirectoryName[zero] != '~')
approximateYears = null; approximateYears = null;
else else
{ {
segments = personDisplayDirectoryName.Split('~'); segments = personDisplayDirectoryName.Split('~');
if (segments.Length == 1 || !int.TryParse(segments[1].Split('-')[0], out int years)) if (segments.Length == 1 || !int.TryParse(segments[1].Split('-')[zero], out int years))
approximateYears = null; approximateYears = null;
else else
approximateYears = years; approximateYears = years;
@ -98,12 +102,22 @@ public class ByDeterministicHashCode
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(personKeyJsonFileName, json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null); _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(personKeyJsonFileName, json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
} }
collection = personBirthdays.OrderByDescending(l => l.Value).ToArray(); collection = personBirthdays.OrderByDescending(l => l.Value).ToArray();
ticks = collection[0].Value.Ticks; personKey = collection[zero].Value.Ticks;
peopleCollection.Add(new(personDisplayDirectoryName, approximateYears, collection, ticks)); if (personBirthdays.Count > 1)
{
for (int i = 1; i < collection.Length; i++)
{
pB = collection[i];
pK = pB.Value.Ticks;
if (!personKeyAliases.ContainsKey(pK))
personKeyAliases.Add(pK, personKey);
}
}
peopleCollection.Add(new(personDisplayDirectoryName, approximateYears, collection, personKey));
for (int i = 0; i < collection.Length; i++) for (int i = 0; i < collection.Length; i++)
{ {
ticks = collection[i].Value.Ticks; personKey = collection[i].Value.Ticks;
personKeys.Add(ticks); personKeys.Add(personKey);
} }
} }
} }
@ -113,48 +127,62 @@ public class ByDeterministicHashCode
DateTime incrementDate = new(Shared.Models.Stateless.IPersonBirthday.FirstYear, 1, 1); DateTime incrementDate = new(Shared.Models.Stateless.IPersonBirthday.FirstYear, 1, 1);
for (int i = 0; i < 500; i++) for (int i = 0; i < 500; i++)
{ {
ticks = incrementDate.Ticks; personKey = incrementDate.Ticks;
personBirthday = new(incrementDate); personBirthday = new(incrementDate);
incrementDate = incrementDate.AddDays(1); incrementDate = incrementDate.AddDays(1);
personKeyFormatted = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(personBirthday); personKeyFormatted = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(personBirthday);
if (personKeys.Contains(ticks)) if (personKeys.Contains(personKey))
continue; continue;
personKeys.Add(ticks); personKeys.Add(personKey);
peopleCollection.Add(new(displayDirectoryName, approximateYears, new PersonBirthday[] { personBirthday }, ticks)); peopleCollection.Add(new(displayDirectoryName, approximateYears, new PersonBirthday[] { personBirthday }, personKey));
} }
} }
internal static void SetCollections(int maxDegreeOfParallelism, long ticks, string zPropertyHolderContentDirectory, Dictionary<long, long> personKeyAliases, List<(PersonBirthday, int, int)> idThenNormalizedPixelPercentageCollection, List<(PersonBirthday, double)> incorrectDeterministicHashCodeCollection, Dictionary<int, List<Face>> keyValuePairs)
internal static void SetKeyValuePairs(string zPropertyHolderContentDirectory, List<(PersonBirthday, double)> deterministicHashCodeCollection, List<(PersonBirthday, double)> incorrectDeterministicHashCodeCollection, Dictionary<int, List<Face>> keyValuePairs)
{ {
int? id;
string[] files; string[] files;
string personKey; long personKey;
const int zero = 0;
string[] yearDirectories; string[] yearDirectories;
string personKeyFormatted;
string ticksDirectoryName; string ticksDirectoryName;
string? personFirstInitial; string? personFirstInitial;
string[] personKeyDirectories; string[] personKeyDirectories;
int? normalizedPixelPercentage;
string[] personNameDirectories; string[] personNameDirectories;
PersonBirthday? personBirthday; PersonBirthday? personBirthday;
string[] personNameLinkDirectories; string[] personNameLinkDirectories;
string? personFirstInitialDirectory; string? personFirstInitialDirectory;
double? reversedDeterministicHashCodeKey;
bool keyValuePairsAny = keyValuePairs.Any(); bool keyValuePairsAny = keyValuePairs.Any();
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
string[] ticksDirectories = Directory.GetDirectories(zPropertyHolderContentDirectory, "*", SearchOption.TopDirectoryOnly); string[] ticksDirectories = Directory.GetDirectories(zPropertyHolderContentDirectory, "*", SearchOption.TopDirectoryOnly);
string message = $") {ticksDirectories.Length:000} ticks Director(ies) - {totalSeconds} total second(s)";
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
using ProgressBar progressBar = new(ticksDirectories.Length, message, options);
foreach (string ticksDirectory in ticksDirectories) foreach (string ticksDirectory in ticksDirectories)
{ {
progressBar.Tick();
ticksDirectoryName = Path.GetFileName(ticksDirectory); ticksDirectoryName = Path.GetFileName(ticksDirectory);
if (ticksDirectoryName.Length < 3 || ticksDirectoryName[0] != '(' || ticksDirectoryName[^1] != ')') if (ticksDirectoryName.Length < 3 || ticksDirectoryName[zero] != '(' || ticksDirectoryName[^1] != ')')
continue; continue;
personKeyDirectories = Directory.GetDirectories(ticksDirectory, "*", SearchOption.TopDirectoryOnly); personKeyDirectories = Directory.GetDirectories(ticksDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string personKeyDirectory in personKeyDirectories) foreach (string personKeyDirectory in personKeyDirectories)
{ {
personKey = Path.GetFileName(personKeyDirectory); personKeyFormatted = Path.GetFileName(personKeyDirectory);
if (personKey.Length != Shared.Models.Stateless.IPersonBirthday.Format.Length) if (personKeyFormatted.Length != Shared.Models.Stateless.IPersonBirthday.Format.Length)
personBirthday = null; personBirthday = null;
else else
{ {
personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(personKey); personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(personKeyFormatted);
if (personBirthday is null) if (personBirthday is null)
continue; continue;
personKey = personBirthday.Value.Ticks;
if (personKeyAliases.ContainsKey(personKey))
{
personKey = personKeyAliases[personKey];
personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(personKey);
}
} }
yearDirectories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly); yearDirectories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string yearDirectory in yearDirectories) foreach (string yearDirectory in yearDirectories)
@ -170,18 +198,20 @@ public class ByDeterministicHashCode
continue; continue;
personFirstInitialDirectory = Path.Combine(yearDirectory, personFirstInitial); personFirstInitialDirectory = Path.Combine(yearDirectory, personFirstInitial);
files = Directory.GetFiles(personNameDirectory, "*", SearchOption.TopDirectoryOnly); files = Directory.GetFiles(personNameDirectory, "*", SearchOption.TopDirectoryOnly);
if (personKey == nameof(Closest) && files.Any()) if (personKeyFormatted == nameof(Models.MapLogic.ForceSingleImage) && files.Any())
throw new Exception($"Move personKey directories up one from {nameof(Closest)} and delete {nameof(Closest)} directory!"); throw new Exception($"Move personKey directories up one from {nameof(Models.MapLogic.ForceSingleImage)} and delete {nameof(Models.MapLogic.ForceSingleImage)} directory!");
if (personKeyFormatted == nameof(Sorting) && files.Any())
throw new Exception($"Move personKey directories up one from {nameof(Sorting)} and delete {nameof(Sorting)} directory!");
if (personBirthday is null) if (personBirthday is null)
continue; continue;
foreach (string file in files) foreach (string file in files)
{ {
if (file.EndsWith(".lnk") || file.EndsWith(".json")) if (file.EndsWith(".lnk") || file.EndsWith(".json"))
continue; continue;
reversedDeterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetReversedDeterministicHashCodeKey(keyValuePairsAny, keyValuePairs, file); (id, normalizedPixelPercentage) = Shared.Models.Stateless.Methods.IMapping.GetReversedDeterministicHashCodeKey(keyValuePairsAny, keyValuePairs, file);
if (reversedDeterministicHashCodeKey is null) if (id is null || normalizedPixelPercentage is null)
continue; continue;
deterministicHashCodeCollection.Add(new(personBirthday, reversedDeterministicHashCodeKey.Value)); idThenNormalizedPixelPercentageCollection.Add(new(personBirthday, id.Value, normalizedPixelPercentage.Value));
} }
personNameLinkDirectories = Directory.GetDirectories(personNameDirectory, "*", SearchOption.TopDirectoryOnly); personNameLinkDirectories = Directory.GetDirectories(personNameDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string personNameLinkDirectory in personNameLinkDirectories) foreach (string personNameLinkDirectory in personNameLinkDirectories)
@ -209,7 +239,7 @@ public class ByDeterministicHashCode
} }
} }
private static List<long> GetTicks(Dictionary<int, PersonBirthday[]> deterministicHashCodeUnknownFaceKeyValuePairs) private static List<long> GetPersonKeys(Dictionary<int, PersonBirthday[]> deterministicHashCodeUnknownFaceKeyValuePairs)
{ {
List<long> results = new(); List<long> results = new();
long personKey; long personKey;
@ -225,58 +255,86 @@ public class ByDeterministicHashCode
return results; return results;
} }
private static void Set(List<(PersonBirthday PersonBirthday, double IdAndNormalizedPixelPercentage)> deterministicHashCodeCollection, List<long> deterministicHashCodePersonKeys, Dictionary<double, List<PersonBirthday>> deterministicHashCodeScope) private static void SetKeyValuePairs(List<(PersonBirthday, int, int)> idThenNormalizedPixelPercentageCollection, List<(PersonBirthday PersonBirthday, double IdAndNormalizedPixelPercentage)> incorrectDeterministicHashCodeCollection, Dictionary<double, PersonBirthday[]> incorrectDeterministicHashCodeKeyValuePairs, Dictionary<int, Dictionary<int, PersonBirthday[]>> idThenNormalizedPixelPercentageKeyValuePairs)
{ {
long personKey;
deterministicHashCodeCollection = (from l in deterministicHashCodeCollection orderby l.IdAndNormalizedPixelPercentage select l).ToList();
foreach ((PersonBirthday personBirthday, double idAndNormalizedPixelPercentage) in deterministicHashCodeCollection)
{
if (!deterministicHashCodeScope.ContainsKey(idAndNormalizedPixelPercentage))
deterministicHashCodeScope.Add(idAndNormalizedPixelPercentage, new());
deterministicHashCodeScope[idAndNormalizedPixelPercentage].Add(personBirthday);
personKey = personBirthday.Value.Ticks;
deterministicHashCodePersonKeys.Add(personKey);
}
}
internal static void SetByRef(string resizeFilenameExtension, Person[] people, List<double> skipCollection, Dictionary<long, (string, int?, PersonBirthday[], long)> peopleKeyValuePairs, List<long> notMappedTicks, Dictionary<int, PersonBirthday[]> deterministicHashCodeUnknownFaceKeyValuePairs, Dictionary<double, PersonBirthday[]> deterministicHashCodeKeyValuePairs, Dictionary<double, PersonBirthday[]> incorrectDeterministicHashCodeKeyValuePairs, string zPropertyHolderContentDirectory, string zPropertyHolderPeopleContentDirectory)
{
Dictionary<int, List<Face>> keyValuePairs = new();
List<long> deterministicHashCodePersonKeys = new();
List<(string, int?, PersonBirthday[], long)> peopleCollection = new();
Dictionary<double, List<PersonBirthday>> deterministicHashCodeScope = new();
Dictionary<double, List<PersonBirthday>> incorrectDeterministicHashCodeScope = new(); Dictionary<double, List<PersonBirthday>> incorrectDeterministicHashCodeScope = new();
List<long> deterministicHashCodeUnknownFacePersonKeys = GetTicks(deterministicHashCodeUnknownFaceKeyValuePairs); Dictionary<int, Dictionary<int, List<PersonBirthday>>> idThenNormalizedPixelPercentageScope = new();
List<(PersonBirthday PersonBirthday, double IdAndNormalizedPixelPercentage)> incorrectDeterministicHashCodeCollection = new();
List<(PersonBirthday PersonBirthday, double IdAndNormalizedPixelPercentage)> deterministicHashCodeCollection = new();
SetOther(resizeFilenameExtension, people, zPropertyHolderPeopleContentDirectory, skipCollection, peopleCollection);
SetKeyValuePairs(zPropertyHolderContentDirectory, deterministicHashCodeCollection, incorrectDeterministicHashCodeCollection, keyValuePairs);
Set(deterministicHashCodeCollection, deterministicHashCodePersonKeys, deterministicHashCodeScope);
incorrectDeterministicHashCodeCollection = (from l in incorrectDeterministicHashCodeCollection orderby l.IdAndNormalizedPixelPercentage select l).ToList();
deterministicHashCodePersonKeys = deterministicHashCodePersonKeys.Distinct().ToList();
foreach ((PersonBirthday personBirthday, double idAndNormalizedPixelPercentage) in incorrectDeterministicHashCodeCollection) foreach ((PersonBirthday personBirthday, double idAndNormalizedPixelPercentage) in incorrectDeterministicHashCodeCollection)
{ {
if (!incorrectDeterministicHashCodeScope.ContainsKey(idAndNormalizedPixelPercentage)) if (!incorrectDeterministicHashCodeScope.ContainsKey(idAndNormalizedPixelPercentage))
incorrectDeterministicHashCodeScope.Add(idAndNormalizedPixelPercentage, new()); incorrectDeterministicHashCodeScope.Add(idAndNormalizedPixelPercentage, new());
incorrectDeterministicHashCodeScope[idAndNormalizedPixelPercentage].Add(personBirthday); incorrectDeterministicHashCodeScope[idAndNormalizedPixelPercentage].Add(personBirthday);
} }
foreach (KeyValuePair<double, List<PersonBirthday>> keyValuePair in deterministicHashCodeScope)
deterministicHashCodeKeyValuePairs.Add(keyValuePair.Key, keyValuePair.Value.Distinct().ToArray());
foreach (KeyValuePair<double, List<PersonBirthday>> keyValuePair in incorrectDeterministicHashCodeScope) foreach (KeyValuePair<double, List<PersonBirthday>> keyValuePair in incorrectDeterministicHashCodeScope)
incorrectDeterministicHashCodeKeyValuePairs.Add(keyValuePair.Key, keyValuePair.Value.Distinct().ToArray()); incorrectDeterministicHashCodeKeyValuePairs.Add(keyValuePair.Key, keyValuePair.Value.Distinct().ToArray());
if (peopleCollection.Any()) string check;
int normalizedPixelPercentageInDecimalForm;
foreach ((PersonBirthday personBirthday, int id, int normalizedPixelPercentage) in idThenNormalizedPixelPercentageCollection)
{ {
foreach ((string displayDirectoryName, int? approximateYears, PersonBirthday[] personBirthdays, long ticks) in peopleCollection) if (!idThenNormalizedPixelPercentageScope.ContainsKey(id))
idThenNormalizedPixelPercentageScope.Add(id, new());
check = normalizedPixelPercentage.ToString();
if (check.Length == Shared.Models.Stateless.ILocation.Digits)
{ {
if (peopleKeyValuePairs.ContainsKey(ticks) && peopleKeyValuePairs[ticks].Item1 != displayDirectoryName) if (!idThenNormalizedPixelPercentageScope[id].ContainsKey(normalizedPixelPercentage))
throw new NotImplementedException(); idThenNormalizedPixelPercentageScope[id].Add(normalizedPixelPercentage, new());
if (deterministicHashCodeUnknownFacePersonKeys.Contains(ticks) || deterministicHashCodePersonKeys.Contains(ticks)) idThenNormalizedPixelPercentageScope[id][normalizedPixelPercentage].Add(personBirthday);
peopleKeyValuePairs.Add(ticks, new(displayDirectoryName, approximateYears, personBirthdays, ticks)); }
else else
notMappedTicks.Add(ticks); {
normalizedPixelPercentageInDecimalForm = int.Parse(check.PadRight(Shared.Models.Stateless.ILocation.Digits, '0'));
if (!idThenNormalizedPixelPercentageScope[id].ContainsKey(normalizedPixelPercentageInDecimalForm))
idThenNormalizedPixelPercentageScope[id].Add(normalizedPixelPercentageInDecimalForm, new());
idThenNormalizedPixelPercentageScope[id][normalizedPixelPercentageInDecimalForm].Add(personBirthday);
} }
} }
if (deterministicHashCodeUnknownFacePersonKeys.Any() || deterministicHashCodePersonKeys.Any()) foreach (KeyValuePair<int, Dictionary<int, List<PersonBirthday>>> keyValuePair in idThenNormalizedPixelPercentageScope)
{
idThenNormalizedPixelPercentageKeyValuePairs.Add(keyValuePair.Key, new());
foreach (KeyValuePair<int, List<PersonBirthday>> innerKeyValuePair in keyValuePair.Value)
idThenNormalizedPixelPercentageKeyValuePairs[keyValuePair.Key].Add(innerKeyValuePair.Key, innerKeyValuePair.Value.Distinct().ToArray());
}
}
internal static void SetByRef(int maxDegreeOfParallelism, long ticks, string resizeFilenameExtension, Person[] people, List<double> skipCollection, Dictionary<long, (string DisplayDirectoryName, int? ApproximateYears, PersonBirthday[] PersonBirthdays, long PersonKey)> peopleKeyValuePairs, List<long> notMappedPersonKeys, Dictionary<int, PersonBirthday[]> deterministicHashCodeUnknownFaceKeyValuePairs, Dictionary<int, Dictionary<int, PersonBirthday[]>> idThenNormalizedPixelPercentageKeyValuePairs, Dictionary<double, PersonBirthday[]> incorrectDeterministicHashCodeKeyValuePairs, string zPropertyHolderContentDirectory, string zPropertyHolderPeopleContentDirectory)
{
Dictionary<long, long> personKeyAliases = new();
Dictionary<int, List<Face>> keyValuePairs = new();
List<long> idThenNormalizedPixelPercentagePersonKeys = new();
List<(string, int?, PersonBirthday[], long)> peopleCollection = new();
List<(PersonBirthday, int, int)> idThenNormalizedPixelPercentageCollection = new();
List<long> deterministicHashCodeUnknownFacePersonKeys = GetPersonKeys(deterministicHashCodeUnknownFaceKeyValuePairs);
List<(PersonBirthday PersonBirthday, double IdAndNormalizedPixelPercentage)> incorrectDeterministicHashCodeCollection = new();
SetOther(resizeFilenameExtension, people, zPropertyHolderPeopleContentDirectory, skipCollection, personKeyAliases, peopleCollection);
SetCollections(maxDegreeOfParallelism, ticks, zPropertyHolderContentDirectory, personKeyAliases, idThenNormalizedPixelPercentageCollection, incorrectDeterministicHashCodeCollection, keyValuePairs);
SetKeyValuePairs(idThenNormalizedPixelPercentageCollection, incorrectDeterministicHashCodeCollection, incorrectDeterministicHashCodeKeyValuePairs, idThenNormalizedPixelPercentageKeyValuePairs);
incorrectDeterministicHashCodeCollection = (from l in incorrectDeterministicHashCodeCollection orderby l.IdAndNormalizedPixelPercentage select l).ToList();
foreach (KeyValuePair<int, Dictionary<int, PersonBirthday[]>> keyValuePair in idThenNormalizedPixelPercentageKeyValuePairs)
{
foreach (KeyValuePair<int, PersonBirthday[]> keyValue in keyValuePair.Value)
idThenNormalizedPixelPercentagePersonKeys.AddRange(from l in keyValue.Value select l.Value.Ticks);
}
idThenNormalizedPixelPercentagePersonKeys = idThenNormalizedPixelPercentagePersonKeys.Distinct().ToList();
foreach (KeyValuePair<int, PersonBirthday[]> keyValuePair in deterministicHashCodeUnknownFaceKeyValuePairs)
deterministicHashCodeUnknownFacePersonKeys.AddRange(from l in keyValuePair.Value select l.Value.Ticks);
deterministicHashCodeUnknownFacePersonKeys = deterministicHashCodeUnknownFacePersonKeys.Distinct().ToList();
if (peopleCollection.Any())
{
foreach ((string displayDirectoryName, int? approximateYears, PersonBirthday[] personBirthdays, long personKey) in peopleCollection)
{
if (peopleKeyValuePairs.ContainsKey(personKey))
{
if (peopleKeyValuePairs[personKey].DisplayDirectoryName == displayDirectoryName)
continue;
throw new NotImplementedException();
}
if (!deterministicHashCodeUnknownFacePersonKeys.Contains(personKey) && !idThenNormalizedPixelPercentagePersonKeys.Contains(personKey))
notMappedPersonKeys.Add(personKey);
else
peopleKeyValuePairs.Add(personKey, new(displayDirectoryName, approximateYears, personBirthdays, personKey));
}
}
if (deterministicHashCodeUnknownFacePersonKeys.Any() || idThenNormalizedPixelPercentagePersonKeys.Any())
{ {
int? approximateYears = null; int? approximateYears = null;
PersonBirthday? personBirthday; PersonBirthday? personBirthday;
@ -289,7 +347,7 @@ public class ByDeterministicHashCode
peopleKeyValuePairs.Add(personKey, new(displayDirectoryName, approximateYears, new PersonBirthday[] { personBirthday }, personKey)); peopleKeyValuePairs.Add(personKey, new(displayDirectoryName, approximateYears, new PersonBirthday[] { personBirthday }, personKey));
} }
} }
foreach (long personKey in deterministicHashCodePersonKeys) foreach (long personKey in idThenNormalizedPixelPercentagePersonKeys)
{ {
if (!peopleKeyValuePairs.ContainsKey(personKey)) if (!peopleKeyValuePairs.ContainsKey(personKey))
{ {

View File

@ -1,45 +0,0 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models;
public class Closest : Properties.IClosest
{
protected readonly bool _AboveTolerance;
protected readonly int _Average;
protected readonly bool? _IsWrongYear;
protected Mapping _Mapping;
protected readonly double _Minimum;
protected readonly DateTime _MinimumDateTime;
protected readonly int _NormalizedPixelPercentage;
protected readonly long? _TicksDelta;
public bool AboveTolerance => _AboveTolerance;
public double Average => _Average;
public bool? IsWrongYear => _IsWrongYear;
public Mapping Mapping => _Mapping;
public double Minimum => _Minimum;
public DateTime MinimumDateTime => _MinimumDateTime;
public int NormalizedPixelPercentage => _NormalizedPixelPercentage;
public long? TicksDelta => _TicksDelta;
[JsonConstructor]
public Closest(bool aboveTolerance, int average, int normalizedPixelPercentage, bool? isWrongYear, Mapping mapping, double minimum, DateTime minimumDateTime, long? ticksDelta)
{
_AboveTolerance = aboveTolerance;
_Average = average;
_NormalizedPixelPercentage = normalizedPixelPercentage;
_IsWrongYear = isWrongYear;
_Mapping = mapping;
_Minimum = minimum;
_MinimumDateTime = minimumDateTime;
_TicksDelta = ticksDelta;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -7,67 +7,47 @@ public class Face : Properties.IFace
{ {
protected DateTime _DateTime; protected DateTime _DateTime;
protected List<FaceDistance> _FaceDistances; protected FaceDistance? _FaceDistance;
protected FaceEncoding? _FaceEncoding; protected FaceEncoding? _FaceEncoding;
protected Dictionary<Stateless.FacePart, FacePoint[]>? _FaceParts; protected Dictionary<Stateless.FacePart, FacePoint[]>? _FaceParts;
protected List<int[]>? _FaceNumbers;
protected readonly OutputResolution? _OutputResolution; protected readonly OutputResolution? _OutputResolution;
protected Location? _Location; protected Location? _Location;
protected readonly int? _LocationIndex; protected readonly int? _LocationIndex;
protected Mapping? _Mapping;
protected readonly string _RelativePath; protected readonly string _RelativePath;
protected List<object> _Tags;
public DateTime DateTime => _DateTime; public DateTime DateTime => _DateTime;
public List<FaceDistance> FaceDistances => _FaceDistances; public FaceDistance? FaceDistance => _FaceDistance;
public FaceEncoding? FaceEncoding => _FaceEncoding; public FaceEncoding? FaceEncoding => _FaceEncoding;
public Dictionary<Stateless.FacePart, FacePoint[]>? FaceParts => _FaceParts; public Dictionary<Stateless.FacePart, FacePoint[]>? FaceParts => _FaceParts;
public List<int[]>? FaceNumbers => _FaceNumbers;
public Location? Location => _Location; public Location? Location => _Location;
public int? LocationIndex => _LocationIndex; public int? LocationIndex => _LocationIndex;
public Mapping? Mapping => _Mapping;
public OutputResolution? OutputResolution => _OutputResolution; public OutputResolution? OutputResolution => _OutputResolution;
public string RelativePath => _RelativePath; public string RelativePath => _RelativePath;
public List<object> Tags => _Tags;
[JsonConstructor] [JsonConstructor]
public Face(DateTime dateTime, List<FaceDistance> faceDistances, FaceEncoding? faceEncoding, Dictionary<Stateless.FacePart, FacePoint[]>? faceParts, List<int[]>? faceNumbers, Location? location, int? locationIndex, OutputResolution? outputResolution, string relativePath) public Face(DateTime dateTime, FaceDistance? faceDistance, FaceEncoding? faceEncoding, Dictionary<Stateless.FacePart, FacePoint[]>? faceParts, Location? location, int? locationIndex, Mapping? mapping, OutputResolution? outputResolution, string relativePath)
{ {
if (faceDistances is null)
faceDistances = new();
_DateTime = dateTime; _DateTime = dateTime;
_FaceDistances = faceDistances; _FaceDistance = faceDistance;
_FaceEncoding = faceEncoding; _FaceEncoding = faceEncoding;
_FaceParts = faceParts; _FaceParts = faceParts;
_FaceNumbers = faceNumbers;
_Location = location; _Location = location;
_LocationIndex = locationIndex; _LocationIndex = locationIndex;
_Mapping = mapping;
_OutputResolution = outputResolution; _OutputResolution = outputResolution;
_RelativePath = relativePath; _RelativePath = relativePath;
_Tags = new();
} }
public Face() :
this(DateTime.MinValue, new(), null, null, null, null, null, null, string.Empty)
{ }
public Face(Location location) :
this(DateTime.MinValue, new(), null, null, null, location, null, null, string.Empty)
{ }
public Face(int facesCount, Face face) : public Face(int facesCount, Face face) :
this(face.DateTime, new(), face.FaceEncoding, face.FaceParts, null, face.Location, face.LocationIndex, face.OutputResolution, face.RelativePath) this(face.DateTime, null, face.FaceEncoding, face.FaceParts, face.Location, face.LocationIndex, null, face.OutputResolution, face.RelativePath)
{ {
if (face.Location?.Confidence is not null && face.OutputResolution is not null) if (face.Location?.Confidence is not null && face.OutputResolution is not null)
_Location = new(face.Location.Confidence, face.OutputResolution.Height, face.Location, face.OutputResolution.Width, facesCount); _Location = new(face.Location.Confidence, face.OutputResolution.Height, face.Location, face.OutputResolution.Width, facesCount);
} }
public Face(int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, Face face) :
this(face.DateTime, new(), face.FaceEncoding, face.FaceParts, null, face.Location, face.LocationIndex, null, face.RelativePath)
{
if (outputResolutionHeight > 0)
_OutputResolution = new(outputResolutionHeight, outputResolutionOrientation, outputResolutionWidth);
}
public Face(Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, string relativePath, int? i, Location? location) : public Face(Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, string relativePath, int? i, Location? location) :
this(DateTime.MinValue, new(), null, null, null, location, i, null, relativePath) this(DateTime.MinValue, null, null, null, location, i, null, null, relativePath)
{ {
DateTime?[] dateTimes; DateTime?[] dateTimes;
_OutputResolution = new(outputResolutionHeight, outputResolutionOrientation, outputResolutionWidth); _OutputResolution = new(outputResolutionHeight, outputResolutionOrientation, outputResolutionWidth);
@ -85,6 +65,10 @@ public class Face : Properties.IFace
public void SetFaceParts(Dictionary<Stateless.FacePart, FacePoint[]> faceParts) => _FaceParts = faceParts; public void SetFaceParts(Dictionary<Stateless.FacePart, FacePoint[]> faceParts) => _FaceParts = faceParts;
public void SetFaceNumbers(List<int[]> faceNumbers) => _FaceNumbers = faceNumbers; public void ReleaseFaceDistance() => _FaceDistance = null;
public void SetMapping(Mapping mapping) => _Mapping = mapping;
public void FaceDistanceAdd(FaceDistance faceDistance) => _FaceDistance = faceDistance;
} }

View File

@ -3,30 +3,39 @@ using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace View_by_Distance.Shared.Models;
public class FaceDistance : Properties.IFaceDistance public record class FaceDistance : Properties.IFaceDistance
{ {
protected readonly List<double> _Distances; public double? Confidence { init; get; }
protected readonly bool? _IsWrongYear; public object? Encoding { init; get; }
protected readonly string _Key; public int Id { init; get; }
protected readonly Mapping _Mapping; public bool? IsWrongYear { init; get; }
protected readonly DateTime _MinimumDateTime; public double? Length { init; get; }
public List<double> Distances => _Distances; public DateTime? MinimumDateTime { init; get; }
public bool? IsWrongYear => _IsWrongYear; public int? NormalizedPixelPercentage { init; get; }
public string Key => _Key;
public Mapping Mapping => _Mapping;
public DateTime MinimumDateTime => _MinimumDateTime;
[JsonConstructor] [JsonConstructor]
public FaceDistance(List<double> distances, bool? isWrongYear, string key, Mapping mapping, DateTime minimumDateTime) public FaceDistance(double? confidence, object? encoding, int id, bool? isWrongYear, double? length, DateTime? minimumDateTime, int? normalizedPixelPercentage)
{ {
_Distances = distances; Confidence = confidence;
_IsWrongYear = isWrongYear; Encoding = encoding;
_Key = key; Id = id;
_Mapping = mapping; IsWrongYear = isWrongYear;
_MinimumDateTime = minimumDateTime; Length = length;
MinimumDateTime = minimumDateTime;
NormalizedPixelPercentage = normalizedPixelPercentage;
} }
public FaceDistance(double? confidence, object? encoding, int id, bool? isWrongYear, DateTime? minimumDateTime, int? normalizedPixelPercentage) :
this(confidence, encoding, id, isWrongYear, null, minimumDateTime, normalizedPixelPercentage)
{ }
public FaceDistance(FaceDistance faceDistance, double length) :
this(faceDistance.Confidence, null, faceDistance.Id, faceDistance.IsWrongYear, length, faceDistance.MinimumDateTime, faceDistance.NormalizedPixelPercentage)
{ }
public FaceDistance(object encoding) => Encoding = encoding;
public override string ToString() public override string ToString()
{ {
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });

View File

@ -0,0 +1,25 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models;
public record class FaceDistanceContainer : Properties.IFaceDistanceContainer
{
public Face Face { init; get; }
public FaceDistance FaceDistance { init; get; }
[JsonConstructor]
public FaceDistanceContainer(Face face, FaceDistance faceDistance)
{
Face = face;
FaceDistance = faceDistance;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -8,10 +8,8 @@ public class Item : Properties.IItem
protected readonly bool? _Abandoned; protected readonly bool? _Abandoned;
protected readonly bool? _Changed; protected readonly bool? _Changed;
protected List<Closest> _Closest;
protected List<Face> _Faces; protected List<Face> _Faces;
protected readonly FileHolder? _ImageFileHolder; protected readonly FileHolder? _ImageFileHolder;
protected List<Mapping> _Mapping;
protected bool? _Moved; protected bool? _Moved;
protected readonly bool? _NoJson; protected readonly bool? _NoJson;
protected Property? _Property; protected Property? _Property;
@ -21,10 +19,8 @@ public class Item : Properties.IItem
protected bool _ValidImageFormatExtension; protected bool _ValidImageFormatExtension;
public bool? Abandoned => _Abandoned; public bool? Abandoned => _Abandoned;
public bool? Changed => _Changed; public bool? Changed => _Changed;
public List<Closest> Closest => _Closest;
public List<Face> Faces => _Faces; public List<Face> Faces => _Faces;
public FileHolder? ImageFileHolder => _ImageFileHolder; public FileHolder? ImageFileHolder => _ImageFileHolder;
public List<Mapping> Mapping => _Mapping;
public bool? Moved => _Moved; public bool? Moved => _Moved;
public bool? NoJson => _NoJson; public bool? NoJson => _NoJson;
public Property? Property => _Property; public Property? Property => _Property;
@ -34,14 +30,12 @@ public class Item : Properties.IItem
public bool ValidImageFormatExtension => _ValidImageFormatExtension; public bool ValidImageFormatExtension => _ValidImageFormatExtension;
[JsonConstructor] [JsonConstructor]
public Item(bool? abandoned, bool? changed, List<Closest> closest, List<Face> faces, FileHolder? imageFileHolder, List<Mapping> mapping, bool? moved, bool? noJson, Property? property, string relativePath, FileHolder? resizedFileHolder, string sourceDirectoryFile, bool validImageFormatExtension) public Item(bool? abandoned, bool? changed, List<Face> faces, FileHolder? imageFileHolder, bool? moved, bool? noJson, Property? property, string relativePath, FileHolder? resizedFileHolder, string sourceDirectoryFile, bool validImageFormatExtension)
{ {
_Abandoned = abandoned; _Abandoned = abandoned;
_Changed = changed; _Changed = changed;
_Closest = closest;
_Faces = faces; _Faces = faces;
_ImageFileHolder = imageFileHolder; _ImageFileHolder = imageFileHolder;
_Mapping = mapping;
_Moved = moved; _Moved = moved;
_NoJson = noJson; _NoJson = noJson;
_Property = property; _Property = property;
@ -54,8 +48,6 @@ public class Item : Properties.IItem
public Item(string sourceDirectoryFile, string relativePath, FileHolder? imageFileInfo, bool isValidImageFormatExtension, Property? property, bool? abandoned, bool? changed) public Item(string sourceDirectoryFile, string relativePath, FileHolder? imageFileInfo, bool isValidImageFormatExtension, Property? property, bool? abandoned, bool? changed)
{ {
_Faces = new(); _Faces = new();
_Mapping = new();
_Closest = new();
_Changed = changed; _Changed = changed;
_Property = property; _Property = property;
_Abandoned = abandoned; _Abandoned = abandoned;

View File

@ -28,16 +28,16 @@ public class Location : Properties.ILocation, IEquatable<Location>
_NormalizedPixelPercentage = normalizedPixelPercentage; _NormalizedPixelPercentage = normalizedPixelPercentage;
_Right = right; _Right = right;
_Top = top; _Top = top;
Check(bottom, left, normalizedPixelPercentage, right, top, zCount: 1); Stateless.Methods.Location.Check(bottom, left, normalizedPixelPercentage, right, top, zCount: 1);
} }
public Location(double confidence, int height, Location location, int width, int zCount) : public Location(double confidence, int height, Location location, int width, int zCount) :
this(location.Bottom, confidence, location.Left, GetNormalizedPixelPercentage(location.Bottom, height, location.Left, location.Right, location.Top, width, zCount), location.Right, location.Top) => this(location.Bottom, confidence, location.Left, Stateless.Methods.Location.GetNormalizedPixelPercentage(location.Bottom, height, location.Left, location.Right, location.Top, width, zCount), location.Right, location.Top) =>
Check(_Bottom, _Left, _NormalizedPixelPercentage, _Right, _Top, zCount); Stateless.Methods.Location.Check(_Bottom, _Left, _NormalizedPixelPercentage, _Right, _Top, zCount);
public Location(int bottom, double confidence, int height, int left, int right, int top, int width, int zCount) : public Location(int bottom, double confidence, int height, int left, int right, int top, int width, int zCount) :
this(bottom, confidence, left, GetNormalizedPixelPercentage(bottom, height, left, right, top, width, zCount), right, top) => this(bottom, confidence, left, Stateless.Methods.Location.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, zCount), right, top) =>
Check(_Bottom, height, _Left, _NormalizedPixelPercentage, _Right, _Top, width, zCount); Stateless.Methods.Location.Check(_Bottom, height, _Left, _NormalizedPixelPercentage, _Right, _Top, width, zCount);
public Location(double confidence, int factor, int height, Location location, int width, int zCount) public Location(double confidence, int factor, int height, Location location, int width, int zCount)
{ {
@ -47,8 +47,8 @@ public class Location : Properties.ILocation, IEquatable<Location>
int left = Math.Max(location.Left - x, 0); int left = Math.Max(location.Left - x, 0);
int right = Math.Min(location.Right + x, width); int right = Math.Min(location.Right + x, width);
int top = Math.Max(location.Top - y, 0); int top = Math.Max(location.Top - y, 0);
int normalizedPixelPercentage = GetNormalizedPixelPercentage(location.Bottom, height, location.Left, location.Right, location.Top, width, zCount); int normalizedPixelPercentage = Stateless.Methods.Location.GetNormalizedPixelPercentage(location.Bottom, height, location.Left, location.Right, location.Top, width, zCount);
Check(bottom, left, _NormalizedPixelPercentage, right, top, zCount); Stateless.Methods.Location.Check(bottom, left, _NormalizedPixelPercentage, right, top, zCount);
_Confidence = confidence; _Confidence = confidence;
_Bottom = bottom; _Bottom = bottom;
_Left = left; _Left = left;
@ -65,53 +65,6 @@ public class Location : Properties.ILocation, IEquatable<Location>
return result; return result;
} }
private static void Check(int bottom, int left, int right, int top, int zCount)
{
if (left < 0)
throw new Exception();
if (right < 0)
throw new Exception();
if (right < left)
throw new Exception();
if (top < 0)
throw new Exception();
if (bottom < 0)
throw new Exception();
if (bottom < top)
throw new Exception();
if (zCount < 0)
throw new Exception();
}
private static void Check(int bottom, int height, int left, int right, int top, int width, int zCount)
{
if (bottom > height)
throw new Exception();
if (left > width)
throw new Exception();
if (right > width)
throw new Exception();
if (top > height)
throw new Exception();
if (zCount < 0)
throw new Exception();
}
private static void Check(int bottom, int left, int? normalizedPixelPercentage, int right, int top, int zCount)
{
Check(bottom, left, right, top, zCount);
if (normalizedPixelPercentage.HasValue && normalizedPixelPercentage.Value < 0)
throw new Exception();
}
private static void Check(int bottom, int height, int left, int? normalizedPixelPercentage, int right, int top, int width, int zCount)
{
Check(bottom, left, right, top, zCount);
Check(bottom, height, left, right, top, width, zCount);
if (normalizedPixelPercentage.HasValue && normalizedPixelPercentage.Value < 0)
throw new Exception();
}
public override int GetHashCode() public override int GetHashCode()
{ {
int hashCode = -773114317; int hashCode = -773114317;
@ -122,22 +75,6 @@ public class Location : Properties.ILocation, IEquatable<Location>
return hashCode; return hashCode;
} }
public static int GetNormalizedPixelPercentage(int bottom, int height, int left, int right, int top, int width, int zCount)
{
int result;
double value;
double total = width * height;
Check(bottom, left, right, top, zCount);
double xCenter = left + ((right - left) / 2);
double yCenter = top + ((bottom - top) / 2);
double at = ((yCenter - 1) * width) + xCenter;
value = at / total;
if (value < 0)
value = 3;
result = (int)(Math.Round(value, Stateless.ILocation.Digits) * Stateless.ILocation.Factor);
return result;
}
public bool Equals(Location? location) public bool Equals(Location? location)
{ {
return location is not null return location is not null

View File

@ -3,52 +3,105 @@ using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace View_by_Distance.Shared.Models;
public class Mapping : Properties.IMapping public class MappingFromItem : Properties.IMappingFromItem
{ {
protected int? _ApproximateYears; public int Id { init; get; }
protected readonly string _DisplayDirectoryName; public FileHolder ImageFileHolder { init; get; }
protected bool? _Filtered; public bool? IsWrongYear { init; get; }
protected bool _Forced; public DateTime MinimumDateTime { init; get; }
protected readonly int? _NormalizedPixelPercentage; public FileHolder ResizedFileHolder { init; get; }
protected PersonBirthday _PersonBirthday;
protected readonly string _SegmentB;
public int? ApproximateYears => _ApproximateYears;
public string DisplayDirectoryName => _DisplayDirectoryName;
public bool? Filtered => _Filtered;
public bool Forced => _Forced;
public int? NormalizedPixelPercentage => _NormalizedPixelPercentage;
public PersonBirthday PersonBirthday => _PersonBirthday;
public string SegmentB => _SegmentB;
[JsonConstructor] [JsonConstructor]
public Mapping(int? approximateYears, string displayDirectoryName, bool? filtered, bool forced, int? normalizedPixelPercentage, PersonBirthday personBirthday, string segmentB) public MappingFromItem(int id, FileHolder imageFileHolder, bool? isWrongYear, DateTime minimumDateTime, FileHolder resizedFileHolder)
{ {
_ApproximateYears = approximateYears; Id = id;
_DisplayDirectoryName = displayDirectoryName; ImageFileHolder = imageFileHolder;
_Filtered = filtered; IsWrongYear = isWrongYear;
_Forced = forced; MinimumDateTime = minimumDateTime;
_NormalizedPixelPercentage = normalizedPixelPercentage; ResizedFileHolder = resizedFileHolder;
_PersonBirthday = personBirthday;
_SegmentB = segmentB;
} }
public Mapping(int? approximateYears, string displayDirectoryName, bool forced, int? normalizedPixelPercentage, PersonBirthday personBirthday, string segmentB) :
this(approximateYears, displayDirectoryName, null, forced, normalizedPixelPercentage, personBirthday, segmentB)
{ }
public Mapping(int? approximateYears, string displayDirectoryName, bool forced, PersonBirthday personBirthday, string segmentB) :
this(approximateYears, displayDirectoryName, null, forced, null, personBirthday, segmentB)
{ }
public override string ToString() public override string ToString()
{ {
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result; return result;
} }
public void SetFiltered() => _Filtered = true; }
public void SetFiltered(bool value) => _Filtered = value; public class MappingFromLocation : Properties.IMappingFromLocation
{
public double Confidence { init; get; }
public string DeterministicHashCodeKeyDisplay { init; get; }
public int NormalizedPixelPercentage { init; get; }
[JsonConstructor]
public MappingFromLocation(double confidence, string deterministicHashCodeKeyDisplay, int normalizedPixelPercentage)
{
Confidence = confidence;
DeterministicHashCodeKeyDisplay = deterministicHashCodeKeyDisplay;
NormalizedPixelPercentage = normalizedPixelPercentage;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}
public class MappingFromPerson : Properties.IMappingFromPerson
{
public int? ApproximateYears { init; get; }
public int? By { init; get; }
public string DisplayDirectoryName { init; get; }
public PersonBirthday? PersonBirthday { init; get; }
public string SegmentB { init; get; }
[JsonConstructor]
public MappingFromPerson(int? approximateYears, int? by, string displayDirectoryName, PersonBirthday? personBirthday, string segmentB)
{
ApproximateYears = approximateYears;
By = by;
DisplayDirectoryName = displayDirectoryName;
PersonBirthday = personBirthday;
SegmentB = segmentB;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}
public class Mapping : Properties.IMapping
{
protected MappingFromPerson _MappingFromPerson;
public MappingFromItem MappingFromItem { init; get; }
public MappingFromLocation MappingFromLocation { init; get; }
public MappingFromPerson MappingFromPerson => _MappingFromPerson;
[JsonConstructor]
public Mapping(MappingFromItem mappingFromItem, MappingFromLocation mappingFromLocation, MappingFromPerson mappingFromPerson)
{
MappingFromItem = mappingFromItem;
MappingFromLocation = mappingFromLocation;
_MappingFromPerson = mappingFromPerson;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
public void UpdateMappingFromPerson(int? approximateYears, int? by, string displayDirectoryName, PersonBirthday personBirthday, string segmentB) => _MappingFromPerson = new(approximateYears, by, displayDirectoryName, personBirthday, segmentB);
} }

View File

@ -1,48 +0,0 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models;
public class MappingContainer : Properties.IMappingContainer
{
protected double? _Distance;
protected readonly Face? _Face;
protected readonly int _Id;
protected readonly bool? _IsWrongYear;
protected readonly string _Key;
protected readonly Mapping _Mapping;
protected readonly DateTime _MinimumDateTime;
public double? Distance => _Distance;
public Face? Face => _Face;
public int Id => _Id;
public bool? IsWrongYear => _IsWrongYear;
public string Key => _Key;
public Mapping Mapping => _Mapping;
public DateTime MinimumDateTime => _MinimumDateTime;
[JsonConstructor]
public MappingContainer(double? distance, Face? face, int id, bool? isWrongYear, string key, Mapping mapping, DateTime minimumDateTime)
{
_Distance = distance;
_Face = face;
_Id = id;
_IsWrongYear = isWrongYear;
_Key = key;
_Mapping = mapping;
_MinimumDateTime = minimumDateTime;
}
public MappingContainer(Face face, int id, bool? isWrongYear, string key, Mapping mapping, DateTime minimumDateTime) :
this(null, face, id, isWrongYear, key, mapping, minimumDateTime)
{ }
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
public void SetDistance(double v) => _Distance = v;
}

View File

@ -1,8 +0,0 @@
namespace View_by_Distance.Shared.Models.Methods;
public interface IClosest : Stateless.Methods.IClosest
{ // ...
//
}

View File

@ -1,8 +0,0 @@
namespace View_by_Distance.Shared.Models.Methods;
public interface INamed : Stateless.Methods.IMapping
{ // ...
//
}

View File

@ -1,14 +0,0 @@
namespace View_by_Distance.Shared.Models.Properties;
public interface IClosest
{
public double Average { get; }
public bool? IsWrongYear { get; }
public Mapping Mapping { get; }
public double Minimum { get; }
public DateTime MinimumDateTime { get; }
public int NormalizedPixelPercentage { get; }
public long? TicksDelta { get; }
}

View File

@ -4,12 +4,12 @@ public interface IFace
{ {
public DateTime DateTime { get; } public DateTime DateTime { get; }
public List<FaceDistance> FaceDistances { get; } public FaceDistance? FaceDistance { get; }
public FaceEncoding? FaceEncoding { get; } public FaceEncoding? FaceEncoding { get; }
public Dictionary<Stateless.FacePart, FacePoint[]>? FaceParts { get; } public Dictionary<Stateless.FacePart, FacePoint[]>? FaceParts { get; }
public List<int[]>? FaceNumbers { get; }
public Location? Location { get; } public Location? Location { get; }
public int? LocationIndex { get; } public int? LocationIndex { get; }
public Mapping? Mapping { get; }
public OutputResolution? OutputResolution { get; } public OutputResolution? OutputResolution { get; }
public string RelativePath { get; } public string RelativePath { get; }

View File

@ -3,10 +3,12 @@ namespace View_by_Distance.Shared.Models.Properties;
public interface IFaceDistance public interface IFaceDistance
{ {
public List<double> Distances { get; } public double? Confidence { init; get; }
public bool? IsWrongYear { get; } public object? Encoding { init; get; }
public string Key { get; } public int Id { init; get; }
public Mapping Mapping { get; } public bool? IsWrongYear { init; get; }
public DateTime MinimumDateTime { get; } public double? Length { init; get; }
public DateTime? MinimumDateTime { init; get; }
public int? NormalizedPixelPercentage { init; get; }
} }

View File

@ -0,0 +1,9 @@
namespace View_by_Distance.Shared.Models.Properties;
public interface IFaceDistanceContainer
{
public Face Face { init; get; }
public FaceDistance FaceDistance { init; get; }
}

View File

@ -5,10 +5,8 @@ public interface IItem
public bool? Abandoned { get; } public bool? Abandoned { get; }
public bool? Changed { get; } public bool? Changed { get; }
public List<Closest> Closest { get; }
public List<Face> Faces { get; } public List<Face> Faces { get; }
public FileHolder? ImageFileHolder { get; } public FileHolder? ImageFileHolder { get; }
public List<Mapping> Mapping { get; }
public bool? Moved { get; } public bool? Moved { get; }
public bool? NoJson { get; } public bool? NoJson { get; }
public Property? Property { get; } public Property? Property { get; }

View File

@ -1,14 +1,41 @@
namespace View_by_Distance.Shared.Models.Properties; namespace View_by_Distance.Shared.Models.Properties;
public interface IMappingFromItem
{
public int Id { init; get; }
public FileHolder ImageFileHolder { init; get; }
public bool? IsWrongYear { init; get; }
public DateTime MinimumDateTime { init; get; }
public FileHolder ResizedFileHolder { init; get; }
}
public interface IMappingFromLocation
{
public double Confidence { init; get; }
public string DeterministicHashCodeKeyDisplay { init; get; }
public int NormalizedPixelPercentage { init; get; }
}
public interface IMappingFromPerson
{
public int? ApproximateYears { init; get; }
public int? By { init; get; }
public string DisplayDirectoryName { init; get; }
public PersonBirthday? PersonBirthday { init; get; }
public string SegmentB { init; get; }
}
public interface IMapping public interface IMapping
{ {
public int? ApproximateYears { get; } public MappingFromItem MappingFromItem { init; get; }
public string DisplayDirectoryName { get; } public MappingFromLocation MappingFromLocation { init; get; }
public bool? Filtered { get; } public MappingFromPerson MappingFromPerson { get; }
public bool Forced { get; }
public int? NormalizedPixelPercentage { get; }
public PersonBirthday PersonBirthday { get; }
public string SegmentB { get; }
} }

View File

@ -1,14 +0,0 @@
namespace View_by_Distance.Shared.Models.Properties;
public interface IMappingContainer
{
public double? Distance { get; }
public Face? Face { get; }
public int Id { get; }
public bool? IsWrongYear { get; }
public string Key { get; }
public Mapping Mapping { get; }
public DateTime MinimumDateTime { get; }
}

View File

@ -3,10 +3,10 @@ namespace View_by_Distance.Shared.Models.Properties;
public interface ISorting public interface ISorting
{ {
public double? Confidence { init; get; } public int DaysDelta { init; get; }
public double? Distance { init; get; } public int DistancePermyriad { init; get; }
public int? FaceEncoding { init; get; }
public int Id { init; get; } public int Id { init; get; }
public int? NormalizedPixelPercentage { init; get; } public int NormalizedPixelPercentage { init; get; }
public int WithinRange { init; get; }
} }

View File

@ -0,0 +1,9 @@
namespace View_by_Distance.Shared.Models.Properties;
public interface ISortingContainer
{
public Face Face { init; get; }
public Sorting Sorting { init; get; }
}

View File

@ -3,32 +3,25 @@ using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace View_by_Distance.Shared.Models;
public class Sorting : Properties.ISorting public record class Sorting : Properties.ISorting
{ {
public double? Confidence { init; get; } public int DaysDelta { init; get; }
public double? Distance { init; get; } public int DistancePermyriad { init; get; }
public int? FaceEncoding { init; get; }
public int Id { init; get; } public int Id { init; get; }
public int? NormalizedPixelPercentage { init; get; } public int NormalizedPixelPercentage { init; get; }
public bool Older { init; get; }
public int WithinRange { init; get; }
[JsonConstructor] [JsonConstructor]
public Sorting(double? confidence, double? distance, int? faceEncoding, int id, int? normalizedPixelPercentage) public Sorting(int daysDelta, int distancePermyriad, int id, int normalizedPixelPercentage, bool older, int withinRange)
{ {
Confidence = confidence; DaysDelta = daysDelta;
Distance = distance; DistancePermyriad = distancePermyriad;
FaceEncoding = faceEncoding;
Id = id;
NormalizedPixelPercentage = normalizedPixelPercentage;
}
public Sorting(double? confidence, int id, int? normalizedPixelPercentage)
{
Confidence = confidence;
Distance = null;
FaceEncoding = int.MaxValue;
Id = id; Id = id;
NormalizedPixelPercentage = normalizedPixelPercentage; NormalizedPixelPercentage = normalizedPixelPercentage;
Older = older;
WithinRange = withinRange;
} }
public override string ToString() public override string ToString()
@ -37,13 +30,4 @@ public class Sorting : Properties.ISorting
return result; return result;
} }
public Sorting(Sorting sorting, double? distance)
{
Confidence = sorting.Confidence;
Distance = distance;
FaceEncoding = null;
Id = sorting.Id;
NormalizedPixelPercentage = sorting.NormalizedPixelPercentage;
}
} }

View File

@ -0,0 +1,25 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models;
public record class SortingContainer : Properties.ISortingContainer
{
public Face Face { init; get; }
public Sorting Sorting { init; get; }
[JsonConstructor]
public SortingContainer(Face face, Sorting sorting)
{
Face = face;
Sorting = sorting;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -1,17 +0,0 @@
namespace View_by_Distance.Shared.Models.Stateless;
public interface IClosest
{
// 637972153144596958
// const int Digits = 3;
// const int Factor = 1000;
// const int MaximumPer = 50;
// const bool SkipIsWrongYear = false;
const int Digits = 3;
const int Factor = 1000;
const int MaximumPer = 50;
const double Tolerance = 0.6d;
}

View File

@ -6,6 +6,7 @@ public interface IFaceDistance
// const int MaximumPer = 999; // const int MaximumPer = 999;
const int HiddenImageFactor = 2; const int HiddenImageFactor = 2;
const int MaximumPer = 9999; const int Permyriad = 10000;
const double Tolerance = 0.2d;
} }

View File

@ -5,7 +5,6 @@ public interface ILocation
const double MinimumConfidence = 0.8d; const double MinimumConfidence = 0.8d;
const int Digits = 6; const int Digits = 6;
const double Tolerance = 0.6d;
const int Factor = 1000000; const int Factor = 1000000;
} }

View File

@ -10,5 +10,6 @@ public interface IMapping
const bool UseDeterministicHashCodeUnknownFaceKeyValuePairsForAddToMapping = false; const bool UseDeterministicHashCodeUnknownFaceKeyValuePairsForAddToMapping = false;
const bool UseDeterministicHashCodeUnknownFaceKeyValuePairsForSaveMapping = false; const bool UseDeterministicHashCodeUnknownFaceKeyValuePairsForSaveMapping = false;
const bool SaveFaceEncoding = false; const bool SaveFaceEncoding = false;
const bool SaveMapped = false;
} }

View File

@ -0,0 +1,13 @@
namespace View_by_Distance.Shared.Models.Stateless;
public interface ISorting
{
const int FacesToSkipAfterSortBeforeLoad = 0;
const int FacesToTakeAfterSortBeforeLoad = 21000;
const int MaximumPerFaceShouldBeHigh = 1000;
const int DaysDeltaTolerance = 700;
const int MaximumPerKey = 27;
const int Sigma = 3;
}

View File

@ -3,19 +3,31 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract class Age internal abstract class Age
{ {
internal static (int, TimeSpan) GetAge(DateTime minuend, DateTime subtrahend) internal static (int, TimeSpan) GetAge(long minuendTicks, long subtrahendTicks)
{ {
TimeSpan result; TimeSpan result;
int years = 0; int years = 0;
DateTime check = new(subtrahend.Ticks); DateTime check = new(subtrahendTicks);
for (int i = 0; i < int.MaxValue; i++) for (int i = 0; i < int.MaxValue; i++)
{ {
check = check.AddYears(1); check = check.AddYears(1);
if (check > minuend) if (check.Ticks > minuendTicks)
break; break;
years += 1; years += 1;
} }
result = new(minuend.Ticks - check.AddYears(-1).Ticks); result = new(minuendTicks - check.AddYears(-1).Ticks);
return (years, result);
}
internal static (int, TimeSpan) GetAge(long minuendTicks, DateTime subtrahend)
{
(int years, TimeSpan result) = GetAge(minuendTicks, subtrahend.Ticks);
return (years, result);
}
internal static (int, TimeSpan) GetAge(DateTime minuend, DateTime subtrahend)
{
(int years, TimeSpan result) = GetAge(minuend.Ticks, subtrahend.Ticks);
return (years, result); return (years, result);
} }

View File

@ -1,39 +0,0 @@
namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract class Closest
{
private static int Get(double rawAverage) => (int)(Math.Round(rawAverage, Stateless.IClosest.Digits) * Stateless.ILocation.Factor);
private static Models.Closest Get(Models.Face face, DateTime minimumDateTime, FaceDistance faceDistance)
{
Models.Closest result;
long? ticksDelta;
double minimum = faceDistance.Distances.Min();
double rawAverage = faceDistance.Distances.Average();
bool aboveTolerance = minimum >= Stateless.IClosest.Tolerance || rawAverage >= Stateless.IClosest.Tolerance;
if (faceDistance.IsWrongYear is null || faceDistance.IsWrongYear.Value)
ticksDelta = null;
else
{
ticksDelta = Math.Abs(faceDistance.MinimumDateTime.Ticks - minimumDateTime.Ticks);
if (faceDistance.MinimumDateTime < faceDistance.Mapping.PersonBirthday.Value)
ticksDelta *= 2;
else if (faceDistance.Mapping.ApproximateYears.HasValue && faceDistance.MinimumDateTime < DateTime.Now.AddYears(-faceDistance.Mapping.ApproximateYears.Value))
ticksDelta *= 2;
}
if (face.Location?.NormalizedPixelPercentage is null)
throw new NullReferenceException(nameof(face.Location.NormalizedPixelPercentage));
int average = Get(rawAverage);
result = new(aboveTolerance, average, face.Location.NormalizedPixelPercentage.Value, faceDistance.IsWrongYear, faceDistance.Mapping, minimum, faceDistance.MinimumDateTime, ticksDelta);
return result;
}
internal static Models.Closest[] GetCollection(Models.Face face, DateTime minimumDateTime, List<FaceDistance> faceDistances)
{
Models.Closest[] results;
Models.Closest[] closestCollection = (from l in faceDistances select Get(face, minimumDateTime, l)).ToArray();
results = (from l in closestCollection orderby l.Average, l.TicksDelta.HasValue, l.TicksDelta select l).ToArray();
return results;
}
}

View File

@ -37,21 +37,6 @@ internal abstract class Face
return jsonElements; return jsonElements;
} }
internal static List<Models.Sorting> GetSortingCollection(Models.Face face)
{
List<Models.Sorting> results = new();
Models.Sorting sorting;
if (face.FaceNumbers is not null)
{
foreach (int[] numbers in face.FaceNumbers)
{
sorting = Sorting.Get(numbers);
results.Add(sorting);
}
}
return results;
}
private static List<Models.Face> GetFaces(string jsonFileFullName, int? maximum) private static List<Models.Face> GetFaces(string jsonFileFullName, int? maximum)
{ {
List<Models.Face> results = new(); List<Models.Face> results = new();

View File

@ -0,0 +1,8 @@
namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract class FaceDistance
{
internal static double GetDefaultValue() => throw new Exception();
}

View File

@ -0,0 +1,6 @@
namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract class FaceDistanceContainer
{
}

View File

@ -3,6 +3,12 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface IAge public interface IAge
{ // ... { // ...
(int, TimeSpan) TestStatic_GetAge(long minuendTicks, long subtrahendTicks);
static (int, TimeSpan) GetAge(long minuendTicks, long subtrahendTicks) => Age.GetAge(minuendTicks, subtrahendTicks);
(int, TimeSpan) TestStatic_GetAge(long minuendTicks, DateTime subtrahend);
static (int, TimeSpan) GetAge(long minuendTicks, DateTime subtrahend) => Age.GetAge(minuendTicks, subtrahend);
(int, TimeSpan) TestStatic_GetAge(DateTime minuend, DateTime subtrahend); (int, TimeSpan) TestStatic_GetAge(DateTime minuend, DateTime subtrahend);
static (int, TimeSpan) GetAge(DateTime minuend, DateTime subtrahend) => Age.GetAge(minuend, subtrahend); static (int, TimeSpan) GetAge(DateTime minuend, DateTime subtrahend) => Age.GetAge(minuend, subtrahend);

View File

@ -1,10 +0,0 @@
namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface IClosest
{ // ...
Models.Closest[] TestStatic_Get(List<FaceDistance> faceDistances);
static Models.Closest[] GetCollection(Models.Face face, DateTime minimumDateTime, List<FaceDistance> faceDistances) => Closest.GetCollection(face, minimumDateTime, faceDistances);
}

View File

@ -18,9 +18,6 @@ public interface IFace
Models.Face[] TestStatic_Getα(Dictionary<FacePart, Models.FacePoint[]> faceParts); Models.Face[] TestStatic_Getα(Dictionary<FacePart, Models.FacePoint[]> faceParts);
static double? Getα(Dictionary<FacePart, Models.FacePoint[]> faceParts) => Face.Getα(faceParts); static double? Getα(Dictionary<FacePart, Models.FacePoint[]> faceParts) => Face.Getα(faceParts);
List<Models.Sorting> TestStatic_GetSortingCollection(Models.Face face);
static List<Models.Sorting> GetSortingCollection(Models.Face face) => Face.GetSortingCollection(face);
int?[] TestStatic_GetInts(List<Models.Face> faces); int?[] TestStatic_GetInts(List<Models.Face> faces);
static int?[] GetInts(List<Models.Face> faces) => static int?[] GetInts(List<Models.Face> faces) =>
(from l in faces where l.FaceEncoding is not null && l.Location?.NormalizedPixelPercentage is not null select l.Location?.NormalizedPixelPercentage).ToArray(); (from l in faces where l.FaceEncoding is not null && l.Location?.NormalizedPixelPercentage is not null select l.Location?.NormalizedPixelPercentage).ToArray();

View File

@ -0,0 +1,10 @@
namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface IFaceDistance
{ // ...
double TestStatic_GetDefaultValue();
static double GetDefaultValue() => FaceDistance.GetDefaultValue();
}

View File

@ -0,0 +1,6 @@
namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface IFaceDistanceContainer
{ // ...
}

View File

@ -3,10 +3,14 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface IFaceFileSystem : IFileSystem public interface IFaceFileSystem : IFileSystem
{ // ... { // ...
void TestStatic_SearchForMissingFile(string fullFileName, FileInfo fileInfo, string dataFullFileName); void TestStatic_SearchForMissingFile(string fullFileName, FileInfo fileInfo, string dataFullFileName) =>
Models.FaceFileSystem[][] TestStatic_GetFaceFileSystemCollection(string requestPath, string rootResultsDirectory, (string RootResultsDirectoryAbsoluteUri, string C_ResizeContentDirectory, string D_FacesContentDirectory, string E_DistanceCollectionDirectory) tuple, string selectedFileFullName); SearchForMissingFile(fullFileName, fileInfo, dataFullFileName);
static void SearchForMissingFile(string fullFileName, FileInfo fileInfo, string dataFullFileName) =>
FaceFileSystem.SearchForMissingFile(fullFileName, fileInfo, dataFullFileName);
static void SearchForMissingFile(string fullFileName, FileInfo fileInfo, string dataFullFileName) => FaceFileSystem.SearchForMissingFile(fullFileName, fileInfo, dataFullFileName); Models.FaceFileSystem[] TestStatic_GetFaceFileSystemCollection(string requestPath, string rootResultsDirectory, (string RootResultsDirectoryAbsoluteUri, string C_ResizeContentDirectory, string D_FacesContentDirectory, string E_DistanceCollectionDirectory) tuple, string selectedFileFullName) =>
static Models.FaceFileSystem[] GetFaceFileSystemCollection(string requestPath, (string RootResultsDirectoryAbsoluteUri, string C_ResizeContentDirectory, string D_FacesContentDirectory, string E_DistanceCollectionDirectory) tuple, string selectedFileFullName) => FaceFileSystem.GetFaceFileSystemCollection(requestPath, tuple, selectedFileFullName); GetFaceFileSystemCollection(requestPath, tuple, selectedFileFullName);
static Models.FaceFileSystem[] GetFaceFileSystemCollection(string requestPath, (string RootResultsDirectoryAbsoluteUri, string C_ResizeContentDirectory, string D_FacesContentDirectory, string E_DistanceCollectionDirectory) tuple, string selectedFileFullName) =>
FaceFileSystem.GetFaceFileSystemCollection(requestPath, tuple, selectedFileFullName);
} }

View File

@ -1,18 +0,0 @@
namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface IMapping
{ // ...
double? TestStatic_GetReversedDeterministicHashCodeKey(string file);
static double? GetReversedDeterministicHashCodeKey(bool keyValuePairsAny, Dictionary<int, List<Models.Face>> keyValuePairs, string file) =>
Mapping.GetReversedDeterministicHashCodeKey(keyValuePairsAny, keyValuePairs, file);
double TestStatic_GetDeterministicHashCodeKey(Models.Item item, Models.Face face);
static double GetDeterministicHashCodeKey(Models.Item item, Models.Face face) =>
Mapping.GetDeterministicHashCodeKey(item, face);
double TestStatic_GetDeterministicHashCodeKey(Models.Item item, Models.Closest closest);
static double GetDeterministicHashCodeKey(Models.Item item, Models.Closest closest) =>
Mapping.GetDeterministicHashCodeKey(item, closest);
}

View File

@ -3,15 +3,24 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface ILocation public interface ILocation
{ // ... { // ...
Models.Location? TestStatic_GetLocation(Models.Location? location, int height, int width, int zCount); Models.Location? TestStatic_GetLocation(Models.Location? location, int height, int width, int zCount) =>
GetLocation(location, height, width, zCount);
static Models.Location? GetLocation(Models.Location? location, int height, int width, int zCount) => static Models.Location? GetLocation(Models.Location? location, int height, int width, int zCount) =>
location is null ? null : new(location.Confidence, height, location, width, zCount); location is null ? null : new(location.Confidence, height, location, width, zCount);
Models.Location? TestStatic_GetLocation(int factor, Models.Location? location, int height, int width, int zCount); Models.Location? TestStatic_GetLocation(int factor, Models.Location? location, int height, int width, int zCount) =>
GetLocation(location, height, width, zCount);
static Models.Location? GetLocation(int factor, Models.Location? location, int height, int width, int zCount) => static Models.Location? GetLocation(int factor, Models.Location? location, int height, int width, int zCount) =>
location is null ? null : new(location.Confidence, factor, height, location, width, zCount); location is null ? null : new(location.Confidence, factor, height, location, width, zCount);
int?[] TestStatic_GetInts(List<Models.Location> locations); int?[] TestStatic_GetInts(List<Models.Location> locations) =>
static int?[] GetInts(List<Models.Location> locations) => (from l in locations where l.NormalizedPixelPercentage is not null select l.NormalizedPixelPercentage).ToArray(); GetInts(locations);
static int?[] GetInts(List<Models.Location> locations) =>
(from l in locations where l.NormalizedPixelPercentage is not null select l.NormalizedPixelPercentage).ToArray();
int TestStatic_GetNormalizedPixelPercentage(int bottom, int height, int left, int right, int top, int width, int zCount) =>
GetNormalizedPixelPercentage(bottom, height, left, right, top, width, zCount);
static int GetNormalizedPixelPercentage(int bottom, int height, int left, int right, int top, int width, int zCount) =>
Location.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, zCount);
} }

View File

@ -0,0 +1,17 @@
namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface IMapping
{ // ...
static string GetDeterministicHashCodeKeyDisplay(int id, int normalizedPixelPercentage)
=> $"{id}.{normalizedPixelPercentage}";
static double GetDeterministicHashCodeKeyValue(int id, int normalizedPixelPercentage)
=> Math.Round(double.Parse($"{id}.{normalizedPixelPercentage}"), Stateless.ILocation.Digits);
(int?, int?) TestStatic_GetReversedDeterministicHashCodeKey(bool keyValuePairsAny, Dictionary<int, List<Models.Face>> keyValuePairs, string file) =>
GetReversedDeterministicHashCodeKey(keyValuePairsAny, keyValuePairs, file);
static (int?, int?) GetReversedDeterministicHashCodeKey(bool keyValuePairsAny, Dictionary<int, List<Models.Face>> keyValuePairs, string file) =>
Mapping.GetReversedDeterministicHashCodeKey(keyValuePairsAny, keyValuePairs, file);
}

View File

@ -11,7 +11,8 @@ public interface IPersonBirthday
// ... // ...
double? TestStatic_GetAge(Models.PersonBirthday birthday); double? TestStatic_GetAge(Models.PersonBirthday birthday) =>
GetAge(birthday);
static double? GetAge(Models.PersonBirthday birthday) => static double? GetAge(Models.PersonBirthday birthday) =>
PersonBirthday.GetAge(birthday); PersonBirthday.GetAge(birthday);
@ -30,10 +31,16 @@ public interface IPersonBirthday
static string GetFileName(Models.PersonBirthday personBirthday) => static string GetFileName(Models.PersonBirthday personBirthday) =>
PersonBirthday.GetFileName(personBirthday); PersonBirthday.GetFileName(personBirthday);
(int, TimeSpan) TestStatic_GetAge(DateTime dateTime, Models.PersonBirthday birthday); (int, TimeSpan) TestStatic_GetAge(DateTime dateTime, Models.PersonBirthday birthday) =>
GetAge(dateTime, birthday);
static (int, TimeSpan) GetAge(DateTime dateTime, Models.PersonBirthday birthday) => static (int, TimeSpan) GetAge(DateTime dateTime, Models.PersonBirthday birthday) =>
PersonBirthday.GetAge(dateTime, birthday); PersonBirthday.GetAge(dateTime, birthday);
(int, TimeSpan) TestStatic_GetAge(long dateTimeTicks, Models.PersonBirthday birthday) =>
GetAge(dateTimeTicks, birthday);
static (int, TimeSpan) GetAge(long dateTimeTicks, Models.PersonBirthday birthday) =>
PersonBirthday.GetAge(dateTimeTicks, birthday);
string TestStatic_GetFormatted(Models.PersonBirthday personBirthday) => string TestStatic_GetFormatted(Models.PersonBirthday personBirthday) =>
PersonBirthday.GetFormatted(personBirthday); PersonBirthday.GetFormatted(personBirthday);
static string GetFormatted(Models.PersonBirthday personBirthday) => static string GetFormatted(Models.PersonBirthday personBirthday) =>
@ -44,16 +51,25 @@ public interface IPersonBirthday
static Models.PersonBirthday? GetPersonBirthday(string personKey) => static Models.PersonBirthday? GetPersonBirthday(string personKey) =>
PersonBirthday.GetPersonBirthday(personKey); PersonBirthday.GetPersonBirthday(personKey);
bool TestStatic_IsCounterPersonBirthday(Models.PersonBirthday personBirthday);
static bool IsCounterPersonBirthday(Models.PersonBirthday personBirthday) =>
PersonBirthday.IsCounterPersonBirthday(personBirthday);
Models.PersonBirthday TestStatic_GetNextBirthDate(Properties.IStorage storage) => Models.PersonBirthday TestStatic_GetNextBirthDate(Properties.IStorage storage) =>
PersonBirthday.GetNextBirthDate(storage); PersonBirthday.GetNextBirthDate(storage);
static Models.PersonBirthday GetNextBirthDate(Properties.IStorage storage) => static Models.PersonBirthday GetNextBirthDate(Properties.IStorage storage) =>
PersonBirthday.GetNextBirthDate(storage); PersonBirthday.GetNextBirthDate(storage);
TimeSpan? TestStatic_Get(DateTime now, Models.PersonBirthday personBirthday) => TimeSpan? TestStatic_Get(DateTime minimumDateTime, Models.PersonBirthday personBirthday) =>
PersonBirthday.GetTimeSpan(now, isWrongYear: false, personBirthday); PersonBirthday.GetTimeSpan(minimumDateTime, isWrongYear: false, personBirthday);
static TimeSpan? GetTimeSpan(DateTime minimumDateTime, Models.PersonBirthday personBirthday) => static TimeSpan? GetTimeSpan(DateTime minimumDateTime, Models.PersonBirthday personBirthday) =>
PersonBirthday.GetTimeSpan(minimumDateTime, isWrongYear: false, personBirthday); PersonBirthday.GetTimeSpan(minimumDateTime, isWrongYear: false, personBirthday);
TimeSpan? TestStatic_Get(long minimumDateTimeTicks, bool? isWrongYear, Models.PersonBirthday personBirthday) =>
PersonBirthday.GetTimeSpan(minimumDateTimeTicks, isWrongYear, personBirthday);
static TimeSpan? GetTimeSpan(long minimumDateTimeTicks, bool? isWrongYear, Models.PersonBirthday personBirthday) =>
PersonBirthday.GetTimeSpan(minimumDateTimeTicks, isWrongYear, personBirthday);
string TestStatic_GetFileFullName(Properties.IStorage storage, Models.PersonBirthday personBirthday) => string TestStatic_GetFileFullName(Properties.IStorage storage, Models.PersonBirthday personBirthday) =>
PersonBirthday.GetFileFullName(storage, personBirthday); PersonBirthday.GetFileFullName(storage, personBirthday);
static string GetFileFullName(Properties.IStorage storage, Models.PersonBirthday personBirthday) => static string GetFileFullName(Properties.IStorage storage, Models.PersonBirthday personBirthday) =>
@ -69,4 +85,8 @@ public interface IPersonBirthday
static TimeSpan? GetTimeSpan(DateTime minimumDateTime, bool? isWrongYear, Models.PersonBirthday personBirthday) => static TimeSpan? GetTimeSpan(DateTime minimumDateTime, bool? isWrongYear, Models.PersonBirthday personBirthday) =>
PersonBirthday.GetTimeSpan(minimumDateTime, isWrongYear, personBirthday); PersonBirthday.GetTimeSpan(minimumDateTime, isWrongYear, personBirthday);
bool TestStatic_IsWrongYearFilterOrCounterPersonBirthday(bool? isWrongYear, Models.PersonBirthday personBirthday);
static bool IsWrongYearFilterOrCounterPersonBirthday(bool? isWrongYear, Models.PersonBirthday personBirthday) =>
PersonBirthday.IsWrongYearFilterOrCounterPersonBirthday(isWrongYear, personBirthday);
} }

View File

@ -3,10 +3,14 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface ISorting public interface ISorting
{ // ... { // ...
Models.Sorting TestStatic_GetSorting(int[] numbers); Models.Sorting[] TestStatic_Sort(List<Models.Sorting> collection) =>
static Models.Sorting GetSorting(int[] numbers) => Sorting.Get(numbers); Sort(collection);
static Models.Sorting[] Sort(List<Models.Sorting> collection) =>
(from l in collection orderby l.WithinRange, l.DistancePermyriad, l.DaysDelta select l).ToArray();
List<int[]> TestStatic_GetFaceNumbers(List<Models.Sorting> collection); Models.Sorting TestStatic_Get(Models.FaceDistance faceDistanceEncoding, Models.FaceDistance faceDistanceLength, bool anyLowerThanTolerance, List<(long lcl, long minimum, long maximum, long ucl)> personKeysRangesCollection) =>
static List<int[]> GetFaceNumbers(List<Models.Sorting> collection) => Sorting.GetFaceNumbers(collection); Get(faceDistanceEncoding, faceDistanceLength, anyLowerThanTolerance, personKeysRangesCollection);
static Models.Sorting Get(Models.FaceDistance faceDistanceEncoding, Models.FaceDistance faceDistanceLength, bool anyLowerThanTolerance, List<(long lcl, long minimum, long maximum, long ucl)> personKeysRangesCollection) =>
Sorting.Get(faceDistanceEncoding, faceDistanceLength, anyLowerThanTolerance, personKeysRangesCollection);
} }

View File

@ -0,0 +1,11 @@
namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface ISortingContainer
{ // ...
Models.SortingContainer[] TestStatic_Sort(List<Models.SortingContainer> collection) =>
Sort(collection);
static Models.SortingContainer[] Sort(List<Models.SortingContainer> collection) =>
(from l in collection orderby l.Sorting.WithinRange, l.Sorting.DistancePermyriad, l.Sorting.DaysDelta select l).ToArray();
}

View File

@ -3,4 +3,67 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract class Location internal abstract class Location
{ {
internal static int GetNormalizedPixelPercentage(int bottom, int height, int left, int right, int top, int width, int zCount)
{
int result;
double value;
double total = width * height;
Check(bottom, left, right, top, zCount);
double xCenter = left + ((right - left) / 2);
double yCenter = top + ((bottom - top) / 2);
double at = ((yCenter - 1) * width) + xCenter;
value = at / total;
if (value < 0)
value = 3;
result = (int)(Math.Round(value, Stateless.ILocation.Digits) * Stateless.ILocation.Factor);
return result;
}
internal static void Check(int bottom, int left, int right, int top, int zCount)
{
if (left < 0)
throw new Exception();
if (right < 0)
throw new Exception();
if (right < left)
throw new Exception();
if (top < 0)
throw new Exception();
if (bottom < 0)
throw new Exception();
if (bottom < top)
throw new Exception();
if (zCount < 0)
throw new Exception();
}
internal static void Check(int bottom, int height, int left, int right, int top, int width, int zCount)
{
if (bottom > height)
throw new Exception();
if (left > width)
throw new Exception();
if (right > width)
throw new Exception();
if (top > height)
throw new Exception();
if (zCount < 0)
throw new Exception();
}
internal static void Check(int bottom, int left, int? normalizedPixelPercentage, int right, int top, int zCount)
{
Check(bottom, left, right, top, zCount);
if (normalizedPixelPercentage.HasValue && normalizedPixelPercentage.Value < 0)
throw new Exception();
}
internal static void Check(int bottom, int height, int left, int? normalizedPixelPercentage, int right, int top, int width, int zCount)
{
Check(bottom, left, right, top, zCount);
Check(bottom, height, left, right, top, width, zCount);
if (normalizedPixelPercentage.HasValue && normalizedPixelPercentage.Value < 0)
throw new Exception();
}
} }

View File

@ -5,24 +5,11 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract class Mapping internal abstract class Mapping
{ {
private static double GetDeterministicHashCodeKey(int id, int normalizedPixelPercentage)
=> Math.Round(double.Parse($"{id}.{normalizedPixelPercentage}"), Stateless.ILocation.Digits);
internal static double GetDeterministicHashCodeKey(Models.Item item, Models.Closest closest)
{
double result;
if (item.Property?.Id is null || item.ImageFileHolder is null)
throw new NullReferenceException();
result = GetDeterministicHashCodeKey(item.Property.Id.Value, closest.NormalizedPixelPercentage);
return result;
}
internal static double GetDeterministicHashCodeKey(Models.Item item, Models.Face face) internal static double GetDeterministicHashCodeKey(Models.Item item, Models.Face face)
{ {
double result;
if (item.Property?.Id is null || item.ImageFileHolder is null || face.Location?.NormalizedPixelPercentage is null) if (item.Property?.Id is null || item.ImageFileHolder is null || face.Location?.NormalizedPixelPercentage is null)
throw new NullReferenceException(); throw new NullReferenceException();
result = GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location.NormalizedPixelPercentage.Value); double result = IMapping.GetDeterministicHashCodeKeyValue(item.Property.Id.Value, face.Location.NormalizedPixelPercentage.Value);
return result; return result;
} }
@ -37,7 +24,7 @@ internal abstract class Mapping
{ {
if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
continue; continue;
if (normalizedPixelPercentageValue != face.Location.NormalizedPixelPercentage.Value && deterministicHashCodeKey != GetDeterministicHashCodeKey(id, face.Location.NormalizedPixelPercentage.Value)) if (normalizedPixelPercentageValue != face.Location.NormalizedPixelPercentage.Value && deterministicHashCodeKey != IMapping.GetDeterministicHashCodeKeyValue(id, face.Location.NormalizedPixelPercentage.Value))
continue; continue;
collection.Add(face); collection.Add(face);
} }
@ -56,36 +43,46 @@ internal abstract class Mapping
} }
} }
private static double? GetReversedDeterministicHashCodeFromSegments(bool keyValuePairsAny, Dictionary<int, List<Models.Face>> keyValuePairs, string file, string[] segments) private static (int?, int?, double?) GetReversedDeterministicHashCodeKeysFromSegments(bool keyValuePairsAny, Dictionary<int, List<Models.Face>> keyValuePairs, string file, string[] segments)
{ {
double? result; double? result;
if (segments.Length != 3) if (segments.Length != 3)
throw new Exception(); throw new Exception();
string id = segments[0]; string id = segments[0];
int normalizedPixelPercentageValue;
string normalizedPixelPercentage = segments[1]; string normalizedPixelPercentage = segments[1];
if (!int.TryParse(id, out int idValue) || !int.TryParse(normalizedPixelPercentage, out int normalizedPixelPercentageValue)) if (!int.TryParse(id, out int idValue) | !int.TryParse(normalizedPixelPercentage, out normalizedPixelPercentageValue))
result = null; result = null;
else else
{ {
result = GetDeterministicHashCodeKey(idValue, normalizedPixelPercentageValue); result = IMapping.GetDeterministicHashCodeKeyValue(idValue, normalizedPixelPercentageValue);
if (keyValuePairsAny && keyValuePairs.ContainsKey(idValue)) if (keyValuePairsAny && keyValuePairs.ContainsKey(idValue))
UseKeyValuePairsSaveFaceEncoding(keyValuePairs, file, idValue, normalizedPixelPercentageValue, result.Value, $".{segments[2]}"); UseKeyValuePairsSaveFaceEncoding(keyValuePairs, file, idValue, normalizedPixelPercentageValue, result.Value, $".{segments[2]}");
} }
return result; return new(idValue, normalizedPixelPercentageValue, result);
} }
internal static double? GetReversedDeterministicHashCodeKey(bool keyValuePairsAny, Dictionary<int, List<Models.Face>> keyValuePairs, string file) internal static (int?, int?) GetReversedDeterministicHashCodeKey(bool keyValuePairsAny, Dictionary<int, List<Models.Face>> keyValuePairs, string file)
{ {
double? result; int? id;
int? normalizedPixelPercentage;
string fileName = Path.GetFileName(file); string fileName = Path.GetFileName(file);
if (fileName.Length < 2 || fileName[1..].Contains('-')) if (fileName.Length < 2 || fileName[1..].Contains('-'))
result = null; {
id = null;
normalizedPixelPercentage = null;
}
else else
{ {
string[] segments = fileName.Split('.'); string[] segments = fileName.Split('.');
result = GetReversedDeterministicHashCodeFromSegments(keyValuePairsAny, keyValuePairs, file, segments); (id, normalizedPixelPercentage, double? result) = GetReversedDeterministicHashCodeKeysFromSegments(keyValuePairsAny, keyValuePairs, file, segments);
if (result is null)
{
id = null;
normalizedPixelPercentage = null;
}
} }
return result; return new(id, normalizedPixelPercentage);
} }
} }

View File

@ -26,16 +26,53 @@ internal abstract class PersonBirthday
return result; return result;
} }
internal static TimeSpan? GetTimeSpan(DateTime minimumDateTime, bool? isWrongYear, Models.PersonBirthday personBirthday) internal static bool IsCounterPersonBirthday(Models.PersonBirthday personBirthday)
{
bool result;
if (personBirthday.Value.Year < 1900)
result = true;
else
result = false;
return result;
}
internal static bool IsWrongYearFilterOrCounterPersonBirthday(bool? isWrongYear, Models.PersonBirthday personBirthday)
{
bool result;
if (isWrongYear is null || isWrongYear.Value || IsCounterPersonBirthday(personBirthday))
result = true;
else
result = false;
return result;
}
internal static TimeSpan? GetTimeSpan(long minimumDateTimeTicks, bool? isWrongYear, Models.PersonBirthday personBirthday)
{ {
TimeSpan? timeSpan; TimeSpan? timeSpan;
if (isWrongYear is null || isWrongYear.Value || personBirthday.Value.Year < 1900) bool isWrongYearFilterOrCounterPersonBirthday = IsWrongYearFilterOrCounterPersonBirthday(isWrongYear, personBirthday);
if (isWrongYearFilterOrCounterPersonBirthday)
timeSpan = null; timeSpan = null;
else else
timeSpan = new(minimumDateTime.Ticks - personBirthday.Value.Ticks); timeSpan = new(minimumDateTimeTicks - personBirthday.Value.Ticks);
return timeSpan; return timeSpan;
} }
internal static TimeSpan? GetTimeSpan(DateTime minimumDateTime, bool? isWrongYear, Models.PersonBirthday personBirthday)
{
TimeSpan? timeSpan = GetTimeSpan(minimumDateTime.Ticks, isWrongYear, personBirthday);
return timeSpan;
}
internal static (int, TimeSpan) GetAge(long dateTimeTicks, Models.PersonBirthday birthday)
{
TimeSpan result;
int years;
if (birthday?.Value is null)
throw new NullReferenceException(nameof(birthday.Value));
(years, result) = Age.GetAge(dateTimeTicks, birthday.Value);
return (years, result);
}
internal static (int, TimeSpan) GetAge(DateTime dateTime, Models.PersonBirthday birthday) internal static (int, TimeSpan) GetAge(DateTime dateTime, Models.PersonBirthday birthday)
{ {
TimeSpan result; TimeSpan result;

View File

@ -3,48 +3,47 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract class Sorting internal abstract class Sorting
{ {
internal static Models.Sorting Get(int[] collection) internal static Models.Sorting Get(Models.FaceDistance faceDistanceEncoding, Models.FaceDistance faceDistanceLength, bool anyLowerThanTolerance, List<(long lcl, long minimum, long maximum, long ucl)> personKeysRangesCollection)
{ {
if (collection.Length != 5)
throw new Exception();
Models.Sorting result; Models.Sorting result;
int id = collection[3]; if (faceDistanceLength.Length is null)
int distance = collection[1]; throw new NotSupportedException();
int confidence = collection[2]; if (faceDistanceLength.NormalizedPixelPercentage is null)
int faceEncoding = collection[0]; throw new NotSupportedException();
int normalizedPixelPercentage = collection[4]; bool older;
result = new(confidence, distance, faceEncoding, id, normalizedPixelPercentage); int daysDelta;
int withinRange;
int distancePermyriad;
if (faceDistanceLength.Length.Value == 0 || (anyLowerThanTolerance && faceDistanceLength.Length.Value >= Stateless.IFaceDistance.Tolerance))
{
older = false;
daysDelta = 0;
withinRange = 0;
distancePermyriad = 0;
}
else
{
if (faceDistanceEncoding.MinimumDateTime is null || faceDistanceLength.MinimumDateTime is null)
throw new NotSupportedException();
List<int> withinRanges = new();
long ticks = faceDistanceEncoding.MinimumDateTime.Value.Ticks;
TimeSpan timeSpan = new(faceDistanceLength.MinimumDateTime.Value.Ticks - ticks);
older = timeSpan.TotalMilliseconds < 0;
daysDelta = (int)Math.Round(Math.Abs(timeSpan.TotalDays), 0);
distancePermyriad = (int)(faceDistanceLength.Length.Value / Stateless.IFaceDistance.Tolerance * Stateless.IFaceDistance.Permyriad);
foreach ((long lcl, long minimum, long maximum, long ucl) in personKeysRangesCollection)
{
if (ticks > minimum && ticks < maximum)
withinRanges.Add(0);
else if (ticks > lcl && ticks < ucl)
withinRanges.Add(1);
else
withinRanges.Add(2);
}
withinRange = withinRanges.Max();
}
result = new(daysDelta, distancePermyriad, faceDistanceLength.Id, faceDistanceLength.NormalizedPixelPercentage.Value, older, withinRange);
return result; return result;
} }
internal static List<int[]> GetFaceNumbers(List<Models.Sorting> collection)
{
List<int[]> results = new();
List<int> faceNumbers;
collection = (from l in collection orderby l.FaceEncoding is not null, l.Distance, l.Confidence descending, l.Id, l.NormalizedPixelPercentage select l).ToList();
foreach (Models.Sorting sorting in collection)
{
faceNumbers = new();
if (sorting.FaceEncoding is null)
faceNumbers.Add(Stateless.ILocation.Factor);
else
faceNumbers.Add(Stateless.ILocation.Factor * 2);
if (sorting.Distance is null)
faceNumbers.Add(Stateless.ILocation.Factor);
else
faceNumbers.Add((int)(Math.Round(sorting.Distance.Value, Stateless.ILocation.Digits) * Stateless.ILocation.Factor));
if (sorting.Confidence is null)
faceNumbers.Add(Stateless.ILocation.Factor);
else
faceNumbers.Add((int)(Math.Round(sorting.Confidence.Value, Stateless.ILocation.Digits) * Stateless.ILocation.Factor));
faceNumbers.Add(sorting.Id);
if (sorting.NormalizedPixelPercentage is null)
faceNumbers.Add(Stateless.ILocation.Factor);
else
faceNumbers.Add(sorting.NormalizedPixelPercentage.Value);
results.Add(faceNumbers.ToArray());
}
return results;
}
} }

View File

@ -0,0 +1,6 @@
namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract class SortingContainer
{
}

View File

@ -19,7 +19,6 @@ public class Configuration
[Display(Name = "Ignore Extensions"), Required] public string[] IgnoreExtensions { get; set; } [Display(Name = "Ignore Extensions"), Required] public string[] IgnoreExtensions { get; set; }
[Display(Name = "Ignore Relative Paths"), Required] public string[] IgnoreRelativePaths { get; set; } [Display(Name = "Ignore Relative Paths"), Required] public string[] IgnoreRelativePaths { get; set; }
[Display(Name = "Julie Phares Copy Birthdays"), Required] public string[] JuliePhares { get; set; } [Display(Name = "Julie Phares Copy Birthdays"), Required] public string[] JuliePhares { get; set; }
[Display(Name = "Load Or Create Then Save Directory Distance Results"), Required] public string[] LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions { get; set; }
[Display(Name = "Load Or Create Then Save Distance Results"), Required] public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { get; set; } [Display(Name = "Load Or Create Then Save Distance Results"), Required] public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { get; set; }
[Display(Name = "Load Or Create Then Save Image Faces Results"), Required] public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; } [Display(Name = "Load Or Create Then Save Image Faces Results"), Required] public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; }
[Display(Name = "Load Or Create Then Save Index"), Required] public bool? LoadOrCreateThenSaveIndex { get; set; } [Display(Name = "Load Or Create Then Save Index"), Required] public bool? LoadOrCreateThenSaveIndex { get; set; }
@ -129,8 +128,6 @@ public class Configuration
throw new NullReferenceException(nameof(configuration.TestDistanceResults)); throw new NullReferenceException(nameof(configuration.TestDistanceResults));
if (configuration.ValidResolutions is null) if (configuration.ValidResolutions is null)
throw new NullReferenceException(nameof(configuration.ValidResolutions)); throw new NullReferenceException(nameof(configuration.ValidResolutions));
if (configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions is null)
configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions = Array.Empty<string>();
if (configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions is null) if (configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions is null)
configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions = Array.Empty<string>(); configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions = Array.Empty<string>();
if (configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions is null) if (configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions is null)
@ -149,7 +146,6 @@ public class Configuration
configuration.IgnoreExtensions, configuration.IgnoreExtensions,
configuration.IgnoreRelativePaths, configuration.IgnoreRelativePaths,
configuration.JuliePhares, configuration.JuliePhares,
configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions,
configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions, configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions,
configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions, configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions,
configuration.LoadOrCreateThenSaveIndex.Value, configuration.LoadOrCreateThenSaveIndex.Value,

View File

@ -18,7 +18,6 @@ public class Configuration
public string[] IgnoreExtensions { init; get; } public string[] IgnoreExtensions { init; get; }
public string[] IgnoreRelativePaths { init; get; } public string[] IgnoreRelativePaths { init; get; }
public string[] JuliePhares { init; get; } public string[] JuliePhares { init; get; }
public string[] LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions { init; get; }
public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { init; get; } public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { init; get; }
public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { init; get; } public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { init; get; }
public bool LoadOrCreateThenSaveIndex { init; get; } public bool LoadOrCreateThenSaveIndex { init; get; }
@ -53,7 +52,7 @@ public class Configuration
public string[] ValidResolutions { init; get; } public string[] ValidResolutions { init; get; }
[JsonConstructor] [JsonConstructor]
public Configuration(Property.Models.Configuration propertyConfiguration, bool checkJsonForDistanceResults, int crossDirectoryMaxItemsInDistanceCollection, int distanceFactor, bool forceFaceLastWriteTimeToCreationTime, bool forceMetadataLastWriteTimeToCreationTime, bool forceResizeLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRelativePaths, string[] juliePhares, string[] loadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions, bool loadOrCreateThenSaveIndex, int locationConfidenceFactor, int? mappedMaxIndex, int maxItemsInDistanceCollection, string[] mixedYearRelativePaths, string modelDirectory, string modelName, int numberOfJitters, int numberOfTimesToUpsample, string outputExtension, int outputQuality, string[] outputResolutions, bool overrideForFaceImages, bool overrideForFaceLandmarkImages, bool overrideForResizeImages, int paddingLoops, string predictorModelName, bool propertiesChangedForDistance, bool propertiesChangedForFaces, bool propertiesChangedForIndex, bool propertiesChangedForMetadata, bool propertiesChangedForResize, bool reverse, string[] saveFaceLandmarkForOutputResolutions, bool saveFullYearOfRandomFiles, bool saveResizedSubfiles, string[] saveShortcutsForOutputResolutions, bool skipSearch, bool testDistanceResults, string[] validResolutions) public Configuration(Property.Models.Configuration propertyConfiguration, bool checkJsonForDistanceResults, int crossDirectoryMaxItemsInDistanceCollection, int distanceFactor, bool forceFaceLastWriteTimeToCreationTime, bool forceMetadataLastWriteTimeToCreationTime, bool forceResizeLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRelativePaths, string[] juliePhares, string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions, bool loadOrCreateThenSaveIndex, int locationConfidenceFactor, int? mappedMaxIndex, int maxItemsInDistanceCollection, string[] mixedYearRelativePaths, string modelDirectory, string modelName, int numberOfJitters, int numberOfTimesToUpsample, string outputExtension, int outputQuality, string[] outputResolutions, bool overrideForFaceImages, bool overrideForFaceLandmarkImages, bool overrideForResizeImages, int paddingLoops, string predictorModelName, bool propertiesChangedForDistance, bool propertiesChangedForFaces, bool propertiesChangedForIndex, bool propertiesChangedForMetadata, bool propertiesChangedForResize, bool reverse, string[] saveFaceLandmarkForOutputResolutions, bool saveFullYearOfRandomFiles, bool saveResizedSubfiles, string[] saveShortcutsForOutputResolutions, bool skipSearch, bool testDistanceResults, string[] validResolutions)
{ {
_PropertyConfiguration = propertyConfiguration; _PropertyConfiguration = propertyConfiguration;
CheckJsonForDistanceResults = checkJsonForDistanceResults; CheckJsonForDistanceResults = checkJsonForDistanceResults;
@ -65,7 +64,6 @@ public class Configuration
IgnoreExtensions = ignoreExtensions; IgnoreExtensions = ignoreExtensions;
IgnoreRelativePaths = ignoreRelativePaths; IgnoreRelativePaths = ignoreRelativePaths;
JuliePhares = juliePhares; JuliePhares = juliePhares;
LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions = loadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions;
LoadOrCreateThenSaveDistanceResultsForOutputResolutions = loadOrCreateThenSaveDistanceResultsForOutputResolutions; LoadOrCreateThenSaveDistanceResultsForOutputResolutions = loadOrCreateThenSaveDistanceResultsForOutputResolutions;
LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = loadOrCreateThenSaveImageFacesResultsForOutputResolutions; LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = loadOrCreateThenSaveImageFacesResultsForOutputResolutions;
LoadOrCreateThenSaveIndex = loadOrCreateThenSaveIndex; LoadOrCreateThenSaveIndex = loadOrCreateThenSaveIndex;

View File

@ -68,6 +68,9 @@ public class UnitTestCalculations
Assert.IsFalse(_PropertyConfiguration is null); Assert.IsFalse(_PropertyConfiguration is null);
} }
[TestMethod]
public void TestMethodGetSort() => Assert.IsTrue(new bool[] { true, false }.OrderByDescending(l => l).First());
[TestMethod] [TestMethod]
public void TestMethodGetAge() public void TestMethodGetAge()
{ {
@ -77,4 +80,39 @@ public class UnitTestCalculations
Assert.IsTrue(age.Value > 42.6092); Assert.IsTrue(age.Value > 42.6092);
} }
[TestMethod]
public void TestMethodRound()
{
Assert.IsTrue(Shared.Models.Stateless.ILocation.Digits == 6);
Assert.IsTrue(Shared.Models.Stateless.ILocation.Factor == 1000000);
double valueA = 0.00001d;
int checkA = (int)(Math.Round(valueA, Shared.Models.Stateless.ILocation.Digits) * Shared.Models.Stateless.ILocation.Factor);
Assert.IsTrue(checkA == 10);
double valueB = 0.01d;
int checkB = (int)(Math.Round(valueB, Shared.Models.Stateless.ILocation.Digits) * Shared.Models.Stateless.ILocation.Factor);
Assert.IsTrue(checkB == 10000);
Assert.IsTrue(checkB > checkA);
}
[TestMethod]
public void TestMethodRoundB()
{
const int DistanceDigits = 3;
const int DistanceFactor = 1000;
const int ToleranceAfterFactor = 600;
Assert.IsTrue(DistanceDigits == 3);
Assert.IsTrue(DistanceFactor == 1000);
Assert.IsTrue(Shared.Models.Stateless.IFaceDistance.Tolerance == 0.6d);
Assert.IsTrue(ToleranceAfterFactor == 600);
double valueA = 0.00001d;
int checkA = (int)(Math.Round(valueA, Shared.Models.Stateless.ILocation.Digits) * Shared.Models.Stateless.ILocation.Factor);
Assert.IsTrue(checkA == 10);
double valueB = 0.01d;
int checkB = (int)(Math.Round(valueB, Shared.Models.Stateless.ILocation.Digits) * Shared.Models.Stateless.ILocation.Factor);
Assert.IsTrue(checkB == 10000);
Assert.IsTrue(checkB > checkA);
int checkC = (int)(Shared.Models.Stateless.IFaceDistance.Tolerance * DistanceFactor);
Assert.IsTrue(checkC == ToleranceAfterFactor);
}
} }

View File

@ -100,7 +100,7 @@ public class UnitTestResize
bottom = 10; bottom = 10;
width = 100; width = 100;
height = 100; height = 100;
normalizedPixelPercentage = Location.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1); normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1);
Assert.IsTrue(normalizedPixelPercentage == 40500); Assert.IsTrue(normalizedPixelPercentage == 40500);
left = 50; left = 50;
top = 50; top = 50;
@ -108,7 +108,7 @@ public class UnitTestResize
bottom = 60; bottom = 60;
width = 100; width = 100;
height = 100; height = 100;
normalizedPixelPercentage = Location.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1); normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1);
Assert.IsTrue(normalizedPixelPercentage == 545500); Assert.IsTrue(normalizedPixelPercentage == 545500);
} }
@ -123,7 +123,7 @@ public class UnitTestResize
bottom = 260; bottom = 260;
width = 500; width = 500;
height = 500; height = 500;
normalizedPixelPercentage = Location.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1); normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1);
Assert.IsTrue(normalizedPixelPercentage == 499000); Assert.IsTrue(normalizedPixelPercentage == 499000);
left = 490; left = 490;
top = 490; top = 490;
@ -131,7 +131,7 @@ public class UnitTestResize
bottom = 510; bottom = 510;
width = 1000; width = 1000;
height = 1000; height = 1000;
normalizedPixelPercentage = Location.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1); normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1);
Assert.IsTrue(normalizedPixelPercentage == 499500); Assert.IsTrue(normalizedPixelPercentage == 499500);
} }
@ -146,7 +146,7 @@ public class UnitTestResize
bottom = 80; bottom = 80;
width = 100; width = 100;
height = 100; height = 100;
normalizedPixelPercentage = Location.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1); normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1);
Assert.IsTrue(normalizedPixelPercentage == 594000); Assert.IsTrue(normalizedPixelPercentage == 594000);
left = 20; left = 20;
top = 40; top = 40;
@ -154,7 +154,7 @@ public class UnitTestResize
bottom = 80; bottom = 80;
width = 100; width = 100;
height = 100; height = 100;
normalizedPixelPercentage = Location.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 10); normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 10);
Assert.IsTrue(normalizedPixelPercentage == 594000); Assert.IsTrue(normalizedPixelPercentage == 594000);
} }

View File

@ -19,7 +19,6 @@ public class Configuration
[Display(Name = "Ignore Extensions"), Required] public string[] IgnoreExtensions { get; set; } [Display(Name = "Ignore Extensions"), Required] public string[] IgnoreExtensions { get; set; }
[Display(Name = "Ignore Relative Paths"), Required] public string[] IgnoreRelativePaths { get; set; } [Display(Name = "Ignore Relative Paths"), Required] public string[] IgnoreRelativePaths { get; set; }
[Display(Name = "Julie Phares Copy Birthdays"), Required] public string[] JuliePhares { get; set; } [Display(Name = "Julie Phares Copy Birthdays"), Required] public string[] JuliePhares { get; set; }
[Display(Name = "Load Or Create Then Save Directory Distance Results"), Required] public string[] LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions { get; set; }
[Display(Name = "Load Or Create Then Save Distance Results"), Required] public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { get; set; } [Display(Name = "Load Or Create Then Save Distance Results"), Required] public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { get; set; }
[Display(Name = "Load Or Create Then Save Image Faces Results"), Required] public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; } [Display(Name = "Load Or Create Then Save Image Faces Results"), Required] public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; }
[Display(Name = "Load Or Create Then Save Index"), Required] public bool? LoadOrCreateThenSaveIndex { get; set; } [Display(Name = "Load Or Create Then Save Index"), Required] public bool? LoadOrCreateThenSaveIndex { get; set; }
@ -129,8 +128,6 @@ public class Configuration
throw new NullReferenceException(nameof(configuration.TestDistanceResults)); throw new NullReferenceException(nameof(configuration.TestDistanceResults));
if (configuration.ValidResolutions is null) if (configuration.ValidResolutions is null)
throw new NullReferenceException(nameof(configuration.ValidResolutions)); throw new NullReferenceException(nameof(configuration.ValidResolutions));
if (configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions is null)
configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions = Array.Empty<string>();
if (configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions is null) if (configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions is null)
configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions = Array.Empty<string>(); configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions = Array.Empty<string>();
if (configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions is null) if (configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions is null)
@ -149,7 +146,6 @@ public class Configuration
configuration.IgnoreExtensions, configuration.IgnoreExtensions,
configuration.IgnoreRelativePaths, configuration.IgnoreRelativePaths,
configuration.JuliePhares, configuration.JuliePhares,
configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions,
configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions, configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions,
configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions, configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions,
configuration.LoadOrCreateThenSaveIndex.Value, configuration.LoadOrCreateThenSaveIndex.Value,

View File

@ -18,7 +18,6 @@ public class Configuration
public string[] IgnoreExtensions { init; get; } public string[] IgnoreExtensions { init; get; }
public string[] IgnoreRelativePaths { init; get; } public string[] IgnoreRelativePaths { init; get; }
public string[] JuliePhares { init; get; } public string[] JuliePhares { init; get; }
public string[] LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions { init; get; }
public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { init; get; } public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { init; get; }
public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { init; get; } public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { init; get; }
public bool LoadOrCreateThenSaveIndex { init; get; } public bool LoadOrCreateThenSaveIndex { init; get; }
@ -53,7 +52,7 @@ public class Configuration
public string[] ValidResolutions { init; get; } public string[] ValidResolutions { init; get; }
[JsonConstructor] [JsonConstructor]
public Configuration(Property.Models.Configuration propertyConfiguration, bool checkJsonForDistanceResults, int crossDirectoryMaxItemsInDistanceCollection, int distanceFactor, bool forceFaceLastWriteTimeToCreationTime, bool forceMetadataLastWriteTimeToCreationTime, bool forceResizeLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRelativePaths, string[] juliePhares, string[] loadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions, bool loadOrCreateThenSaveIndex, int locationConfidenceFactor, int? mappedMaxIndex, int maxItemsInDistanceCollection, string[] mixedYearRelativePaths, string modelDirectory, string modelName, int numberOfJitters, int numberOfTimesToUpsample, string outputExtension, int outputQuality, string[] outputResolutions, bool overrideForFaceImages, bool overrideForFaceLandmarkImages, bool overrideForResizeImages, int paddingLoops, string predictorModelName, bool propertiesChangedForDistance, bool propertiesChangedForFaces, bool propertiesChangedForIndex, bool propertiesChangedForMetadata, bool propertiesChangedForResize, bool reverse, string[] saveFaceLandmarkForOutputResolutions, bool saveFullYearOfRandomFiles, bool saveResizedSubfiles, string[] saveShortcutsForOutputResolutions, bool skipSearch, bool testDistanceResults, string[] validResolutions) public Configuration(Property.Models.Configuration propertyConfiguration, bool checkJsonForDistanceResults, int crossDirectoryMaxItemsInDistanceCollection, int distanceFactor, bool forceFaceLastWriteTimeToCreationTime, bool forceMetadataLastWriteTimeToCreationTime, bool forceResizeLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRelativePaths, string[] juliePhares, string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions, bool loadOrCreateThenSaveIndex, int locationConfidenceFactor, int? mappedMaxIndex, int maxItemsInDistanceCollection, string[] mixedYearRelativePaths, string modelDirectory, string modelName, int numberOfJitters, int numberOfTimesToUpsample, string outputExtension, int outputQuality, string[] outputResolutions, bool overrideForFaceImages, bool overrideForFaceLandmarkImages, bool overrideForResizeImages, int paddingLoops, string predictorModelName, bool propertiesChangedForDistance, bool propertiesChangedForFaces, bool propertiesChangedForIndex, bool propertiesChangedForMetadata, bool propertiesChangedForResize, bool reverse, string[] saveFaceLandmarkForOutputResolutions, bool saveFullYearOfRandomFiles, bool saveResizedSubfiles, string[] saveShortcutsForOutputResolutions, bool skipSearch, bool testDistanceResults, string[] validResolutions)
{ {
_PropertyConfiguration = propertyConfiguration; _PropertyConfiguration = propertyConfiguration;
CheckJsonForDistanceResults = checkJsonForDistanceResults; CheckJsonForDistanceResults = checkJsonForDistanceResults;
@ -65,7 +64,6 @@ public class Configuration
IgnoreExtensions = ignoreExtensions; IgnoreExtensions = ignoreExtensions;
IgnoreRelativePaths = ignoreRelativePaths; IgnoreRelativePaths = ignoreRelativePaths;
JuliePhares = juliePhares; JuliePhares = juliePhares;
LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions = loadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions;
LoadOrCreateThenSaveDistanceResultsForOutputResolutions = loadOrCreateThenSaveDistanceResultsForOutputResolutions; LoadOrCreateThenSaveDistanceResultsForOutputResolutions = loadOrCreateThenSaveDistanceResultsForOutputResolutions;
LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = loadOrCreateThenSaveImageFacesResultsForOutputResolutions; LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = loadOrCreateThenSaveImageFacesResultsForOutputResolutions;
LoadOrCreateThenSaveIndex = loadOrCreateThenSaveIndex; LoadOrCreateThenSaveIndex = loadOrCreateThenSaveIndex;

View File

@ -214,9 +214,9 @@ public class UnitTestFace
List<(int, Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary<FacePart, FacePoint[]>? FaceParts)> collection; List<(int, Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary<FacePart, FacePoint[]>? FaceParts)> collection;
collection = faceRecognition.GetCollection(image, includeFaceEncoding: true, includeFaceParts: true, sortByNormalizedPixelPercentage: true); collection = faceRecognition.GetCollection(image, includeFaceEncoding: true, includeFaceParts: true, sortByNormalizedPixelPercentage: true);
Assert.IsTrue(collection.Count == 2); Assert.IsTrue(collection.Count == 2);
FaceRecognitionDotNet.FaceEncoding[] faceEncodings = (from l in collection where l.FaceEncoding is not null select l.FaceEncoding).ToArray(); List<FaceDistance> faceDistanceEncodings = (from l in collection where l.FaceEncoding is not null select new FaceDistance(l.FaceEncoding)).ToList();
List<double> faceDistances = FaceRecognition.FaceDistances(faceEncodings, faceEncodings[0]); List<FaceDistance> faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncodings[0]);
Assert.IsTrue(faceDistances.Count == 2); Assert.IsTrue(faceDistanceLengths.Count == 2);
Assert.IsNotNull(sourceFileName); Assert.IsNotNull(sourceFileName);
} }

View File

@ -29,6 +29,7 @@
"c": "When looping through all files and file not in collection path&name or date is different from collection value", "c": "When looping through all files and file not in collection path&name or date is different from collection value",
"d": "Get id in normal fashion", "d": "Get id in normal fashion",
"e": "If id is in collection update collection to new path/name", "e": "If id is in collection update collection to new path/name",
"f": "If not save and add to collection" "f": "If not save and add to collection",
"g": "Nicéphore Niépce in 1826 or 1827"
} }
} }