|
|
|
@ -261,9 +261,60 @@ public partial class DlibDotNet
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SetMapping(Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers, MapLogic mapLogic, Item item, bool? isFocusRelativePath, bool? isIgnoreRelativePath, MappingFromItem mappingFromItem, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection, List<Shared.Models.Face> faces)
|
|
|
|
|
{
|
|
|
|
|
string? model;
|
|
|
|
|
Mapping mapping;
|
|
|
|
|
bool? isFocusModel;
|
|
|
|
|
int faceAreaPermyriad;
|
|
|
|
|
int confidencePercent;
|
|
|
|
|
int normalizedRectangle;
|
|
|
|
|
string deterministicHashCodeKey;
|
|
|
|
|
MappingFromFilter mappingFromFilter;
|
|
|
|
|
MappingFromLocation? mappingFromLocation;
|
|
|
|
|
IReadOnlyList<MetadataExtractor.Directory> directories;
|
|
|
|
|
List<LocationContainer<MetadataExtractor.Directory>>? locationContainers;
|
|
|
|
|
if (string.IsNullOrEmpty(_Configuration.FocusModel))
|
|
|
|
|
isFocusModel = null;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!idToLocationContainers.TryGetValue(mappingFromItem.Id, out locationContainers) || !locationContainers.Any())
|
|
|
|
|
isFocusModel = false;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
directories = locationContainers.First().Directories;
|
|
|
|
|
model = Metadata.Models.Stateless.Methods.IMetadata.GetModel(directories);
|
|
|
|
|
if (model is null)
|
|
|
|
|
directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(mappingFromItem.ResizedFileHolder.FullName);
|
|
|
|
|
model = Metadata.Models.Stateless.Methods.IMetadata.GetModel(directories);
|
|
|
|
|
isFocusModel = model is not null && model.Contains(_Configuration.FocusModel);
|
|
|
|
|
if (isFocusModel.Value)
|
|
|
|
|
isFocusModel = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
mappingFromFilter = new(isFocusModel, isFocusRelativePath, isIgnoreRelativePath);
|
|
|
|
|
foreach (Shared.Models.Face face in faces)
|
|
|
|
|
{
|
|
|
|
|
if (item.Property?.Id is null || face.FaceEncoding is null || face.Location is null || face.OutputResolution is null)
|
|
|
|
|
mappingFromLocation = null;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
confidencePercent = Shared.Models.Stateless.Methods.ILocation.GetConfidencePercent(_Configuration.FaceConfidencePercent, _Configuration.RangeFaceConfidence, face.Location.Confidence);
|
|
|
|
|
faceAreaPermyriad = Shared.Models.Stateless.Methods.IMapping.GetAreaPermyriad(_Configuration.FaceAreaPermyriad, face.Location, 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);
|
|
|
|
|
mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, normalizedRectangle);
|
|
|
|
|
}
|
|
|
|
|
mapping = new(mappingFromItem, mappingFromFilter, mappingFromLocation, mappingFromPhotoPrismCollection);
|
|
|
|
|
_ = mapLogic.UpdateMappingFromPerson(mapping);
|
|
|
|
|
face.SetMapping(mapping);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void FullParallelForWork(A_Property propertyLogic,
|
|
|
|
|
B_Metadata metadata,
|
|
|
|
|
Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers,
|
|
|
|
|
MapLogic mapLogic,
|
|
|
|
|
string outputResolution,
|
|
|
|
|
string cResultsFullGroupDirectory,
|
|
|
|
|
string dResultsDateGroupDirectory,
|
|
|
|
@ -274,7 +325,9 @@ public partial class DlibDotNet
|
|
|
|
|
Container container,
|
|
|
|
|
int index,
|
|
|
|
|
Item item,
|
|
|
|
|
DateTime[] containerDateTimes)
|
|
|
|
|
DateTime[] containerDateTimes,
|
|
|
|
|
bool? isFocusRelativePath,
|
|
|
|
|
bool? isIgnoreRelativePath)
|
|
|
|
|
{
|
|
|
|
|
if (_Log is null)
|
|
|
|
|
throw new NullReferenceException(nameof(_Log));
|
|
|
|
@ -364,6 +417,7 @@ public partial class DlibDotNet
|
|
|
|
|
&& _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)
|
|
|
|
|
&& !anyFacesSaved && collection is not null)
|
|
|
|
|
_Distance.LookForMatchFacesAndPossiblyRename(_Faces.FileNameExtension, eDistanceContentDirectory, mappingFromItem, faces, collection);
|
|
|
|
|
SetMapping(idToLocationContainers, mapLogic, item, isFocusRelativePath, isIgnoreRelativePath, mappingFromItem, mappingFromPhotoPrismCollection, faces);
|
|
|
|
|
if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution))
|
|
|
|
|
{
|
|
|
|
|
bool saveRotated = false;
|
|
|
|
@ -384,6 +438,7 @@ public partial class DlibDotNet
|
|
|
|
|
A_Property propertyLogic,
|
|
|
|
|
B_Metadata metadata,
|
|
|
|
|
Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers,
|
|
|
|
|
MapLogic mapLogic,
|
|
|
|
|
string outputResolution,
|
|
|
|
|
string cResultsFullGroupDirectory,
|
|
|
|
|
string dResultsDateGroupDirectory,
|
|
|
|
@ -399,9 +454,12 @@ public partial class DlibDotNet
|
|
|
|
|
throw new NullReferenceException(nameof(_Log));
|
|
|
|
|
int result = 0;
|
|
|
|
|
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
|
|
|
|
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
|
|
|
|
DateTime[] containerDateTimes = Shared.Models.Stateless.Methods.IContainer.GetContainerDateTimes(filteredItems);
|
|
|
|
|
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
|
|
|
|
using ProgressBar progressBar = new(filteredItems.Length, message, options);
|
|
|
|
|
string focusRelativePath = Path.GetFullPath(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, _Configuration.FocusDirectory));
|
|
|
|
|
bool? isFocusRelativePath = string.IsNullOrEmpty(_Configuration.FocusDirectory) ? null : container.SourceDirectory.StartsWith(focusRelativePath);
|
|
|
|
|
bool? isIgnoreRelativePath = !_Configuration.IgnoreRelativePaths.Any() ? null : _Configuration.IgnoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && Shared.Models.Stateless.Methods.IContainer.IsIgnoreRelativePath(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, container.SourceDirectory);
|
|
|
|
|
_ = Parallel.For(0, filteredItems.Length, parallelOptions, (i, state) =>
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
@ -409,6 +467,7 @@ public partial class DlibDotNet
|
|
|
|
|
FullParallelForWork(propertyLogic,
|
|
|
|
|
metadata,
|
|
|
|
|
idToLocationContainers,
|
|
|
|
|
mapLogic,
|
|
|
|
|
outputResolution,
|
|
|
|
|
cResultsFullGroupDirectory,
|
|
|
|
|
dResultsDateGroupDirectory,
|
|
|
|
@ -419,7 +478,9 @@ public partial class DlibDotNet
|
|
|
|
|
container,
|
|
|
|
|
index: i,
|
|
|
|
|
filteredItems[i],
|
|
|
|
|
containerDateTimes);
|
|
|
|
|
containerDateTimes,
|
|
|
|
|
isFocusRelativePath,
|
|
|
|
|
isIgnoreRelativePath);
|
|
|
|
|
if (i == 0 || sourceDirectoryChanges.Any())
|
|
|
|
|
progressBar.Tick();
|
|
|
|
|
}
|
|
|
|
@ -514,7 +575,7 @@ public partial class DlibDotNet
|
|
|
|
|
return new(cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void FullDoWork(string argZero, string propertyRoot, long ticks, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, int t, Container[] containers, A_Property propertyLogic, B_Metadata metadata, string eDistanceContentDirectory, Dictionary<string, List<MappingFromPhotoPrism>> fileNameToCollection, Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers)
|
|
|
|
|
private void FullDoWork(string argZero, string propertyRoot, long ticks, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, int t, Container[] containers, A_Property propertyLogic, B_Metadata metadata, string eDistanceContentDirectory, Dictionary<string, List<MappingFromPhotoPrism>> fileNameToCollection, Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers, MapLogic mapLogic)
|
|
|
|
|
{
|
|
|
|
|
if (_Log is null)
|
|
|
|
|
throw new NullReferenceException(nameof(_Log));
|
|
|
|
@ -560,6 +621,7 @@ public partial class DlibDotNet
|
|
|
|
|
propertyLogic,
|
|
|
|
|
metadata,
|
|
|
|
|
idToLocationContainers,
|
|
|
|
|
mapLogic,
|
|
|
|
|
outputResolution,
|
|
|
|
|
cResultsFullGroupDirectory,
|
|
|
|
|
dResultsDateGroupDirectory,
|
|
|
|
@ -590,86 +652,6 @@ public partial class DlibDotNet
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SetMapping(string argZero, Container[] containers, Dictionary<string, List<MappingFromPhotoPrism>> fileNameToCollection, Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers)
|
|
|
|
|
{
|
|
|
|
|
string? model;
|
|
|
|
|
Mapping mapping;
|
|
|
|
|
bool? isFocusModel;
|
|
|
|
|
int faceAreaPermyriad;
|
|
|
|
|
Item[] filteredItems;
|
|
|
|
|
int confidencePercent;
|
|
|
|
|
int normalizedRectangle;
|
|
|
|
|
bool? isFocusRelativePath;
|
|
|
|
|
bool? isIgnoreRelativePath;
|
|
|
|
|
DateTime[] containerDateTimes;
|
|
|
|
|
string deterministicHashCodeKey;
|
|
|
|
|
MappingFromItem mappingFromItem;
|
|
|
|
|
MappingFromFilter mappingFromFilter;
|
|
|
|
|
MappingFromLocation? mappingFromLocation;
|
|
|
|
|
IReadOnlyList<MetadataExtractor.Directory> directories;
|
|
|
|
|
List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection;
|
|
|
|
|
List<LocationContainer<MetadataExtractor.Directory>>? locationContainers;
|
|
|
|
|
string focusRelativePath = Path.GetFullPath(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, _Configuration.FocusDirectory));
|
|
|
|
|
foreach (Container container in containers)
|
|
|
|
|
{
|
|
|
|
|
if (!container.Items.Any())
|
|
|
|
|
continue;
|
|
|
|
|
if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
|
|
|
|
|
continue;
|
|
|
|
|
filteredItems = Shared.Models.Stateless.Methods.IContainer.GetFilterItems(_Configuration.PropertyConfiguration, container);
|
|
|
|
|
if (!filteredItems.Any())
|
|
|
|
|
continue;
|
|
|
|
|
containerDateTimes = Shared.Models.Stateless.Methods.IContainer.GetContainerDateTimes(filteredItems);
|
|
|
|
|
isFocusRelativePath = string.IsNullOrEmpty(_Configuration.FocusDirectory) ? null : container.SourceDirectory.StartsWith(focusRelativePath);
|
|
|
|
|
if (!_Configuration.IgnoreRelativePaths.Any())
|
|
|
|
|
isIgnoreRelativePath = null;
|
|
|
|
|
else
|
|
|
|
|
isIgnoreRelativePath = _Configuration.IgnoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && Shared.Models.Stateless.Methods.IContainer.IsIgnoreRelativePath(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, container.SourceDirectory);
|
|
|
|
|
foreach (Item item in filteredItems)
|
|
|
|
|
{
|
|
|
|
|
if (item.Property?.Id is null || item.ResizedFileHolder is null)
|
|
|
|
|
continue;
|
|
|
|
|
mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item);
|
|
|
|
|
if (string.IsNullOrEmpty(_Configuration.FocusModel))
|
|
|
|
|
isFocusModel = null;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!idToLocationContainers.TryGetValue(mappingFromItem.Id, out locationContainers) || !locationContainers.Any())
|
|
|
|
|
isFocusModel = false;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
directories = locationContainers.First().Directories;
|
|
|
|
|
model = Metadata.Models.Stateless.Methods.IMetadata.GetModel(directories);
|
|
|
|
|
if (model is null)
|
|
|
|
|
directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(mappingFromItem.ResizedFileHolder.FullName);
|
|
|
|
|
model = Metadata.Models.Stateless.Methods.IMetadata.GetModel(directories);
|
|
|
|
|
isFocusModel = model is not null && model.Contains(_Configuration.FocusModel);
|
|
|
|
|
if (isFocusModel.Value)
|
|
|
|
|
isFocusModel = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
mappingFromFilter = new(isFocusModel, isFocusRelativePath, isIgnoreRelativePath);
|
|
|
|
|
foreach (Shared.Models.Face face in item.Faces)
|
|
|
|
|
{
|
|
|
|
|
if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null)
|
|
|
|
|
mappingFromLocation = null;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
confidencePercent = Shared.Models.Stateless.Methods.ILocation.GetConfidencePercent(_Configuration.FaceConfidencePercent, _Configuration.RangeFaceConfidence, face.Location.Confidence);
|
|
|
|
|
faceAreaPermyriad = Shared.Models.Stateless.Methods.IMapping.GetAreaPermyriad(_Configuration.FaceAreaPermyriad, face.Location, 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);
|
|
|
|
|
mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, normalizedRectangle);
|
|
|
|
|
}
|
|
|
|
|
if (!fileNameToCollection.TryGetValue(mappingFromItem.RelativePath[1..], out mappingFromPhotoPrismCollection))
|
|
|
|
|
mappingFromPhotoPrismCollection = null;
|
|
|
|
|
mapping = new(mappingFromItem, mappingFromFilter, mappingFromLocation, mappingFromPhotoPrismCollection);
|
|
|
|
|
face.SetMapping(mapping);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private (List<int>, List<Shared.Models.Face>) GetFilteredDistinct(string argZero, Container[] containers)
|
|
|
|
|
{
|
|
|
|
|
List<int> resultIds = new();
|
|
|
|
@ -1103,14 +1085,12 @@ public partial class DlibDotNet
|
|
|
|
|
propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory);
|
|
|
|
|
}
|
|
|
|
|
containers = Shared.Models.Stateless.Methods.IContainer.SortContainers(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, _ArgZeroIsConfigurationRootDirectory, argZero, containers);
|
|
|
|
|
MapLogic? mapLogic = _Configuration.DistanceMoveUnableToMatch ? null : new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, ticks, _PersonContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory);
|
|
|
|
|
personKeyToIds = mapLogic is null ? new() : mapLogic.GetPersonKeyToIds();
|
|
|
|
|
MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, ticks, _PersonContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory);
|
|
|
|
|
personKeyToIds = mapLogic.GetPersonKeyToIds();
|
|
|
|
|
fileNameToCollection = !Directory.Exists(fPhotoPrismSingletonDirectory) ? fileNameToCollection = new() : F_PhotoPrism.GetFileNameToCollection(fPhotoPrismSingletonDirectory);
|
|
|
|
|
Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers = GetDictionary(ticks, a2PeopleContentDirectory, eDistanceContentDirectory);
|
|
|
|
|
FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, t, containers, propertyLogic, metadata, eDistanceContentDirectory, fileNameToCollection, idToLocationContainers);
|
|
|
|
|
FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, t, containers, propertyLogic, metadata, eDistanceContentDirectory, fileNameToCollection, idToLocationContainers, mapLogic);
|
|
|
|
|
_Distance.Clear();
|
|
|
|
|
mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, ticks, _PersonContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory);
|
|
|
|
|
SetMapping(argZero, containers, fileNameToCollection, idToLocationContainers);
|
|
|
|
|
if (!personKeyToIds.Any())
|
|
|
|
|
personKeyToIds = mapLogic.GetPersonKeyToIds();
|
|
|
|
|
(List<int> distinctFilteredIds, List<Shared.Models.Face> distinctFilteredFaces) = GetFilteredDistinct(argZero, containers);
|
|
|
|
|