PhotoPrism for more locations

This commit is contained in:
Mike Phares 2022-12-25 13:54:17 -07:00
parent a510019c1d
commit 37c7b6760d
31 changed files with 395 additions and 509 deletions

View File

@ -257,7 +257,7 @@ public partial class E_Distance
{
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);
intersectRectangle = System.Drawing.Rectangle.Intersect(sourceRectangle, checkRectangle);
intersectRectangle = System.Drawing.Rectangle.Intersect(checkRectangle, sourceRectangle);
if (intersectRectangle.Width == 0 || intersectRectangle.Height == 0)
continue;
percent = (double)intersectRectangle.Width * intersectRectangle.Height / (checkRectangle.Width * checkRectangle.Height);

View File

@ -179,8 +179,11 @@ public partial class Form : System.Windows.Forms.Form
_ProgressBar.Step = 1;
bool isIgnoreExtension;
_ProgressBar.Value = 0;
string checkFileExtension;
bool skipOneAllAreNumbers;
DateTime? minimumDateTime;
const string jpg = ".jpg";
const string jpeg = ".jpeg";
_ProgressBar.Visible = true;
bool isValidImageFormatExtension;
string? extraLargeBitmapThumbnail;
@ -201,8 +204,16 @@ public partial class Form : System.Windows.Forms.Form
{
skipOneAllAreNumbers = fileHolder.NameWithoutExtension[1..].All(l => char.IsNumber(l));
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;
}
}
if (!isIgnoreExtension && isValidImageFormatExtension)
extraLargeBitmapThumbnail = null;
else
@ -224,7 +235,8 @@ public partial class Form : System.Windows.Forms.Form
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)
{
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))
continue;
File.Move(fileHolder.FullName, checkFile);
@ -238,7 +250,8 @@ public partial class Form : System.Windows.Forms.Form
if (fileHolder.DirectoryName is null)
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))
continue;
File.Move(fileHolder.FullName, checkFile);

View File

