PhotoPrism for more locations
This commit is contained in:
parent
a510019c1d
commit
37c7b6760d
@ -257,7 +257,7 @@ public partial class E_Distance
|
|||||||
{
|
{
|
||||||
useOldWay = i == 1;
|
useOldWay = i == 1;
|
||||||
sourceRectangle = Shared.Models.Stateless.Methods.ILocation.GetRectangle(checkRectangle, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, normalizedRectangle, face.OutputResolution, useOldWay);
|
sourceRectangle = Shared.Models.Stateless.Methods.ILocation.GetRectangle(checkRectangle, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, normalizedRectangle, face.OutputResolution, useOldWay);
|
||||||
intersectRectangle = System.Drawing.Rectangle.Intersect(sourceRectangle, checkRectangle);
|
intersectRectangle = System.Drawing.Rectangle.Intersect(checkRectangle, sourceRectangle);
|
||||||
if (intersectRectangle.Width == 0 || intersectRectangle.Height == 0)
|
if (intersectRectangle.Width == 0 || intersectRectangle.Height == 0)
|
||||||
continue;
|
continue;
|
||||||
percent = (double)intersectRectangle.Width * intersectRectangle.Height / (checkRectangle.Width * checkRectangle.Height);
|
percent = (double)intersectRectangle.Width * intersectRectangle.Height / (checkRectangle.Width * checkRectangle.Height);
|
||||||
|
@ -179,8 +179,11 @@ public partial class Form : System.Windows.Forms.Form
|
|||||||
_ProgressBar.Step = 1;
|
_ProgressBar.Step = 1;
|
||||||
bool isIgnoreExtension;
|
bool isIgnoreExtension;
|
||||||
_ProgressBar.Value = 0;
|
_ProgressBar.Value = 0;
|
||||||
|
string checkFileExtension;
|
||||||
bool skipOneAllAreNumbers;
|
bool skipOneAllAreNumbers;
|
||||||
DateTime? minimumDateTime;
|
DateTime? minimumDateTime;
|
||||||
|
const string jpg = ".jpg";
|
||||||
|
const string jpeg = ".jpeg";
|
||||||
_ProgressBar.Visible = true;
|
_ProgressBar.Visible = true;
|
||||||
bool isValidImageFormatExtension;
|
bool isValidImageFormatExtension;
|
||||||
string? extraLargeBitmapThumbnail;
|
string? extraLargeBitmapThumbnail;
|
||||||
@ -201,7 +204,15 @@ public partial class Form : System.Windows.Forms.Form
|
|||||||
{
|
{
|
||||||
skipOneAllAreNumbers = fileHolder.NameWithoutExtension[1..].All(l => char.IsNumber(l));
|
skipOneAllAreNumbers = fileHolder.NameWithoutExtension[1..].All(l => char.IsNumber(l));
|
||||||
if ((skipOneAllAreNumbers && fileHolder.NameWithoutExtension[0] == '-') || (skipOneAllAreNumbers && char.IsNumber(fileHolder.NameWithoutExtension[0])))
|
if ((skipOneAllAreNumbers && fileHolder.NameWithoutExtension[0] == '-') || (skipOneAllAreNumbers && char.IsNumber(fileHolder.NameWithoutExtension[0])))
|
||||||
|
{
|
||||||
|
if (fileHolder.ExtensionLowered == jpeg)
|
||||||
|
{
|
||||||
|
if (File.Exists($"{fileHolder.FullName}.id"))
|
||||||
|
File.Move($"{fileHolder.FullName}.id", Path.Combine(fileHolder.DirectoryName, $"{fileHolder.NameWithoutExtension}{jpg}.id"));
|
||||||
|
File.Move(fileHolder.FullName, Path.Combine(fileHolder.DirectoryName, $"{fileHolder.NameWithoutExtension}{jpg}"));
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!isIgnoreExtension && isValidImageFormatExtension)
|
if (!isIgnoreExtension && isValidImageFormatExtension)
|
||||||
extraLargeBitmapThumbnail = null;
|
extraLargeBitmapThumbnail = null;
|
||||||
@ -224,7 +235,8 @@ public partial class Form : System.Windows.Forms.Form
|
|||||||
dateTime = IProperty.GetDateTimeFromName(fileHolder);
|
dateTime = IProperty.GetDateTimeFromName(fileHolder);
|
||||||
if (dateTime is not null && minimumDateTime is not null && new TimeSpan(Math.Abs(minimumDateTime.Value.Ticks - dateTime.Value.Ticks)).TotalMinutes > 2)
|
if (dateTime is not null && minimumDateTime is not null && new TimeSpan(Math.Abs(minimumDateTime.Value.Ticks - dateTime.Value.Ticks)).TotalMinutes > 2)
|
||||||
{
|
{
|
||||||
checkFile = Path.Combine(fileHolder.DirectoryName, $"{dateTime.Value:yyyy-MM-dd}.{dateTime.Value.Ticks}{fileHolder.ExtensionLowered}");
|
checkFileExtension = fileHolder.ExtensionLowered == jpeg ? jpg : fileHolder.ExtensionLowered;
|
||||||
|
checkFile = Path.Combine(fileHolder.DirectoryName, $"{dateTime.Value:yyyy-MM-dd}.{dateTime.Value.Ticks}{checkFileExtension}");
|
||||||
if (checkFile == fileHolder.FullName || File.Exists(checkFile))
|
if (checkFile == fileHolder.FullName || File.Exists(checkFile))
|
||||||
continue;
|
continue;
|
||||||
File.Move(fileHolder.FullName, checkFile);
|
File.Move(fileHolder.FullName, checkFile);
|
||||||
@ -238,7 +250,8 @@ public partial class Form : System.Windows.Forms.Form
|
|||||||
if (fileHolder.DirectoryName is null)
|
if (fileHolder.DirectoryName is null)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
checkFile = Path.Combine(fileHolder.DirectoryName, $"{id.Value}{fileHolder.ExtensionLowered}");
|
checkFileExtension = fileHolder.ExtensionLowered == jpeg ? jpg : fileHolder.ExtensionLowered;
|
||||||
|
checkFile = Path.Combine(fileHolder.DirectoryName, $"{id.Value}{checkFileExtension}");
|
||||||
if (checkFile == fileHolder.FullName || File.Exists(checkFile))
|
if (checkFile == fileHolder.FullName || File.Exists(checkFile))
|
||||||
continue;
|
continue;
|
||||||
File.Move(fileHolder.FullName, checkFile);
|
File.Move(fileHolder.FullName, checkFile);
|
||||||
|
@ -43,7 +43,6 @@ public class D_Face
|
|||||||
private readonly int _FaceDistanceHiddenImageFactor;
|
private readonly int _FaceDistanceHiddenImageFactor;
|
||||||
private readonly EncoderParameters _EncoderParameters;
|
private readonly EncoderParameters _EncoderParameters;
|
||||||
private readonly ImageCodecInfo _HiddenImageCodecInfo;
|
private readonly ImageCodecInfo _HiddenImageCodecInfo;
|
||||||
private readonly bool _RetryImagesWithoutAFaceLocation;
|
|
||||||
private readonly bool _ForceFaceLastWriteTimeToCreationTime;
|
private readonly bool _ForceFaceLastWriteTimeToCreationTime;
|
||||||
private readonly EncoderParameters _HiddenEncoderParameters;
|
private readonly EncoderParameters _HiddenEncoderParameters;
|
||||||
private readonly JsonSerializerOptions _WriteIndentedAndWhenWritingNull;
|
private readonly JsonSerializerOptions _WriteIndentedAndWhenWritingNull;
|
||||||
@ -63,7 +62,6 @@ public class D_Face
|
|||||||
string modelDirectory,
|
string modelDirectory,
|
||||||
string modelName,
|
string modelName,
|
||||||
bool overrideForFaceImages,
|
bool overrideForFaceImages,
|
||||||
bool retryImagesWithoutAFaceLocation,
|
|
||||||
string predictorModelName,
|
string predictorModelName,
|
||||||
bool propertiesChangedForFaces)
|
bool propertiesChangedForFaces)
|
||||||
{
|
{
|
||||||
@ -81,7 +79,6 @@ public class D_Face
|
|||||||
_CheckDFaceAndUpWriteDates = checkDFaceAndUpWriteDates;
|
_CheckDFaceAndUpWriteDates = checkDFaceAndUpWriteDates;
|
||||||
_PropertiesChangedForFaces = propertiesChangedForFaces;
|
_PropertiesChangedForFaces = propertiesChangedForFaces;
|
||||||
_FaceDistanceHiddenImageFactor = faceDistanceHiddenImageFactor;
|
_FaceDistanceHiddenImageFactor = faceDistanceHiddenImageFactor;
|
||||||
_RetryImagesWithoutAFaceLocation = retryImagesWithoutAFaceLocation;
|
|
||||||
_ForceFaceLastWriteTimeToCreationTime = forceFaceLastWriteTimeToCreationTime;
|
_ForceFaceLastWriteTimeToCreationTime = forceFaceLastWriteTimeToCreationTime;
|
||||||
(Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(modelDirectory, modelName, predictorModelName);
|
(Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(modelDirectory, modelName, predictorModelName);
|
||||||
_Model = model;
|
_Model = model;
|
||||||
@ -215,7 +212,7 @@ public class D_Face
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Shared.Models.Face> GetFaces(Shared.Models.Property property, MappingFromItem mappingFromItem, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation)
|
private List<Shared.Models.Face> GetFaces(Shared.Models.Property property, MappingFromItem mappingFromItem, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, List<Location> locations)
|
||||||
{
|
{
|
||||||
if (_Log is null)
|
if (_Log is null)
|
||||||
throw new NullReferenceException(nameof(_Log));
|
throw new NullReferenceException(nameof(_Log));
|
||||||
@ -225,25 +222,18 @@ public class D_Face
|
|||||||
throw new NullReferenceException(nameof(_Configuration.NumberOfTimesToUpsample));
|
throw new NullReferenceException(nameof(_Configuration.NumberOfTimesToUpsample));
|
||||||
List<Shared.Models.Face> results = new();
|
List<Shared.Models.Face> results = new();
|
||||||
FaceRecognitionDotNet.Image? unknownImage;
|
FaceRecognitionDotNet.Image? unknownImage;
|
||||||
if (!mappingFromItem.ResizedFileHolder.Exists)
|
try
|
||||||
unknownImage = null;
|
{ unknownImage = FaceRecognition.LoadImageFile(mappingFromItem.ResizedFileHolder.FullName); }
|
||||||
else
|
catch (Exception)
|
||||||
{
|
{
|
||||||
try
|
unknownImage = null;
|
||||||
{ unknownImage = FaceRecognition.LoadImageFile(mappingFromItem.ResizedFileHolder.FullName); }
|
_Log.Info(string.Concat(new StackFrame().GetMethod()?.Name, " <", mappingFromItem.ResizedFileHolder.FullName, ">"));
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
unknownImage = null;
|
|
||||||
_Log.Info(string.Concat(new StackFrame().GetMethod()?.Name, " <", mappingFromItem.ResizedFileHolder.FullName, ">"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (unknownImage is null)
|
if (unknownImage is not null)
|
||||||
results.Add(new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, location: null));
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
List<(Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary<FacePart, FacePoint[]>? FaceParts)> collection;
|
List<(Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary<FacePart, FacePoint[]>? FaceParts)> collection;
|
||||||
FaceRecognition faceRecognition = new(_Configuration.NumberOfJitters.Value, _Configuration.NumberOfTimesToUpsample.Value, _Model, _ModelParameter, _PredictorModel);
|
FaceRecognition faceRecognition = new(_Configuration.NumberOfJitters.Value, _Configuration.NumberOfTimesToUpsample.Value, _Model, _ModelParameter, _PredictorModel);
|
||||||
collection = faceRecognition.GetCollection(unknownImage, includeFaceEncoding: true, includeFaceParts: true);
|
collection = faceRecognition.GetCollection(unknownImage, locations, includeFaceEncoding: true, includeFaceParts: true);
|
||||||
if (!collection.Any())
|
if (!collection.Any())
|
||||||
results.Add(new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, location: null));
|
results.Add(new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, location: null));
|
||||||
else
|
else
|
||||||
@ -268,8 +258,6 @@ public class D_Face
|
|||||||
unknownImage.Dispose();
|
unknownImage.Dispose();
|
||||||
faceRecognition.Dispose();
|
faceRecognition.Dispose();
|
||||||
}
|
}
|
||||||
if (!results.Any())
|
|
||||||
throw new Exception();
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,12 +291,13 @@ public class D_Face
|
|||||||
|
|
||||||
#pragma warning restore CA1416
|
#pragma warning restore CA1416
|
||||||
|
|
||||||
public List<Shared.Models.Face> GetFaces(string dResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation)
|
public List<Shared.Models.Face> GetFaces(string dResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection)
|
||||||
{
|
{
|
||||||
List<Shared.Models.Face>? results;
|
List<Shared.Models.Face>? results;
|
||||||
if (string.IsNullOrEmpty(dResultsFullGroupDirectory))
|
if (string.IsNullOrEmpty(dResultsFullGroupDirectory))
|
||||||
throw new NullReferenceException(nameof(dResultsFullGroupDirectory));
|
throw new NullReferenceException(nameof(dResultsFullGroupDirectory));
|
||||||
string json;
|
string json;
|
||||||
|
List<Location> locations = 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) };
|
||||||
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();
|
||||||
string dCollectionFile = Path.Combine(dResultsFullGroupDirectory, "[]", _Configuration.ResultAllInOne, $"{mappingFromItem.Id}{mappingFromItem.ImageFileHolder.ExtensionLowered}.json");
|
string dCollectionFile = Path.Combine(dResultsFullGroupDirectory, "[]", _Configuration.ResultAllInOne, $"{mappingFromItem.Id}{mappingFromItem.ImageFileHolder.ExtensionLowered}.json");
|
||||||
@ -345,18 +334,21 @@ public class D_Face
|
|||||||
parseExceptions.Add(nameof(D_Face));
|
parseExceptions.Add(nameof(D_Face));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (results is null || (_RetryImagesWithoutAFaceLocation && results.Count == 1 && results[0].Location is null))
|
if (mappingFromPhotoPrismCollection is not null && results is not null)
|
||||||
|
locations.AddRange(Shared.Models.Stateless.Methods.ILocation.GetLocations(mappingFromPhotoPrismCollection, results));
|
||||||
|
if (results is null || locations.Any())
|
||||||
{
|
{
|
||||||
bool wasNull = results is null;
|
results = GetFaces(property, mappingFromItem, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, locations);
|
||||||
results = GetFaces(property, mappingFromItem, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation);
|
if (!results.Any())
|
||||||
if (wasNull || (!wasNull && results.Any(l => l.Location is not null)))
|
File.Move(mappingFromItem.ResizedFileHolder.FullName, $"{mappingFromItem.ResizedFileHolder.FullName}.err");
|
||||||
|
else
|
||||||
{
|
{
|
||||||
json = JsonSerializer.Serialize(results, _WriteIndentedAndWhenWritingNull);
|
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))
|
||||||
{
|
{
|
||||||
if (!_ForceFaceLastWriteTimeToCreationTime && (!fileInfo.Exists || fileInfo.LastWriteTime == fileInfo.CreationTime))
|
if (!_ForceFaceLastWriteTimeToCreationTime)
|
||||||
subFileTuples.Add(new Tuple<string, DateTime>(nameof(D_Face), DateTime.Now));
|
subFileTuples.Add(new Tuple<string, DateTime>(nameof(D_Face), DateTime.Now));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -370,126 +362,6 @@ public class D_Face
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteAllText(Dictionary<string, List<RelativeLocation>>? results, List<DateTime> dateTimes, FileInfo fileInfo)
|
|
||||||
{
|
|
||||||
string json = JsonSerializer.Serialize(results, _WriteIndentedAndWhenWritingNull);
|
|
||||||
bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime;
|
|
||||||
DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max();
|
|
||||||
if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime))
|
|
||||||
{
|
|
||||||
if (!_ForceFaceLastWriteTimeToCreationTime && (!fileInfo.Exists || fileInfo.LastWriteTime == fileInfo.CreationTime))
|
|
||||||
; // subFileTuples.Add(new Tuple<string, DateTime>(nameof(D_Face), DateTime.Now));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime);
|
|
||||||
fileInfo.Refresh();
|
|
||||||
// subFileTuples.Add(new Tuple<string, DateTime>(nameof(D_Face), fileInfo.CreationTime));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dictionary<string, List<RelativeLocation>> GetRelativeLocations(string outputResolution, string dResultsDateGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, string original, Dictionary<string, int[]> imageResizeKeyValuePairs, List<Shared.Models.Face> faces)
|
|
||||||
{
|
|
||||||
Dictionary<string, List<RelativeLocation>>? results;
|
|
||||||
if (string.IsNullOrEmpty(dResultsDateGroupDirectory))
|
|
||||||
throw new NullReferenceException(nameof(dResultsDateGroupDirectory));
|
|
||||||
if (!imageResizeKeyValuePairs.ContainsKey(original))
|
|
||||||
throw new Exception();
|
|
||||||
if (!imageResizeKeyValuePairs.ContainsKey(outputResolution))
|
|
||||||
throw new Exception();
|
|
||||||
string json;
|
|
||||||
decimal? h, l, t, w;
|
|
||||||
RelativeLocation relativeLocation;
|
|
||||||
List<RelativeLocation> relativeLocations = new();
|
|
||||||
int[] resize = imageResizeKeyValuePairs[outputResolution];
|
|
||||||
string key = $"{resize[0].ToString().PadLeft(6, '0')}.{resize[1].ToString().PadLeft(6, '0')}";
|
|
||||||
string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) };
|
|
||||||
List<DateTime> dateTimes = (from d in subFileTuples where changesFrom.Contains(d.Item1) select d.Item2).ToList();
|
|
||||||
string dCollectionDirectory = Path.Combine(dResultsDateGroupDirectory, "[]", _Configuration.ResultAllInOne);
|
|
||||||
string dCollectionFile = Path.Combine(dCollectionDirectory, $"{mappingFromItem.Id}{mappingFromItem.ImageFileHolder.ExtensionLowered}.json");
|
|
||||||
if (!Directory.Exists(dCollectionDirectory))
|
|
||||||
_ = Directory.CreateDirectory(dCollectionDirectory);
|
|
||||||
FileInfo fileInfo = new(dCollectionFile);
|
|
||||||
if (_ForceFaceLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete")))
|
|
||||||
{
|
|
||||||
File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName);
|
|
||||||
fileInfo.Refresh();
|
|
||||||
}
|
|
||||||
if (_ForceFaceLastWriteTimeToCreationTime && fileInfo.Exists && fileInfo.LastWriteTime != fileInfo.CreationTime)
|
|
||||||
{
|
|
||||||
File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime);
|
|
||||||
fileInfo.Refresh();
|
|
||||||
}
|
|
||||||
if (_PropertiesChangedForFaces)
|
|
||||||
results = null;
|
|
||||||
else if (!fileInfo.Exists)
|
|
||||||
results = null;
|
|
||||||
else if (_CheckDFaceAndUpWriteDates && dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime)
|
|
||||||
results = null;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
json = Shared.Models.Stateless.Methods.IFace.GetJson(fileInfo.FullName);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
results = JsonSerializer.Deserialize<Dictionary<string, List<RelativeLocation>>>(json);
|
|
||||||
if (results is null)
|
|
||||||
throw new NullReferenceException(nameof(results));
|
|
||||||
bool added = false;
|
|
||||||
relativeLocations.Clear();
|
|
||||||
foreach (KeyValuePair<string, List<RelativeLocation>> keyValuePair in results)
|
|
||||||
relativeLocations.AddRange(keyValuePair.Value);
|
|
||||||
if (!results.ContainsKey(key))
|
|
||||||
results.Add(key, new());
|
|
||||||
foreach (Shared.Models.Face face in faces)
|
|
||||||
{
|
|
||||||
if (face.Location is null || face.OutputResolution is null)
|
|
||||||
continue;
|
|
||||||
(h, l, t, w) = Shared.Models.Stateless.Methods.ILocation.GetHeightLeftTopWidth(face.Location, face.OutputResolution);
|
|
||||||
if (h is null || l is null || t is null || w is null)
|
|
||||||
continue;
|
|
||||||
relativeLocation = new(face.Location.Confidence, h.Value.ToString(), l.Value.ToString(), t.Value.ToString(), w.Value.ToString());
|
|
||||||
if (relativeLocations.Any(r => r.Match(h, l, t, w)))
|
|
||||||
continue;
|
|
||||||
if (!added)
|
|
||||||
added = true;
|
|
||||||
results[key].Add(relativeLocation);
|
|
||||||
}
|
|
||||||
if (added)
|
|
||||||
{
|
|
||||||
List<(string Key, List<RelativeLocation> Value)> sort = new();
|
|
||||||
foreach (KeyValuePair<string, List<RelativeLocation>> keyValuePair in results)
|
|
||||||
sort.Add(new(keyValuePair.Key, keyValuePair.Value));
|
|
||||||
results.Clear();
|
|
||||||
foreach ((string k, List<RelativeLocation> v) in sort.OrderBy(l => l.Key))
|
|
||||||
results.Add(k, v.OrderByDescending(l => l.Confidence).ToList());
|
|
||||||
WriteAllText(results, dateTimes, fileInfo);
|
|
||||||
}
|
|
||||||
// subFileTuples.Add(new Tuple<string, DateTime>(nameof(D_Face), fileInfo.LastWriteTime));
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
results = null;
|
|
||||||
parseExceptions.Add(nameof(D_Face));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (results is null)
|
|
||||||
{
|
|
||||||
results = new() { { key, new() } };
|
|
||||||
foreach (Shared.Models.Face face in faces)
|
|
||||||
{
|
|
||||||
if (face.Location is null || face.OutputResolution is null)
|
|
||||||
continue;
|
|
||||||
(h, l, t, w) = Shared.Models.Stateless.Methods.ILocation.GetHeightLeftTopWidth(face.Location, face.OutputResolution);
|
|
||||||
if (h is null || l is null || t is null || w is null)
|
|
||||||
continue;
|
|
||||||
relativeLocation = new(face.Location.Confidence, h.Value.ToString(), l.Value.ToString(), t.Value.ToString(), w.Value.ToString());
|
|
||||||
results[key].Add(relativeLocation);
|
|
||||||
}
|
|
||||||
WriteAllText(results, dateTimes, fileInfo);
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SaveFaces(string dResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, MappingFromItem mappingFromItem, string facesDirectory, List<Shared.Models.Face> faces)
|
public bool SaveFaces(string dResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, MappingFromItem mappingFromItem, string facesDirectory, List<Shared.Models.Face> faces)
|
||||||
{
|
{
|
||||||
FileInfo fileInfo;
|
FileInfo fileInfo;
|
||||||
|
@ -198,7 +198,7 @@ public class FaceRecognition : DisposableObject
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<(Location, FaceEncoding?, Dictionary<FacePart, FacePoint[]>?)> GetCollection(Image image, bool includeFaceEncoding, bool includeFaceParts)
|
public List<(Location, FaceEncoding?, Dictionary<FacePart, FacePoint[]>?)> GetCollection(Image image, List<Location> locations, bool includeFaceEncoding, bool includeFaceParts)
|
||||||
{
|
{
|
||||||
List<(Location, FaceEncoding?, Dictionary<FacePart, FacePoint[]>?)> results = new();
|
List<(Location, FaceEncoding?, Dictionary<FacePart, FacePoint[]>?)> results = new();
|
||||||
if (image is null)
|
if (image is null)
|
||||||
@ -207,7 +207,7 @@ public class FaceRecognition : DisposableObject
|
|||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
if (_PredictorModel == PredictorModel.Custom)
|
if (_PredictorModel == PredictorModel.Custom)
|
||||||
throw new NotSupportedException("FaceRecognition.PredictorModel.Custom is not supported.");
|
throw new NotSupportedException("FaceRecognition.PredictorModel.Custom is not supported.");
|
||||||
List<Location> locations = GetLocations(image);
|
locations.AddRange(GetLocations(image));
|
||||||
List<FullObjectDetection> fullObjectDetections = GetFullObjectDetections(image, locations);
|
List<FullObjectDetection> fullObjectDetections = GetFullObjectDetections(image, locations);
|
||||||
if (fullObjectDetections.Count != locations.Count)
|
if (fullObjectDetections.Count != locations.Count)
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
|
@ -33,9 +33,11 @@ public partial class DlibDotNet
|
|||||||
private readonly List<string> _Exceptions;
|
private readonly List<string> _Exceptions;
|
||||||
private readonly IsEnvironment _IsEnvironment;
|
private readonly IsEnvironment _IsEnvironment;
|
||||||
private readonly bool _PropertyRootExistedBefore;
|
private readonly bool _PropertyRootExistedBefore;
|
||||||
|
private readonly PersonContainer[] _PersonContainers;
|
||||||
private readonly Models.Configuration _Configuration;
|
private readonly Models.Configuration _Configuration;
|
||||||
private readonly bool _ArgZeroIsConfigurationRootDirectory;
|
private readonly bool _ArgZeroIsConfigurationRootDirectory;
|
||||||
private readonly Map.Models.Configuration _MapConfiguration;
|
private readonly Map.Models.Configuration _MapConfiguration;
|
||||||
|
private readonly Dictionary<string, List<MappingFromPhotoPrism>> _FileNameToCollection;
|
||||||
|
|
||||||
public DlibDotNet(
|
public DlibDotNet(
|
||||||
List<string> args,
|
List<string> args,
|
||||||
@ -46,13 +48,13 @@ public partial class DlibDotNet
|
|||||||
bool isSilent,
|
bool isSilent,
|
||||||
IConsole console)
|
IConsole console)
|
||||||
{
|
{
|
||||||
_Console = console;
|
|
||||||
string message;
|
string message;
|
||||||
|
_Console = console;
|
||||||
_AppSettings = appSettings;
|
_AppSettings = appSettings;
|
||||||
|
_FileNameToCollection = new();
|
||||||
_IsEnvironment = isEnvironment;
|
_IsEnvironment = isEnvironment;
|
||||||
long ticks = DateTime.Now.Ticks;
|
long ticks = DateTime.Now.Ticks;
|
||||||
_Exceptions = new List<string>();
|
_Exceptions = new List<string>();
|
||||||
PersonContainer[] personContainers;
|
|
||||||
_Log = Serilog.Log.ForContext<DlibDotNet>();
|
_Log = Serilog.Log.ForContext<DlibDotNet>();
|
||||||
Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot);
|
Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot);
|
||||||
Models.Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration);
|
Models.Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration);
|
||||||
@ -94,7 +96,6 @@ public partial class DlibDotNet
|
|||||||
configuration.ModelDirectory,
|
configuration.ModelDirectory,
|
||||||
configuration.ModelName,
|
configuration.ModelName,
|
||||||
configuration.OverrideForFaceImages,
|
configuration.OverrideForFaceImages,
|
||||||
configuration.RetryImagesWithoutAFaceLocation,
|
|
||||||
configuration.PredictorModelName,
|
configuration.PredictorModelName,
|
||||||
configuration.PropertiesChangedForFaces);
|
configuration.PropertiesChangedForFaces);
|
||||||
}
|
}
|
||||||
@ -106,7 +107,7 @@ public partial class DlibDotNet
|
|||||||
_MapConfiguration = Get(configuration, _Faces.FileNameExtension, _Faces.HiddenFileNameExtension, _FaceParts.FileNameExtension);
|
_MapConfiguration = Get(configuration, _Faces.FileNameExtension, _Faces.HiddenFileNameExtension, _FaceParts.FileNameExtension);
|
||||||
_Distance = new(configuration.DistanceMoveUnableToMatch, configuration.DistanceRenameToMatch, _Configuration.FaceConfidencePercent, configuration.RangeDistanceTolerance, configuration.RangeFaceConfidence);
|
_Distance = new(configuration.DistanceMoveUnableToMatch, configuration.DistanceRenameToMatch, _Configuration.FaceConfidencePercent, configuration.RangeDistanceTolerance, configuration.RangeFaceConfidence);
|
||||||
if (_PropertyRootExistedBefore || !_ArgZeroIsConfigurationRootDirectory)
|
if (_PropertyRootExistedBefore || !_ArgZeroIsConfigurationRootDirectory)
|
||||||
personContainers = Array.Empty<PersonContainer>();
|
_PersonContainers = Array.Empty<PersonContainer>();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||||
@ -120,7 +121,7 @@ public partial class DlibDotNet
|
|||||||
if (rootResultsDirectory is null)
|
if (rootResultsDirectory is null)
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory);
|
Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory);
|
||||||
personContainers = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers(storage, configuration.PersonBirthdayFormat, _Faces.FileNameExtension);
|
_PersonContainers = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers(storage, configuration.PersonBirthdayFormat, _Faces.FileNameExtension);
|
||||||
}
|
}
|
||||||
if (!isSilent && configuration.TestDistanceResults)
|
if (!isSilent && configuration.TestDistanceResults)
|
||||||
{
|
{
|
||||||
@ -142,7 +143,7 @@ public partial class DlibDotNet
|
|||||||
filenameExtension);
|
filenameExtension);
|
||||||
}
|
}
|
||||||
if (!configuration.SkipSearch)
|
if (!configuration.SkipSearch)
|
||||||
Search(ticks, argZero, propertyRoot, personContainers);
|
Search(ticks, argZero, propertyRoot);
|
||||||
if (!_PropertyRootExistedBefore && !_IsEnvironment.Development && _Exceptions.Count == 0 && _ArgZeroIsConfigurationRootDirectory)
|
if (!_PropertyRootExistedBefore && !_IsEnvironment.Development && _Exceptions.Count == 0 && _ArgZeroIsConfigurationRootDirectory)
|
||||||
{
|
{
|
||||||
List<string[]> directoryCollections = _Rename.GetDirectoryRenameCollections(
|
List<string[]> directoryCollections = _Rename.GetDirectoryRenameCollections(
|
||||||
@ -205,7 +206,7 @@ public partial class DlibDotNet
|
|||||||
private void Verify(Models.Configuration configuration)
|
private void Verify(Models.Configuration configuration)
|
||||||
{
|
{
|
||||||
if (!configuration.OutputResolutions.Any() || string.IsNullOrEmpty(configuration.OutputResolutions[0]) || !configuration.ValidResolutions.Contains(configuration.OutputResolutions[0]))
|
if (!configuration.OutputResolutions.Any() || string.IsNullOrEmpty(configuration.OutputResolutions[0]) || !configuration.ValidResolutions.Contains(configuration.OutputResolutions[0]))
|
||||||
throw new NullReferenceException($"{nameof(configuration.OutputResolutions)} must be a valid outputResolution!");
|
throw new NullReferenceException($"{nameof(configuration.OutputResolutions)} must be _FileNameToCollection 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.LoadOrCreateThenSaveDistanceResultsForOutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any())
|
if ((from l in configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any())
|
||||||
@ -249,13 +250,13 @@ public partial class DlibDotNet
|
|||||||
string[] segments = sourceDirectoryNames[0].Split(' ');
|
string[] segments = sourceDirectoryNames[0].Split(' ');
|
||||||
century = segments[^1].Length == 4 ? segments[^1][..2] : null;
|
century = segments[^1].Length == 4 ? segments[^1][..2] : null;
|
||||||
if (segments.Length < 2 || century is null || (century != "18" && century != "19" && century != "20"))
|
if (segments.Length < 2 || century is null || (century != "18" && century != "19" && century != "20"))
|
||||||
throw new Exception("root subdirectory must have a year at the end or directory name needs to be added to the exclude list!");
|
throw new Exception("root subdirectory must have _FileNameToCollection year at the end or directory name needs to be added to the exclude list!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
string[] resizeMatch = (from l in sourceDirectoryNames where configuration.ValidResolutions.Contains(l) select l).ToArray();
|
string[] resizeMatch = (from l in sourceDirectoryNames where configuration.ValidResolutions.Contains(l) select l).ToArray();
|
||||||
if (resizeMatch.Any())
|
if (resizeMatch.Any())
|
||||||
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 _FileNameToCollection resized directory!");
|
||||||
if (configuration.LocationDigits != Shared.Models.Stateless.ILocation.Digits)
|
if (configuration.LocationDigits != Shared.Models.Stateless.ILocation.Digits)
|
||||||
throw new Exception("Configuration has to match interface!");
|
throw new Exception("Configuration has to match interface!");
|
||||||
if (configuration.LocationFactor != Shared.Models.Stateless.ILocation.Factor)
|
if (configuration.LocationFactor != Shared.Models.Stateless.ILocation.Factor)
|
||||||
@ -294,7 +295,6 @@ public partial class DlibDotNet
|
|||||||
Dictionary<string, int[]> imageResizeKeyValuePairs;
|
Dictionary<string, int[]> imageResizeKeyValuePairs;
|
||||||
List<Tuple<string, DateTime>> subFileTuples = new();
|
List<Tuple<string, DateTime>> subFileTuples = new();
|
||||||
List<KeyValuePair<string, string>> metadataCollection;
|
List<KeyValuePair<string, string>> metadataCollection;
|
||||||
// Dictionary<string, List<RelativeLocation>> relativeLocations;
|
|
||||||
if (item.Property is not null && item.Property.Id is not null && !item.Any())
|
if (item.Property is not null && item.Property.Id is not null && !item.Any())
|
||||||
{
|
{
|
||||||
property = item.Property;
|
property = item.Property;
|
||||||
@ -354,17 +354,21 @@ public partial class DlibDotNet
|
|||||||
string path = Path.Combine(resizedFileHolder.DirectoryName, resizedFileHolder.NameWithoutExtension);
|
string path = Path.Combine(resizedFileHolder.DirectoryName, resizedFileHolder.NameWithoutExtension);
|
||||||
File.WriteAllBytes(path, bytes);
|
File.WriteAllBytes(path, bytes);
|
||||||
}
|
}
|
||||||
if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution))
|
if (!mappingFromItem.ResizedFileHolder.Exists && !File.Exists(mappingFromItem.ResizedFileHolder.FullName))
|
||||||
|
faces = new();
|
||||||
|
else if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution))
|
||||||
faces = new();
|
faces = new();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
List<(string, int, IReadOnlyList<MetadataExtractor.Directory>?)>? collection;
|
|
||||||
int[] outputResolutionCollection = imageResizeKeyValuePairs[outputResolution];
|
int[] outputResolutionCollection = imageResizeKeyValuePairs[outputResolution];
|
||||||
int outputResolutionWidth = outputResolutionCollection[0];
|
int outputResolutionWidth = outputResolutionCollection[0];
|
||||||
int outputResolutionHeight = outputResolutionCollection[1];
|
int outputResolutionHeight = outputResolutionCollection[1];
|
||||||
int outputResolutionOrientation = outputResolutionCollection[2];
|
int outputResolutionOrientation = outputResolutionCollection[2];
|
||||||
faces = _Faces.GetFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation);
|
List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection;
|
||||||
// relativeLocations = _Faces.GetRelativeLocations(outputResolution, dResultsDateGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, original, imageResizeKeyValuePairs, faces);
|
List<(string, int, IReadOnlyList<MetadataExtractor.Directory>?)>? collection;
|
||||||
|
if (!_FileNameToCollection.TryGetValue(mappingFromItem.RelativePath[1..], out mappingFromPhotoPrismCollection))
|
||||||
|
mappingFromPhotoPrismCollection = null;
|
||||||
|
faces = _Faces.GetFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, mappingFromPhotoPrismCollection);
|
||||||
if (_AppSettings.MaxDegreeOfParallelism < 2)
|
if (_AppSettings.MaxDegreeOfParallelism < 2)
|
||||||
ticks = LogDelta(ticks, nameof(D_Face.GetFaces));
|
ticks = LogDelta(ticks, nameof(D_Face.GetFaces));
|
||||||
bool anyFacesSaved = _Faces.SaveFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, mappingFromItem, facesDirectory, faces);
|
bool anyFacesSaved = _Faces.SaveFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, mappingFromItem, facesDirectory, faces);
|
||||||
@ -439,25 +443,24 @@ public partial class DlibDotNet
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
FullParallelForWork(
|
FullParallelForWork(propertyLogic,
|
||||||
propertyLogic,
|
idToMappedFaceFilesWithCollection,
|
||||||
idToMappedFaceFilesWithCollection,
|
outputResolution,
|
||||||
outputResolution,
|
bResultsFullGroupDirectory,
|
||||||
bResultsFullGroupDirectory,
|
cResultsFullGroupDirectory,
|
||||||
cResultsFullGroupDirectory,
|
dResultsDateGroupDirectory,
|
||||||
dResultsDateGroupDirectory,
|
dResultsFullGroupDirectory,
|
||||||
dResultsFullGroupDirectory,
|
eDistanceContentDirectory,
|
||||||
eDistanceContentDirectory,
|
sourceDirectoryChanges,
|
||||||
sourceDirectoryChanges,
|
propertyFileHolderCollection,
|
||||||
propertyFileHolderCollection,
|
propertyCollection,
|
||||||
propertyCollection,
|
metadataCollection,
|
||||||
metadataCollection,
|
resizeKeyValuePairs,
|
||||||
resizeKeyValuePairs,
|
imageFaceCollections,
|
||||||
imageFaceCollections,
|
container,
|
||||||
container,
|
index: i,
|
||||||
index: i,
|
filteredItems[i],
|
||||||
filteredItems[i],
|
containerDateTimes);
|
||||||
containerDateTimes);
|
|
||||||
if (i == 0 || sourceDirectoryChanges.Any())
|
if (i == 0 || sourceDirectoryChanges.Any())
|
||||||
progressBar.Tick();
|
progressBar.Tick();
|
||||||
}
|
}
|
||||||
@ -627,7 +630,7 @@ public partial class DlibDotNet
|
|||||||
_Metadata.SetAngleBracketCollection(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, container.SourceDirectory);
|
_Metadata.SetAngleBracketCollection(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, container.SourceDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FullDoWork(string argZero, string propertyRoot, long ticks, PersonContainer[] personContainers, A_Property propertyLogic, int t, Container[] containers, string? a2PeopleContentDirectory, string eDistanceContentDirectory)
|
private void FullDoWork(string argZero, string propertyRoot, long ticks, A_Property propertyLogic, int t, Container[] containers, string? a2PeopleContentDirectory, string eDistanceContentDirectory)
|
||||||
{
|
{
|
||||||
if (_Log is null)
|
if (_Log is null)
|
||||||
throw new NullReferenceException(nameof(_Log));
|
throw new NullReferenceException(nameof(_Log));
|
||||||
@ -651,7 +654,7 @@ public partial class DlibDotNet
|
|||||||
int maxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism;
|
int maxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism;
|
||||||
List<Shared.Models.Property?> nullablePropertyCollection = new();
|
List<Shared.Models.Property?> nullablePropertyCollection = new();
|
||||||
List<List<KeyValuePair<string, string>>> metadataCollection = new();
|
List<List<KeyValuePair<string, string>>> metadataCollection = new();
|
||||||
Dictionary<int, List<(string, int, IReadOnlyList<MetadataExtractor.Directory>?)>> idToMappedFaceFilesWithCollection = GetCollection(ticks, personContainers, a2PeopleContentDirectory, eDistanceContentDirectory);
|
Dictionary<int, List<(string, int, IReadOnlyList<MetadataExtractor.Directory>?)>> idToMappedFaceFilesWithCollection = GetCollection(ticks, a2PeopleContentDirectory, eDistanceContentDirectory);
|
||||||
string dResultsDateGroupDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(D_Face));
|
string dResultsDateGroupDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(D_Face));
|
||||||
foreach (string outputResolution in _Configuration.OutputResolutions)
|
foreach (string outputResolution in _Configuration.OutputResolutions)
|
||||||
{
|
{
|
||||||
@ -739,7 +742,7 @@ public partial class DlibDotNet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetMapping(string argZero, Container[] containers)
|
private void SetMapping(Dictionary<string, List<MappingFromPhotoPrism>> fileNameToCollection, string argZero, Container[] containers)
|
||||||
{
|
{
|
||||||
Mapping mapping;
|
Mapping mapping;
|
||||||
int faceAreaPermille;
|
int faceAreaPermille;
|
||||||
@ -751,6 +754,7 @@ public partial class DlibDotNet
|
|||||||
string deterministicHashCodeKey;
|
string deterministicHashCodeKey;
|
||||||
MappingFromItem mappingFromItem;
|
MappingFromItem mappingFromItem;
|
||||||
MappingFromLocation mappingFromLocation;
|
MappingFromLocation mappingFromLocation;
|
||||||
|
List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection;
|
||||||
foreach (Container container in containers)
|
foreach (Container container in containers)
|
||||||
{
|
{
|
||||||
if (!container.Items.Any())
|
if (!container.Items.Any())
|
||||||
@ -776,7 +780,9 @@ public partial class DlibDotNet
|
|||||||
normalizedRectangle = Shared.Models.Stateless.Methods.ILocation.GetNormalizedRectangle(face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution);
|
normalizedRectangle = Shared.Models.Stateless.Methods.ILocation.GetNormalizedRectangle(face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution);
|
||||||
deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution);
|
deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution);
|
||||||
mappingFromLocation = new(faceAreaPermille, confidencePercent, deterministicHashCodeKey, normalizedRectangle);
|
mappingFromLocation = new(faceAreaPermille, confidencePercent, deterministicHashCodeKey, normalizedRectangle);
|
||||||
mapping = new(mappingFromItem, mappingFromLocation);
|
if (!fileNameToCollection.TryGetValue(mappingFromItem.RelativePath[1..], out mappingFromPhotoPrismCollection))
|
||||||
|
mappingFromPhotoPrismCollection = null;
|
||||||
|
mapping = new(mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection);
|
||||||
face.SetMapping(mapping);
|
face.SetMapping(mapping);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -847,7 +853,7 @@ public partial class DlibDotNet
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MapLogic(string argZero, long ticks, PersonContainer[] personContainers, Container[] containers, string a2PeopleSingletonDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, MapLogicSupport mapLogicSupport, MapLogic mapLogic, string outputResolution)
|
private void MapLogic(string argZero, long ticks, Container[] containers, string a2PeopleSingletonDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, MapLogicSupport mapLogicSupport, MapLogic mapLogic, string outputResolution)
|
||||||
{
|
{
|
||||||
int? useFiltersCounter = null;
|
int? useFiltersCounter = null;
|
||||||
SortingContainer[] sortingContainers;
|
SortingContainer[] sortingContainers;
|
||||||
@ -857,17 +863,12 @@ public partial class DlibDotNet
|
|||||||
Mapping[] mappingCollection = MapLogicSupport.GetSelectedMappingCollection(distinctFilteredFaces);
|
Mapping[] mappingCollection = MapLogicSupport.GetSelectedMappingCollection(distinctFilteredFaces);
|
||||||
string dFacesCollectionDirectory = Path.Combine(dResultsFullGroupDirectory, "[]", _Configuration.PropertyConfiguration.ResultAllInOne);
|
string dFacesCollectionDirectory = Path.Combine(dResultsFullGroupDirectory, "[]", _Configuration.PropertyConfiguration.ResultAllInOne);
|
||||||
(Dictionary<long, int> personKeyToCount, int totalNotMapped) = mapLogic.AddToMapping(mappingCollection);
|
(Dictionary<long, int> personKeyToCount, int totalNotMapped) = mapLogic.AddToMapping(mappingCollection);
|
||||||
if (_Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution) || (!string.IsNullOrEmpty(_Configuration.PhotoPrismDirectory) && Directory.Exists(_Configuration.PhotoPrismDirectory)))
|
if (!string.IsNullOrEmpty(_Configuration.PhotoPrismDirectory) && Directory.Exists(_Configuration.PhotoPrismDirectory))
|
||||||
|
mapLogic.WriteMatches(ticks, distinctFilteredFaces);
|
||||||
|
if (_Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution))
|
||||||
{
|
{
|
||||||
List<Item> filteredItems = GetItems(argZero, containers);
|
List<Item> filteredItems = GetItems(argZero, containers);
|
||||||
if (!string.IsNullOrEmpty(_Configuration.PhotoPrismDirectory))
|
mapLogic.SaveShortcutsForOutputResolutions(filteredItems, mappingCollection, personKeyToCount);
|
||||||
{
|
|
||||||
mapLogic.SaveMarkers();
|
|
||||||
mapLogic.FindMatch(filteredItems);
|
|
||||||
mapLogic.LoadMatches();
|
|
||||||
}
|
|
||||||
if (_Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution))
|
|
||||||
mapLogic.SaveShortcutsForOutputResolutions(filteredItems, mappingCollection, personKeyToCount);
|
|
||||||
}
|
}
|
||||||
Dictionary<int, Dictionary<int, Mapping>> idToNormalizedRectangleToMapping = MapLogicSupport.GetIdToNormalizedRectangleToFace(mappingCollection);
|
Dictionary<int, Dictionary<int, Mapping>> idToNormalizedRectangleToMapping = MapLogicSupport.GetIdToNormalizedRectangleToFace(mappingCollection);
|
||||||
mapLogic.CopyManualFiles(dFacesContentDirectory, idToNormalizedRectangleToMapping);
|
mapLogic.CopyManualFiles(dFacesContentDirectory, idToNormalizedRectangleToMapping);
|
||||||
@ -876,7 +877,7 @@ public partial class DlibDotNet
|
|||||||
if (_Configuration.SaveMappedForOutputResolutions.Contains(outputResolution))
|
if (_Configuration.SaveMappedForOutputResolutions.Contains(outputResolution))
|
||||||
mapLogic.SaveMapped(dFacesContentDirectory, d2FacePartsContentDirectory, mappingCollection, idToNormalizedRectangleToMapping, personKeyToCount, totalNotMapped);
|
mapLogic.SaveMapped(dFacesContentDirectory, d2FacePartsContentDirectory, mappingCollection, idToNormalizedRectangleToMapping, personKeyToCount, totalNotMapped);
|
||||||
if (_Configuration.SaveFilteredOriginalImagesFromJLinksForOutputResolutions.Contains(outputResolution))
|
if (_Configuration.SaveFilteredOriginalImagesFromJLinksForOutputResolutions.Contains(outputResolution))
|
||||||
mapLogic.SaveFilteredOriginalImagesFromJLinks(_Configuration.JLinks, a2PeopleSingletonDirectory, personContainers, mappingCollection, personKeyToCount, totalNotMapped);
|
mapLogic.SaveFilteredOriginalImagesFromJLinks(_Configuration.JLinks, _PersonContainers, a2PeopleSingletonDirectory, mappingCollection, personKeyToCount, totalNotMapped);
|
||||||
if (_Configuration.SaveFaceDistancesForOutputResolutions.Contains(outputResolution))
|
if (_Configuration.SaveFaceDistancesForOutputResolutions.Contains(outputResolution))
|
||||||
{
|
{
|
||||||
mapLogic.UpdatedPersonKeyToRanges(_MapConfiguration, ticks, mappingCollection);
|
mapLogic.UpdatedPersonKeyToRanges(_MapConfiguration, ticks, mappingCollection);
|
||||||
@ -952,7 +953,7 @@ public partial class DlibDotNet
|
|||||||
bool isValidImageFormatExtension;
|
bool isValidImageFormatExtension;
|
||||||
for (int y = 0; y < int.MaxValue; y++)
|
for (int y = 0; y < int.MaxValue; y++)
|
||||||
{
|
{
|
||||||
_Log.Information("Enter a url for a image");
|
_Log.Information("Enter _FileNameToCollection url for _FileNameToCollection image");
|
||||||
line = _Console.ReadLine();
|
line = _Console.ReadLine();
|
||||||
if (string.IsNullOrEmpty(line))
|
if (string.IsNullOrEmpty(line))
|
||||||
break;
|
break;
|
||||||
@ -1011,12 +1012,12 @@ public partial class DlibDotNet
|
|||||||
collection.Add(new(value.MappedFaceFile, normalizedRectangle.Value, directories));
|
collection.Add(new(value.MappedFaceFile, normalizedRectangle.Value, directories));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<int, List<(string, int, IReadOnlyList<MetadataExtractor.Directory>?)>> GetCollection(long ticks, PersonContainer[] personContainers, string? a2PeopleContentDirectory, string? eDistanceContentDirectory)
|
private Dictionary<int, List<(string, int, IReadOnlyList<MetadataExtractor.Directory>?)>> GetCollection(long ticks, string? a2PeopleContentDirectory, string? eDistanceContentDirectory)
|
||||||
{
|
{
|
||||||
Dictionary<int, List<(string, int, IReadOnlyList<MetadataExtractor.Directory>?)>> results = new();
|
Dictionary<int, List<(string, int, IReadOnlyList<MetadataExtractor.Directory>?)>> results = new();
|
||||||
int? id;
|
int? id;
|
||||||
int? normalizedRectangle;
|
int? normalizedRectangle;
|
||||||
List<(string, string[], string)> collection = Map.Models.Stateless.Methods.IMapLogic.DeleteEmptyDirectoriesAndGetMappedFaceFiles(_MapConfiguration, ticks, a2PeopleContentDirectory, eDistanceContentDirectory, personContainers);
|
List<(string, string[], string)> collection = Map.Models.Stateless.Methods.IMapLogic.DeleteEmptyDirectoriesAndGetMappedFaceFiles(_MapConfiguration, _PersonContainers, ticks, a2PeopleContentDirectory, eDistanceContentDirectory);
|
||||||
foreach ((string personKeyFormatted, string[] personDisplayDirectoryNames, string mappedFaceFile) in collection)
|
foreach ((string personKeyFormatted, string[] personDisplayDirectoryNames, string mappedFaceFile) in collection)
|
||||||
{
|
{
|
||||||
(id, normalizedRectangle) = Shared.Models.Stateless.Methods.IMapping.GetConverted(_Faces.FileNameExtension, mappedFaceFile);
|
(id, normalizedRectangle) = Shared.Models.Stateless.Methods.IMapping.GetConverted(_Faces.FileNameExtension, mappedFaceFile);
|
||||||
@ -1043,7 +1044,7 @@ public partial class DlibDotNet
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Search(long ticks, string argZero, string propertyRoot, PersonContainer[] personContainers)
|
private void Search(long ticks, string argZero, string propertyRoot)
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
int f;
|
int f;
|
||||||
@ -1056,6 +1057,13 @@ public partial class DlibDotNet
|
|||||||
string dResultsFullGroupDirectory;
|
string dResultsFullGroupDirectory;
|
||||||
string? eDistanceContentDirectory;
|
string? eDistanceContentDirectory;
|
||||||
string d2ResultsFullGroupDirectory;
|
string d2ResultsFullGroupDirectory;
|
||||||
|
if (!string.IsNullOrEmpty(_Configuration.PhotoPrismDirectory) && Directory.Exists(_Configuration.PhotoPrismDirectory))
|
||||||
|
{
|
||||||
|
Map.Models.MapLogic.SaveMarkers(_Configuration.PhotoPrismDirectory);
|
||||||
|
Dictionary<string, List<MappingFromPhotoPrism>> fileNameToCollection = Map.Models.MapLogic.GetFileNameToCollection(_Configuration.PhotoPrismDirectory);
|
||||||
|
foreach (KeyValuePair<string, List<MappingFromPhotoPrism>> keyValuePair in fileNameToCollection)
|
||||||
|
_FileNameToCollection.Add(keyValuePair.Key, keyValuePair.Value);
|
||||||
|
}
|
||||||
string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "{}");
|
string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "{}");
|
||||||
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 = $") Building Container(s) - {totalSeconds} total second(s)";
|
string message = $") Building Container(s) - {totalSeconds} total second(s)";
|
||||||
@ -1092,10 +1100,10 @@ public partial class DlibDotNet
|
|||||||
}
|
}
|
||||||
containers = Shared.Models.Stateless.Methods.IContainer.SortContainers(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, _ArgZeroIsConfigurationRootDirectory, argZero, containers);
|
containers = Shared.Models.Stateless.Methods.IContainer.SortContainers(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, _ArgZeroIsConfigurationRootDirectory, argZero, containers);
|
||||||
MapLogicSupport mapLogicSupport = new(_Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeFaceAreaPermilleTolerance, _Configuration.SortingMaximumPerFaceShouldBeHigh);
|
MapLogicSupport mapLogicSupport = new(_Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeFaceAreaPermilleTolerance, _Configuration.SortingMaximumPerFaceShouldBeHigh);
|
||||||
MapLogic? mapLogic = _Configuration.DistanceMoveUnableToMatch ? null : new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, ticks, personContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory, mapLogicSupport);
|
MapLogic? mapLogic = _Configuration.DistanceMoveUnableToMatch ? null : new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, ticks, _PersonContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory, mapLogicSupport);
|
||||||
FullDoWork(argZero, propertyRoot, ticks, personContainers, propertyLogic, t, containers, a2PeopleContentDirectory, eDistanceContentDirectory);
|
FullDoWork(argZero, propertyRoot, ticks, propertyLogic, t, containers, a2PeopleContentDirectory, eDistanceContentDirectory);
|
||||||
_Distance.Clear();
|
_Distance.Clear();
|
||||||
mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, ticks, personContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory, mapLogicSupport);
|
mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, ticks, _PersonContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory, mapLogicSupport);
|
||||||
foreach (string outputResolution in _Configuration.OutputResolutions)
|
foreach (string outputResolution in _Configuration.OutputResolutions)
|
||||||
{
|
{
|
||||||
if (_PropertyRootExistedBefore || container is not null)
|
if (_PropertyRootExistedBefore || container is not null)
|
||||||
@ -1112,8 +1120,8 @@ public partial class DlibDotNet
|
|||||||
{
|
{
|
||||||
if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Any())
|
if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Any())
|
||||||
break;
|
break;
|
||||||
SetMapping(argZero, containers);
|
SetMapping(_FileNameToCollection, argZero, containers);
|
||||||
MapLogic(argZero, ticks, personContainers, containers, a2PeopleSingletonDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, mapLogicSupport, mapLogic, outputResolution);
|
MapLogic(argZero, ticks, containers, a2PeopleSingletonDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, mapLogicSupport, mapLogic, outputResolution);
|
||||||
if (_IsEnvironment.Development)
|
if (_IsEnvironment.Development)
|
||||||
continue;
|
continue;
|
||||||
List<MappingFromItem> mappingFromItemCollection = GetMappingFromItemCollection(containers);
|
List<MappingFromItem> mappingFromItemCollection = GetMappingFromItemCollection(containers);
|
||||||
|
@ -62,7 +62,6 @@ public class Configuration
|
|||||||
[Display(Name = "Face Distance Tolerance"), Required] public double[] RangeDistanceTolerance { get; set; }
|
[Display(Name = "Face Distance Tolerance"), Required] public double[] RangeDistanceTolerance { get; set; }
|
||||||
[Display(Name = "Face Area Permille Tolerance"), Required] public int[] RangeFaceAreaPermilleTolerance { get; set; }
|
[Display(Name = "Face Area Permille Tolerance"), Required] public int[] RangeFaceAreaPermilleTolerance { get; set; }
|
||||||
[Display(Name = "Location Minimum Confidence"), Required] public double[] RangeFaceConfidence { get; set; }
|
[Display(Name = "Location Minimum Confidence"), Required] public double[] RangeFaceConfidence { get; set; }
|
||||||
[Display(Name = "Retry Images Without a Face"), Required] public bool? RetryImagesWithoutAFaceLocation { get; set; }
|
|
||||||
[Display(Name = "Reverse"), Required] public bool? Reverse { get; set; }
|
[Display(Name = "Reverse"), Required] public bool? Reverse { get; set; }
|
||||||
[Display(Name = "Save Face Distances"), Required] public string[] SaveFaceDistancesForOutputResolutions { get; set; }
|
[Display(Name = "Save Face Distances"), Required] public string[] SaveFaceDistancesForOutputResolutions { get; set; }
|
||||||
[Display(Name = "Save Face Landmark For Output Resolutions"), Required] public string[] SaveFaceLandmarkForOutputResolutions { get; set; }
|
[Display(Name = "Save Face Landmark For Output Resolutions"), Required] public string[] SaveFaceLandmarkForOutputResolutions { get; set; }
|
||||||
@ -180,8 +179,6 @@ public class Configuration
|
|||||||
throw new NullReferenceException(nameof(configuration.RangeFaceConfidence));
|
throw new NullReferenceException(nameof(configuration.RangeFaceConfidence));
|
||||||
if (configuration.RangeDistanceTolerance is null || configuration.RangeDistanceTolerance.Length != 3)
|
if (configuration.RangeDistanceTolerance is null || configuration.RangeDistanceTolerance.Length != 3)
|
||||||
throw new NullReferenceException(nameof(configuration.RangeDistanceTolerance));
|
throw new NullReferenceException(nameof(configuration.RangeDistanceTolerance));
|
||||||
if (configuration.RetryImagesWithoutAFaceLocation is null)
|
|
||||||
throw new NullReferenceException(nameof(configuration.RetryImagesWithoutAFaceLocation));
|
|
||||||
if (configuration.Reverse is null)
|
if (configuration.Reverse is null)
|
||||||
throw new NullReferenceException(nameof(configuration.Reverse));
|
throw new NullReferenceException(nameof(configuration.Reverse));
|
||||||
configuration.SaveFaceDistancesForOutputResolutions ??= Array.Empty<string>();
|
configuration.SaveFaceDistancesForOutputResolutions ??= Array.Empty<string>();
|
||||||
@ -258,7 +255,6 @@ public class Configuration
|
|||||||
configuration.RangeFaceAreaPermilleTolerance,
|
configuration.RangeFaceAreaPermilleTolerance,
|
||||||
configuration.RangeFaceConfidence,
|
configuration.RangeFaceConfidence,
|
||||||
configuration.RangeDistanceTolerance,
|
configuration.RangeDistanceTolerance,
|
||||||
configuration.RetryImagesWithoutAFaceLocation.Value,
|
|
||||||
configuration.Reverse.Value,
|
configuration.Reverse.Value,
|
||||||
configuration.SaveFaceDistancesForOutputResolutions,
|
configuration.SaveFaceDistancesForOutputResolutions,
|
||||||
configuration.SaveFaceLandmarkForOutputResolutions,
|
configuration.SaveFaceLandmarkForOutputResolutions,
|
||||||
|
@ -58,7 +58,6 @@ public class Configuration
|
|||||||
public int[] RangeFaceAreaPermilleTolerance { init; get; }
|
public int[] RangeFaceAreaPermilleTolerance { init; get; }
|
||||||
public double[] RangeFaceConfidence { init; get; }
|
public double[] RangeFaceConfidence { init; get; }
|
||||||
public double[] RangeDistanceTolerance { init; get; }
|
public double[] RangeDistanceTolerance { init; get; }
|
||||||
public bool RetryImagesWithoutAFaceLocation { init; get; }
|
|
||||||
public bool Reverse { init; get; }
|
public bool Reverse { init; get; }
|
||||||
public string[] SaveFaceDistancesForOutputResolutions { init; get; }
|
public string[] SaveFaceDistancesForOutputResolutions { init; get; }
|
||||||
public string[] SaveFaceLandmarkForOutputResolutions { init; get; }
|
public string[] SaveFaceLandmarkForOutputResolutions { init; get; }
|
||||||
@ -126,7 +125,6 @@ public class Configuration
|
|||||||
int[] rangeFaceAreaPermilleTolerance,
|
int[] rangeFaceAreaPermilleTolerance,
|
||||||
double[] rangeFaceConfidence,
|
double[] rangeFaceConfidence,
|
||||||
double[] rangeDistanceTolerance,
|
double[] rangeDistanceTolerance,
|
||||||
bool retryImagesWithoutAFaceLocation,
|
|
||||||
bool reverse,
|
bool reverse,
|
||||||
string[] saveFaceDistancesForOutputResolutions,
|
string[] saveFaceDistancesForOutputResolutions,
|
||||||
string[] saveFaceLandmarkForOutputResolutions,
|
string[] saveFaceLandmarkForOutputResolutions,
|
||||||
@ -193,7 +191,6 @@ public class Configuration
|
|||||||
RangeFaceAreaPermilleTolerance = rangeFaceAreaPermilleTolerance;
|
RangeFaceAreaPermilleTolerance = rangeFaceAreaPermilleTolerance;
|
||||||
RangeFaceConfidence = rangeFaceConfidence;
|
RangeFaceConfidence = rangeFaceConfidence;
|
||||||
RangeDistanceTolerance = rangeDistanceTolerance;
|
RangeDistanceTolerance = rangeDistanceTolerance;
|
||||||
RetryImagesWithoutAFaceLocation = retryImagesWithoutAFaceLocation;
|
|
||||||
Reverse = reverse;
|
Reverse = reverse;
|
||||||
SaveFaceDistancesForOutputResolutions = saveFaceDistancesForOutputResolutions;
|
SaveFaceDistancesForOutputResolutions = saveFaceDistancesForOutputResolutions;
|
||||||
SaveFaceLandmarkForOutputResolutions = saveFaceLandmarkForOutputResolutions;
|
SaveFaceLandmarkForOutputResolutions = saveFaceLandmarkForOutputResolutions;
|
||||||
|
@ -101,7 +101,6 @@
|
|||||||
"ResultCollection": "[]",
|
"ResultCollection": "[]",
|
||||||
"ResultContent": "()",
|
"ResultContent": "()",
|
||||||
"ResultSingleton": "{}",
|
"ResultSingleton": "{}",
|
||||||
"RetryImagesWithoutAFaceLocation": false,
|
|
||||||
"Reverse": false,
|
"Reverse": false,
|
||||||
"RootDirectory": "D:/Images",
|
"RootDirectory": "D:/Images",
|
||||||
"SaveFullYearOfRandomFiles": true,
|
"SaveFullYearOfRandomFiles": true,
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace View_by_Distance.Map.Models;
|
|
||||||
|
|
||||||
public record DatabaseFileRoot(
|
|
||||||
[property: JsonPropertyName("table")] string Table,
|
|
||||||
[property: JsonPropertyName("rows")] IReadOnlyList<DatabaseFile> Files
|
|
||||||
);
|
|
@ -936,7 +936,7 @@ public class MapLogic
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveFilteredOriginalImagesFromJLinks(string[] jLinks, string a2PeopleSingletonDirectory, PersonContainer[] personContainers, Mapping[] mappingCollection, Dictionary<long, int> personKeyToCount, int totalNotMapped)
|
public void SaveFilteredOriginalImagesFromJLinks(string[] jLinks, PersonContainer[] personContainers, string a2PeopleSingletonDirectory, Mapping[] mappingCollection, Dictionary<long, int> personKeyToCount, int totalNotMapped)
|
||||||
{
|
{
|
||||||
if (_Configuration is null)
|
if (_Configuration is null)
|
||||||
throw new NullReferenceException(nameof(_Configuration));
|
throw new NullReferenceException(nameof(_Configuration));
|
||||||
@ -1149,237 +1149,166 @@ public class MapLogic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DatabaseFileRoot GetDatabaseFileRoot()
|
private static JsonProperty[] GetJsonProperty(string fileName)
|
||||||
{
|
{
|
||||||
if (_Configuration is null)
|
JsonProperty[] results;
|
||||||
throw new NullReferenceException(nameof(_Configuration));
|
string json = File.ReadAllText(fileName);
|
||||||
string file = Path.Combine(_Configuration.PhotoPrismDirectory, "files.json");
|
JsonElement? jsonElement = JsonSerializer.Deserialize<JsonElement>(json);
|
||||||
string json = File.ReadAllText(file);
|
results = jsonElement.Value.EnumerateObject().ToArray();
|
||||||
DatabaseFileRoot? databaseFileRoot = JsonSerializer.Deserialize<DatabaseFileRoot>(json);
|
|
||||||
if (databaseFileRoot is null)
|
|
||||||
throw new NullReferenceException(nameof(databaseFileRoot));
|
|
||||||
return databaseFileRoot;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Marker[] GetMarkers()
|
|
||||||
{
|
|
||||||
if (_Configuration is null)
|
|
||||||
throw new NullReferenceException(nameof(_Configuration));
|
|
||||||
string file = Path.Combine(_Configuration.PhotoPrismDirectory, "markers.json");
|
|
||||||
string json = File.ReadAllText(file);
|
|
||||||
Marker[]? markerRoot = JsonSerializer.Deserialize<Marker[]>(json);
|
|
||||||
if (markerRoot is null)
|
|
||||||
throw new NullReferenceException(nameof(markerRoot));
|
|
||||||
return markerRoot;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Dictionary<string, DatabaseFile> Get(DatabaseFileRoot databaseFileRoot)
|
|
||||||
{
|
|
||||||
Dictionary<string, DatabaseFile> fileUidToFile = new();
|
|
||||||
for (int i = 0; i < databaseFileRoot.Files.Count; i++)
|
|
||||||
fileUidToFile.Add(databaseFileRoot.Files[i].FileUid, databaseFileRoot.Files[i]);
|
|
||||||
return fileUidToFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MarkerWith GetMarkerWith(int? dlib, DatabaseFile databaseFile, Marker marker, int? count, double? percent, int? normalizedRectangle, long? personKey, string personKeyFormatted)
|
|
||||||
{
|
|
||||||
return new(marker.MarkerUid,
|
|
||||||
marker.FileUid,
|
|
||||||
marker.MarkerType,
|
|
||||||
marker.MarkerSrc,
|
|
||||||
marker.MarkerName,
|
|
||||||
marker.MarkerReview,
|
|
||||||
marker.MarkerInvalid,
|
|
||||||
marker.SubjUid,
|
|
||||||
marker.SubjSrc,
|
|
||||||
marker.FaceId,
|
|
||||||
marker.FaceDist,
|
|
||||||
marker.EmbeddingsJson,
|
|
||||||
marker.LandmarksJson,
|
|
||||||
marker.X,
|
|
||||||
marker.Y,
|
|
||||||
marker.W,
|
|
||||||
marker.H,
|
|
||||||
marker.Q,
|
|
||||||
marker.Size,
|
|
||||||
marker.Score,
|
|
||||||
marker.Thumb,
|
|
||||||
marker.MatchedAt,
|
|
||||||
marker.CreatedAt,
|
|
||||||
marker.UpdatedAt,
|
|
||||||
databaseFile.Id,
|
|
||||||
databaseFile.FileName,
|
|
||||||
dlib,
|
|
||||||
count,
|
|
||||||
percent,
|
|
||||||
normalizedRectangle,
|
|
||||||
personKey,
|
|
||||||
personKeyFormatted);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Dictionary<string, List<Face>> GetFacesByFileName(List<Item> filteredItems)
|
|
||||||
{
|
|
||||||
Dictionary<string, List<Face>> results = new();
|
|
||||||
string key;
|
|
||||||
foreach (Item item in filteredItems)
|
|
||||||
{
|
|
||||||
foreach (Face face in item.Faces)
|
|
||||||
{
|
|
||||||
if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null || face.Mapping is null)
|
|
||||||
continue;
|
|
||||||
key = Path.GetFileNameWithoutExtension(face.Mapping.MappingFromItem.RelativePath);
|
|
||||||
if (!results.ContainsKey(key))
|
|
||||||
results.Add(key, new());
|
|
||||||
results[key].Add(face);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FindMatch(List<Item> filteredItems)
|
private static Marker[]? GetMarkers(string photoPrismDirectory)
|
||||||
{
|
{
|
||||||
if (_Configuration is null)
|
Marker[]? results;
|
||||||
throw new NullReferenceException(nameof(_Configuration));
|
string file = Path.Combine(photoPrismDirectory, "markers.json");
|
||||||
int? dlib;
|
JsonProperty[] jsonProperties = GetJsonProperty(file);
|
||||||
double? percent;
|
results = JsonSerializer.Deserialize<Marker[]>(jsonProperties[1].Value);
|
||||||
long? personKey;
|
return results;
|
||||||
const int zero = 0;
|
|
||||||
List<Face>? matches;
|
|
||||||
MarkerWith markerWith;
|
|
||||||
int? normalizedRectangle;
|
|
||||||
string personKeyFormatted;
|
|
||||||
DatabaseFile? databaseFile;
|
|
||||||
PersonBirthday personBirthday;
|
|
||||||
Marker[] markers = GetMarkers();
|
|
||||||
string fileNameWithoutExtension;
|
|
||||||
PersonContainer[]? personContainers;
|
|
||||||
System.Drawing.Rectangle dlibRectangle;
|
|
||||||
System.Drawing.Rectangle prismRectangle;
|
|
||||||
System.Drawing.Rectangle intersectRectangle;
|
|
||||||
(Face Face, double Percent)[] sortedCollection;
|
|
||||||
List<(Face Face, double Percent)> collection = new();
|
|
||||||
DatabaseFileRoot databaseFileRoot = GetDatabaseFileRoot();
|
|
||||||
Dictionary<string, DatabaseFile> fileUidToFile = Get(databaseFileRoot);
|
|
||||||
Dictionary<int, PersonContainer[]>? normalizedRectangleToPersonContainers;
|
|
||||||
Dictionary<string, List<Face>> keyValuePairs = GetFacesByFileName(filteredItems);
|
|
||||||
foreach (Marker marker in markers)
|
|
||||||
{
|
|
||||||
dlib = null;
|
|
||||||
personKey = null;
|
|
||||||
collection.Clear();
|
|
||||||
normalizedRectangle = null;
|
|
||||||
personKeyFormatted = string.Empty;
|
|
||||||
normalizedRectangleToPersonContainers = null;
|
|
||||||
if (!fileUidToFile.TryGetValue(marker.FileUid, out databaseFile))
|
|
||||||
continue;
|
|
||||||
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(Path.Combine("C:", databaseFile.FileName));
|
|
||||||
prismRectangle = new((int)(marker.X * databaseFile.FileWidth), (int)(marker.Y * databaseFile.FileHeight), (int)(marker.W * databaseFile.FileWidth), (int)(marker.H * databaseFile.FileHeight));
|
|
||||||
if (!keyValuePairs.TryGetValue(fileNameWithoutExtension, out matches) || !int.TryParse(fileNameWithoutExtension, out int id))
|
|
||||||
percent = null;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dlib = id;
|
|
||||||
_ = _IdThenNormalizedRectangleToPersonContainers.TryGetValue(dlib.Value, out normalizedRectangleToPersonContainers);
|
|
||||||
foreach (Face face in matches)
|
|
||||||
{
|
|
||||||
if (face.Location is null || face.OutputResolution is null)
|
|
||||||
continue;
|
|
||||||
dlibRectangle = new(face.Location.Left, face.Location.Top, face.Location.Right - face.Location.Left, face.Location.Bottom - face.Location.Top);
|
|
||||||
intersectRectangle = System.Drawing.Rectangle.Intersect(prismRectangle, dlibRectangle);
|
|
||||||
if (intersectRectangle.Width == 0 || intersectRectangle.Height == 0)
|
|
||||||
continue;
|
|
||||||
percent = (double)intersectRectangle.Width * intersectRectangle.Height / (dlibRectangle.Width * dlibRectangle.Height);
|
|
||||||
if (percent < 0.000001)
|
|
||||||
continue;
|
|
||||||
collection.Add(new(face, percent.Value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!collection.Any())
|
|
||||||
percent = null;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sortedCollection = collection.OrderByDescending(l => l.Percent).ToArray();
|
|
||||||
percent = sortedCollection[zero].Percent;
|
|
||||||
normalizedRectangle = sortedCollection[zero].Face.Mapping?.MappingFromLocation.NormalizedRectangle;
|
|
||||||
if (normalizedRectangleToPersonContainers is null || normalizedRectangle is null || !normalizedRectangleToPersonContainers.TryGetValue(normalizedRectangle.Value, out personContainers))
|
|
||||||
personContainers = null;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (PersonContainer personContainer in personContainers)
|
|
||||||
{
|
|
||||||
if (personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any())
|
|
||||||
continue;
|
|
||||||
personBirthday = personContainer.Birthdays[zero];
|
|
||||||
personKey = personBirthday.Value.Ticks;
|
|
||||||
personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, personBirthday);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
markerWith = GetMarkerWith(dlib, databaseFile, marker, collection.Count, percent, normalizedRectangle, personKey, personKeyFormatted);
|
|
||||||
string json = JsonSerializer.Serialize(markerWith, new JsonSerializerOptions() { WriteIndented = true });
|
|
||||||
if (IPath.WriteAllText(Path.Combine(_Configuration.PhotoPrismDirectory, "With", $"{marker.MarkerUid}.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveMarkers()
|
public static void SaveMarkers(string photoPrismDirectory)
|
||||||
{
|
{
|
||||||
if (_Configuration is null)
|
if (string.IsNullOrEmpty(photoPrismDirectory))
|
||||||
throw new NullReferenceException(nameof(_Configuration));
|
throw new Exception();
|
||||||
double[]? encoding;
|
// double[]? encoding;
|
||||||
string file = Path.Combine(_Configuration.PhotoPrismDirectory, "markers.json");
|
// Marker[]? markers = GetMarkers(photoPrismDirectory);
|
||||||
string json = File.ReadAllText(file);
|
// if (markers is null)
|
||||||
Marker[]? markers = JsonSerializer.Deserialize<Marker[]>(json);
|
// throw new NullReferenceException(nameof(markers));
|
||||||
|
// foreach (Marker marker in markers)
|
||||||
|
// {
|
||||||
|
// encoding = JsonSerializer.Deserialize<double[]>(marker.EmbeddingsJson[1..^1]);
|
||||||
|
// File.WriteAllText(Path.Combine(photoPrismDirectory, "EmbeddingsJson", $"{marker.MarkerUid}.json"), marker.EmbeddingsJson);
|
||||||
|
// if (encoding is null)
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<string, List<Marker>> GetFileUIdToMarkers(string photoPrismDirectory)
|
||||||
|
{
|
||||||
|
Dictionary<string, List<Marker>> results = new();
|
||||||
|
Marker[]? markers = GetMarkers(photoPrismDirectory);
|
||||||
if (markers is null)
|
if (markers is null)
|
||||||
throw new NullReferenceException(nameof(markers));
|
throw new NullReferenceException(nameof(markers));
|
||||||
foreach (Marker marker in markers)
|
foreach (Marker marker in markers)
|
||||||
{
|
{
|
||||||
encoding = JsonSerializer.Deserialize<double[]>(marker.EmbeddingsJson[1..^1]);
|
if (!results.ContainsKey(marker.FileUid))
|
||||||
File.WriteAllText(Path.Combine(_Configuration.PhotoPrismDirectory, "EmbeddingsJson", $"{marker.MarkerUid}.json"), marker.EmbeddingsJson);
|
results.Add(marker.FileUid, new());
|
||||||
if (encoding is null)
|
results[marker.FileUid].Add(marker);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadMatches()
|
private static DatabaseFile[]? GetDatabaseFiles(string photoPrismDirectory)
|
||||||
|
{
|
||||||
|
DatabaseFile[]? results;
|
||||||
|
string file = Path.Combine(photoPrismDirectory, "files.json");
|
||||||
|
JsonProperty[] jsonProperties = GetJsonProperty(file);
|
||||||
|
results = JsonSerializer.Deserialize<DatabaseFile[]>(jsonProperties[1].Value);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, List<MappingFromPhotoPrism>> GetFileNameToCollection(string photoPrismDirectory)
|
||||||
|
{
|
||||||
|
Dictionary<string, List<MappingFromPhotoPrism>> results = new();
|
||||||
|
List<Marker>? makers;
|
||||||
|
MappingFromPhotoPrism mappingFromPhotoPrism;
|
||||||
|
List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection;
|
||||||
|
DatabaseFile[]? databaseFiles = GetDatabaseFiles(photoPrismDirectory);
|
||||||
|
if (databaseFiles is null)
|
||||||
|
throw new NullReferenceException(nameof(databaseFiles));
|
||||||
|
Dictionary<string, List<Marker>> fileUIdToMarkers = GetFileUIdToMarkers(photoPrismDirectory);
|
||||||
|
foreach (DatabaseFile databaseFile in databaseFiles)
|
||||||
|
{
|
||||||
|
if (!results.TryGetValue(databaseFile.FileName, out mappingFromPhotoPrismCollection))
|
||||||
|
{
|
||||||
|
results.Add(databaseFile.FileName, new());
|
||||||
|
if (!results.TryGetValue(databaseFile.FileName, out mappingFromPhotoPrismCollection))
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
if (!fileUIdToMarkers.TryGetValue(databaseFile.FileUid, out makers))
|
||||||
|
mappingFromPhotoPrism = new(databaseFile, new());
|
||||||
|
else
|
||||||
|
mappingFromPhotoPrism = new(databaseFile, makers);
|
||||||
|
mappingFromPhotoPrismCollection.Add(mappingFromPhotoPrism);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteMatches(long ticks, Face[] distinctFilteredFaces)
|
||||||
{
|
{
|
||||||
if (_Configuration is null)
|
if (_Configuration is null)
|
||||||
throw new NullReferenceException(nameof(_Configuration));
|
throw new NullReferenceException(nameof(_Configuration));
|
||||||
string json;
|
long? personKey;
|
||||||
MarkerWith? markerWith;
|
const int zero = 0;
|
||||||
List<MarkerWith> collection = new();
|
int? normalizedRectangle;
|
||||||
|
string personKeyFormatted;
|
||||||
|
List<string> subjects = new();
|
||||||
|
PersonBirthday personBirthday;
|
||||||
|
string personDisplayDirectoryName;
|
||||||
StringBuilder stringBuilder = new();
|
StringBuilder stringBuilder = new();
|
||||||
List<(int Count, MarkerWith MarkerWith)> countCollection = new();
|
PersonContainer[]? personContainers;
|
||||||
List<(double Percent, MarkerWith MarkerWith)> percentCollection = new();
|
System.Drawing.Rectangle dlibRectangle;
|
||||||
string[] files = Directory.GetFiles(Path.Combine(_Configuration.PhotoPrismDirectory, "With"), "*.json", SearchOption.TopDirectoryOnly);
|
System.Drawing.Rectangle? prismRectangle;
|
||||||
foreach (string file in files)
|
System.Drawing.Rectangle intersectRectangle;
|
||||||
|
Dictionary<int, PersonContainer[]>? normalizedRectangleToPersonContainers;
|
||||||
|
(MappingFromPhotoPrism MappingFromPhotoPrism, Marker Marker, double Percent)[] sortedCollection;
|
||||||
|
List<(MappingFromPhotoPrism MappingFromPhotoPrism, Marker Marker, double Percent)> collection = new();
|
||||||
|
foreach (Face face in distinctFilteredFaces)
|
||||||
{
|
{
|
||||||
json = File.ReadAllText(file);
|
collection.Clear();
|
||||||
markerWith = JsonSerializer.Deserialize<MarkerWith>(json);
|
normalizedRectangle = face.Mapping?.MappingFromLocation.NormalizedRectangle;
|
||||||
if (markerWith is null || markerWith.DlibId is null)
|
if (normalizedRectangle is null)
|
||||||
continue;
|
continue;
|
||||||
collection.Add(markerWith);
|
if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null || face.Mapping is null)
|
||||||
if (markerWith.Count is null || markerWith.Count.Value == 0)
|
|
||||||
continue;
|
continue;
|
||||||
countCollection.Add(new(markerWith.Count.Value, markerWith));
|
if (face.Mapping.MappingFromPhotoPrismCollection is null)
|
||||||
if (markerWith.Percent is null)
|
|
||||||
continue;
|
continue;
|
||||||
percentCollection.Add(new(markerWith.Percent.Value, markerWith));
|
_ = _IdThenNormalizedRectangleToPersonContainers.TryGetValue(face.Mapping.MappingFromItem.Id, out normalizedRectangleToPersonContainers);
|
||||||
if (string.IsNullOrEmpty(markerWith.PersonKeyFormatted))
|
if (normalizedRectangleToPersonContainers is null || !normalizedRectangleToPersonContainers.TryGetValue(normalizedRectangle.Value, out personContainers))
|
||||||
continue;
|
continue;
|
||||||
_ = stringBuilder.
|
dlibRectangle = new(face.Location.Left, face.Location.Top, face.Location.Right - face.Location.Left, face.Location.Bottom - face.Location.Top);
|
||||||
Append("update `markers` set subj_src = 'manual' marker_name = '").
|
foreach (MappingFromPhotoPrism mappingFromPhotoPrism in face.Mapping.MappingFromPhotoPrismCollection)
|
||||||
Append(markerWith.PersonKeyFormatted).
|
{
|
||||||
Append("' where marker_uid = '").
|
foreach (Marker marker in mappingFromPhotoPrism.Markers)
|
||||||
Append(markerWith.MarkerUid).
|
{
|
||||||
AppendLine("';");
|
prismRectangle = ILocation.GetRectangle(face.OutputResolution, mappingFromPhotoPrism.DatabaseFile, marker);
|
||||||
|
if (prismRectangle is null)
|
||||||
|
continue;
|
||||||
|
intersectRectangle = System.Drawing.Rectangle.Intersect(dlibRectangle, prismRectangle.Value);
|
||||||
|
if (intersectRectangle.Width == 0 || intersectRectangle.Height == 0)
|
||||||
|
continue;
|
||||||
|
double percent = (double)intersectRectangle.Width * intersectRectangle.Height / (dlibRectangle.Width * dlibRectangle.Height);
|
||||||
|
if (percent < 0.000001)
|
||||||
|
continue;
|
||||||
|
collection.Add(new(mappingFromPhotoPrism, marker, percent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!collection.Any())
|
||||||
|
continue;
|
||||||
|
sortedCollection = collection.OrderByDescending(l => l.Percent).ToArray();
|
||||||
|
foreach ((MappingFromPhotoPrism mappingFromPhotoPrism, Marker marker, double percent) in sortedCollection)
|
||||||
|
{
|
||||||
|
foreach (PersonContainer personContainer in personContainers)
|
||||||
|
{
|
||||||
|
if (personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any())
|
||||||
|
continue;
|
||||||
|
personBirthday = personContainer.Birthdays[zero];
|
||||||
|
personKey = personBirthday.Value.Ticks;
|
||||||
|
personDisplayDirectoryName = personContainer.DisplayDirectoryName;
|
||||||
|
personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, personBirthday);
|
||||||
|
subjects.Add($"update `subjects` set subj_alias = '{personKeyFormatted}' where subj_name = '{personDisplayDirectoryName}';");
|
||||||
|
_ = stringBuilder.
|
||||||
|
Append("update `markers` set subj_src = 'manual', marker_name = '").
|
||||||
|
Append(personDisplayDirectoryName).
|
||||||
|
Append("' where marker_uid = '").
|
||||||
|
Append(marker.MarkerUid).
|
||||||
|
AppendLine("';");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
(int, MarkerWith)[] countSorted = countCollection.OrderByDescending(l => l.Count).ToArray();
|
File.WriteAllLines(Path.Combine(_Configuration.PhotoPrismDirectory, $"{ticks}-subject_alias_update.sql"), subjects.Distinct());
|
||||||
(double, MarkerWith)[] percentSorted = percentCollection.OrderBy(l => l.Percent).ToArray();
|
File.WriteAllText(Path.Combine(_Configuration.PhotoPrismDirectory, $"{ticks}-marker_name_update.sql"), stringBuilder.ToString());
|
||||||
if (collection.Any())
|
|
||||||
{ }
|
|
||||||
File.WriteAllText(Path.Combine(_Configuration.PhotoPrismDirectory, "marker_name_update.sql"), stringBuilder.ToString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dictionary<int, Dictionary<int, PersonContainer[]>> GetMissing(Dictionary<int, Dictionary<int, Mapping>> idToNormalizedRectangleToMapping)
|
public Dictionary<int, Dictionary<int, PersonContainer[]>> GetMissing(Dictionary<int, Dictionary<int, Mapping>> idToNormalizedRectangleToMapping)
|
||||||
|
@ -189,7 +189,7 @@ internal abstract class MapLogic
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static List<(string, string[], string)> DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, long ticks, string? a2PeopleContentDirectory, string? eDistanceContentDirectory, PersonContainer[] personContainers)
|
internal static List<(string, string[], string)> DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, PersonContainer[] personContainers, long ticks, string? a2PeopleContentDirectory, string? eDistanceContentDirectory)
|
||||||
{
|
{
|
||||||
List<(string, string[], string)> results;
|
List<(string, string[], string)> results;
|
||||||
string personKeyFormatted;
|
string personKeyFormatted;
|
||||||
|
@ -3,9 +3,9 @@ namespace View_by_Distance.Map.Models.Stateless.Methods;
|
|||||||
public interface IMapLogic
|
public interface IMapLogic
|
||||||
{ // ...
|
{ // ...
|
||||||
|
|
||||||
List<(string, string[], string)> TestStatic_DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, long ticks, string? a2PeopleContentDirectory, string? eDistanceContentDirectory, Shared.Models.PersonContainer[] personContainers) =>
|
List<(string, string[], string)> TestStatic_DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, Shared.Models.PersonContainer[] personContainers, long ticks, string? a2PeopleContentDirectory, string? eDistanceContentDirectory) =>
|
||||||
DeleteEmptyDirectoriesAndGetMappedFaceFiles(configuration, ticks, a2PeopleContentDirectory, eDistanceContentDirectory, personContainers);
|
DeleteEmptyDirectoriesAndGetMappedFaceFiles(configuration, personContainers, ticks, a2PeopleContentDirectory, eDistanceContentDirectory);
|
||||||
static List<(string, string[], string)> DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, long ticks, string? a2PeopleContentDirectory, string? eDistanceContentDirectory, Shared.Models.PersonContainer[] personContainers) =>
|
static List<(string, string[], string)> DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, Shared.Models.PersonContainer[] personContainers, long ticks, string? a2PeopleContentDirectory, string? eDistanceContentDirectory) =>
|
||||||
MapLogic.DeleteEmptyDirectoriesAndGetMappedFaceFiles(configuration, ticks, a2PeopleContentDirectory, eDistanceContentDirectory, personContainers);
|
MapLogic.DeleteEmptyDirectoriesAndGetMappedFaceFiles(configuration, personContainers, ticks, a2PeopleContentDirectory, eDistanceContentDirectory);
|
||||||
|
|
||||||
}
|
}
|
@ -142,7 +142,7 @@ public class B_Metadata
|
|||||||
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))
|
||||||
{
|
{
|
||||||
if (!_ForceMetadataLastWriteTimeToCreationTime && (!fileInfo.Exists || fileInfo.LastWriteTime == fileInfo.CreationTime))
|
if (!_ForceMetadataLastWriteTimeToCreationTime)
|
||||||
subFileTuples.Add(new Tuple<string, DateTime>(nameof(B_Metadata), DateTime.Now));
|
subFileTuples.Add(new Tuple<string, DateTime>(nameof(B_Metadata), DateTime.Now));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -267,7 +267,7 @@
|
|||||||
// propertyTicks = null;
|
// propertyTicks = null;
|
||||||
// foreach (PropertyCompare.Models.PropertyCompare propertyCompare in propertyCompareCollection)
|
// foreach (PropertyCompare.Models.PropertyCompare propertyCompare in propertyCompareCollection)
|
||||||
// {
|
// {
|
||||||
// if (propertyCompare?.Property?.Id is null)
|
// if (propertyCompare?.Property?.FileId is null)
|
||||||
// continue;
|
// continue;
|
||||||
// if (ticks != propertyCompare.MinimumDateTime.Ticks)
|
// if (ticks != propertyCompare.MinimumDateTime.Ticks)
|
||||||
// {
|
// {
|
||||||
@ -276,7 +276,7 @@
|
|||||||
// }
|
// }
|
||||||
// if (!regexResult.Equals(propertyCompare.RegexResult, StringComparison.CurrentCultureIgnoreCase))
|
// if (!regexResult.Equals(propertyCompare.RegexResult, StringComparison.CurrentCultureIgnoreCase))
|
||||||
// continue;
|
// continue;
|
||||||
// propertyId = propertyCompare.Property.Id;
|
// propertyId = propertyCompare.Property.FileId;
|
||||||
// propertyTicks = propertyCompare.MinimumDateTime.Ticks;
|
// propertyTicks = propertyCompare.MinimumDateTime.Ticks;
|
||||||
// mappedIndex = mappedIndices.IndexOf(index);
|
// mappedIndex = mappedIndices.IndexOf(index);
|
||||||
// if (mappedIndex > -1)
|
// if (mappedIndex > -1)
|
||||||
@ -290,7 +290,7 @@
|
|||||||
// string[] duplicatesLines = (
|
// string[] duplicatesLines = (
|
||||||
// from l
|
// from l
|
||||||
// in duplicates
|
// in duplicates
|
||||||
// select $"{l.Property.Id}\t{l.RegexResult}\t{l.MinimumDateTime:yyyy-MM-dd_HH-mm-ss}\t{l.MinimumDateTime}\t{l.RelativeDirectory}\t{l.FileNameWithoutExtension}{l.Extension}.___"
|
// select $"{l.Property.FileId}\t{l.RegexResult}\t{l.MinimumDateTime:yyyy-MM-dd_HH-mm-ss}\t{l.MinimumDateTime}\t{l.RelativeDirectory}\t{l.FileNameWithoutExtension}{l.Extension}.___"
|
||||||
// ).ToArray();
|
// ).ToArray();
|
||||||
// string[] matchedLines = (
|
// string[] matchedLines = (
|
||||||
// from l
|
// from l
|
||||||
@ -575,11 +575,11 @@
|
|||||||
// Dictionary<int, List<PropertyCompare.Models.PropertyCompare>> results = new();
|
// Dictionary<int, List<PropertyCompare.Models.PropertyCompare>> results = new();
|
||||||
// foreach (PropertyCompare.Models.PropertyCompare propertyCompare in propertyCompares)
|
// foreach (PropertyCompare.Models.PropertyCompare propertyCompare in propertyCompares)
|
||||||
// {
|
// {
|
||||||
// if (propertyCompare?.Property?.Id is null)
|
// if (propertyCompare?.Property?.FileId is null)
|
||||||
// continue;
|
// continue;
|
||||||
// if (!results.ContainsKey(propertyCompare.Property.Id.Value))
|
// if (!results.ContainsKey(propertyCompare.Property.FileId.Value))
|
||||||
// results.Add(propertyCompare.Property.Id.Value, new());
|
// results.Add(propertyCompare.Property.FileId.Value, new());
|
||||||
// results[propertyCompare.Property.Id.Value].Add(propertyCompare);
|
// results[propertyCompare.Property.FileId.Value].Add(propertyCompare);
|
||||||
// }
|
// }
|
||||||
// return results;
|
// return results;
|
||||||
// }
|
// }
|
||||||
@ -628,9 +628,9 @@
|
|||||||
// if (keyValuePairs.ContainsKey(index))
|
// if (keyValuePairs.ContainsKey(index))
|
||||||
// {
|
// {
|
||||||
// propertyCompare = keyValuePairs[index][0];
|
// propertyCompare = keyValuePairs[index][0];
|
||||||
// if (propertyCompare?.Property?.Id is null)
|
// if (propertyCompare?.Property?.FileId is null)
|
||||||
// continue;
|
// continue;
|
||||||
// propertyId = propertyCompare.Property.Id;
|
// propertyId = propertyCompare.Property.FileId;
|
||||||
// propertyTicks = propertyCompare.MinimumDateTime.Ticks;
|
// propertyTicks = propertyCompare.MinimumDateTime.Ticks;
|
||||||
// }
|
// }
|
||||||
// collection.Add(new(index, relativeDirectory, $"{fileNameWithoutExtension}{extension}", regexResult, ticks, propertyId, propertyTicks));
|
// collection.Add(new(index, relativeDirectory, $"{fileNameWithoutExtension}{extension}", regexResult, ticks, propertyId, propertyTicks));
|
||||||
|
@ -44,7 +44,7 @@ public partial class PropertyCompare
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// internal static string GetSelect(PropertyCompare item) => string.Concat(item.JsonFileNameWithoutExtension, item.ImageFileName, '\t', item.Property.CreationTime.Ticks, '\t', GetDateTime(item.Property).ToString("yyyy-MM-dd_HH-mm-ss"), '\t', item.Property.Id, '\t', item.Property.FileSize, '\t', item.Property.Width, '\t', item.Property.Height);
|
// internal static string GetSelect(PropertyCompare item) => string.Concat(item.JsonFileNameWithoutExtension, item.ImageFileName, '\t', item.Property.CreationTime.Ticks, '\t', GetDateTime(item.Property).ToString("yyyy-MM-dd_HH-mm-ss"), '\t', item.Property.FileId, '\t', item.Property.FileSize, '\t', item.Property.Width, '\t', item.Property.Height);
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@
|
|||||||
// extension = Path.GetExtension(files[index]);
|
// extension = Path.GetExtension(files[index]);
|
||||||
// string json = File.ReadAllText(jsonFile);
|
// string json = File.ReadAllText(jsonFile);
|
||||||
// Shared.Models.Property? property = JsonSerializer.Deserialize<Shared.Models.Property>(json);
|
// Shared.Models.Property? property = JsonSerializer.Deserialize<Shared.Models.Property>(json);
|
||||||
// if (property?.Id is null)
|
// if (property?.FileId is null)
|
||||||
// throw new NullReferenceException(nameof(property));
|
// throw new NullReferenceException(nameof(property));
|
||||||
// DateTime minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(property);
|
// DateTime minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(property);
|
||||||
// corrected = string.Concat(relativeDirectory, jsonFileNameWithoutExtension);
|
// corrected = string.Concat(relativeDirectory, jsonFileNameWithoutExtension);
|
||||||
@ -195,11 +195,11 @@
|
|||||||
// {
|
// {
|
||||||
// n = i switch
|
// n = i switch
|
||||||
// {
|
// {
|
||||||
// 0 => property.Id.Value,
|
// 0 => property.FileId.Value,
|
||||||
// 1 => property.Id.Value,
|
// 1 => property.FileId.Value,
|
||||||
// 2 => property.Id.Value,
|
// 2 => property.FileId.Value,
|
||||||
// 3 => property.Id.Value,
|
// 3 => property.FileId.Value,
|
||||||
// 4 => property.Id.Value,
|
// 4 => property.FileId.Value,
|
||||||
// 5 => Shared.Models.Stateless.Methods.IProperty.GetDateTime(property).Ticks,
|
// 5 => Shared.Models.Stateless.Methods.IProperty.GetDateTime(property).Ticks,
|
||||||
// 6 => property.CreationTime.Ticks,
|
// 6 => property.CreationTime.Ticks,
|
||||||
// 7 => property.FileSize,
|
// 7 => property.FileSize,
|
||||||
@ -229,8 +229,8 @@
|
|||||||
// results.Add(propertyCompare);
|
// results.Add(propertyCompare);
|
||||||
// if (duplicates is not null)
|
// if (duplicates is not null)
|
||||||
// {
|
// {
|
||||||
// string value = $"{property.Id.Value}\t{property}";
|
// string value = $"{property.FileId.Value}\t{property}";
|
||||||
// index = ids.IndexOf(property.Id.Value);
|
// index = ids.IndexOf(property.FileId.Value);
|
||||||
// if (index > -1)
|
// if (index > -1)
|
||||||
// {
|
// {
|
||||||
// lock (@lock)
|
// lock (@lock)
|
||||||
@ -241,7 +241,7 @@
|
|||||||
// }
|
// }
|
||||||
// lock (@lock)
|
// lock (@lock)
|
||||||
// {
|
// {
|
||||||
// ids.Add(property.Id.Value);
|
// ids.Add(property.FileId.Value);
|
||||||
// collection.Add(propertyCompare);
|
// collection.Add(propertyCompare);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
@ -333,7 +333,7 @@ public class A_Property
|
|||||||
json = JsonSerializer.Serialize(result, _WriteIndentedJsonSerializerOptions);
|
json = JsonSerializer.Serialize(result, _WriteIndentedJsonSerializerOptions);
|
||||||
if (populateId && Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: true, compareBeforeWrite: true))
|
if (populateId && Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: true, compareBeforeWrite: true))
|
||||||
{
|
{
|
||||||
if (!_Configuration.ForcePropertyLastWriteTimeToCreationTime && (!fileInfo.Exists || fileInfo.LastWriteTime == fileInfo.CreationTime))
|
if (!_Configuration.ForcePropertyLastWriteTimeToCreationTime)
|
||||||
sourceDirectoryFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), DateTime.Now));
|
sourceDirectoryFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), DateTime.Now));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -16,7 +16,7 @@ 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 = "Max Images In Directory For Top Level First Pass"), Required] public int? MaxImagesInDirectoryForTopLevelFirstPass { get; set; }
|
[Display(Name = "Max Images In Directory For Top Level First Pass"), Required] public int? MaxImagesInDirectoryForTopLevelFirstPass { get; set; }
|
||||||
[Display(Name = "Pattern"), Required] public string Pattern { get; set; }
|
[Display(Name = "Pattern"), Required] public string Pattern { get; set; }
|
||||||
[Display(Name = "Populate Properties Id"), Required] public bool? PopulatePropertyId { get; set; }
|
[Display(Name = "Populate Properties FileId"), Required] public bool? PopulatePropertyId { get; set; }
|
||||||
[Display(Name = "Properties Changed For Property"), Required] public bool? PropertiesChangedForProperty { get; set; }
|
[Display(Name = "Properties Changed For Property"), Required] public bool? PropertiesChangedForProperty { get; set; }
|
||||||
[Display(Name = "Property Content Collection Files"), Required] public string[] PropertyContentCollectionFiles { get; set; }
|
[Display(Name = "Property Content Collection Files"), Required] public string[] PropertyContentCollectionFiles { get; set; }
|
||||||
[Display(Name = "Result All In One"), Required] public string ResultAllInOne { get; set; }
|
[Display(Name = "Result All In One"), Required] public string ResultAllInOne { get; set; }
|
||||||
|
@ -216,6 +216,7 @@ public class Container
|
|||||||
{
|
{
|
||||||
string relativePath;
|
string relativePath;
|
||||||
string checkFileName;
|
string checkFileName;
|
||||||
|
string? checkDirectoryName;
|
||||||
List<string> checkCollection = new();
|
List<string> checkCollection = new();
|
||||||
checkCollection.AddRange(otherCollection);
|
checkCollection.AddRange(otherCollection);
|
||||||
int length = configuration.RootDirectory.Length;
|
int length = configuration.RootDirectory.Length;
|
||||||
@ -225,6 +226,9 @@ public class Container
|
|||||||
{
|
{
|
||||||
relativePath = Shared.Models.Stateless.Methods.IPath.GetRelativePath(fileHolder.FullName, length);
|
relativePath = Shared.Models.Stateless.Methods.IPath.GetRelativePath(fileHolder.FullName, length);
|
||||||
checkFileName = Path.GetFullPath(string.Concat(aPropertySingletonDirectory, relativePath));
|
checkFileName = Path.GetFullPath(string.Concat(aPropertySingletonDirectory, relativePath));
|
||||||
|
checkDirectoryName = Path.GetDirectoryName(checkFileName);
|
||||||
|
if (string.IsNullOrEmpty(checkDirectoryName) || !Directory.Exists(checkDirectoryName))
|
||||||
|
continue;
|
||||||
if (!checkCollection.Remove(checkFileName))
|
if (!checkCollection.Remove(checkFileName))
|
||||||
File.WriteAllText(checkFileName, string.Empty);
|
File.WriteAllText(checkFileName, string.Empty);
|
||||||
}
|
}
|
||||||
|
@ -505,7 +505,7 @@ public class C_Resize
|
|||||||
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))
|
||||||
{
|
{
|
||||||
if (!_ForceResizeLastWriteTimeToCreationTime && (!fileInfo.Exists || fileInfo.LastWriteTime == fileInfo.CreationTime))
|
if (!_ForceResizeLastWriteTimeToCreationTime)
|
||||||
subFileTuples.Add(new Tuple<string, DateTime>(nameof(C_Resize), DateTime.Now));
|
subFileTuples.Add(new Tuple<string, DateTime>(nameof(C_Resize), DateTime.Now));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace View_by_Distance.Map.Models;
|
namespace View_by_Distance.Shared.Models;
|
||||||
|
|
||||||
public record DatabaseFile(
|
public record DatabaseFile(
|
||||||
[property: JsonPropertyName("id")] int Id,
|
[property: JsonPropertyName("id")] int Id,
|
@ -74,6 +74,21 @@ public class MappingFromLocation : Properties.IMappingFromLocation
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class MappingFromPhotoPrism : Properties.IMappingFromPhotoPrism
|
||||||
|
{
|
||||||
|
|
||||||
|
public DatabaseFile DatabaseFile { init; get; }
|
||||||
|
public List<Marker> Markers { init; get; }
|
||||||
|
|
||||||
|
[JsonConstructor]
|
||||||
|
public MappingFromPhotoPrism(DatabaseFile databaseFile, List<Marker> markers)
|
||||||
|
{
|
||||||
|
DatabaseFile = databaseFile;
|
||||||
|
Markers = markers;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public class MappingFromPerson : Properties.IMappingFromPerson
|
public class MappingFromPerson : Properties.IMappingFromPerson
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -109,23 +124,25 @@ public class Mapping : Properties.IMapping
|
|||||||
public int? By => _By;
|
public int? By => _By;
|
||||||
public MappingFromItem MappingFromItem { init; get; }
|
public MappingFromItem MappingFromItem { init; get; }
|
||||||
public MappingFromLocation MappingFromLocation { init; get; }
|
public MappingFromLocation MappingFromLocation { init; get; }
|
||||||
|
public List<MappingFromPhotoPrism>? MappingFromPhotoPrismCollection { init; get; }
|
||||||
public MappingFromPerson? MappingFromPerson => _MappingFromPerson;
|
public MappingFromPerson? MappingFromPerson => _MappingFromPerson;
|
||||||
public string? SegmentC => _SegmentC;
|
public string? SegmentC => _SegmentC;
|
||||||
public SortingContainer? SortingContainer => _SortingContainer;
|
public SortingContainer? SortingContainer => _SortingContainer;
|
||||||
|
|
||||||
[JsonConstructor]
|
[JsonConstructor]
|
||||||
public Mapping(int? by, MappingFromItem mappingFromItem, MappingFromLocation mappingFromLocation, MappingFromPerson? mappingFromPerson, string? segmentC, SortingContainer? sortingContainer)
|
public Mapping(int? by, MappingFromItem mappingFromItem, MappingFromLocation mappingFromLocation, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection, MappingFromPerson? mappingFromPerson, string? segmentC, SortingContainer? sortingContainer)
|
||||||
{
|
{
|
||||||
_By = by;
|
_By = by;
|
||||||
_SegmentC = segmentC;
|
_SegmentC = segmentC;
|
||||||
MappingFromItem = mappingFromItem;
|
MappingFromItem = mappingFromItem;
|
||||||
MappingFromLocation = mappingFromLocation;
|
MappingFromLocation = mappingFromLocation;
|
||||||
|
MappingFromPhotoPrismCollection = mappingFromPhotoPrismCollection;
|
||||||
_MappingFromPerson = mappingFromPerson;
|
_MappingFromPerson = mappingFromPerson;
|
||||||
_SortingContainer = sortingContainer;
|
_SortingContainer = sortingContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mapping(MappingFromItem mappingFromItem, MappingFromLocation mappingFromLocation) :
|
public Mapping(MappingFromItem mappingFromItem, MappingFromLocation mappingFromLocation, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection) :
|
||||||
this(null, mappingFromItem, mappingFromLocation, null, null, null)
|
this(null, mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection, null, null, null)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
@ -14,8 +14,8 @@ public record Marker(
|
|||||||
[property: JsonPropertyName("subj_src")] string SubjSrc,
|
[property: JsonPropertyName("subj_src")] string SubjSrc,
|
||||||
[property: JsonPropertyName("face_id")] string FaceId,
|
[property: JsonPropertyName("face_id")] string FaceId,
|
||||||
[property: JsonPropertyName("face_dist")] double FaceDist,
|
[property: JsonPropertyName("face_dist")] double FaceDist,
|
||||||
[property: JsonPropertyName("embeddings_json")] string EmbeddingsJson,
|
// [property: JsonPropertyName("embeddings_json")] string EmbeddingsJson,
|
||||||
[property: JsonPropertyName("landmarks_json")] string LandmarksJson,
|
// [property: JsonPropertyName("landmarks_json")] string LandmarksJson,
|
||||||
[property: JsonPropertyName("x")] double X,
|
[property: JsonPropertyName("x")] double X,
|
||||||
[property: JsonPropertyName("y")] double Y,
|
[property: JsonPropertyName("y")] double Y,
|
||||||
[property: JsonPropertyName("w")] double W,
|
[property: JsonPropertyName("w")] double W,
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
namespace View_by_Distance.Shared.Models;
|
|
||||||
|
|
||||||
public record MarkerWith(
|
|
||||||
string MarkerUid,
|
|
||||||
string FileUid,
|
|
||||||
string MarkerType,
|
|
||||||
string MarkerSrc,
|
|
||||||
string MarkerName,
|
|
||||||
int MarkerReview,
|
|
||||||
int MarkerInvalid,
|
|
||||||
string SubjUid,
|
|
||||||
string SubjSrc,
|
|
||||||
string FaceId,
|
|
||||||
double FaceDist,
|
|
||||||
string EmbeddingsJson,
|
|
||||||
string LandmarksJson,
|
|
||||||
double X,
|
|
||||||
double Y,
|
|
||||||
double W,
|
|
||||||
double H,
|
|
||||||
int Q,
|
|
||||||
int Size,
|
|
||||||
int Score,
|
|
||||||
string Thumb,
|
|
||||||
string MatchedAt,
|
|
||||||
string CreatedAt,
|
|
||||||
string UpdatedAt,
|
|
||||||
int FileId,
|
|
||||||
string FileName,
|
|
||||||
int? DlibId,
|
|
||||||
int? Count,
|
|
||||||
double? Percent,
|
|
||||||
int? NormalizedRectangle,
|
|
||||||
long? PersonKey,
|
|
||||||
string PersonKeyFormatted
|
|
||||||
);
|
|
@ -23,6 +23,14 @@ public interface IMappingFromLocation
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface IMappingFromPhotoPrism
|
||||||
|
{
|
||||||
|
|
||||||
|
public DatabaseFile DatabaseFile { init; get; }
|
||||||
|
public List<Marker> Markers { init; get; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public interface IMappingFromPerson
|
public interface IMappingFromPerson
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -40,6 +48,7 @@ public interface IMapping
|
|||||||
public string? SegmentC { get; }
|
public string? SegmentC { get; }
|
||||||
public MappingFromItem MappingFromItem { init; get; }
|
public MappingFromItem MappingFromItem { init; get; }
|
||||||
public MappingFromLocation MappingFromLocation { init; get; }
|
public MappingFromLocation MappingFromLocation { init; get; }
|
||||||
|
public List<MappingFromPhotoPrism>? MappingFromPhotoPrismCollection { init; get; }
|
||||||
public MappingFromPerson? MappingFromPerson { get; }
|
public MappingFromPerson? MappingFromPerson { get; }
|
||||||
public SortingContainer? SortingContainer { get; }
|
public SortingContainer? SortingContainer { get; }
|
||||||
|
|
||||||
|
@ -5,6 +5,21 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
|||||||
public interface ILocation
|
public interface ILocation
|
||||||
{ // ...
|
{ // ...
|
||||||
|
|
||||||
|
Rectangle? TestStatic_GetRectangle(Models.OutputResolution outputResolution, DatabaseFile databaseFile, Marker marker) =>
|
||||||
|
GetRectangle(outputResolution, databaseFile, marker);
|
||||||
|
static Rectangle? GetRectangle(Models.OutputResolution outputResolution, DatabaseFile databaseFile, Marker marker) =>
|
||||||
|
Location.GetRectangle(outputResolution, databaseFile, marker);
|
||||||
|
|
||||||
|
Models.Location? TestStatic_GetLocation(Models.OutputResolution outputResolution, DatabaseFile databaseFile, Marker marker) =>
|
||||||
|
GetLocation(outputResolution, databaseFile, marker);
|
||||||
|
static Models.Location? GetLocation(Models.OutputResolution outputResolution, DatabaseFile databaseFile, Marker marker) =>
|
||||||
|
Location.GetLocation(outputResolution, databaseFile, marker);
|
||||||
|
|
||||||
|
List<Models.Location> TestStatic_GetLocations(List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, List<Models.Face> faces) =>
|
||||||
|
GetLocations(mappingFromPhotoPrismCollection, faces);
|
||||||
|
static List<Models.Location> GetLocations(List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, List<Models.Face> faces) =>
|
||||||
|
Location.GetLocations(mappingFromPhotoPrismCollection, faces);
|
||||||
|
|
||||||
Rectangle TestStatic_GetRectangle(Rectangle checkRectangle, int locationDigits, int locationFactor, int normalizedRectangle, Models.OutputResolution outputResolution, bool useOldWay) =>
|
Rectangle TestStatic_GetRectangle(Rectangle checkRectangle, int locationDigits, int locationFactor, int normalizedRectangle, Models.OutputResolution outputResolution, bool useOldWay) =>
|
||||||
GetRectangle(checkRectangle, locationDigits, locationFactor, normalizedRectangle, outputResolution, useOldWay);
|
GetRectangle(checkRectangle, locationDigits, locationFactor, normalizedRectangle, outputResolution, useOldWay);
|
||||||
static Rectangle GetRectangle(Rectangle checkRectangle, int locationDigits, int locationFactor, int normalizedRectangle, Models.OutputResolution outputResolution, bool useOldWay) =>
|
static Rectangle GetRectangle(Rectangle checkRectangle, int locationDigits, int locationFactor, int normalizedRectangle, Models.OutputResolution outputResolution, bool useOldWay) =>
|
||||||
|
@ -17,6 +17,7 @@ public interface IPath
|
|||||||
DeleteEmptyDirectories(rootDirectory, deletedDirectories);
|
DeleteEmptyDirectories(rootDirectory, deletedDirectories);
|
||||||
static void DeleteEmptyDirectories(string rootDirectory, List<string> deletedDirectories) =>
|
static void DeleteEmptyDirectories(string rootDirectory, List<string> deletedDirectories) =>
|
||||||
XPath.DeleteEmptyDirectories(rootDirectory, deletedDirectories);
|
XPath.DeleteEmptyDirectories(rootDirectory, deletedDirectories);
|
||||||
|
// $dirs = gci "" -directory -recurse | Where { (gci $_.fullName).count -eq 0 } | select -expandproperty FullName $dirs | Foreach-Object { Remove-Item $_ }
|
||||||
|
|
||||||
string[] TestStatic_GetDirectoryNames(string directory) =>
|
string[] TestStatic_GetDirectoryNames(string directory) =>
|
||||||
GetDirectoryNames(directory);
|
GetDirectoryNames(directory);
|
||||||
|
@ -189,4 +189,81 @@ internal abstract class Location
|
|||||||
return result.Value;
|
return result.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool Matches(Models.OutputResolution outputResolution, DatabaseFile databaseFile)
|
||||||
|
{
|
||||||
|
bool result = outputResolution.Height == databaseFile.FileHeight && outputResolution.Width == databaseFile.FileWidth;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Rectangle? GetRectangle(Models.OutputResolution outputResolution, DatabaseFile databaseFile, Marker marker)
|
||||||
|
{
|
||||||
|
Rectangle? result;
|
||||||
|
bool matches = Matches(outputResolution, databaseFile);
|
||||||
|
if (!matches)
|
||||||
|
result = null;
|
||||||
|
else
|
||||||
|
result = new((int)Math.Ceiling(marker.X * databaseFile.FileWidth), (int)Math.Ceiling(marker.Y * databaseFile.FileHeight), (int)Math.Ceiling(marker.W * databaseFile.FileWidth), (int)Math.Ceiling(marker.H * databaseFile.FileHeight));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Models.Location? GetLocation(Marker marker, Rectangle rectangle)
|
||||||
|
{
|
||||||
|
Models.Location? result;
|
||||||
|
bool verified = Check(rectangle.Bottom, rectangle.Height, rectangle.Left, rectangle.Right, rectangle.Top, rectangle.Width, zCount: 1, throwException: false);
|
||||||
|
if (!verified)
|
||||||
|
result = null;
|
||||||
|
else
|
||||||
|
result = new(rectangle.Bottom, marker.Score / 100, rectangle.Left, rectangle.Right, rectangle.Top);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Models.Location? GetLocation(Models.OutputResolution outputResolution, DatabaseFile databaseFile, Marker marker)
|
||||||
|
{
|
||||||
|
Models.Location? result;
|
||||||
|
Rectangle? rectangle = GetRectangle(outputResolution, databaseFile, marker);
|
||||||
|
if (rectangle is null)
|
||||||
|
result = null;
|
||||||
|
else
|
||||||
|
result = GetLocation(marker, rectangle.Value);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static List<Models.Location> GetLocations(List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, List<Models.Face> faces)
|
||||||
|
{
|
||||||
|
List<Models.Location> results = new();
|
||||||
|
double percent;
|
||||||
|
Rectangle dlibRectangle;
|
||||||
|
Rectangle? prismRectangle;
|
||||||
|
Models.Location? location;
|
||||||
|
Rectangle intersectRectangle;
|
||||||
|
foreach (Models.Face face in faces)
|
||||||
|
{
|
||||||
|
if (face.Location is null || face.OutputResolution is null)
|
||||||
|
continue;
|
||||||
|
foreach (MappingFromPhotoPrism mappingFromPhotoPrism in mappingFromPhotoPrismCollection)
|
||||||
|
{
|
||||||
|
dlibRectangle = new(face.Location.Left, face.Location.Top, face.Location.Right - face.Location.Left, face.Location.Bottom - face.Location.Top);
|
||||||
|
foreach (Marker marker in mappingFromPhotoPrism.Markers)
|
||||||
|
{
|
||||||
|
prismRectangle = GetRectangle(face.OutputResolution, mappingFromPhotoPrism.DatabaseFile, marker);
|
||||||
|
if (prismRectangle is null)
|
||||||
|
{
|
||||||
|
location = new(1, 0, 0, 1, 0);
|
||||||
|
results.Add(location);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
location = GetLocation(marker, prismRectangle.Value);
|
||||||
|
if (location is null)
|
||||||
|
continue;
|
||||||
|
intersectRectangle = Rectangle.Intersect(dlibRectangle, prismRectangle.Value);
|
||||||
|
percent = (double)intersectRectangle.Width * intersectRectangle.Height / (dlibRectangle.Width * dlibRectangle.Height);
|
||||||
|
if (percent > 0.000001)
|
||||||
|
continue;
|
||||||
|
results.Add(location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -60,7 +60,6 @@ public class Configuration
|
|||||||
[Display(Name = "Face Area Permille Tolerance"), Required] public int[] RangeFaceAreaPermilleTolerance { get; set; }
|
[Display(Name = "Face Area Permille Tolerance"), Required] public int[] RangeFaceAreaPermilleTolerance { get; set; }
|
||||||
[Display(Name = "Location Minimum Confidence"), Required] public double[] RangeFaceConfidence { get; set; }
|
[Display(Name = "Location Minimum Confidence"), Required] public double[] RangeFaceConfidence { get; set; }
|
||||||
[Display(Name = "Face Distance Tolerance"), Required] public double[] RangeDistanceTolerance { get; set; }
|
[Display(Name = "Face Distance Tolerance"), Required] public double[] RangeDistanceTolerance { get; set; }
|
||||||
[Display(Name = "Retry Images Without a Face"), Required] public bool? RetryImagesWithoutAFaceLocation { get; set; }
|
|
||||||
[Display(Name = "Reverse"), Required] public bool? Reverse { get; set; }
|
[Display(Name = "Reverse"), Required] public bool? Reverse { get; set; }
|
||||||
[Display(Name = "Save Face Landmark For Output Resolutions"), Required] public string[] SaveFaceLandmarkForOutputResolutions { get; set; }
|
[Display(Name = "Save Face Landmark For Output Resolutions"), Required] public string[] SaveFaceLandmarkForOutputResolutions { get; set; }
|
||||||
[Display(Name = "Save Full Year Of Random Files"), Required] public bool? SaveFullYearOfRandomFiles { get; set; }
|
[Display(Name = "Save Full Year Of Random Files"), Required] public bool? SaveFullYearOfRandomFiles { get; set; }
|
||||||
@ -171,8 +170,6 @@ public class Configuration
|
|||||||
throw new NullReferenceException(nameof(configuration.RangeFaceConfidence));
|
throw new NullReferenceException(nameof(configuration.RangeFaceConfidence));
|
||||||
if (configuration.RangeDistanceTolerance is null || configuration.RangeDistanceTolerance.Length != 3)
|
if (configuration.RangeDistanceTolerance is null || configuration.RangeDistanceTolerance.Length != 3)
|
||||||
throw new NullReferenceException(nameof(configuration.RangeDistanceTolerance));
|
throw new NullReferenceException(nameof(configuration.RangeDistanceTolerance));
|
||||||
if (configuration.RetryImagesWithoutAFaceLocation is null)
|
|
||||||
throw new NullReferenceException(nameof(configuration.RetryImagesWithoutAFaceLocation));
|
|
||||||
if (configuration.Reverse is null)
|
if (configuration.Reverse is null)
|
||||||
throw new NullReferenceException(nameof(configuration.Reverse));
|
throw new NullReferenceException(nameof(configuration.Reverse));
|
||||||
configuration.SaveFaceLandmarkForOutputResolutions ??= Array.Empty<string>();
|
configuration.SaveFaceLandmarkForOutputResolutions ??= Array.Empty<string>();
|
||||||
@ -245,7 +242,6 @@ public class Configuration
|
|||||||
configuration.RangeFaceAreaPermilleTolerance,
|
configuration.RangeFaceAreaPermilleTolerance,
|
||||||
configuration.RangeFaceConfidence,
|
configuration.RangeFaceConfidence,
|
||||||
configuration.RangeDistanceTolerance,
|
configuration.RangeDistanceTolerance,
|
||||||
configuration.RetryImagesWithoutAFaceLocation.Value,
|
|
||||||
configuration.Reverse.Value,
|
configuration.Reverse.Value,
|
||||||
configuration.SaveFaceLandmarkForOutputResolutions,
|
configuration.SaveFaceLandmarkForOutputResolutions,
|
||||||
configuration.SaveFullYearOfRandomFiles.Value,
|
configuration.SaveFullYearOfRandomFiles.Value,
|
||||||
|
@ -58,7 +58,6 @@ public class Configuration
|
|||||||
public int[] RangeFaceAreaPermilleTolerance { init; get; }
|
public int[] RangeFaceAreaPermilleTolerance { init; get; }
|
||||||
public double[] RangeFaceConfidence { init; get; }
|
public double[] RangeFaceConfidence { init; get; }
|
||||||
public double[] RangeDistanceTolerance { init; get; }
|
public double[] RangeDistanceTolerance { init; get; }
|
||||||
public bool RetryImagesWithoutAFaceLocation { init; get; }
|
|
||||||
public bool Reverse { init; get; }
|
public bool Reverse { init; get; }
|
||||||
public string[] SaveFaceLandmarkForOutputResolutions { init; get; }
|
public string[] SaveFaceLandmarkForOutputResolutions { init; get; }
|
||||||
public bool SaveFullYearOfRandomFiles { init; get; }
|
public bool SaveFullYearOfRandomFiles { init; get; }
|
||||||
@ -123,7 +122,6 @@ public class Configuration
|
|||||||
int[] rangeFaceAreaPermilleTolerance,
|
int[] rangeFaceAreaPermilleTolerance,
|
||||||
double[] rangeFaceConfidence,
|
double[] rangeFaceConfidence,
|
||||||
double[] rangeDistanceTolerance,
|
double[] rangeDistanceTolerance,
|
||||||
bool retryImagesWithoutAFaceLocation,
|
|
||||||
bool reverse,
|
bool reverse,
|
||||||
string[] saveFaceLandmarkForOutputResolutions,
|
string[] saveFaceLandmarkForOutputResolutions,
|
||||||
bool saveFullYearOfRandomFiles,
|
bool saveFullYearOfRandomFiles,
|
||||||
@ -187,7 +185,6 @@ public class Configuration
|
|||||||
RangeFaceAreaPermilleTolerance = rangeFaceAreaPermilleTolerance;
|
RangeFaceAreaPermilleTolerance = rangeFaceAreaPermilleTolerance;
|
||||||
RangeFaceConfidence = rangeFaceConfidence;
|
RangeFaceConfidence = rangeFaceConfidence;
|
||||||
RangeDistanceTolerance = rangeDistanceTolerance;
|
RangeDistanceTolerance = rangeDistanceTolerance;
|
||||||
RetryImagesWithoutAFaceLocation = retryImagesWithoutAFaceLocation;
|
|
||||||
Reverse = reverse;
|
Reverse = reverse;
|
||||||
SaveFaceLandmarkForOutputResolutions = saveFaceLandmarkForOutputResolutions;
|
SaveFaceLandmarkForOutputResolutions = saveFaceLandmarkForOutputResolutions;
|
||||||
SaveFullYearOfRandomFiles = saveFullYearOfRandomFiles;
|
SaveFullYearOfRandomFiles = saveFullYearOfRandomFiles;
|
||||||
|
@ -231,7 +231,7 @@ public class UnitTestFace
|
|||||||
(Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(_Configuration);
|
(Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(_Configuration);
|
||||||
FaceRecognition faceRecognition = new(_Configuration.NumberOfJitters, _Configuration.NumberOfTimesToUpsample, model, modelParameter, predictorModel);
|
FaceRecognition faceRecognition = new(_Configuration.NumberOfJitters, _Configuration.NumberOfTimesToUpsample, model, modelParameter, predictorModel);
|
||||||
List<(Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary<FacePart, FacePoint[]>? FaceParts)> collection;
|
List<(Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary<FacePart, FacePoint[]>? FaceParts)> collection;
|
||||||
collection = faceRecognition.GetCollection(image, includeFaceEncoding: true, includeFaceParts: true);
|
collection = faceRecognition.GetCollection(image, locations: new(), includeFaceEncoding: true, includeFaceParts: true);
|
||||||
Assert.IsTrue(collection.Count == 2);
|
Assert.IsTrue(collection.Count == 2);
|
||||||
List<FaceDistance> faceDistanceEncodings = (from l in collection where l.FaceEncoding is not null select new FaceDistance(l.FaceEncoding)).ToList();
|
List<FaceDistance> faceDistanceEncodings = (from l in collection where l.FaceEncoding is not null select new FaceDistance(l.FaceEncoding)).ToList();
|
||||||
List<FaceDistance> faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncodings[0]);
|
List<FaceDistance> faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncodings[0]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user