Closest is usable with
NamedDeterministicHashCodeIdAndFaceLocationIndex
This commit is contained in:
@ -6,6 +6,7 @@ using View_by_Distance.Metadata.Models;
|
||||
using View_by_Distance.Property.Models;
|
||||
using View_by_Distance.Resize.Models;
|
||||
using View_by_Distance.Shared.Models.Stateless;
|
||||
using WindowsShortcutFactory;
|
||||
|
||||
namespace View_by_Distance.Instance.Models;
|
||||
|
||||
@ -198,11 +199,13 @@ internal class E_Distance
|
||||
throw new NullReferenceException(nameof(_Configuration.CheckJsonForDistanceResults));
|
||||
if (_Configuration.PropertiesChangedForDistance is null)
|
||||
throw new NullReferenceException(nameof(_Configuration.PropertiesChangedForDistance));
|
||||
Item item;
|
||||
string json;
|
||||
bool check = false;
|
||||
string parentCheck;
|
||||
FileHolder? fileHolder;
|
||||
string usingRelativePath;
|
||||
DateTime? dateTime = null;
|
||||
string dCollectionDirectory;
|
||||
FileInfo[] fileInfoCollection;
|
||||
bool updateDateWhenMatches = false;
|
||||
List<string[]> directories = new();
|
||||
@ -216,26 +219,37 @@ internal class E_Distance
|
||||
eResultsFullGroupDirectory,
|
||||
contentDescription: ".tvs File",
|
||||
singletonDescription: string.Empty,
|
||||
collectionDescription: "n json file(s) for each face found (one to many)");
|
||||
collectionDescription: "n json file(s) for each face found (one to many)",
|
||||
converted: true);
|
||||
for (int i = 0; i < filteredItems.Length; i++)
|
||||
{
|
||||
fileHolder = filteredItems[i].ImageFileHolder;
|
||||
if (fileHolder is null)
|
||||
item = filteredItems[i];
|
||||
if (item.ImageFileHolder is null || item.Property?.Id is null)
|
||||
continue;
|
||||
directoryInfo = new System.IO.DirectoryInfo(Path.Combine(directoryInfoCollection[0].Replace("<>", "[]"), fileHolder.NameWithoutExtension));
|
||||
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 (directoryInfo.Parent?.Parent is null)
|
||||
throw new Exception();
|
||||
parentCheck = Path.Combine(directoryInfo.Parent.Parent.FullName, directoryInfo.Name);
|
||||
if (Directory.Exists(parentCheck))
|
||||
if (Directory.Exists(usingRelativePath))
|
||||
{
|
||||
foreach (string file in Directory.GetFiles(parentCheck))
|
||||
File.Delete(file);
|
||||
Directory.Delete(parentCheck);
|
||||
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("<>", "()"), fileHolder.NameWithoutExtension));
|
||||
tvsDirectoryInfo = new System.IO.DirectoryInfo(Path.Combine(directoryInfoCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension));
|
||||
directories.Add(new string[] { directoryInfo.FullName, tvsDirectoryInfo.FullName });
|
||||
if (_Configuration.CheckJsonForDistanceResults.Value && directoryInfo.Exists)
|
||||
{
|
||||
@ -517,7 +531,7 @@ internal class E_Distance
|
||||
return results;
|
||||
}
|
||||
|
||||
private static Closest? GetClosestParallelFor(float maxMinimum, DateTime minimumDateTime, bool? isWrongYear, Shared.Models.Properties.IFace face, FaceEncoding faceEncoding, (DateTime MinimumDateTime, bool? IsWrongYear, Shared.Models.PersonBirthday PersonBirthday, FaceEncoding[] FaceEncodings) tuple)
|
||||
private static Closest? GetClosestParallelFor(DateTime minimumDateTime, bool? isWrongYear, Shared.Models.Properties.IFace face, FaceEncoding faceEncoding, (DateTime MinimumDateTime, bool? IsWrongYear, Shared.Models.PersonBirthday PersonBirthday, FaceEncoding[] FaceEncodings) tuple)
|
||||
{
|
||||
Closest? result;
|
||||
if (isWrongYear.HasValue && !isWrongYear.Value && minimumDateTime < tuple.PersonBirthday.Value)
|
||||
@ -526,19 +540,20 @@ internal class E_Distance
|
||||
{
|
||||
List<double> faceDistances = FaceRecognition.FaceDistances(tuple.FaceEncodings, faceEncoding);
|
||||
result = new(face.LocationIndex, tuple.MinimumDateTime, tuple.IsWrongYear, tuple.PersonBirthday, faceDistances);
|
||||
if (result.Minimum > maxMinimum)
|
||||
if (result.Minimum > Closest.MaximumMinimum)
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<Closest> GetClosestCollection(int maxDegreeOfParallelism, List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> collection, float maxMinimum, DateTime itemMinimumDateTime, bool? itemIsWrongYear, Shared.Models.Properties.IFace face)
|
||||
private static Closest[] GetClosestCollection(int maxDegreeOfParallelism, List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> collection, DateTime itemMinimumDateTime, bool? itemIsWrongYear, Shared.Models.Properties.IFace face)
|
||||
{
|
||||
List<Closest> results;
|
||||
Closest[] results;
|
||||
List<Closest> closestCollection;
|
||||
FaceEncoding faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
|
||||
if (maxDegreeOfParallelism == 1)
|
||||
{
|
||||
results = new();
|
||||
closestCollection = new();
|
||||
Closest closest;
|
||||
List<double> faceDistances;
|
||||
foreach ((DateTime minimumDateTime, bool? isWrongYear, Shared.Models.PersonBirthday personBirthday, FaceEncoding[] faceEncodings) in collection)
|
||||
@ -547,35 +562,36 @@ internal class E_Distance
|
||||
continue;
|
||||
faceDistances = FaceRecognition.FaceDistances(faceEncodings, faceEncoding);
|
||||
closest = new(face.LocationIndex, minimumDateTime, isWrongYear, personBirthday, faceDistances);
|
||||
if (closest.Minimum > maxMinimum)
|
||||
if (closest.Minimum > Closest.MaximumMinimum)
|
||||
continue;
|
||||
results.Add(closest);
|
||||
closestCollection.Add(closest);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
results = new();
|
||||
closestCollection = new();
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
||||
_ = Parallel.For(0, collection.Count, parallelOptions, i =>
|
||||
{
|
||||
Closest? closest = GetClosestParallelFor(maxMinimum, itemMinimumDateTime, itemIsWrongYear, face, faceEncoding, collection[i]);
|
||||
Closest? closest = GetClosestParallelFor(itemMinimumDateTime, itemIsWrongYear, face, faceEncoding, collection[i]);
|
||||
if (closest is not null)
|
||||
{
|
||||
lock (results)
|
||||
results.Add(closest);
|
||||
lock (closestCollection)
|
||||
closestCollection.Add(closest);
|
||||
}
|
||||
});
|
||||
}
|
||||
results = Closest.Get(closestCollection);
|
||||
return results;
|
||||
}
|
||||
|
||||
private static void AddClosest(int maxDegreeOfParallelism, string argZero, List<Container> containers, List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> collection, bool skipIsWrongYear, int maxPer, float maxMinimum)
|
||||
private static void AddClosest(int maxDegreeOfParallelism, string argZero, List<Container> containers, List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> collection)
|
||||
{
|
||||
string key;
|
||||
Closest closest;
|
||||
bool? itemIsWrongYear;
|
||||
Closest[] closestCollection;
|
||||
DateTime? itemMinimumDateTime;
|
||||
List<Closest> closestCollection;
|
||||
Shared.Models.Properties.IFace face;
|
||||
Dictionary<string, int> results = new();
|
||||
foreach (Container container in containers)
|
||||
@ -592,7 +608,7 @@ internal class E_Distance
|
||||
if (itemMinimumDateTime is null)
|
||||
continue;
|
||||
(itemIsWrongYear, _) = item.IsWrongYear();
|
||||
if (skipIsWrongYear && itemIsWrongYear.HasValue && itemIsWrongYear.Value)
|
||||
if (Closest.SkipIsWrongYear && itemIsWrongYear.HasValue && itemIsWrongYear.Value)
|
||||
continue;
|
||||
item.Closest.Clear();
|
||||
for (int i = 0; i < item.Faces.Count; i++)
|
||||
@ -602,19 +618,21 @@ internal class E_Distance
|
||||
item.Closest.Add(closest);
|
||||
if (!face.Populated)
|
||||
continue;
|
||||
closestCollection = GetClosestCollection(maxDegreeOfParallelism, collection, maxMinimum, itemMinimumDateTime.Value, itemIsWrongYear, face);
|
||||
if (!closestCollection.Any())
|
||||
continue;
|
||||
closest = Closest.Get(closestCollection);
|
||||
if (closest.PersonBirthday is null)
|
||||
continue;
|
||||
key = Item.GetKey(closest.MinimumDateTime, closest.IsWrongYear, closest.PersonBirthday);
|
||||
if (!results.ContainsKey(key))
|
||||
results.Add(key, 0);
|
||||
else if (results[key] > maxPer)
|
||||
continue;
|
||||
results[key] += 1;
|
||||
item.Closest[0] = closest;
|
||||
closestCollection = GetClosestCollection(maxDegreeOfParallelism, collection, itemMinimumDateTime.Value, itemIsWrongYear, face);
|
||||
for (int j = 0; j < closestCollection.Length; j++)
|
||||
{
|
||||
closest = closestCollection[j];
|
||||
if (closest.PersonBirthday is null)
|
||||
continue;
|
||||
key = Item.GetKey(closest.MinimumDateTime, closest.IsWrongYear, closest.PersonBirthday);
|
||||
if (!results.ContainsKey(key))
|
||||
results.Add(key, 0);
|
||||
else if (results[key] > Closest.MaximumPer)
|
||||
continue;
|
||||
results[key] += 1;
|
||||
item.Closest[0] = closest;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -623,12 +641,9 @@ internal class E_Distance
|
||||
internal static List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> ParallelWork(int maxDegreeOfParallelism, string argZero, List<Container> containers)
|
||||
{
|
||||
List<(DateTime, bool?, Shared.Models.PersonBirthday, FaceEncoding[])> results;
|
||||
const int maxPer = 5;
|
||||
const float maxMinimum = 0.50f;
|
||||
const bool skipIsWrongYear = true;
|
||||
Dictionary<string, List<(DateTime, bool?, Shared.Models.PersonBirthday, Shared.Models.Properties.IFace)>> keyValuePairs = Item.GetKeyValuePairs(argZero, containers);
|
||||
results = GetThreeSigmaFaceEncodings(maxDegreeOfParallelism, keyValuePairs);
|
||||
AddClosest(maxDegreeOfParallelism, argZero, containers, results, skipIsWrongYear, maxPer, maxMinimum);
|
||||
AddClosest(maxDegreeOfParallelism, argZero, containers, results);
|
||||
return results;
|
||||
}
|
||||
|
||||
@ -692,17 +707,21 @@ internal class E_Distance
|
||||
}
|
||||
}
|
||||
|
||||
internal static void SaveClosest(string argZero, List<Container> containers, Dictionary<string, List<Shared.Models.Person>> peopleCollection, string eDistanceContentDirectory, string dFacesContentDirectory)
|
||||
internal static List<(FileHolder? resizedFileHolder, string directory, FileInfo? faceFileInfo, string checkFile, string shortcutFile)> GetClosest(string argZero, List<Container> containers, Dictionary<string, List<Shared.Models.Person>> peopleCollection, PropertyLogic propertyLogic, string eDistanceContentDirectory, string dFacesContentDirectory)
|
||||
{
|
||||
string copyFile;
|
||||
List<(FileHolder?, string, FileInfo?, string, string)> results = new();
|
||||
string checkFile;
|
||||
string directory;
|
||||
string personKey;
|
||||
string personName;
|
||||
string shortcutFile;
|
||||
FileInfo faceFileInfo;
|
||||
string? directoryName;
|
||||
string facesDirectory;
|
||||
string faceFullFileName;
|
||||
string personDirectory;
|
||||
Shared.Models.Person person;
|
||||
const string facePopulatedKey = "Closest";
|
||||
string deterministicHashCodeIdAndFaceLocationIndex;
|
||||
const string pattern = @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]";
|
||||
foreach (Container container in containers)
|
||||
{
|
||||
@ -723,31 +742,73 @@ internal class E_Distance
|
||||
{
|
||||
if (closest.Average is null || closest.FaceLocationIndex is null || closest.PersonBirthday is null)
|
||||
continue;
|
||||
deterministicHashCodeIdAndFaceLocationIndex = $"{closest.FaceLocationIndex.Value} - {item.Property.Id.Value}";
|
||||
if (propertyLogic.NamedDeterministicHashCodeIdAndFaceLocationIndex.Contains(deterministicHashCodeIdAndFaceLocationIndex))
|
||||
continue;
|
||||
personKey = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(closest.PersonBirthday);
|
||||
directory = Item.GetDirectory(eDistanceContentDirectory, facePopulatedKey, closest.MinimumDateTime, closest.IsWrongYear, closest.PersonBirthday, personKey);
|
||||
if (!Directory.Exists(directory))
|
||||
_ = Directory.CreateDirectory(directory);
|
||||
// checkFile = Path.Combine(directory, item.ImageFileHolder.Name);
|
||||
checkFile = Path.Combine(directory, $"{closest.FaceLocationIndex.Value} - {item.Property.Id.Value}{item.ImageFileHolder.ExtensionLowered}");
|
||||
if (peopleCollection.ContainsKey(personKey))
|
||||
if (!peopleCollection.ContainsKey(personKey))
|
||||
personDirectory = string.Empty;
|
||||
else
|
||||
{
|
||||
person = peopleCollection[personKey][0];
|
||||
directory = Path.Combine(directory, Regex.Replace(Shared.Models.Stateless.Methods.IPersonName.GetFullName(person.Name), pattern, string.Empty));
|
||||
if (!Directory.Exists(directory))
|
||||
_ = Directory.CreateDirectory(directory);
|
||||
personName = Shared.Models.Stateless.Methods.IPersonName.GetFullName(person.Name);
|
||||
personDirectory = Path.Combine(directory, Regex.Replace(personName, pattern, string.Empty));
|
||||
results.Add(new(null, personDirectory, null, string.Empty, string.Empty));
|
||||
}
|
||||
facesDirectory = string.Concat(dFacesContentDirectory, Path.Combine(directoryName, item.ImageFileHolder.NameWithoutExtension));
|
||||
faceFullFileName = Path.Combine(facesDirectory, $"{closest.FaceLocationIndex.Value} - {item.ImageFileHolder.NameWithoutExtension}.png");
|
||||
if (Directory.Exists(facesDirectory) && File.Exists(faceFullFileName))
|
||||
copyFile = faceFullFileName;
|
||||
faceFileInfo = new(Path.Combine(facesDirectory, $"{closest.FaceLocationIndex.Value} - {item.ImageFileHolder.NameWithoutExtension}.png"));
|
||||
checkFile = Path.Combine(directory, $"{deterministicHashCodeIdAndFaceLocationIndex}{item.ImageFileHolder.ExtensionLowered}");
|
||||
if (string.IsNullOrEmpty(personDirectory))
|
||||
shortcutFile = string.Empty;
|
||||
else
|
||||
copyFile = item.ResizedFileHolder.FullName;
|
||||
if (File.Exists(checkFile))
|
||||
continue;
|
||||
File.Copy(copyFile, checkFile);
|
||||
shortcutFile = Path.Combine(personDirectory, $"{deterministicHashCodeIdAndFaceLocationIndex}{item.ImageFileHolder.ExtensionLowered}.lnk");
|
||||
results.Add(new(item.ResizedFileHolder, directory, faceFileInfo, checkFile, shortcutFile));
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
internal static void SaveClosest(string argZero, List<Container> containers, Dictionary<string, List<Shared.Models.Person>> peopleCollection, PropertyLogic propertyLogic, string eDistanceContentDirectory, string dFacesContentDirectory)
|
||||
{
|
||||
WindowsShortcut windowsShortcut;
|
||||
List<(FileHolder? resizedFileHolder, string directory, FileInfo? faceFileInfo, string checkFile, string shortcutFile)> collection = GetClosest(argZero, containers, peopleCollection, propertyLogic, eDistanceContentDirectory, dFacesContentDirectory);
|
||||
string[] directories = (from l in collection select l.directory).Distinct().ToArray();
|
||||
foreach (string directory in directories)
|
||||
{
|
||||
if (string.IsNullOrEmpty(directory))
|
||||
continue;
|
||||
if (!Directory.Exists(directory))
|
||||
_ = Directory.CreateDirectory(directory);
|
||||
}
|
||||
foreach ((FileHolder? resizedFileHolder, string directory, FileInfo? faceFileInfo, string checkFile, string shortcutFile) in collection)
|
||||
{
|
||||
if (string.IsNullOrEmpty(directory) || string.IsNullOrEmpty(checkFile) || resizedFileHolder is null || faceFileInfo is null)
|
||||
continue;
|
||||
if (File.Exists(checkFile))
|
||||
continue;
|
||||
if (faceFileInfo.Directory is not null && faceFileInfo.Directory.Exists && faceFileInfo.Exists)
|
||||
File.Copy(faceFileInfo.FullName, checkFile);
|
||||
else
|
||||
File.Copy(resizedFileHolder.FullName, checkFile);
|
||||
}
|
||||
foreach ((FileHolder? resizedFileHolder, string directory, FileInfo? faceFileInfo, string checkFile, string shortcutFile) in collection)
|
||||
{
|
||||
if (string.IsNullOrEmpty(directory) || string.IsNullOrEmpty(checkFile) || resizedFileHolder is null || faceFileInfo is null)
|
||||
continue;
|
||||
if (string.IsNullOrEmpty(shortcutFile))
|
||||
continue;
|
||||
try
|
||||
{
|
||||
windowsShortcut = new() { Path = resizedFileHolder.FullName };
|
||||
windowsShortcut.Save(shortcutFile);
|
||||
windowsShortcut.Dispose();
|
||||
}
|
||||
catch (Exception)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user