@ -43,7 +43,6 @@ public class D_Face
private readonly int _FaceDistanceHiddenImageFactor;
private readonly EncoderParameters _EncoderParameters;
private readonly ImageCodecInfo _HiddenImageCodecInfo;
private readonly bool _RetryImagesWithoutAFaceLocation;
private readonly bool _ForceFaceLastWriteTimeToCreationTime;
private readonly EncoderParameters _HiddenEncoderParameters;
private readonly JsonSerializerOptions _WriteIndentedAndWhenWritingNull;
@ -63,7 +62,6 @@ public class D_Face
string modelDirectory,
string modelName,
bool overrideForFaceImages,
bool retryImagesWithoutAFaceLocation,
string predictorModelName,
bool propertiesChangedForFaces)
{
@ -81,7 +79,6 @@ public class D_Face
_CheckDFaceAndUpWriteDates = checkDFaceAndUpWriteDates;
_PropertiesChangedForFaces = propertiesChangedForFaces;
_FaceDistanceHiddenImageFactor = faceDistanceHiddenImageFactor;
_RetryImagesWithoutAFaceLocation = retryImagesWithoutAFaceLocation;
_ForceFaceLastWriteTimeToCreationTime = forceFaceLastWriteTimeToCreationTime;
(Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(modelDirectory, modelName, predictorModelName);
_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)
throw new NullReferenceException(nameof(_Log));
@ -225,10 +222,6 @@ public class D_Face
throw new NullReferenceException(nameof(_Configuration.NumberOfTimesToUpsample));
List<Shared.Models.Face> results = new();
FaceRecognitionDotNet.Image? unknownImage;
if (!mappingFromItem.ResizedFileHolder.Exists)
unknownImage = null;
else
{
try
{ unknownImage = FaceRecognition.LoadImageFile(mappingFromItem.ResizedFileHolder.FullName); }
catch (Exception)
@ -236,14 +229,11 @@ public class D_Face
unknownImage = null;
_Log.Info(string.Concat(new StackFrame().GetMethod()?.Name, " <", mappingFromItem.ResizedFileHolder.FullName, ">"));
}
}
if (unknownImage is null)
results.Add(new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, location: null));
else
if (unknownImage is not null)
{
List<(Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary<FacePart, FacePoint[]>? FaceParts)> collection;
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())
results.Add(new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, location: null));
else
@ -268,8 +258,6 @@ public class D_Face
unknownImage.Dispose();
faceRecognition.Dispose();
}
if (!results.Any())
throw new Exception();
return results;
}
@ -303,12 +291,13 @@ public class D_Face
#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;
if (string.IsNullOrEmpty(dResultsFullGroupDirectory))
throw new NullReferenceException(nameof(dResultsFullGroupDirectory));
string json;
List<Location> locations = new();
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();
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));
}
}
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);
if (wasNull || (!wasNull && results.Any(l => l.Location is not null)))
results = GetFaces(property, mappingFromItem, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, locations);
if (!results.Any())
File.Move(mappingFromItem.ResizedFileHolder.FullName, $"{mappingFromItem.ResizedFileHolder.FullName}.err");
else
{
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))
if (!_ForceFaceLastWriteTimeToCreationTime)
subFileTuples.Add(new Tuple<string, DateTime>(nameof(D_Face), DateTime.Now));
else
{
@ -370,126 +362,6 @@ public class D_Face
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)
{
FileInfo fileInfo;

View File

@ -198,7 +198,7 @@ public class FaceRecognition : DisposableObject
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();
if (image is null)
@ -207,7 +207,7 @@ public class FaceRecognition : DisposableObject
ThrowIfDisposed();
if (_PredictorModel == PredictorModel.Custom)
throw new NotSupportedException("FaceRecognition.PredictorModel.Custom is not supported.");
List<Location> locations = GetLocations(image);
locations.AddRange(GetLocations(image));
List<FullObjectDetection> fullObjectDetections = GetFullObjectDetections(image, locations);
if (fullObjectDetections.Count != locations.Count)
throw new Exception();

View File

@ -33,9 +33,11 @@ public partial class DlibDotNet
private readonly List<string> _Exceptions;
private readonly IsEnvironment _IsEnvironment;
private readonly bool _PropertyRootExistedBefore;
private readonly PersonContainer[] _PersonContainers;
private readonly Models.Configuration _Configuration;
private readonly bool _ArgZeroIsConfigurationRootDirectory;
private readonly Map.Models.Configuration _MapConfiguration;
private readonly Dictionary<string, List<MappingFromPhotoPrism>> _FileNameToCollection;
public DlibDotNet(
List<string> args,
@ -46,13 +48,13 @@ public partial class DlibDotNet
bool isSilent,
IConsole console)
{
_Console = console;
string message;
_Console = console;
_AppSettings = appSettings;
_FileNameToCollection = new();
_IsEnvironment = isEnvironment;
long ticks = DateTime.Now.Ticks;
_Exceptions = new List<string>();
PersonContainer[] personContainers;
_Log = Serilog.Log.ForContext<DlibDotNet>();
Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot);
Models.Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration);
@ -94,7 +96,6 @@ public partial class DlibDotNet
configuration.ModelDirectory,
configuration.ModelName,
configuration.OverrideForFaceImages,
configuration.RetryImagesWithoutAFaceLocation,
configuration.PredictorModelName,
configuration.PropertiesChangedForFaces);
}
@ -106,7 +107,7 @@ public partial class DlibDotNet
_MapConfiguration = Get(configuration, _Faces.FileNameExtension, _Faces.HiddenFileNameExtension, _FaceParts.FileNameExtension);
_Distance = new(configuration.DistanceMoveUnableToMatch, configuration.DistanceRenameToMatch, _Configuration.FaceConfidencePercent, configuration.RangeDistanceTolerance, configuration.RangeFaceConfidence);
if (_PropertyRootExistedBefore || !_ArgZeroIsConfigurationRootDirectory)
personContainers = Array.Empty<PersonContainer>();
_PersonContainers = Array.Empty<PersonContainer>();
else
{
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
@ -120,7 +121,7 @@ public partial class DlibDotNet
if (rootResultsDirectory is null)
throw new Exception();
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)
{
@ -142,7 +143,7 @@ public partial class DlibDotNet
filenameExtension);
}
if (!configuration.SkipSearch)
Search(ticks, argZero, propertyRoot, personContainers);
Search(ticks, argZero, propertyRoot);
if (!_PropertyRootExistedBefore && !_IsEnvironment.Development && _Exceptions.Count == 0 && _ArgZeroIsConfigurationRootDirectory)
{
List<string[]> directoryCollections = _Rename.GetDirectoryRenameCollections(
@ -205,7 +206,7 @@ public partial class DlibDotNet
private void Verify(Models.Configuration configuration)
{
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())
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())
@ -249,13 +250,13 @@ public partial class DlibDotNet
string[] segments = sourceDirectoryNames[0].Split(' ');
century = segments[^1].Length == 4 ? segments[^1][..2] : null;
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();
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)
throw new Exception("Configuration has to match interface!");
if (configuration.LocationFactor != Shared.Models.Stateless.ILocation.Factor)
@ -294,7 +295,6 @@ public partial class DlibDotNet
Dictionary<string, int[]> imageResizeKeyValuePairs;
List<Tuple<string, DateTime>> subFileTuples = new();
List<KeyValuePair<string, string>> metadataCollection;
// Dictionary<string, List<RelativeLocation>> relativeLocations;
if (item.Property is not null && item.Property.Id is not null && !item.Any())
{
property = item.Property;
@ -354,17 +354,21 @@ public partial class DlibDotNet
string path = Path.Combine(resizedFileHolder.DirectoryName, resizedFileHolder.NameWithoutExtension);
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();
else
{
List<(string, int, IReadOnlyList<MetadataExtractor.Directory>?)>? collection;
int[] outputResolutionCollection = imageResizeKeyValuePairs[outputResolution];
int outputResolutionWidth = outputResolutionCollection[0];
int outputResolutionHeight = outputResolutionCollection[1];
int outputResolutionOrientation = outputResolutionCollection[2];
faces = _Faces.GetFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation);
// relativeLocations = _Faces.GetRelativeLocations(outputResolution, dResultsDateGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, original, imageResizeKeyValuePairs, faces);
List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection;
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)
ticks = LogDelta(ticks, nameof(D_Face.GetFaces));
bool anyFacesSaved = _Faces.SaveFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, mappingFromItem, facesDirectory, faces);
@ -439,8 +443,7 @@ public partial class DlibDotNet
{
try
{
FullParallelForWork(
propertyLogic,
FullParallelForWork(propertyLogic,
idToMappedFaceFilesWithCollection,
outputResolution,
bResultsFullGroupDirectory,
@ -627,7 +630,7 @@ public partial class DlibDotNet
_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)
throw new NullReferenceException(nameof(_Log));
@ -651,7 +654,7 @@ public partial class DlibDotNet
int maxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism;
List<Shared.Models.Property?> nullablePropertyCollection = 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));
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;
int faceAreaPermille;
@ -751,6 +754,7 @@ public partial class DlibDotNet
string deterministicHashCodeKey;
MappingFromItem mappingFromItem;
MappingFromLocation mappingFromLocation;
List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection;
foreach (Container container in containers)
{
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);
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);
mapping = new(mappingFromItem, mappingFromLocation);
if (!fileNameToCollection.TryGetValue(mappingFromItem.RelativePath[1..], out mappingFromPhotoPrismCollection))
mappingFromPhotoPrismCollection = null;
mapping = new(mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection);
face.SetMapping(mapping);
}
}
@ -847,7 +853,7 @@ public partial class DlibDotNet
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;
SortingContainer[] sortingContainers;
@ -857,16 +863,11 @@ public partial class DlibDotNet
Mapping[] mappingCollection = MapLogicSupport.GetSelectedMappingCollection(distinctFilteredFaces);
string dFacesCollectionDirectory = Path.Combine(dResultsFullGroupDirectory, "[]", _Configuration.PropertyConfiguration.ResultAllInOne);
(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);
if (!string.IsNullOrEmpty(_Configuration.PhotoPrismDirectory))
{
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);
@ -876,7 +877,7 @@ public partial class DlibDotNet
if (_Configuration.SaveMappedForOutputResolutions.Contains(outputResolution))
mapLogic.SaveMapped(dFacesContentDirectory, d2FacePartsContentDirectory, mappingCollection, idToNormalizedRectangleToMapping, personKeyToCount, totalNotMapped);
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))
{
mapLogic.UpdatedPersonKeyToRanges(_MapConfiguration, ticks, mappingCollection);
@ -952,7 +953,7 @@ public partial class DlibDotNet
bool isValidImageFormatExtension;
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();
if (string.IsNullOrEmpty(line))
break;
@ -1011,12 +1012,12 @@ public partial class DlibDotNet
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();
int? id;
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)
{
(id, normalizedRectangle) = Shared.Models.Stateless.Methods.IMapping.GetConverted(_Faces.FileNameExtension, mappedFaceFile);
@ -1043,7 +1044,7 @@ public partial class DlibDotNet
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 f;
@ -1056,6 +1057,13 @@ public partial class DlibDotNet
string dResultsFullGroupDirectory;
string? eDistanceContentDirectory;
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), "{}");
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
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);
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);
FullDoWork(argZero, propertyRoot, ticks, personContainers, propertyLogic, t, containers, a2PeopleContentDirectory, eDistanceContentDirectory);
MapLogic? mapLogic = _Configuration.DistanceMoveUnableToMatch ? null : new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, ticks, _PersonContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory, mapLogicSupport);
FullDoWork(argZero, propertyRoot, ticks, propertyLogic, t, containers, a2PeopleContentDirectory, eDistanceContentDirectory);
_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)
{
if (_PropertyRootExistedBefore || container is not null)
@ -1112,8 +1120,8 @@ public partial class DlibDotNet
{
if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Any())
break;
SetMapping(argZero, containers);
MapLogic(argZero, ticks, personContainers, containers, a2PeopleSingletonDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, mapLogicSupport, mapLogic, outputResolution);
SetMapping(_FileNameToCollection, argZero, containers);
MapLogic(argZero, ticks, containers, a2PeopleSingletonDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, mapLogicSupport, mapLogic, outputResolution);
if (_IsEnvironment.Development)
continue;
List<MappingFromItem> mappingFromItemCollection = GetMappingFromItemCollection(containers);

View File

@ -62,7 +62,6 @@ public class Configuration
[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 = "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 = "Save Face Distances"), Required] public string[] SaveFaceDistancesForOutputResolutions { 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));
if (configuration.RangeDistanceTolerance is null || configuration.RangeDistanceTolerance.Length != 3)
throw new NullReferenceException(nameof(configuration.RangeDistanceTolerance));
if (configuration.RetryImagesWithoutAFaceLocation is null)
throw new NullReferenceException(nameof(configuration.RetryImagesWithoutAFaceLocation));
if (configuration.Reverse is null)
throw new NullReferenceException(nameof(configuration.Reverse));
configuration.SaveFaceDistancesForOutputResolutions ??= Array.Empty<string>();
@ -258,7 +255,6 @@ public class Configuration
configuration.RangeFaceAreaPermilleTolerance,
configuration.RangeFaceConfidence,
configuration.RangeDistanceTolerance,
configuration.RetryImagesWithoutAFaceLocation.Value,
configuration.Reverse.Value,
configuration.SaveFaceDistancesForOutputResolutions,
configuration.SaveFaceLandmarkForOutputResolutions,

View File

@ -58,7 +58,6 @@ public class Configuration
public int[] RangeFaceAreaPermilleTolerance { init; get; }
public double[] RangeFaceConfidence { init; get; }
public double[] RangeDistanceTolerance { init; get; }
public bool RetryImagesWithoutAFaceLocation { init; get; }
public bool Reverse { init; get; }
public string[] SaveFaceDistancesForOutputResolutions { init; get; }
public string[] SaveFaceLandmarkForOutputResolutions { init; get; }
@ -126,7 +125,6 @@ public class Configuration
int[] rangeFaceAreaPermilleTolerance,
double[] rangeFaceConfidence,
double[] rangeDistanceTolerance,
bool retryImagesWithoutAFaceLocation,
bool reverse,
string[] saveFaceDistancesForOutputResolutions,
string[] saveFaceLandmarkForOutputResolutions,
@ -193,7 +191,6 @@ public class Configuration
RangeFaceAreaPermilleTolerance = rangeFaceAreaPermilleTolerance;
RangeFaceConfidence = rangeFaceConfidence;
RangeDistanceTolerance = rangeDistanceTolerance;
RetryImagesWithoutAFaceLocation = retryImagesWithoutAFaceLocation;
Reverse = reverse;
SaveFaceDistancesForOutputResolutions = saveFaceDistancesForOutputResolutions;
SaveFaceLandmarkForOutputResolutions = saveFaceLandmarkForOutputResolutions;

View File

@ -101,7 +101,6 @@
"ResultCollection": "[]",
"ResultContent": "()",
"ResultSingleton": "{}",
"RetryImagesWithoutAFaceLocation": false,
"Reverse": false,
"RootDirectory": "D:/Images",
"SaveFullYearOfRandomFiles": true,

View File

@ -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
);

View File

@ -936,7 +936,7 @@ public class MapLogic
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)
throw new NullReferenceException(nameof(_Configuration));
@ -1149,161 +1149,145 @@ public class MapLogic
}
}
private DatabaseFileRoot GetDatabaseFileRoot()
private static JsonProperty[] GetJsonProperty(string fileName)
{
if (_Configuration is null)
throw new NullReferenceException(nameof(_Configuration));
string file = Path.Combine(_Configuration.PhotoPrismDirectory, "files.json");
string json = File.ReadAllText(file);
DatabaseFileRoot? databaseFileRoot = JsonSerializer.Deserialize<DatabaseFileRoot>(json);
if (databaseFileRoot is null)
throw new NullReferenceException(nameof(databaseFileRoot));
return databaseFileRoot;
JsonProperty[] results;
string json = File.ReadAllText(fileName);
JsonElement? jsonElement = JsonSerializer.Deserialize<JsonElement>(json);
results = jsonElement.Value.EnumerateObject().ToArray();
return results;
}
private Marker[] GetMarkers()
private static Marker[]? GetMarkers(string photoPrismDirectory)
{
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;
Marker[]? results;
string file = Path.Combine(photoPrismDirectory, "markers.json");
JsonProperty[] jsonProperties = GetJsonProperty(file);
results = JsonSerializer.Deserialize<Marker[]>(jsonProperties[1].Value);
return results;
}
private static Dictionary<string, DatabaseFile> Get(DatabaseFileRoot databaseFileRoot)
public static void SaveMarkers(string photoPrismDirectory)
{
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;
if (string.IsNullOrEmpty(photoPrismDirectory))
throw new Exception();
// double[]? encoding;
// Marker[]? markers = GetMarkers(photoPrismDirectory);
// if (markers is null)
// 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 MarkerWith GetMarkerWith(int? dlib, DatabaseFile databaseFile, Marker marker, int? count, double? percent, int? normalizedRectangle, long? personKey, string personKeyFormatted)
private static Dictionary<string, List<Marker>> GetFileUIdToMarkers(string photoPrismDirectory)
{
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<Marker>> results = new();
Marker[]? markers = GetMarkers(photoPrismDirectory);
if (markers is null)
throw new NullReferenceException(nameof(markers));
foreach (Marker marker in markers)
{
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);
}
if (!results.ContainsKey(marker.FileUid))
results.Add(marker.FileUid, new());
results[marker.FileUid].Add(marker);
}
return results;
}
public void FindMatch(List<Item> filteredItems)
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)
throw new NullReferenceException(nameof(_Configuration));
int? dlib;
double? percent;
long? personKey;
const int zero = 0;
List<Face>? matches;
MarkerWith markerWith;
int? normalizedRectangle;
string personKeyFormatted;
DatabaseFile? databaseFile;
List<string> subjects = new();
PersonBirthday personBirthday;
Marker[] markers = GetMarkers();
string fileNameWithoutExtension;
string personDisplayDirectoryName;
StringBuilder stringBuilder = new();
PersonContainer[]? personContainers;
System.Drawing.Rectangle dlibRectangle;
System.Drawing.Rectangle prismRectangle;
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)
(MappingFromPhotoPrism MappingFromPhotoPrism, Marker Marker, double Percent)[] sortedCollection;
List<(MappingFromPhotoPrism MappingFromPhotoPrism, Marker Marker, double Percent)> collection = new();
foreach (Face face in distinctFilteredFaces)
{
dlib = null;
personKey = null;
collection.Clear();
normalizedRectangle = null;
personKeyFormatted = string.Empty;
normalizedRectangleToPersonContainers = null;
if (!fileUidToFile.TryGetValue(marker.FileUid, out databaseFile))
normalizedRectangle = face.Mapping?.MappingFromLocation.NormalizedRectangle;
if (normalizedRectangle is null)
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)
if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null || face.Mapping is null)
continue;
if (face.Mapping.MappingFromPhotoPrismCollection is null)
continue;
_ = _IdThenNormalizedRectangleToPersonContainers.TryGetValue(face.Mapping.MappingFromItem.Id, out normalizedRectangleToPersonContainers);
if (normalizedRectangleToPersonContainers is null || !normalizedRectangleToPersonContainers.TryGetValue(normalizedRectangle.Value, out personContainers))
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);
foreach (MappingFromPhotoPrism mappingFromPhotoPrism in face.Mapping.MappingFromPhotoPrismCollection)
{
foreach (Marker marker in mappingFromPhotoPrism.Markers)
{
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;
percent = (double)intersectRectangle.Width * intersectRectangle.Height / (dlibRectangle.Width * dlibRectangle.Height);
double percent = (double)intersectRectangle.Width * intersectRectangle.Height / (dlibRectangle.Width * dlibRectangle.Height);
if (percent < 0.000001)
continue;
collection.Add(new(face, percent.Value));
collection.Add(new(mappingFromPhotoPrism, marker, percent));
}
}
if (!collection.Any())
percent = null;
else
{
continue;
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 ((MappingFromPhotoPrism mappingFromPhotoPrism, Marker marker, double percent) in sortedCollection)
{
foreach (PersonContainer personContainer in personContainers)
{
@ -1311,75 +1295,20 @@ public class MapLogic
continue;
personBirthday = personContainer.Birthdays[zero];
personKey = personBirthday.Value.Ticks;
personDisplayDirectoryName = personContainer.DisplayDirectoryName;
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()
{
if (_Configuration is null)
throw new NullReferenceException(nameof(_Configuration));
double[]? encoding;
string file = Path.Combine(_Configuration.PhotoPrismDirectory, "markers.json");
string json = File.ReadAllText(file);
Marker[]? markers = JsonSerializer.Deserialize<Marker[]>(json);
if (markers is null)
throw new NullReferenceException(nameof(markers));
foreach (Marker marker in markers)
{
encoding = JsonSerializer.Deserialize<double[]>(marker.EmbeddingsJson[1..^1]);
File.WriteAllText(Path.Combine(_Configuration.PhotoPrismDirectory, "EmbeddingsJson", $"{marker.MarkerUid}.json"), marker.EmbeddingsJson);
if (encoding is null)
continue;
}
}
public void LoadMatches()
{
if (_Configuration is null)
throw new NullReferenceException(nameof(_Configuration));
string json;
MarkerWith? markerWith;
List<MarkerWith> collection = new();
StringBuilder stringBuilder = new();
List<(int Count, MarkerWith MarkerWith)> countCollection = new();
List<(double Percent, MarkerWith MarkerWith)> percentCollection = new();
string[] files = Directory.GetFiles(Path.Combine(_Configuration.PhotoPrismDirectory, "With"), "*.json", SearchOption.TopDirectoryOnly);
foreach (string file in files)
{
json = File.ReadAllText(file);
markerWith = JsonSerializer.Deserialize<MarkerWith>(json);
if (markerWith is null || markerWith.DlibId is null)
continue;
collection.Add(markerWith);
if (markerWith.Count is null || markerWith.Count.Value == 0)
continue;
countCollection.Add(new(markerWith.Count.Value, markerWith));
if (markerWith.Percent is null)
continue;
percentCollection.Add(new(markerWith.Percent.Value, markerWith));
if (string.IsNullOrEmpty(markerWith.PersonKeyFormatted))
continue;
subjects.Add($"update `subjects` set subj_alias = '{personKeyFormatted}' where subj_name = '{personDisplayDirectoryName}';");
_ = stringBuilder.
Append("update `markers` set subj_src = 'manual' marker_name = '").
Append(markerWith.PersonKeyFormatted).
Append("update `markers` set subj_src = 'manual', marker_name = '").
Append(personDisplayDirectoryName).
Append("' where marker_uid = '").
Append(markerWith.MarkerUid).
Append(marker.MarkerUid).
AppendLine("';");
}
(int, MarkerWith)[] countSorted = countCollection.OrderByDescending(l => l.Count).ToArray();
(double, MarkerWith)[] percentSorted = percentCollection.OrderBy(l => l.Percent).ToArray();
if (collection.Any())
{ }
File.WriteAllText(Path.Combine(_Configuration.PhotoPrismDirectory, "marker_name_update.sql"), stringBuilder.ToString());
}
}
File.WriteAllLines(Path.Combine(_Configuration.PhotoPrismDirectory, $"{ticks}-subject_alias_update.sql"), subjects.Distinct());
File.WriteAllText(Path.Combine(_Configuration.PhotoPrismDirectory, $"{ticks}-marker_name_update.sql"), stringBuilder.ToString());
}
public Dictionary<int, Dictionary<int, PersonContainer[]>> GetMissing(Dictionary<int, Dictionary<int, Mapping>> idToNormalizedRectangleToMapping)

View File

@ -189,7 +189,7 @@ internal abstract class MapLogic
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;
string personKeyFormatted;

View File

@ -3,9 +3,9 @@ namespace View_by_Distance.Map.Models.Stateless.Methods;
public interface IMapLogic
{ // ...
List<(string, string[], string)> TestStatic_DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, long ticks, string? a2PeopleContentDirectory, string? eDistanceContentDirectory, Shared.Models.PersonContainer[] personContainers) =>
DeleteEmptyDirectoriesAndGetMappedFaceFiles(configuration, ticks, a2PeopleContentDirectory, eDistanceContentDirectory, personContainers);
static List<(string, string[], string)> DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, long ticks, string? a2PeopleContentDirectory, string? eDistanceContentDirectory, Shared.Models.PersonContainer[] personContainers) =>
MapLogic.DeleteEmptyDirectoriesAndGetMappedFaceFiles(configuration, ticks, a2PeopleContentDirectory, eDistanceContentDirectory, personContainers);
List<(string, string[], string)> TestStatic_DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, Shared.Models.PersonContainer[] personContainers, long ticks, string? a2PeopleContentDirectory, string? eDistanceContentDirectory) =>
DeleteEmptyDirectoriesAndGetMappedFaceFiles(configuration, personContainers, ticks, a2PeopleContentDirectory, eDistanceContentDirectory);
static List<(string, string[], string)> DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, Shared.Models.PersonContainer[] personContainers, long ticks, string? a2PeopleContentDirectory, string? eDistanceContentDirectory) =>
MapLogic.DeleteEmptyDirectoriesAndGetMappedFaceFiles(configuration, personContainers, ticks, a2PeopleContentDirectory, eDistanceContentDirectory);
}

View File

@ -142,7 +142,7 @@ public class B_Metadata
DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max();
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));
else
{

View File

@ -267,7 +267,7 @@
// propertyTicks = null;
// foreach (PropertyCompare.Models.PropertyCompare propertyCompare in propertyCompareCollection)
// {
// if (propertyCompare?.Property?.Id is null)
// if (propertyCompare?.Property?.FileId is null)
// continue;
// if (ticks != propertyCompare.MinimumDateTime.Ticks)
// {
@ -276,7 +276,7 @@
// }
// if (!regexResult.Equals(propertyCompare.RegexResult, StringComparison.CurrentCultureIgnoreCase))
// continue;
// propertyId = propertyCompare.Property.Id;
// propertyId = propertyCompare.Property.FileId;
// propertyTicks = propertyCompare.MinimumDateTime.Ticks;
// mappedIndex = mappedIndices.IndexOf(index);
// if (mappedIndex > -1)
@ -290,7 +290,7 @@
// string[] duplicatesLines = (
// from l
// 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();
// string[] matchedLines = (
// from l
@ -575,11 +575,11 @@
// Dictionary<int, List<PropertyCompare.Models.PropertyCompare>> results = new();
// foreach (PropertyCompare.Models.PropertyCompare propertyCompare in propertyCompares)
// {
// if (propertyCompare?.Property?.Id is null)
// if (propertyCompare?.Property?.FileId is null)
// continue;
// if (!results.ContainsKey(propertyCompare.Property.Id.Value))
// results.Add(propertyCompare.Property.Id.Value, new());
// results[propertyCompare.Property.Id.Value].Add(propertyCompare);
// if (!results.ContainsKey(propertyCompare.Property.FileId.Value))
// results.Add(propertyCompare.Property.FileId.Value, new());
// results[propertyCompare.Property.FileId.Value].Add(propertyCompare);
// }
// return results;
// }
@ -628,9 +628,9 @@
// if (keyValuePairs.ContainsKey(index))
// {
// propertyCompare = keyValuePairs[index][0];
// if (propertyCompare?.Property?.Id is null)
// if (propertyCompare?.Property?.FileId is null)
// continue;
// propertyId = propertyCompare.Property.Id;
// propertyId = propertyCompare.Property.FileId;
// propertyTicks = propertyCompare.MinimumDateTime.Ticks;
// }
// collection.Add(new(index, relativeDirectory, $"{fileNameWithoutExtension}{extension}", regexResult, ticks, propertyId, propertyTicks));

View File

@ -44,7 +44,7 @@ public partial class PropertyCompare
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

View File

@ -176,7 +176,7 @@
// extension = Path.GetExtension(files[index]);
// string json = File.ReadAllText(jsonFile);
// 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));
// DateTime minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(property);
// corrected = string.Concat(relativeDirectory, jsonFileNameWithoutExtension);
@ -195,11 +195,11 @@
// {
// n = i switch
// {
// 0 => property.Id.Value,
// 1 => property.Id.Value,
// 2 => property.Id.Value,
// 3 => property.Id.Value,
// 4 => property.Id.Value,
// 0 => property.FileId.Value,
// 1 => property.FileId.Value,
// 2 => property.FileId.Value,
// 3 => property.FileId.Value,
// 4 => property.FileId.Value,
// 5 => Shared.Models.Stateless.Methods.IProperty.GetDateTime(property).Ticks,
// 6 => property.CreationTime.Ticks,
// 7 => property.FileSize,
@ -229,8 +229,8 @@
// results.Add(propertyCompare);
// if (duplicates is not null)
// {
// string value = $"{property.Id.Value}\t{property}";
// index = ids.IndexOf(property.Id.Value);
// string value = $"{property.FileId.Value}\t{property}";
// index = ids.IndexOf(property.FileId.Value);
// if (index > -1)
// {
// lock (@lock)
@ -241,7 +241,7 @@
// }
// lock (@lock)
// {
// ids.Add(property.Id.Value);
// ids.Add(property.FileId.Value);
// collection.Add(propertyCompare);
// }
// }

View File

@ -333,7 +333,7 @@ public class A_Property
json = JsonSerializer.Serialize(result, _WriteIndentedJsonSerializerOptions);
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));
else
{

View File

@ -16,7 +16,7 @@ public class Configuration
[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 = "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 = "Property Content Collection Files"), Required] public string[] PropertyContentCollectionFiles { get; set; }
[Display(Name = "Result All In One"), Required] public string ResultAllInOne { get; set; }

View File

@ -216,6 +216,7 @@ public class Container
{
string relativePath;
string checkFileName;
string? checkDirectoryName;
List<string> checkCollection = new();
checkCollection.AddRange(otherCollection);
int length = configuration.RootDirectory.Length;
@ -225,6 +226,9 @@ public class Container
{
relativePath = Shared.Models.Stateless.Methods.IPath.GetRelativePath(fileHolder.FullName, length);
checkFileName = Path.GetFullPath(string.Concat(aPropertySingletonDirectory, relativePath));
checkDirectoryName = Path.GetDirectoryName(checkFileName);
if (string.IsNullOrEmpty(checkDirectoryName) || !Directory.Exists(checkDirectoryName))
continue;
if (!checkCollection.Remove(checkFileName))
File.WriteAllText(checkFileName, string.Empty);
}

View File

@ -505,7 +505,7 @@ public class C_Resize
DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max();
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));
else
{

View File

@ -1,6 +1,6 @@
using System.Text.Json.Serialization;
namespace View_by_Distance.Map.Models;
namespace View_by_Distance.Shared.Models;
public record DatabaseFile(
[property: JsonPropertyName("id")] int Id,

View File

@ -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
{
@ -109,23 +124,25 @@ public class Mapping : Properties.IMapping
public int? By => _By;
public MappingFromItem MappingFromItem { init; get; }
public MappingFromLocation MappingFromLocation { init; get; }
public List<MappingFromPhotoPrism>? MappingFromPhotoPrismCollection { init; get; }
public MappingFromPerson? MappingFromPerson => _MappingFromPerson;
public string? SegmentC => _SegmentC;
public SortingContainer? SortingContainer => _SortingContainer;
[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;
_SegmentC = segmentC;
MappingFromItem = mappingFromItem;
MappingFromLocation = mappingFromLocation;
MappingFromPhotoPrismCollection = mappingFromPhotoPrismCollection;
_MappingFromPerson = mappingFromPerson;
_SortingContainer = sortingContainer;
}
public Mapping(MappingFromItem mappingFromItem, MappingFromLocation mappingFromLocation) :
this(null, mappingFromItem, mappingFromLocation, null, null, null)
public Mapping(MappingFromItem mappingFromItem, MappingFromLocation mappingFromLocation, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection) :
this(null, mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection, null, null, null)
{ }
public override string ToString()

View File

@ -14,8 +14,8 @@ public record Marker(
[property: JsonPropertyName("subj_src")] string SubjSrc,
[property: JsonPropertyName("face_id")] string FaceId,
[property: JsonPropertyName("face_dist")] double FaceDist,
[property: JsonPropertyName("embeddings_json")] string EmbeddingsJson,
[property: JsonPropertyName("landmarks_json")] string LandmarksJson,
// [property: JsonPropertyName("embeddings_json")] string EmbeddingsJson,
// [property: JsonPropertyName("landmarks_json")] string LandmarksJson,
[property: JsonPropertyName("x")] double X,
[property: JsonPropertyName("y")] double Y,
[property: JsonPropertyName("w")] double W,

View File

@ -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
);

View File

@ -23,6 +23,14 @@ public interface IMappingFromLocation
}
public interface IMappingFromPhotoPrism
{
public DatabaseFile DatabaseFile { init; get; }
public List<Marker> Markers { init; get; }
}
public interface IMappingFromPerson
{
@ -40,6 +48,7 @@ public interface IMapping
public string? SegmentC { get; }
public MappingFromItem MappingFromItem { init; get; }
public MappingFromLocation MappingFromLocation { init; get; }
public List<MappingFromPhotoPrism>? MappingFromPhotoPrismCollection { init; get; }
public MappingFromPerson? MappingFromPerson { get; }
public SortingContainer? SortingContainer { get; }

View File

@ -5,6 +5,21 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
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) =>
GetRectangle(checkRectangle, locationDigits, locationFactor, normalizedRectangle, outputResolution, useOldWay);
static Rectangle GetRectangle(Rectangle checkRectangle, int locationDigits, int locationFactor, int normalizedRectangle, Models.OutputResolution outputResolution, bool useOldWay) =>

View File

@ -17,6 +17,7 @@ public interface IPath
DeleteEmptyDirectories(rootDirectory, deletedDirectories);
static void DeleteEmptyDirectories(string rootDirectory, List<string> 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) =>
GetDirectoryNames(directory);

View File

@ -189,4 +189,81 @@ internal abstract class Location
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;
}
}

View File

@ -60,7 +60,6 @@ public class Configuration
[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 = "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 = "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; }
@ -171,8 +170,6 @@ public class Configuration
throw new NullReferenceException(nameof(configuration.RangeFaceConfidence));
if (configuration.RangeDistanceTolerance is null || configuration.RangeDistanceTolerance.Length != 3)
throw new NullReferenceException(nameof(configuration.RangeDistanceTolerance));
if (configuration.RetryImagesWithoutAFaceLocation is null)
throw new NullReferenceException(nameof(configuration.RetryImagesWithoutAFaceLocation));
if (configuration.Reverse is null)
throw new NullReferenceException(nameof(configuration.Reverse));
configuration.SaveFaceLandmarkForOutputResolutions ??= Array.Empty<string>();
@ -245,7 +242,6 @@ public class Configuration
configuration.RangeFaceAreaPermilleTolerance,
configuration.RangeFaceConfidence,
configuration.RangeDistanceTolerance,
configuration.RetryImagesWithoutAFaceLocation.Value,
configuration.Reverse.Value,
configuration.SaveFaceLandmarkForOutputResolutions,
configuration.SaveFullYearOfRandomFiles.Value,

View File

@ -58,7 +58,6 @@ public class Configuration
public int[] RangeFaceAreaPermilleTolerance { init; get; }
public double[] RangeFaceConfidence { init; get; }
public double[] RangeDistanceTolerance { init; get; }
public bool RetryImagesWithoutAFaceLocation { init; get; }
public bool Reverse { init; get; }
public string[] SaveFaceLandmarkForOutputResolutions { init; get; }
public bool SaveFullYearOfRandomFiles { init; get; }
@ -123,7 +122,6 @@ public class Configuration
int[] rangeFaceAreaPermilleTolerance,
double[] rangeFaceConfidence,
double[] rangeDistanceTolerance,
bool retryImagesWithoutAFaceLocation,
bool reverse,
string[] saveFaceLandmarkForOutputResolutions,
bool saveFullYearOfRandomFiles,
@ -187,7 +185,6 @@ public class Configuration
RangeFaceAreaPermilleTolerance = rangeFaceAreaPermilleTolerance;
RangeFaceConfidence = rangeFaceConfidence;
RangeDistanceTolerance = rangeDistanceTolerance;
RetryImagesWithoutAFaceLocation = retryImagesWithoutAFaceLocation;
Reverse = reverse;
SaveFaceLandmarkForOutputResolutions = saveFaceLandmarkForOutputResolutions;
SaveFullYearOfRandomFiles = saveFullYearOfRandomFiles;

View File

@ -231,7 +231,7 @@ public class UnitTestFace
(Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(_Configuration);
FaceRecognition faceRecognition = new(_Configuration.NumberOfJitters, _Configuration.NumberOfTimesToUpsample, model, modelParameter, predictorModel);
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);
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]);