Split out classes
This commit is contained in:
@ -3,6 +3,9 @@ using Phares.Shared;
|
||||
using ShellProgressBar;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Text.Json;
|
||||
using View_by_Distance.Distance.Models;
|
||||
using View_by_Distance.Face.Models;
|
||||
using View_by_Distance.FaceParts.Models;
|
||||
using View_by_Distance.FaceRecognitionDotNet;
|
||||
using View_by_Distance.Instance.Models;
|
||||
using View_by_Distance.Map.Models;
|
||||
@ -37,7 +40,14 @@ public partial class DlibDotNet
|
||||
private readonly List<KeyValuePair<string, string>> _FileKeyValuePairs;
|
||||
private readonly Dictionary<string, List<Tuple<string, Shared.Models.Property>>> _FilePropertiesKeyValuePairs;
|
||||
|
||||
public DlibDotNet(List<string> args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console)
|
||||
public DlibDotNet(
|
||||
List<string> args,
|
||||
IsEnvironment isEnvironment,
|
||||
IConfigurationRoot configurationRoot,
|
||||
AppSettings appSettings,
|
||||
string workingDirectory,
|
||||
bool isSilent,
|
||||
IConsole console)
|
||||
{
|
||||
_Console = console;
|
||||
string argZero;
|
||||
@ -73,7 +83,27 @@ public partial class DlibDotNet
|
||||
{
|
||||
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetPngLowQuality();
|
||||
(ImageCodecInfo hiddenImageCodecInfo, EncoderParameters hiddenEncoderParameters, string hiddenFileNameExtension) = C_Resize.GetGifLowQuality();
|
||||
_Faces = new D_Face(configuration, argZero, model, modelParameter, predictorModel, imageCodecInfo, encoderParameters, filenameExtension, hiddenImageCodecInfo, hiddenEncoderParameters, hiddenFileNameExtension);
|
||||
_Faces = new D_Face(
|
||||
argZero,
|
||||
configuration.CheckDFaceAndUpWriteDates,
|
||||
configuration.PropertyConfiguration,
|
||||
encoderParameters,
|
||||
configuration.FaceDistanceHiddenImageFactor,
|
||||
filenameExtension,
|
||||
configuration.ForceFaceLastWriteTimeToCreationTime,
|
||||
hiddenEncoderParameters,
|
||||
hiddenFileNameExtension,
|
||||
hiddenImageCodecInfo,
|
||||
imageCodecInfo,
|
||||
configuration.LocationDigits,
|
||||
configuration.LocationFactor,
|
||||
model,
|
||||
modelParameter,
|
||||
configuration.NumberOfJitters,
|
||||
configuration.NumberOfTimesToUpsample,
|
||||
configuration.OverrideForFaceImages,
|
||||
predictorModel,
|
||||
configuration.PropertiesChangedForFaces);
|
||||
}
|
||||
if (_FirstRun || !_ArgZeroIsConfigurationRootDirectory)
|
||||
personContainers = Array.Empty<PersonContainer>();
|
||||
@ -84,7 +114,17 @@ public partial class DlibDotNet
|
||||
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||
using ProgressBar progressBar = new(1, message, options);
|
||||
progressBar.Tick();
|
||||
personContainers = A2_People.GetPersonContainers(configuration, propertyConfiguration, _Faces.FileNameExtension);
|
||||
string rootDirectory = propertyConfiguration.RootDirectory;
|
||||
string peopleRootDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A2_People));
|
||||
string? rootResultsDirectory = Path.GetDirectoryName(Path.GetDirectoryName(peopleRootDirectory));
|
||||
if (rootResultsDirectory is null)
|
||||
throw new Exception();
|
||||
Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory);
|
||||
personContainers = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers(
|
||||
storage,
|
||||
configuration.LocationDigits,
|
||||
configuration.PersonBirthdayFormat,
|
||||
_Faces.FileNameExtension);
|
||||
}
|
||||
if (!isSilent && configuration.TestDistanceResults)
|
||||
{
|
||||
@ -94,17 +134,32 @@ public partial class DlibDotNet
|
||||
}
|
||||
{
|
||||
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetGifLowQuality();
|
||||
_FaceParts = new D2_FaceParts(configuration, imageCodecInfo, encoderParameters, filenameExtension);
|
||||
_FaceParts = new D2_FaceParts(imageCodecInfo, encoderParameters, filenameExtension, configuration.CheckDFaceAndUpWriteDates, configuration.OverrideForFaceLandmarkImages);
|
||||
}
|
||||
{
|
||||
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetTuple(configuration.OutputExtension, configuration.OutputQuality);
|
||||
_Resize = new C_Resize(configuration.ForceResizeLastWriteTimeToCreationTime, configuration.OverrideForResizeImages, configuration.PropertiesChangedForResize, configuration.ValidResolutions, imageCodecInfo, encoderParameters, filenameExtension);
|
||||
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetTuple(
|
||||
configuration.OutputExtension,
|
||||
configuration.OutputQuality);
|
||||
_Resize = new C_Resize(
|
||||
configuration.ForceResizeLastWriteTimeToCreationTime,
|
||||
configuration.OverrideForResizeImages,
|
||||
configuration.PropertiesChangedForResize,
|
||||
configuration.ValidResolutions,
|
||||
imageCodecInfo,
|
||||
encoderParameters,
|
||||
filenameExtension);
|
||||
}
|
||||
if (!configuration.SkipSearch)
|
||||
Search(ticks, model, predictorModel, argZero, propertyRoot, personContainers);
|
||||
if (!_FirstRun && !_IsEnvironment.Development && _Exceptions.Count == 0 && _ArgZeroIsConfigurationRootDirectory)
|
||||
{
|
||||
List<string[]> directoryCollections = _Rename.GetDirectoryRenameCollections(propertyConfiguration, model, predictorModel, relativePath: string.Empty, newDirectoryName: string.Empty, jsonFiles4InfoAny: false);
|
||||
List<string[]> directoryCollections = _Rename.GetDirectoryRenameCollections(
|
||||
propertyConfiguration,
|
||||
model,
|
||||
predictorModel,
|
||||
relativePath: string.Empty,
|
||||
newDirectoryName: string.Empty,
|
||||
jsonFiles4InfoAny: false);
|
||||
foreach (string[] directoryCollection in directoryCollections)
|
||||
{
|
||||
_Log.Information(string.Concat("Cleaning <", directoryCollection[0], ">"));
|
||||
@ -287,17 +342,32 @@ public partial class DlibDotNet
|
||||
return result;
|
||||
}
|
||||
|
||||
private void FullParallelForWork(A_Property propertyLogic, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, List<Tuple<string, DateTime>> sourceDirectoryChanges, List<FileHolder?> propertyFileHolderCollection, List<Shared.Models.Property?> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollections, List<Dictionary<string, int[]>> resizeKeyValuePairs, List<List<Face>?> imageFaceCollections, Container container, int index, Item item)
|
||||
private void FullParallelForWork(
|
||||
A_Property propertyLogic,
|
||||
string outputResolution,
|
||||
string bResultsFullGroupDirectory,
|
||||
string cResultsFullGroupDirectory,
|
||||
string dResultsFullGroupDirectory,
|
||||
string d2ResultsFullGroupDirectory,
|
||||
List<Tuple<string, DateTime>> sourceDirectoryChanges,
|
||||
List<FileHolder?> propertyFileHolderCollection,
|
||||
List<Shared.Models.Property?> propertyCollection,
|
||||
List<List<KeyValuePair<string, string>>> metadataCollections,
|
||||
List<Dictionary<string, int[]>> resizeKeyValuePairs,
|
||||
List<List<Shared.Models.Face>?> imageFaceCollections,
|
||||
Container container,
|
||||
int index,
|
||||
Item item)
|
||||
{
|
||||
if (item.ImageFileHolder is null)
|
||||
throw new NullReferenceException(nameof(item.ImageFileHolder));
|
||||
List<Face>? faceCollection;
|
||||
string original = "Original";
|
||||
FileHolder? resizedFileHolder;
|
||||
Shared.Models.Property property;
|
||||
long ticks = DateTime.Now.Ticks;
|
||||
DateTime dateTime = DateTime.Now;
|
||||
List<string> parseExceptions = new();
|
||||
List<Shared.Models.Face>? faceCollection;
|
||||
Dictionary<string, int[]> imageResizeKeyValuePairs;
|
||||
List<Tuple<string, DateTime>> subFileTuples = new();
|
||||
List<KeyValuePair<string, string>> metadataCollection;
|
||||
@ -317,10 +387,22 @@ public partial class DlibDotNet
|
||||
sourceDirectoryChanges.Add(new Tuple<string, DateTime>(nameof(A_Property), (from l in subFileTuples select l.Item2).Max()));
|
||||
}
|
||||
}
|
||||
(int metadataGroups, metadataCollection) = _Metadata.GetMetadataCollection(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, subFileTuples, parseExceptions, item);
|
||||
(int metadataGroups, metadataCollection) = _Metadata.GetMetadataCollection(
|
||||
_Configuration.PropertyConfiguration,
|
||||
bResultsFullGroupDirectory,
|
||||
subFileTuples,
|
||||
parseExceptions,
|
||||
item);
|
||||
if (_AppSettings.MaxDegreeOfParallelism < 2)
|
||||
ticks = LogDelta(ticks, nameof(B_Metadata.GetMetadataCollection));
|
||||
imageResizeKeyValuePairs = _Resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, subFileTuples, parseExceptions, original, metadataCollection, item);
|
||||
imageResizeKeyValuePairs = _Resize.GetResizeKeyValuePairs(
|
||||
_Configuration.PropertyConfiguration,
|
||||
cResultsFullGroupDirectory,
|
||||
subFileTuples,
|
||||
parseExceptions,
|
||||
original,
|
||||
metadataCollection,
|
||||
item);
|
||||
if (_AppSettings.MaxDegreeOfParallelism < 2)
|
||||
ticks = LogDelta(ticks, nameof(C_Resize.GetResizeKeyValuePairs));
|
||||
if (_Configuration.SaveResizedSubfiles)
|
||||
@ -345,7 +427,15 @@ public partial class DlibDotNet
|
||||
int outputResolutionWidth = outputResolutionCollection[0];
|
||||
int outputResolutionHeight = outputResolutionCollection[1];
|
||||
int outputResolutionOrientation = outputResolutionCollection[2];
|
||||
faceCollection = _Faces.GetFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, item, property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation);
|
||||
faceCollection = _Faces.GetFaces(
|
||||
dResultsFullGroupDirectory,
|
||||
subFileTuples,
|
||||
parseExceptions,
|
||||
item,
|
||||
property,
|
||||
outputResolutionWidth,
|
||||
outputResolutionHeight,
|
||||
outputResolutionOrientation);
|
||||
if (_AppSettings.MaxDegreeOfParallelism < 2)
|
||||
ticks = LogDelta(ticks, nameof(D_Face.GetFaces));
|
||||
_Faces.SaveFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, item, faceCollection);
|
||||
@ -357,7 +447,9 @@ public partial class DlibDotNet
|
||||
{
|
||||
|
||||
bool saveRotated = _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution);
|
||||
string sourceDirectorySegment = Property.Models.Stateless.IResult.GetRelativePath(_Configuration.PropertyConfiguration, container.SourceDirectory);
|
||||
string sourceDirectorySegment = Property.Models.Stateless.IResult.GetRelativePath(
|
||||
_Configuration.PropertyConfiguration,
|
||||
container.SourceDirectory);
|
||||
string facesDirectory = Path.GetFullPath(Path.Combine($"{Path.Combine(d2ResultsFullGroupDirectory, "()")}{sourceDirectorySegment}", item.ImageFileHolder.NameWithoutExtension));
|
||||
_FaceParts.SaveFaceLandmarkImages(facesDirectory, subFileTuples, parseExceptions, item, faceCollection, saveRotated);
|
||||
if (_AppSettings.MaxDegreeOfParallelism < 2)
|
||||
@ -375,14 +467,33 @@ public partial class DlibDotNet
|
||||
}
|
||||
}
|
||||
|
||||
private int FullParallelWork(int maxDegreeOfParallelism, A_Property propertyLogic, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, List<Tuple<string, DateTime>> sourceDirectoryChanges, List<FileHolder?> propertyFileHolderCollection, List<Shared.Models.Property?> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollection, List<Dictionary<string, int[]>> resizeKeyValuePairs, List<List<Face>?> imageFaceCollections, Container container, Item[] filteredItems, string message)
|
||||
private int FullParallelWork(
|
||||
int maxDegreeOfParallelism,
|
||||
A_Property propertyLogic,
|
||||
string outputResolution,
|
||||
string bResultsFullGroupDirectory,
|
||||
string cResultsFullGroupDirectory,
|
||||
string dResultsFullGroupDirectory,
|
||||
string d2ResultsFullGroupDirectory,
|
||||
List<Tuple<string, DateTime>> sourceDirectoryChanges,
|
||||
List<FileHolder?> propertyFileHolderCollection,
|
||||
List<Shared.Models.Property?> propertyCollection,
|
||||
List<List<KeyValuePair<string, string>>> metadataCollection,
|
||||
List<Dictionary<string, int[]>> resizeKeyValuePairs,
|
||||
List<List<Shared.Models.Face>?> imageFaceCollections,
|
||||
Container container,
|
||||
Item[] filteredItems,
|
||||
string message)
|
||||
{
|
||||
if (_Log is null)
|
||||
throw new NullReferenceException(nameof(_Log));
|
||||
int result = 0;
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
||||
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||
if (imageFaceCollections.Count != filteredItems.Length || metadataCollection.Count != filteredItems.Length || resizeKeyValuePairs.Count != filteredItems.Length || propertyCollection.Count != filteredItems.Length)
|
||||
if (imageFaceCollections.Count != filteredItems.Length
|
||||
|| metadataCollection.Count != filteredItems.Length
|
||||
|| resizeKeyValuePairs.Count != filteredItems.Length
|
||||
|| propertyCollection.Count != filteredItems.Length)
|
||||
{
|
||||
for (int f = 0; f < filteredItems.Length; f++)
|
||||
{
|
||||
@ -398,7 +509,22 @@ public partial class DlibDotNet
|
||||
{
|
||||
try
|
||||
{
|
||||
FullParallelForWork(propertyLogic, outputResolution, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, sourceDirectoryChanges, propertyFileHolderCollection, propertyCollection, metadataCollection, resizeKeyValuePairs, imageFaceCollections, container, index: i, filteredItems[i]);
|
||||
FullParallelForWork(
|
||||
propertyLogic,
|
||||
outputResolution,
|
||||
bResultsFullGroupDirectory,
|
||||
cResultsFullGroupDirectory,
|
||||
dResultsFullGroupDirectory,
|
||||
d2ResultsFullGroupDirectory,
|
||||
sourceDirectoryChanges,
|
||||
propertyFileHolderCollection,
|
||||
propertyCollection,
|
||||
metadataCollection,
|
||||
resizeKeyValuePairs,
|
||||
imageFaceCollections,
|
||||
container,
|
||||
index: i,
|
||||
filteredItems[i]);
|
||||
if (i == 0 || sourceDirectoryChanges.Any())
|
||||
progressBar.Tick();
|
||||
}
|
||||
@ -448,7 +574,15 @@ public partial class DlibDotNet
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteGroup(A_Property propertyLogic, Shared.Models.Property[] propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollection, List<Dictionary<string, int[]>> resizeKeyValuePairs, List<List<Face>?> imageFaceCollections, string outputResolution, Container container, Item[] filteredItems)
|
||||
private void WriteGroup(
|
||||
A_Property propertyLogic,
|
||||
Shared.Models.Property[] propertyCollection,
|
||||
List<List<KeyValuePair<string, string>>> metadataCollection,
|
||||
List<Dictionary<string, int[]>> resizeKeyValuePairs,
|
||||
List<List<Shared.Models.Face>?> imageFaceCollections,
|
||||
string outputResolution,
|
||||
Container container,
|
||||
Item[] filteredItems)
|
||||
{
|
||||
Item item;
|
||||
string key;
|
||||
@ -461,11 +595,13 @@ public partial class DlibDotNet
|
||||
if (!(from l in propertyCollection where l?.Width is null select true).Any())
|
||||
{
|
||||
string checkDirectory;
|
||||
List<KeyValuePair<string, List<Face>?>> imageFaceCollectionsKeyValuePairs = new();
|
||||
List<KeyValuePair<string, List<Shared.Models.Face>?>> imageFaceCollectionsKeyValuePairs = new();
|
||||
List<KeyValuePair<string, Shared.Models.Property>> propertyCollectionKeyValuePairs = new();
|
||||
List<KeyValuePair<string, Dictionary<string, int[]>>> resizeKeyValuePairsCollections = new();
|
||||
List<KeyValuePair<string, List<KeyValuePair<string, string>>>> metadataCollectionKeyValuePairs = new();
|
||||
(int level, List<string> directories) = Shared.Models.Stateless.Methods.IPath.Get(_Configuration.PropertyConfiguration.RootDirectory, container.SourceDirectory);
|
||||
(int level, List<string> directories) = Shared.Models.Stateless.Methods.IPath.Get(
|
||||
_Configuration.PropertyConfiguration.RootDirectory,
|
||||
container.SourceDirectory);
|
||||
string fileName = string.Concat(string.Join(_Configuration.PropertyConfiguration.FileNameDirectorySeparator, directories), ".json");
|
||||
for (int i = 0; i < filteredItems.Length; i++)
|
||||
{
|
||||
@ -480,7 +616,7 @@ public partial class DlibDotNet
|
||||
_FileKeyValuePairs.Add(new KeyValuePair<string, string>(container.SourceDirectory, key));
|
||||
_FilePropertiesKeyValuePairs[container.SourceDirectory].Add(new Tuple<string, Shared.Models.Property>(key, propertyCollection[i]));
|
||||
}
|
||||
imageFaceCollectionsKeyValuePairs.Add(new KeyValuePair<string, List<Face>?>(key, imageFaceCollections[i]));
|
||||
imageFaceCollectionsKeyValuePairs.Add(new KeyValuePair<string, List<Shared.Models.Face>?>(key, imageFaceCollections[i]));
|
||||
propertyCollectionKeyValuePairs.Add(new KeyValuePair<string, Shared.Models.Property>(key, propertyCollection[i]));
|
||||
resizeKeyValuePairsCollections.Add(new KeyValuePair<string, Dictionary<string, int[]>>(key, resizeKeyValuePairs[i]));
|
||||
metadataCollectionKeyValuePairs.Add(new KeyValuePair<string, List<KeyValuePair<string, string>>>(key, metadataCollection[i]));
|
||||
@ -528,24 +664,77 @@ public partial class DlibDotNet
|
||||
}
|
||||
}
|
||||
|
||||
private (string, string, string, string, string, string) GetResultsFullGroupDirectories(Model? model, PredictorModel? predictorModel, string outputResolution)
|
||||
private (string, string, string, string, string, string) GetResultsFullGroupDirectories(
|
||||
Model? model,
|
||||
PredictorModel? predictorModel,
|
||||
string outputResolution)
|
||||
{
|
||||
string aResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
|
||||
_Configuration.PropertyConfiguration, model, predictorModel, nameof(A_Property), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false);
|
||||
_Configuration.PropertyConfiguration,
|
||||
model,
|
||||
predictorModel,
|
||||
nameof(A_Property),
|
||||
outputResolution,
|
||||
includeResizeGroup: false,
|
||||
includeModel: false,
|
||||
includePredictorModel: false);
|
||||
string bResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
|
||||
_Configuration.PropertyConfiguration, model, predictorModel, nameof(B_Metadata), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false);
|
||||
_Configuration.PropertyConfiguration,
|
||||
model,
|
||||
predictorModel,
|
||||
nameof(B_Metadata),
|
||||
outputResolution,
|
||||
includeResizeGroup: false,
|
||||
includeModel: false,
|
||||
includePredictorModel: false);
|
||||
string cResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
|
||||
_Configuration.PropertyConfiguration, model, predictorModel, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false);
|
||||
_Configuration.PropertyConfiguration,
|
||||
model,
|
||||
predictorModel,
|
||||
nameof(C_Resize),
|
||||
outputResolution,
|
||||
includeResizeGroup: true,
|
||||
includeModel: false,
|
||||
includePredictorModel: false);
|
||||
string dResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
|
||||
_Configuration.PropertyConfiguration, model, predictorModel, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true);
|
||||
_Configuration.PropertyConfiguration,
|
||||
model,
|
||||
predictorModel,
|
||||
nameof(D_Face),
|
||||
outputResolution,
|
||||
includeResizeGroup: true,
|
||||
includeModel: true,
|
||||
includePredictorModel: true);
|
||||
string d2ResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
|
||||
_Configuration.PropertyConfiguration, model, predictorModel, nameof(D2_FaceParts), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true);
|
||||
_Configuration.PropertyConfiguration,
|
||||
model,
|
||||
predictorModel,
|
||||
nameof(D2_FaceParts),
|
||||
outputResolution,
|
||||
includeResizeGroup: true,
|
||||
includeModel: true,
|
||||
includePredictorModel: true);
|
||||
string eResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
|
||||
_Configuration.PropertyConfiguration, model, predictorModel, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true);
|
||||
_Configuration.PropertyConfiguration,
|
||||
model,
|
||||
predictorModel,
|
||||
nameof(E_Distance),
|
||||
outputResolution,
|
||||
includeResizeGroup: true,
|
||||
includeModel: true,
|
||||
includePredictorModel: true);
|
||||
return new(aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory);
|
||||
}
|
||||
|
||||
private void SetAngleBracketCollections(A_Property propertyLogic, string outputResolution, Container container, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory)
|
||||
private void SetAngleBracketCollections(
|
||||
A_Property propertyLogic,
|
||||
string outputResolution,
|
||||
Container container,
|
||||
string aResultsFullGroupDirectory,
|
||||
string bResultsFullGroupDirectory,
|
||||
string cResultsFullGroupDirectory,
|
||||
string dResultsFullGroupDirectory,
|
||||
string d2ResultsFullGroupDirectory)
|
||||
{
|
||||
_Faces.AngleBracketCollection.Clear();
|
||||
_Resize.AngleBracketCollection.Clear();
|
||||
@ -595,7 +784,29 @@ public partial class DlibDotNet
|
||||
converted: false);
|
||||
}
|
||||
|
||||
private void FullDoWork(string argZero, Model? model, PredictorModel? predictorModel, string propertyRoot, long ticks, A_Property propertyLogic, int t, Container[] containers)
|
||||
private Item[] GetFilterItems(Container container)
|
||||
{
|
||||
List<Item> results = new();
|
||||
foreach (Item item in container.Items)
|
||||
{
|
||||
if (item.ImageFileHolder is not null
|
||||
&& (item.Abandoned is null || !item.Abandoned.Value)
|
||||
&& item.ValidImageFormatExtension
|
||||
&& !_Configuration.IgnoreExtensions.Contains(item.ImageFileHolder.ExtensionLowered))
|
||||
results.Add(item);
|
||||
}
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
private void FullDoWork(
|
||||
string argZero,
|
||||
Model? model,
|
||||
PredictorModel? predictorModel,
|
||||
string propertyRoot,
|
||||
long ticks,
|
||||
A_Property propertyLogic,
|
||||
int t,
|
||||
Container[] containers)
|
||||
{
|
||||
if (_Log is null)
|
||||
throw new NullReferenceException(nameof(_Log));
|
||||
@ -613,7 +824,7 @@ public partial class DlibDotNet
|
||||
string d2ResultsFullGroupDirectory;
|
||||
int containersLength = containers.Length;
|
||||
Shared.Models.Property[] propertyCollection;
|
||||
List<List<Face>?> imageFaceCollections = new();
|
||||
List<List<Shared.Models.Face>?> imageFaceCollections = new();
|
||||
List<FileHolder?> propertyFileHolderCollection = new();
|
||||
List<Dictionary<string, int[]>> resizeKeyValuePairs = new();
|
||||
List<Tuple<string, DateTime>> sourceDirectoryChanges = new();
|
||||
@ -626,7 +837,15 @@ public partial class DlibDotNet
|
||||
total = 0;
|
||||
_FileKeyValuePairs.Clear();
|
||||
_FilePropertiesKeyValuePairs.Clear();
|
||||
(aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory) = GetResultsFullGroupDirectories(model, predictorModel, outputResolution);
|
||||
(aResultsFullGroupDirectory,
|
||||
bResultsFullGroupDirectory,
|
||||
cResultsFullGroupDirectory,
|
||||
dResultsFullGroupDirectory,
|
||||
d2ResultsFullGroupDirectory,
|
||||
eResultsFullGroupDirectory) = GetResultsFullGroupDirectories(
|
||||
model,
|
||||
predictorModel,
|
||||
outputResolution);
|
||||
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(eResultsFullGroupDirectory, "()"));
|
||||
for (int i = 0; i < containers.Length; i++)
|
||||
{
|
||||
@ -635,7 +854,7 @@ public partial class DlibDotNet
|
||||
continue;
|
||||
if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
|
||||
continue;
|
||||
filteredItems = (from l in container.Items where l.ImageFileHolder is not null && (l.Abandoned is null || !l.Abandoned.Value) && l.ValidImageFormatExtension && !_Configuration.IgnoreExtensions.Contains(l.ImageFileHolder.ExtensionLowered) select l).ToArray();
|
||||
filteredItems = GetFilterItems(container);
|
||||
if (!filteredItems.Any())
|
||||
continue;
|
||||
metadataCollection.Clear();
|
||||
@ -647,7 +866,23 @@ public partial class DlibDotNet
|
||||
totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||
message = $"{i + 1:000}.{container.G} [{filteredItems.Length:000} files] / {containersLength:000} - {total} / {t} total files - {totalSeconds} total second(s) - {outputResolution} - {container.SourceDirectory}";
|
||||
SetAngleBracketCollections(propertyLogic, outputResolution, container, aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory);
|
||||
exceptionCount = FullParallelWork(maxDegreeOfParallelism, propertyLogic, outputResolution, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, sourceDirectoryChanges, propertyFileHolderCollection, nullablePropertyCollection, metadataCollection, resizeKeyValuePairs, imageFaceCollections, container, filteredItems, message);
|
||||
exceptionCount = FullParallelWork(
|
||||
maxDegreeOfParallelism,
|
||||
propertyLogic,
|
||||
outputResolution,
|
||||
bResultsFullGroupDirectory,
|
||||
cResultsFullGroupDirectory,
|
||||
dResultsFullGroupDirectory,
|
||||
d2ResultsFullGroupDirectory,
|
||||
sourceDirectoryChanges,
|
||||
propertyFileHolderCollection,
|
||||
nullablePropertyCollection,
|
||||
metadataCollection,
|
||||
resizeKeyValuePairs,
|
||||
imageFaceCollections,
|
||||
container,
|
||||
filteredItems,
|
||||
message);
|
||||
if (metadataCollection.Count != filteredItems.Length || nullablePropertyCollection.Count != filteredItems.Length || resizeKeyValuePairs.Count != filteredItems.Length || imageFaceCollections.Count != filteredItems.Length)
|
||||
throw new Exception("Counts don't match!");
|
||||
if (exceptionCount != 0)
|
||||
@ -684,9 +919,9 @@ public partial class DlibDotNet
|
||||
}
|
||||
}
|
||||
|
||||
private List<Face> SetMappingThenGetDistinctFilteredFacesWithMapping(string argZero, Container[] containers)
|
||||
private List<Shared.Models.Face> SetMappingThenGetDistinctFilteredFacesWithMapping(string argZero, Container[] containers)
|
||||
{
|
||||
List<Face> results = new();
|
||||
List<Shared.Models.Face> results = new();
|
||||
Mapping mapping;
|
||||
bool? isWrongYear;
|
||||
Item[] filteredItems;
|
||||
@ -701,7 +936,7 @@ public partial class DlibDotNet
|
||||
continue;
|
||||
if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
|
||||
continue;
|
||||
filteredItems = (from l in container.Items where l.ImageFileHolder is not null && (l.Abandoned is null || !l.Abandoned.Value) && l.ValidImageFormatExtension && !_Configuration.IgnoreExtensions.Contains(l.ImageFileHolder.ExtensionLowered) select l).ToArray();
|
||||
filteredItems = GetFilterItems(container);
|
||||
if (!filteredItems.Any())
|
||||
continue;
|
||||
foreach (Item item in filteredItems)
|
||||
@ -710,7 +945,7 @@ public partial class DlibDotNet
|
||||
continue;
|
||||
if (!item.Faces.Any())
|
||||
continue;
|
||||
foreach (Face face in item.Faces)
|
||||
foreach (Shared.Models.Face face in item.Faces)
|
||||
{
|
||||
if (face.RelativePath != item.RelativePath)
|
||||
break;
|
||||
@ -731,20 +966,55 @@ public partial class DlibDotNet
|
||||
return results;
|
||||
}
|
||||
|
||||
private void DistanceThenMapLogic(string argZero, long ticks, PersonContainer[] personContainers, Container[] containers, string dResultsFullGroupDirectory, string eResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, string outputResolution)
|
||||
private void DistanceThenMapLogic(
|
||||
string argZero,
|
||||
long ticks,
|
||||
PersonContainer[] personContainers,
|
||||
Container[] containers,
|
||||
string dResultsFullGroupDirectory,
|
||||
string eResultsFullGroupDirectory,
|
||||
string d2ResultsFullGroupDirectory,
|
||||
string outputResolution)
|
||||
{
|
||||
E_Distance distance = new();
|
||||
if (string.IsNullOrEmpty(eResultsFullGroupDirectory))
|
||||
throw new NullReferenceException(nameof(eResultsFullGroupDirectory));
|
||||
List<Face> distinctFilteredFaces = SetMappingThenGetDistinctFilteredFacesWithMapping(argZero, containers);
|
||||
List<Face> selectedFilteredFaces = E_Distance.GetSelectedFilteredFaces(distinctFilteredFaces);
|
||||
string eDistanceContentDirectory = Path.Combine(eResultsFullGroupDirectory, "()");
|
||||
List<Shared.Models.Face> distinctFilteredFaces = SetMappingThenGetDistinctFilteredFacesWithMapping(argZero, containers);
|
||||
List<Shared.Models.Face> selectedFilteredFaces = E_Distance.GetSelectedFilteredFaces(distinctFilteredFaces);
|
||||
E_Distance.SetFaceDistances(_AppSettings.MaxDegreeOfParallelism, ticks, selectedFilteredFaces);
|
||||
MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _Faces.FileNameExtension, _Faces.HiddenFileNameExtension, _FaceParts.FileNameExtension, ticks, personContainers, eResultsFullGroupDirectory, distinctFilteredFaces, distance);
|
||||
SortingContainer[] sortingContainers = E_Distance.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, _MapConfiguration, ticks, mapLogic, selectedFilteredFaces);
|
||||
string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(
|
||||
_Configuration.PropertyConfiguration,
|
||||
nameof(A2_People),
|
||||
"{}");
|
||||
MapLogic mapLogic = new(
|
||||
_AppSettings.MaxDegreeOfParallelism,
|
||||
_Configuration.PropertyConfiguration,
|
||||
_MapConfiguration,
|
||||
_Faces.FileNameExtension,
|
||||
_Faces.HiddenFileNameExtension,
|
||||
_FaceParts.FileNameExtension,
|
||||
ticks,
|
||||
personContainers,
|
||||
eDistanceContentDirectory,
|
||||
a2PeopleSingletonDirectory,
|
||||
distinctFilteredFaces,
|
||||
distance);
|
||||
SortingContainer[] sortingContainers = E_Distance.SetFaceMappingSortingCollectionThenGetSortingContainers(
|
||||
_AppSettings.MaxDegreeOfParallelism,
|
||||
_MapConfiguration,
|
||||
ticks,
|
||||
mapLogic,
|
||||
selectedFilteredFaces);
|
||||
E_Distance.SaveFaceDistances(_Configuration.PropertyConfiguration, eResultsFullGroupDirectory, sortingContainers);
|
||||
int totalNotMapped = mapLogic.AddToMapping(distinctFilteredFaces);
|
||||
if (totalNotMapped > 0)
|
||||
mapLogic.ForceSingleImageThenSaveMapping(dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, distinctFilteredFaces, sortingContainers, totalNotMapped);
|
||||
mapLogic.ForceSingleImageThenSaveMapping(
|
||||
dResultsFullGroupDirectory,
|
||||
d2ResultsFullGroupDirectory,
|
||||
distinctFilteredFaces,
|
||||
sortingContainers,
|
||||
totalNotMapped);
|
||||
mapLogic.CopyManualFiles(dResultsFullGroupDirectory, distinctFilteredFaces);
|
||||
if (_MapConfiguration.MappingSaveNotMapped)
|
||||
mapLogic.SaveNotMappedTicks();
|
||||
@ -818,7 +1088,13 @@ public partial class DlibDotNet
|
||||
return result;
|
||||
}
|
||||
|
||||
private void Search(long ticks, Model? model, PredictorModel? predictorModel, string argZero, string propertyRoot, PersonContainer[] personContainers)
|
||||
private void Search(
|
||||
long ticks,
|
||||
Model? model,
|
||||
PredictorModel? predictorModel,
|
||||
string argZero,
|
||||
string propertyRoot,
|
||||
PersonContainer[] personContainers)
|
||||
{
|
||||
int j;
|
||||
int f;
|
||||
@ -844,33 +1120,72 @@ public partial class DlibDotNet
|
||||
{
|
||||
string? newRootDirectory = SaveUrlAndGetNewRootDirectory(container);
|
||||
for (int i = 1; i < 10; i++)
|
||||
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, string.Empty, create: true));
|
||||
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Property.Models.Stateless.IResult.GetResultsGroupDirectory(
|
||||
_Configuration.PropertyConfiguration,
|
||||
string.Empty,
|
||||
create: true));
|
||||
argZero = newRootDirectory;
|
||||
_Configuration.PropertyConfiguration.ChangeRootDirectory(newRootDirectory);
|
||||
propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), create: false);
|
||||
propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, model, predictorModel);
|
||||
propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(
|
||||
_Configuration.PropertyConfiguration,
|
||||
nameof(A_Property),
|
||||
create: false);
|
||||
propertyLogic = new(
|
||||
_AppSettings.MaxDegreeOfParallelism,
|
||||
_Configuration.PropertyConfiguration,
|
||||
_Resize.FileNameExtension,
|
||||
_Configuration.Reverse,
|
||||
model,
|
||||
predictorModel);
|
||||
}
|
||||
FullDoWork(argZero, model, predictorModel, propertyRoot, ticks, propertyLogic, t, containers);
|
||||
foreach (string outputResolution in _Configuration.OutputResolutions)
|
||||
{
|
||||
if (_FirstRun || container is not null)
|
||||
break;
|
||||
(aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory) = GetResultsFullGroupDirectories(model, predictorModel, outputResolution);
|
||||
if (_ArgZeroIsConfigurationRootDirectory && _Configuration.SaveResizedSubfiles && outputResolution == _Configuration.OutputResolutions[0] && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution) && _Exceptions.Count == 0)
|
||||
(aResultsFullGroupDirectory,
|
||||
bResultsFullGroupDirectory,
|
||||
cResultsFullGroupDirectory,
|
||||
dResultsFullGroupDirectory,
|
||||
d2ResultsFullGroupDirectory,
|
||||
eResultsFullGroupDirectory) = GetResultsFullGroupDirectories(
|
||||
model,
|
||||
predictorModel,
|
||||
outputResolution);
|
||||
if (_ArgZeroIsConfigurationRootDirectory
|
||||
&& _Configuration.SaveResizedSubfiles
|
||||
&& outputResolution == _Configuration.OutputResolutions[0]
|
||||
&& _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)
|
||||
&& _Exceptions.Count == 0)
|
||||
{
|
||||
if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Any())
|
||||
break;
|
||||
DistanceThenMapLogic(argZero, ticks, personContainers, containers, dResultsFullGroupDirectory, eResultsFullGroupDirectory, d2ResultsFullGroupDirectory, outputResolution);
|
||||
DistanceThenMapLogic(
|
||||
argZero,
|
||||
ticks,
|
||||
personContainers,
|
||||
containers,
|
||||
dResultsFullGroupDirectory,
|
||||
eResultsFullGroupDirectory,
|
||||
d2ResultsFullGroupDirectory,
|
||||
outputResolution);
|
||||
if (_IsEnvironment.Development)
|
||||
continue;
|
||||
if (_FileKeyValuePairs.Any())
|
||||
_Random.Random(_Configuration.PropertyConfiguration, _Configuration.OutputResolutions[0], _FileKeyValuePairs);
|
||||
G2_Identify identify = new(_Configuration);
|
||||
List<G2_Identify> identifiedCollection = identify.GetIdentifiedCollection(_IsEnvironment, _Configuration.PropertyConfiguration, _Faces.FileNameExtension);
|
||||
A2_People.WriteAllText(_Configuration.PropertyConfiguration, _Configuration.OutputResolutions[0], identifiedCollection);
|
||||
List<G2_Identify> identifiedCollection = identify.GetIdentifiedCollection(
|
||||
_IsEnvironment,
|
||||
_Configuration.PropertyConfiguration,
|
||||
_Faces.FileNameExtension);
|
||||
identify.WriteAllText(_Configuration.PropertyConfiguration, _Configuration.OutputResolutions[0], identifiedCollection);
|
||||
if (_Configuration.LoadOrCreateThenSaveIndex && _FilePropertiesKeyValuePairs.Any())
|
||||
_Index.SetIndex(_Configuration.PropertyConfiguration, model, predictorModel, _Configuration.OutputResolutions[0], _FilePropertiesKeyValuePairs);
|
||||
_Index.SetIndex(
|
||||
_Configuration.PropertyConfiguration,
|
||||
model,
|
||||
predictorModel,
|
||||
_Configuration.OutputResolutions[0],
|
||||
_FilePropertiesKeyValuePairs);
|
||||
}
|
||||
if (!_IsEnvironment.Development)
|
||||
{
|
||||
@ -887,6 +1202,9 @@ public partial class DlibDotNet
|
||||
}
|
||||
}
|
||||
|
||||
internal void RenameQueue(Model? model, PredictorModel? predictorModel) => _Rename.RenameQueue(_Configuration.PropertyConfiguration, model, predictorModel);
|
||||
internal void RenameQueue(Model? model, PredictorModel? predictorModel) => _Rename.RenameQueue(
|
||||
_Configuration.PropertyConfiguration,
|
||||
model,
|
||||
predictorModel);
|
||||
|
||||
}
|
@ -54,6 +54,9 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" />
|
||||
<ProjectReference Include="..\Distance\Distance.csproj" />
|
||||
<ProjectReference Include="..\Face\Face.csproj" />
|
||||
<ProjectReference Include="..\FaceParts\FaceParts.csproj" />
|
||||
<ProjectReference Include="..\Map\Map.csproj" />
|
||||
<ProjectReference Include="..\Metadata\Metadata.csproj" />
|
||||
<ProjectReference Include="..\Property-Compare\Property-Compare.csproj" />
|
||||
|
@ -1,60 +1,7 @@
|
||||
using System.Text.Json;
|
||||
using View_by_Distance.Shared.Models;
|
||||
|
||||
namespace View_by_Distance.Instance.Models;
|
||||
|
||||
/// <summary>
|
||||
// ?
|
||||
/// </summary>
|
||||
internal class A2_People
|
||||
{
|
||||
|
||||
internal static void WriteAllText(Property.Models.Configuration configuration, string outputResolution, List<G2_Identify> identifiedCollection)
|
||||
{
|
||||
string key;
|
||||
string json;
|
||||
string jsonFile;
|
||||
FileInfo fileInfo;
|
||||
string[] segments;
|
||||
string directoryFullName;
|
||||
Dictionary<string, List<G2_Identify>> keyValuePairs = new();
|
||||
JsonSerializerOptions writeIndentedJsonSerializerOptions = new() { WriteIndented = true };
|
||||
string a2PeopleCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A2_People), "[]");
|
||||
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(Property.Models.A_Property), "{}");
|
||||
foreach (G2_Identify identified in identifiedCollection)
|
||||
{
|
||||
fileInfo = new FileInfo(string.Concat(aPropertySingletonDirectory, identified.RelativePath));
|
||||
if (fileInfo?.Directory is null || !fileInfo.Directory.Exists || fileInfo.Exists)
|
||||
continue;
|
||||
key = string.Concat(identified.ParentDirectoryName, '|', identified.Person);
|
||||
if (!keyValuePairs.ContainsKey(key))
|
||||
keyValuePairs.Add(key, new List<G2_Identify>());
|
||||
keyValuePairs[key].Add(identified);
|
||||
}
|
||||
foreach (KeyValuePair<string, List<G2_Identify>> keyValuePair in keyValuePairs)
|
||||
{
|
||||
segments = keyValuePair.Key.Split('|');
|
||||
directoryFullName = Path.Combine(a2PeopleCollectionDirectory, segments[0]);
|
||||
if (!Directory.Exists(directoryFullName))
|
||||
_ = Directory.CreateDirectory(directoryFullName);
|
||||
jsonFile = Path.Combine(directoryFullName, $"{segments[1]}.json");
|
||||
json = JsonSerializer.Serialize(keyValuePair.Value, writeIndentedJsonSerializerOptions);
|
||||
if (!Shared.Models.Stateless.Methods.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches: true, compareBeforeWrite: true))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
internal static PersonContainer[] GetPersonContainers(Configuration configuration, Property.Models.Configuration propertyConfiguration, string facesFileNameExtension)
|
||||
{
|
||||
PersonContainer[] results;
|
||||
string rootDirectory = propertyConfiguration.RootDirectory;
|
||||
string peopleRootDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A2_People));
|
||||
string? rootResultsDirectory = Path.GetDirectoryName(Path.GetDirectoryName(peopleRootDirectory));
|
||||
if (rootResultsDirectory is null)
|
||||
throw new Exception();
|
||||
Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory);
|
||||
results = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers(storage, configuration.LocationDigits, configuration.PersonBirthdayFormat, facesFileNameExtension);
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
||||
{ }
|
@ -1,182 +0,0 @@
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Text.Json;
|
||||
using View_by_Distance.Metadata.Models;
|
||||
using View_by_Distance.Resize.Models;
|
||||
using View_by_Distance.Shared.Models;
|
||||
using View_by_Distance.Shared.Models.Properties;
|
||||
using View_by_Distance.Shared.Models.Stateless;
|
||||
|
||||
namespace View_by_Distance.Instance.Models;
|
||||
|
||||
/// <summary>
|
||||
// *.png
|
||||
/// </summary>
|
||||
internal class D2_FaceParts
|
||||
{
|
||||
|
||||
protected readonly string _FileNameExtension;
|
||||
public string FileNameExtension => _FileNameExtension;
|
||||
|
||||
private readonly Serilog.ILogger? _Log;
|
||||
private readonly Configuration _Configuration;
|
||||
private readonly ImageCodecInfo _ImageCodecInfo;
|
||||
private readonly EncoderParameters _EncoderParameters;
|
||||
|
||||
internal D2_FaceParts(Configuration configuration, ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension)
|
||||
{
|
||||
_Configuration = configuration;
|
||||
_ImageCodecInfo = imageCodecInfo;
|
||||
_EncoderParameters = encoderParameters;
|
||||
_FileNameExtension = filenameExtension;
|
||||
_Log = Serilog.Log.ForContext<D2_FaceParts>();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma warning disable CA1416
|
||||
|
||||
private static Bitmap RotateBitmap(Image image, float angle)
|
||||
{
|
||||
Bitmap result;
|
||||
Bitmap bitmap = new(image);
|
||||
result = D_Face.RotateBitmap(bitmap, angle);
|
||||
if (bitmap is not null)
|
||||
bitmap.Dispose();
|
||||
return result;
|
||||
}
|
||||
|
||||
private void SaveFaceParts(int pointSize, IFileHolder resizedFileHolder, bool saveRotated, List<(Face, string, string)> collection)
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
double? α;
|
||||
int width;
|
||||
int height;
|
||||
Bitmap rotated;
|
||||
foreach ((Face face, string fileName, string rotatedFileName) in collection)
|
||||
{
|
||||
if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
|
||||
continue;
|
||||
try
|
||||
{
|
||||
using (Image image = Image.FromFile(resizedFileHolder.FullName))
|
||||
{
|
||||
using Graphics graphic = Graphics.FromImage(image);
|
||||
if (face.FaceParts is null || !face.FaceParts.Any())
|
||||
{
|
||||
if (face.Location is null)
|
||||
continue;
|
||||
width = face.Location.Right - face.Location.Left;
|
||||
height = face.Location.Bottom - face.Location.Top;
|
||||
graphic.DrawEllipse(Pens.Red, face.Location.Left, face.Location.Top, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ((FacePart facePart, FacePoint[] facePoints) in face.FaceParts)
|
||||
{
|
||||
foreach (FacePoint facePoint in facePoints)
|
||||
{
|
||||
if (face.Location is null)
|
||||
continue;
|
||||
graphic.DrawEllipse(Pens.GreenYellow, face.Location.Left + facePoint.X - pointSize, face.Location.Top + facePoint.Y - pointSize, pointSize * 2, pointSize * 2);
|
||||
}
|
||||
if (facePart == FacePart.Chin)
|
||||
continue;
|
||||
if (facePoints.Length < 3)
|
||||
continue;
|
||||
x = (int)(from l in facePoints select l.X).Average();
|
||||
y = (int)(from l in facePoints select l.Y).Average();
|
||||
if (face.Location is null)
|
||||
continue;
|
||||
graphic.DrawEllipse(Pens.Purple, face.Location.Left + x - pointSize, face.Location.Top + y - pointSize, pointSize * 2, pointSize * 2);
|
||||
}
|
||||
}
|
||||
image.Save(fileName, _ImageCodecInfo, _EncoderParameters);
|
||||
}
|
||||
if (saveRotated && face.FaceParts is not null)
|
||||
{
|
||||
α = Shared.Models.Stateless.Methods.IFace.Getα(face.FaceParts);
|
||||
if (α is null)
|
||||
continue;
|
||||
using Image image = Image.FromFile(resizedFileHolder.FullName);
|
||||
rotated = RotateBitmap(image, (float)α.Value);
|
||||
if (rotated is not null)
|
||||
{
|
||||
rotated.Save(rotatedFileName, _ImageCodecInfo, _EncoderParameters);
|
||||
rotated.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore CA1416
|
||||
|
||||
internal void SaveFaceLandmarkImages(string facesDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Item item, List<Face> faceCollection, bool saveRotated)
|
||||
{
|
||||
if (item.ImageFileHolder is null)
|
||||
throw new NullReferenceException(nameof(item.ImageFileHolder));
|
||||
if (item.ResizedFileHolder is null)
|
||||
throw new NullReferenceException(nameof(item.ResizedFileHolder));
|
||||
FileInfo fileInfo;
|
||||
bool check = false;
|
||||
string parentCheck;
|
||||
const int pointSize = 2;
|
||||
FileInfo rotatedFileInfo;
|
||||
DateTime? dateTime = null;
|
||||
long ticks = DateTime.Now.Ticks;
|
||||
bool updateDateWhenMatches = false;
|
||||
string deterministicHashCodeKeyDisplay;
|
||||
List<(Face, string, string)> collection = new();
|
||||
string[] changesFrom = new string[] { nameof(Property.Models.A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) };
|
||||
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
|
||||
if (!Directory.Exists(facesDirectory))
|
||||
_ = Directory.CreateDirectory(facesDirectory);
|
||||
foreach (Face face in faceCollection)
|
||||
{
|
||||
if (item.Property?.Id is null || face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
|
||||
{
|
||||
collection.Add(new(face, string.Empty, string.Empty));
|
||||
continue;
|
||||
}
|
||||
deterministicHashCodeKeyDisplay = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location.NormalizedPixelPercentage.Value);
|
||||
fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKeyDisplay}{item.ImageFileHolder.ExtensionLowered}{_FileNameExtension}"));
|
||||
if (!fileInfo.Exists)
|
||||
{
|
||||
if (fileInfo.Directory?.Parent is null)
|
||||
throw new Exception();
|
||||
parentCheck = Path.Combine(fileInfo.Directory.Parent.FullName, fileInfo.Name);
|
||||
if (File.Exists(parentCheck))
|
||||
File.Delete(parentCheck);
|
||||
}
|
||||
if (string.IsNullOrEmpty(fileInfo.DirectoryName))
|
||||
continue;
|
||||
rotatedFileInfo = new FileInfo(Path.Combine(fileInfo.DirectoryName, $"{deterministicHashCodeKeyDisplay} - R{item.ImageFileHolder.ExtensionLowered}{_FileNameExtension}"));
|
||||
collection.Add(new(face, fileInfo.FullName, rotatedFileInfo.FullName));
|
||||
if (check)
|
||||
continue;
|
||||
else if (_Configuration.OverrideForFaceLandmarkImages)
|
||||
check = true;
|
||||
else if (!fileInfo.Exists)
|
||||
check = true;
|
||||
else if (saveRotated && !rotatedFileInfo.Exists)
|
||||
check = true;
|
||||
else if (_Configuration.CheckDFaceAndUpWriteDates && dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime)
|
||||
check = true;
|
||||
if (check && !updateDateWhenMatches)
|
||||
{
|
||||
updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime;
|
||||
dateTime = !updateDateWhenMatches ? null : dateTimes.Max();
|
||||
}
|
||||
}
|
||||
if (check)
|
||||
SaveFaceParts(pointSize, item.ResizedFileHolder, saveRotated, collection);
|
||||
}
|
||||
|
||||
}
|
@ -1,451 +0,0 @@
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using View_by_Distance.FaceRecognitionDotNet;
|
||||
using View_by_Distance.Metadata.Models;
|
||||
using View_by_Distance.Property.Models;
|
||||
using View_by_Distance.Resize.Models;
|
||||
using View_by_Distance.Shared.Models;
|
||||
using View_by_Distance.Shared.Models.Stateless;
|
||||
|
||||
namespace View_by_Distance.Instance.Models;
|
||||
|
||||
/// <summary>
|
||||
// List<D_Faces>
|
||||
/// </summary>
|
||||
public class D_Face
|
||||
{
|
||||
|
||||
internal List<string> AngleBracketCollection { get; }
|
||||
|
||||
protected readonly string _FileNameExtension;
|
||||
public string FileNameExtension => _FileNameExtension;
|
||||
|
||||
protected readonly string _HiddenFileNameExtension;
|
||||
public string HiddenFileNameExtension => _HiddenFileNameExtension;
|
||||
|
||||
private readonly Model _Model;
|
||||
private readonly string _ArgZero;
|
||||
private readonly Serilog.ILogger? _Log;
|
||||
private readonly Configuration _Configuration;
|
||||
private readonly ImageCodecInfo _ImageCodecInfo;
|
||||
private readonly ModelParameter _ModelParameter;
|
||||
private readonly PredictorModel _PredictorModel;
|
||||
private readonly ConstructorInfo _ConstructorInfo;
|
||||
private readonly EncoderParameters _EncoderParameters;
|
||||
private readonly ImageCodecInfo _HiddenImageCodecInfo;
|
||||
private readonly EncoderParameters _HiddenEncoderParameters;
|
||||
private readonly JsonSerializerOptions _WriteIndentedAndWhenWritingNull;
|
||||
|
||||
internal D_Face(Configuration configuration, string argZero, Model model, ModelParameter modelParameter, PredictorModel predictorModel, ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension, ImageCodecInfo hiddenImageCodecInfo, EncoderParameters hiddenEncoderParameters, string hiddenFileNameExtension)
|
||||
{
|
||||
_Model = model;
|
||||
_ArgZero = argZero;
|
||||
_Configuration = configuration;
|
||||
_ImageCodecInfo = imageCodecInfo;
|
||||
_ModelParameter = modelParameter;
|
||||
_PredictorModel = predictorModel;
|
||||
_EncoderParameters = encoderParameters;
|
||||
_FileNameExtension = filenameExtension;
|
||||
_Log = Serilog.Log.ForContext<D_Face>();
|
||||
AngleBracketCollection = new List<string>();
|
||||
_HiddenImageCodecInfo = hiddenImageCodecInfo;
|
||||
_HiddenEncoderParameters = hiddenEncoderParameters;
|
||||
_HiddenFileNameExtension = hiddenFileNameExtension;
|
||||
ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, Array.Empty<Type>(), null);
|
||||
if (constructorInfo is null)
|
||||
throw new Exception();
|
||||
_ConstructorInfo = constructorInfo;
|
||||
_WriteIndentedAndWhenWritingNull = new JsonSerializerOptions { WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull };
|
||||
}
|
||||
|
||||
private static void GetPointBounds(PointF[] points, out float xMinimum, out float xMaximum, out float yMinimum, out float yMaximum)
|
||||
{
|
||||
xMinimum = points[0].X;
|
||||
xMaximum = xMinimum;
|
||||
yMinimum = points[0].Y;
|
||||
yMaximum = yMinimum;
|
||||
foreach (PointF point in points)
|
||||
{
|
||||
if (xMinimum > point.X)
|
||||
xMinimum = point.X;
|
||||
if (xMaximum < point.X)
|
||||
xMaximum = point.X;
|
||||
if (yMinimum > point.Y)
|
||||
yMinimum = point.Y;
|
||||
if (yMaximum < point.Y)
|
||||
yMaximum = point.Y;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma warning disable CA1416
|
||||
|
||||
internal static Bitmap RotateBitmap(Bitmap bitmap, float angle)
|
||||
{
|
||||
Bitmap result;
|
||||
#if Linux
|
||||
throw new Exception("Built on Linux!");
|
||||
#elif OSX
|
||||
throw new Exception("Built on macOS!");
|
||||
#elif Windows
|
||||
// Make a Matrix to represent rotation
|
||||
// by this angle.
|
||||
Matrix rotate_at_origin = new();
|
||||
rotate_at_origin.Rotate(angle);
|
||||
|
||||
// Rotate the image's corners to see how big
|
||||
// it will be after rotation.
|
||||
PointF[] points =
|
||||
{
|
||||
new PointF(0, 0),
|
||||
new PointF(bitmap.Width, 0),
|
||||
new PointF(bitmap.Width, bitmap.Height),
|
||||
new PointF(0, bitmap.Height),
|
||||
};
|
||||
rotate_at_origin.TransformPoints(points);
|
||||
float xMinimum, xMaximum, yMinimum, yMaximum;
|
||||
GetPointBounds(points, out xMinimum, out xMaximum, out yMinimum, out yMaximum);
|
||||
|
||||
// Make a bitmap to hold the rotated result.
|
||||
int wid = (int)Math.Round(xMaximum - xMinimum);
|
||||
int hgt = (int)Math.Round(yMaximum - yMinimum);
|
||||
result = new Bitmap(wid, hgt);
|
||||
|
||||
// Create the real rotation transformation.
|
||||
Matrix rotate_at_center = new();
|
||||
rotate_at_center.RotateAt(angle,
|
||||
new PointF(wid / 2f, hgt / 2f));
|
||||
|
||||
// Draw the image onto the new bitmap rotated.
|
||||
using (Graphics gr = Graphics.FromImage(result))
|
||||
{
|
||||
// Use smooth image interpolation.
|
||||
gr.InterpolationMode = InterpolationMode.High;
|
||||
|
||||
// Clear with the color in the image's upper left corner.
|
||||
gr.Clear(bitmap.GetPixel(0, 0));
|
||||
|
||||
// For debugging. (It's easier to see the background.)
|
||||
// gr.Clear(Color.LightBlue);
|
||||
|
||||
// Set up the transformation to rotate.
|
||||
gr.Transform = rotate_at_center;
|
||||
|
||||
// Draw the image centered on the bitmap.
|
||||
int x = (wid - bitmap.Width) / 2;
|
||||
int y = (hgt - bitmap.Height) / 2;
|
||||
gr.DrawImage(bitmap, x, y);
|
||||
}
|
||||
#endif
|
||||
// Return the result bitmap.
|
||||
return result;
|
||||
}
|
||||
|
||||
private static byte[] GetBytes(string value)
|
||||
{
|
||||
byte[] results = new byte[value.Length + 1];
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
results[i] = (byte)value[i];
|
||||
results[value.Length] = 0x00;
|
||||
return results;
|
||||
}
|
||||
|
||||
private PropertyItem GetPropertyItem(int id, string value)
|
||||
{
|
||||
PropertyItem result = (PropertyItem)_ConstructorInfo.Invoke(null);
|
||||
byte[] bytes = GetBytes(value);
|
||||
result.Id = id;
|
||||
result.Len = value.Length + 1;
|
||||
result.Type = 2;
|
||||
result.Value = bytes;
|
||||
return result;
|
||||
}
|
||||
|
||||
private void SaveFaces(FileHolder resizedFileHolder, List<(Face, FileInfo?, string)> collection)
|
||||
{
|
||||
int pixel;
|
||||
int width;
|
||||
int height;
|
||||
string json;
|
||||
Bitmap bitmap;
|
||||
Graphics graphics;
|
||||
Location? location;
|
||||
Rectangle rectangle;
|
||||
PropertyItem? propertyItem;
|
||||
int software = (int)IExif.Tags.Software;
|
||||
int userComment = (int)IExif.Tags.UserComment;
|
||||
using Bitmap source = new(resizedFileHolder.FullName);
|
||||
int imageDescription = (int)IExif.Tags.ImageDescription;
|
||||
foreach ((Face face, FileInfo? fileInfo, string fileName) in collection)
|
||||
{
|
||||
if (fileInfo is null)
|
||||
continue;
|
||||
if (face.FaceEncoding is null || face?.Location?.NormalizedPixelPercentage is null || face?.OutputResolution is null)
|
||||
continue;
|
||||
location = Shared.Models.Stateless.Methods.ILocation.GetLocation(face.Location, _Configuration.LocationDigits, _Configuration.LocationFactor, source.Height, source.Width, collection.Count);
|
||||
if (location is null)
|
||||
continue;
|
||||
width = location.Right - location.Left;
|
||||
height = location.Bottom - location.Top;
|
||||
json = JsonSerializer.Serialize(face.FaceEncoding);
|
||||
pixel = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(face.Location, _Configuration.LocationDigits, _Configuration.LocationFactor, face.OutputResolution);
|
||||
rectangle = new Rectangle(location.Left, location.Top, width, height);
|
||||
using (bitmap = new(width, height))
|
||||
{
|
||||
using (graphics = Graphics.FromImage(bitmap))
|
||||
graphics.DrawImage(source, new Rectangle(0, 0, width, height), rectangle, GraphicsUnit.Pixel);
|
||||
propertyItem = GetPropertyItem(userComment, json);
|
||||
bitmap.SetPropertyItem(propertyItem);
|
||||
propertyItem = GetPropertyItem(imageDescription, pixel.ToString());
|
||||
bitmap.SetPropertyItem(propertyItem);
|
||||
propertyItem = GetPropertyItem(software, face.Location.NormalizedPixelPercentage.Value.ToString());
|
||||
bitmap.SetPropertyItem(propertyItem);
|
||||
bitmap.Save(fileInfo.FullName, _ImageCodecInfo, _EncoderParameters);
|
||||
}
|
||||
if (File.Exists(fileName))
|
||||
File.Delete(fileName);
|
||||
location = Shared.Models.Stateless.Methods.ILocation.GetLocation(_Configuration.FaceDistanceHiddenImageFactor, face.Location, _Configuration.LocationDigits, _Configuration.LocationFactor, source.Height, source.Width, collection.Count);
|
||||
if (location is null)
|
||||
continue;
|
||||
width = location.Right - location.Left;
|
||||
height = location.Bottom - location.Top;
|
||||
rectangle = new Rectangle(location.Left, location.Top, width, height);
|
||||
using (bitmap = new(width, height))
|
||||
{
|
||||
using (graphics = Graphics.FromImage(bitmap))
|
||||
graphics.DrawImage(source, new Rectangle(0, 0, width, height), rectangle, GraphicsUnit.Pixel);
|
||||
bitmap.Save(fileName, _HiddenImageCodecInfo, _HiddenEncoderParameters);
|
||||
}
|
||||
File.SetAttributes(fileName, FileAttributes.Hidden);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Face> GetFaces(Item item, Shared.Models.Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation)
|
||||
{
|
||||
List<Face> results = new();
|
||||
if (item.ImageFileHolder is null)
|
||||
throw new NullReferenceException(nameof(item.ImageFileHolder));
|
||||
if (item.ResizedFileHolder is null)
|
||||
throw new NullReferenceException(nameof(item.ResizedFileHolder));
|
||||
FaceRecognitionDotNet.Image? unknownImage;
|
||||
if (!item.ResizedFileHolder.Exists)
|
||||
unknownImage = null;
|
||||
else
|
||||
{
|
||||
try
|
||||
{ unknownImage = FaceRecognition.LoadImageFile(item.ResizedFileHolder.FullName); }
|
||||
catch (Exception)
|
||||
{ unknownImage = null; }
|
||||
}
|
||||
if (unknownImage is null)
|
||||
results.Add(new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, item.RelativePath, i: null, location: null));
|
||||
else
|
||||
{
|
||||
List<(int, Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary<FacePart, FacePoint[]>? FaceParts)> collection;
|
||||
FaceRecognition faceRecognition = new(_Configuration.NumberOfTimesToUpsample, _Configuration.NumberOfJitters, _PredictorModel, _Model, _ModelParameter);
|
||||
collection = faceRecognition.GetCollection(unknownImage, includeFaceEncoding: true, includeFaceParts: true, sortByNormalizedPixelPercentage: true);
|
||||
if (!collection.Any())
|
||||
results.Add(new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, item.RelativePath, i: null, location: null));
|
||||
else
|
||||
{
|
||||
Face face;
|
||||
double[] rawEncoding;
|
||||
Shared.Models.FaceEncoding convertedFaceEncoding;
|
||||
foreach ((int locationIndex, Location location, FaceRecognitionDotNet.FaceEncoding? faceEncoding, Dictionary<FacePart, FacePoint[]>? faceParts) in collection)
|
||||
{
|
||||
face = new(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, item.RelativePath, locationIndex, location);
|
||||
if (faceEncoding is not null)
|
||||
{
|
||||
rawEncoding = faceEncoding.GetRawEncoding();
|
||||
convertedFaceEncoding = new(rawEncoding, faceEncoding.Size);
|
||||
face.SetFaceEncoding(convertedFaceEncoding);
|
||||
}
|
||||
if (faceParts is not null)
|
||||
face.SetFaceParts(faceParts);
|
||||
results.Add(face);
|
||||
}
|
||||
}
|
||||
unknownImage.Dispose();
|
||||
faceRecognition.Dispose();
|
||||
}
|
||||
if (!results.Any())
|
||||
throw new Exception();
|
||||
return results;
|
||||
}
|
||||
|
||||
#pragma warning restore CA1416
|
||||
|
||||
internal List<Face> GetFaces(string dResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Item item, Shared.Models.Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation)
|
||||
{
|
||||
List<Face>? results;
|
||||
if (item.Property?.Id is null)
|
||||
throw new NullReferenceException(nameof(item.Property.Id));
|
||||
if (item.ImageFileHolder is null)
|
||||
throw new NullReferenceException(nameof(item.ImageFileHolder));
|
||||
if (string.IsNullOrEmpty(dResultsFullGroupDirectory))
|
||||
throw new NullReferenceException(nameof(dResultsFullGroupDirectory));
|
||||
string json;
|
||||
int?[] normalizedPixelPercentageCollection;
|
||||
int normalizedPixelPercentageDistinctCount;
|
||||
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 usingRelativePath = Path.Combine(AngleBracketCollection[0].Replace("<>", "[]"), $"{item.ImageFileHolder.NameWithoutExtension}.json");
|
||||
string dCollectionFile = Path.Combine(dResultsFullGroupDirectory, "[]", _Configuration.PropertyConfiguration.ResultAllInOne, $"{item.Property.Id.Value}{item.ImageFileHolder.ExtensionLowered}.json");
|
||||
FileInfo fileInfo = new(dCollectionFile);
|
||||
if (!fileInfo.Exists)
|
||||
{
|
||||
if (File.Exists(usingRelativePath))
|
||||
{
|
||||
File.Move(usingRelativePath, fileInfo.FullName);
|
||||
fileInfo.Refresh();
|
||||
}
|
||||
if (!fileInfo.Exists)
|
||||
{
|
||||
if (fileInfo.Directory?.Parent is null)
|
||||
throw new Exception();
|
||||
string parentCheck = Path.Combine(fileInfo.Directory.Parent.FullName, fileInfo.Name);
|
||||
if (File.Exists(parentCheck))
|
||||
{
|
||||
File.Move(parentCheck, fileInfo.FullName);
|
||||
fileInfo.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_Configuration.ForceFaceLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete")))
|
||||
{
|
||||
File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName);
|
||||
fileInfo.Refresh();
|
||||
}
|
||||
if (_Configuration.ForceFaceLastWriteTimeToCreationTime && fileInfo.Exists && fileInfo.LastWriteTime != fileInfo.CreationTime)
|
||||
{
|
||||
File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime);
|
||||
fileInfo.Refresh();
|
||||
}
|
||||
if (_Configuration.PropertiesChangedForFaces)
|
||||
results = null;
|
||||
else if (!fileInfo.Exists)
|
||||
results = null;
|
||||
else if (_Configuration.CheckDFaceAndUpWriteDates && dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime)
|
||||
results = null;
|
||||
else
|
||||
{
|
||||
json = Shared.Models.Stateless.Methods.IFace.GetJson(fileInfo.FullName);
|
||||
try
|
||||
{
|
||||
results = JsonSerializer.Deserialize<List<Face>>(json);
|
||||
if (results is null)
|
||||
throw new NullReferenceException(nameof(results));
|
||||
if (!_Configuration.ForceFaceLastWriteTimeToCreationTime)
|
||||
{
|
||||
normalizedPixelPercentageCollection = Shared.Models.Stateless.Methods.IFace.GetInts(results);
|
||||
normalizedPixelPercentageDistinctCount = normalizedPixelPercentageCollection.Distinct().Count();
|
||||
if (normalizedPixelPercentageDistinctCount != normalizedPixelPercentageCollection.Length)
|
||||
throw new Exception($"Not distinct! <{fileInfo.FullName}>");
|
||||
}
|
||||
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 = GetFaces(item, property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation);
|
||||
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))
|
||||
subFileTuples.Add(new Tuple<string, DateTime>(nameof(D_Face), DateTime.Now));
|
||||
}
|
||||
if (_Configuration.ForceFaceLastWriteTimeToCreationTime)
|
||||
{
|
||||
results = (from l in results select new Face(_Configuration.LocationDigits, _Configuration.LocationFactor, results.Count, l)).ToList();
|
||||
normalizedPixelPercentageCollection = Shared.Models.Stateless.Methods.IFace.GetInts(results);
|
||||
normalizedPixelPercentageDistinctCount = normalizedPixelPercentageCollection.Distinct().Count();
|
||||
if (normalizedPixelPercentageDistinctCount != normalizedPixelPercentageCollection.Length)
|
||||
throw new Exception($"Not distinct! <{fileInfo.FullName}>");
|
||||
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))
|
||||
{
|
||||
File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime);
|
||||
fileInfo.Refresh();
|
||||
subFileTuples.Add(new Tuple<string, DateTime>(nameof(D_Face), fileInfo.CreationTime));
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
internal void SaveFaces(string dResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Item item, List<Face> faceCollection)
|
||||
{
|
||||
if (item.ImageFileHolder is null)
|
||||
throw new NullReferenceException(nameof(item.ImageFileHolder));
|
||||
if (item.ResizedFileHolder is null)
|
||||
throw new NullReferenceException(nameof(item.ResizedFileHolder));
|
||||
FileInfo fileInfo;
|
||||
bool check = false;
|
||||
string parentCheck;
|
||||
string deterministicHashCodeKeyDisplay;
|
||||
List<(Face, FileInfo?, string)> collection = new();
|
||||
string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) };
|
||||
string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension);
|
||||
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
|
||||
bool facesDirectoryExisted = Directory.Exists(facesDirectory);
|
||||
if (!facesDirectoryExisted)
|
||||
_ = Directory.CreateDirectory(facesDirectory);
|
||||
foreach (Face face in faceCollection)
|
||||
{
|
||||
if (item.Property?.Id is null || face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
|
||||
{
|
||||
collection.Add(new(face, null, string.Empty));
|
||||
continue;
|
||||
}
|
||||
deterministicHashCodeKeyDisplay = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location.NormalizedPixelPercentage.Value);
|
||||
fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKeyDisplay}{item.ImageFileHolder.ExtensionLowered}{_FileNameExtension}"));
|
||||
if (!fileInfo.Exists)
|
||||
{
|
||||
if (fileInfo.Directory?.Parent is null)
|
||||
throw new Exception();
|
||||
parentCheck = Path.Combine(fileInfo.Directory.Parent.FullName, fileInfo.Name);
|
||||
if (File.Exists(parentCheck))
|
||||
File.Delete(parentCheck);
|
||||
}
|
||||
collection.Add(new(face, fileInfo, Path.Combine(facesDirectory, $"{deterministicHashCodeKeyDisplay}{item.ImageFileHolder.ExtensionLowered}{_HiddenFileNameExtension}")));
|
||||
if (_Configuration.OverrideForFaceImages)
|
||||
check = true;
|
||||
else if (!fileInfo.Exists)
|
||||
check = true;
|
||||
else if (_Configuration.CheckDFaceAndUpWriteDates && dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime)
|
||||
check = true;
|
||||
}
|
||||
if (check)
|
||||
SaveFaces(item.ResizedFileHolder, collection);
|
||||
}
|
||||
|
||||
private static bool HasLeftAndRight(Dictionary<string, FacePoint[]> faceParts)
|
||||
{
|
||||
bool result = true;
|
||||
if (!faceParts.ContainsKey(FacePart.LeftEye.ToString()))
|
||||
result = false;
|
||||
else if (!faceParts.ContainsKey(FacePart.RightEye.ToString()))
|
||||
result = false;
|
||||
else if (!faceParts.ContainsKey(FacePart.LeftEyebrow.ToString()))
|
||||
result = false;
|
||||
else if (!faceParts.ContainsKey(FacePart.RightEyebrow.ToString()))
|
||||
result = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
using System.Text.Json;
|
||||
using View_by_Distance.Distance.Models;
|
||||
using View_by_Distance.Face.Models;
|
||||
using View_by_Distance.Instance.Models.Stateless;
|
||||
using View_by_Distance.Metadata.Models;
|
||||
using View_by_Distance.Resize.Models;
|
||||
|
@ -1,4 +1,7 @@
|
||||
using System.Text.Json;
|
||||
using View_by_Distance.Distance.Models;
|
||||
using View_by_Distance.Face.Models;
|
||||
using View_by_Distance.FaceParts.Models;
|
||||
using View_by_Distance.Metadata.Models;
|
||||
using View_by_Distance.Resize.Models;
|
||||
using View_by_Distance.Shared.Models.Stateless;
|
||||
|
@ -1,241 +0,0 @@
|
||||
using ShellProgressBar;
|
||||
using System.Text.Json;
|
||||
using View_by_Distance.FaceRecognitionDotNet;
|
||||
using View_by_Distance.Map.Models;
|
||||
using View_by_Distance.Shared.Models;
|
||||
using View_by_Distance.Shared.Models.Properties;
|
||||
|
||||
namespace View_by_Distance.Instance.Models;
|
||||
|
||||
internal class E_Distance : Shared.Models.Methods.IFaceDistance
|
||||
{
|
||||
|
||||
internal static void SaveFaceDistances(Property.Models.Configuration propertyConfiguration, string eResultsFullGroupDirectory, SortingContainer[] sortingContainers)
|
||||
{
|
||||
string eDistanceContentCollectionDirectory = Path.Combine(eResultsFullGroupDirectory, "([])");
|
||||
if (!Directory.Exists(eDistanceContentCollectionDirectory))
|
||||
_ = Directory.CreateDirectory(eDistanceContentCollectionDirectory);
|
||||
#pragma warning disable
|
||||
string[] results = (from l in sortingContainers select string.Concat(l.Sorting.WithinRange, '\t', l.Sorting.DistancePermyriad, '\t', l.Sorting.DaysDelta, '\t', l.Sorting.Id, '\t', l.Sorting.NormalizedPixelPercentage, '\t', l.Sorting.Older, '\t', l.Face.Mapping.MappingFromItem.Id, '\t', l.Face.Mapping.MappingFromLocation.NormalizedPixelPercentage)).ToArray();
|
||||
#pragma warning restore
|
||||
string eDistanceContentFileName = Path.Combine(eDistanceContentCollectionDirectory, $"{propertyConfiguration.ResultAllInOne}.tvs");
|
||||
File.WriteAllLines(eDistanceContentFileName, results);
|
||||
}
|
||||
|
||||
private static List<Sorting> GetSortingCollection(Map.Models.Configuration configuration, MapLogic mapLogic, List<FaceDistance> faceDistanceEncodings, int faceDistanceContainersLength, int i, FaceDistance faceDistanceEncoding)
|
||||
{
|
||||
List<Sorting> results;
|
||||
List<FaceDistance> faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncoding);
|
||||
if (faceDistanceLengths.Count != faceDistanceContainersLength)
|
||||
throw new NotSupportedException();
|
||||
bool anyLowerThanTolerance = (from l in faceDistanceLengths where l.Length is not null && l.Length.Value != 0 && l.Length.Value < configuration.FaceDistanceTolerance select true).Any();
|
||||
results = mapLogic.GetSortingCollection(i, faceDistanceEncoding, faceDistanceLengths, anyLowerThanTolerance);
|
||||
return results;
|
||||
}
|
||||
|
||||
private static List<SortingContainer> GetSortingContainers(Map.Models.Configuration configuration, Face face, FaceDistance faceDistanceEncoding, List<Sorting> sortingCollection)
|
||||
{
|
||||
List<SortingContainer> results = new();
|
||||
SortingContainer sortingContainer;
|
||||
Sorting[] collection = Shared.Models.Stateless.Methods.ISorting.Sort(sortingCollection);
|
||||
foreach (Sorting sorting in collection)
|
||||
{
|
||||
if (face.Mapping is null || faceDistanceEncoding.NormalizedPixelPercentage is null)
|
||||
throw new NotSupportedException();
|
||||
if (face.Mapping.MappingFromLocation.Confidence < configuration.FaceDistanceMinimumConfidence || sorting.DistancePermyriad > configuration.FaceDistancePermyriad || sorting.DaysDelta > configuration.SortingDaysDeltaTolerance)
|
||||
continue;
|
||||
sortingContainer = new(face, sorting);
|
||||
results.Add(sortingContainer);
|
||||
if (results.Count >= configuration.SortingMaximumPerFaceShouldBeHigh)
|
||||
break;
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static List<FaceDistance> GetFaceDistanceEncodings(FaceDistanceContainer[] faceDistanceContainers)
|
||||
{
|
||||
List<FaceDistance> faceDistanceEncodings = new();
|
||||
foreach (FaceDistanceContainer faceDistanceContainer in faceDistanceContainers)
|
||||
{
|
||||
if (faceDistanceContainer.FaceDistance.Encoding is null)
|
||||
continue;
|
||||
faceDistanceEncodings.Add(faceDistanceContainer.FaceDistance);
|
||||
}
|
||||
return faceDistanceEncodings;
|
||||
}
|
||||
|
||||
internal static SortingContainer[] SetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, Map.Models.Configuration configuration, long ticks, MapLogic mapLogic, List<Face> selectedFilteredFaces)
|
||||
{
|
||||
SortingContainer[] results;
|
||||
List<SortingContainer> collection = new();
|
||||
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
||||
FaceDistanceContainer[] faceDistanceContainers = GetFaceDistanceContainers(selectedFilteredFaces);
|
||||
List<FaceDistance> faceDistanceEncodings = GetFaceDistanceEncodings(faceDistanceContainers);
|
||||
string message = $") {faceDistanceContainers.Length:000} Get Sorting Containers Then Set Face Mapping Sorting Collection - {totalSeconds} total second(s)";
|
||||
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||
selectedFilteredFaces.Clear();
|
||||
using ProgressBar progressBar = new(faceDistanceContainers.Length, message, options);
|
||||
_ = Parallel.For(0, faceDistanceContainers.Length, parallelOptions, (i, state) =>
|
||||
{
|
||||
progressBar.Tick();
|
||||
Face face = faceDistanceContainers[i].Face;
|
||||
if (face.Mapping is null)
|
||||
throw new NotSupportedException();
|
||||
FaceDistance faceDistanceEncoding = faceDistanceContainers[i].FaceDistance;
|
||||
List<Sorting> sortingCollection = GetSortingCollection(configuration, mapLogic, faceDistanceEncodings, faceDistanceContainers.Length, i, faceDistanceEncoding);
|
||||
List<SortingContainer> sortingContainers = GetSortingContainers(configuration, face, faceDistanceEncoding, sortingCollection);
|
||||
lock (collection)
|
||||
collection.AddRange(sortingContainers);
|
||||
lock (face)
|
||||
face.ReleaseFaceDistance();
|
||||
});
|
||||
results = Shared.Models.Stateless.Methods.ISortingContainer.Sort(collection);
|
||||
return results;
|
||||
}
|
||||
|
||||
private static FaceDistanceContainer[] GetFaceDistanceContainers(List<Face> selectedFilteredFaces)
|
||||
{
|
||||
FaceDistanceContainer[] results;
|
||||
FaceDistance faceDistance;
|
||||
FaceDistanceContainer faceDistanceContainer;
|
||||
List<FaceDistanceContainer> collection = new();
|
||||
foreach (Face face in selectedFilteredFaces)
|
||||
{
|
||||
if (face.Mapping is null)
|
||||
throw new NotSupportedException();
|
||||
if (face.FaceDistance?.Encoding is not FaceRecognitionDotNet.FaceEncoding faceEncoding)
|
||||
continue;
|
||||
faceDistance = new(face.Mapping.MappingFromLocation.Confidence, faceEncoding, face.Mapping.MappingFromItem.Id, face.Mapping.MappingFromItem.IsWrongYear, face.Mapping.MappingFromItem.MinimumDateTime, face.Mapping.MappingFromLocation.NormalizedPixelPercentage);
|
||||
faceDistanceContainer = new(face, faceDistance);
|
||||
collection.Add(faceDistanceContainer);
|
||||
}
|
||||
results = (from l in collection orderby l.FaceDistance.Encoding is not null select l).ToArray();
|
||||
if (results.Any() && results[0].FaceDistance.Encoding is null)
|
||||
throw new Exception("Sorting failed!");
|
||||
return results;
|
||||
}
|
||||
|
||||
internal static List<Face> GetSelectedFilteredFaces(List<Face> distinctFilteredFaces)
|
||||
{
|
||||
List<Face> results;
|
||||
Face[] orderedFilteredFaces = (from l in distinctFilteredFaces orderby l.Mapping is not null, l.Mapping?.MappingFromItem.MinimumDateTime descending select l).ToArray();
|
||||
results = orderedFilteredFaces.ToList();
|
||||
return results;
|
||||
}
|
||||
|
||||
internal static void SetFaceDistances(int maxDegreeOfParallelism, long ticks, List<Face> selectedFilteredFaces)
|
||||
{
|
||||
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
||||
string message = $") {selectedFilteredFaces.Count:000} Load Face Encoding - {totalSeconds} total second(s)";
|
||||
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||
using ProgressBar progressBar = new(selectedFilteredFaces.Count, message, options);
|
||||
_ = Parallel.For(0, selectedFilteredFaces.Count, parallelOptions, (i, state) =>
|
||||
{
|
||||
progressBar.Tick();
|
||||
FaceDistance faceDistance;
|
||||
Face face = selectedFilteredFaces[i];
|
||||
FaceRecognitionDotNet.FaceEncoding faceEncoding;
|
||||
if (face.FaceEncoding is null || face.Mapping is null)
|
||||
throw new NotSupportedException();
|
||||
faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
|
||||
faceDistance = new(face.Mapping.MappingFromLocation.Confidence, faceEncoding, face.Mapping.MappingFromItem.Id, face.Mapping.MappingFromItem.IsWrongYear, face.Mapping.MappingFromItem.MinimumDateTime, face.Mapping.MappingFromLocation.NormalizedPixelPercentage);
|
||||
lock (face)
|
||||
face.FaceDistanceAdd(faceDistance);
|
||||
});
|
||||
}
|
||||
|
||||
List<Face> Shared.Models.Methods.IFaceDistance.GetMatchingFaces(double faceDistanceTolerance, string checkFile, List<Face> faces)
|
||||
{
|
||||
List<Face> results = new();
|
||||
Face face;
|
||||
FaceDistance faceDistanceLength;
|
||||
string json = File.ReadAllText(checkFile);
|
||||
List<(Face Face, double Length)> collection = new();
|
||||
Shared.Models.FaceEncoding? modelsFaceEncoding = JsonSerializer.Deserialize<Shared.Models.FaceEncoding>(json);
|
||||
if (modelsFaceEncoding is null)
|
||||
throw new NotSupportedException();
|
||||
FaceRecognitionDotNet.FaceEncoding faceRecognitionDotNetFaceEncoding = FaceRecognition.LoadFaceEncoding(modelsFaceEncoding.RawEncoding);
|
||||
FaceDistance faceDistanceEncoding = new(faceRecognitionDotNetFaceEncoding);
|
||||
FaceDistanceContainer[] faceDistanceContainers = GetFaceDistanceContainers(faces);
|
||||
int faceDistanceContainersLength = faceDistanceContainers.Length;
|
||||
if (faceDistanceContainersLength != faces.Count)
|
||||
throw new NotSupportedException();
|
||||
List<FaceDistance> faceDistanceEncodings = GetFaceDistanceEncodings(faceDistanceContainers);
|
||||
if (faceDistanceEncodings.Count != faces.Count)
|
||||
throw new NotSupportedException();
|
||||
List<FaceDistance> faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncoding);
|
||||
if (faceDistanceLengths.Count != faceDistanceContainersLength)
|
||||
throw new NotSupportedException();
|
||||
for (int i = 0; i < faces.Count; i++)
|
||||
{
|
||||
face = faces[i];
|
||||
faceDistanceLength = faceDistanceLengths[i];
|
||||
if (face.Mapping is null || faceDistanceLength.Length is null)
|
||||
throw new NotSupportedException();
|
||||
if (faceDistanceLength.Length.Value > faceDistanceTolerance)
|
||||
continue;
|
||||
collection.Add(new(face, faceDistanceLength.Length.Value));
|
||||
}
|
||||
if (collection.Any())
|
||||
{
|
||||
collection = (from l in collection orderby l.Length select l).ToList();
|
||||
results.Add(collection[0].Face);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
void Shared.Models.Methods.IFaceDistance.SavePossiblyNewPersonContainers(IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, string facesFileNameExtension, Dictionary<long, PersonContainer> personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer)
|
||||
{
|
||||
char @char;
|
||||
string json;
|
||||
string[] files;
|
||||
string checkFile;
|
||||
string[] segments;
|
||||
const int zero = 0;
|
||||
string personKeyFormatted;
|
||||
string personDisplayDirectory;
|
||||
PersonBirthday personBirthday;
|
||||
string personDisplayDirectoryName;
|
||||
string checkPersonDisplayDirectory;
|
||||
string checkPersonKeyFormattedDirectory;
|
||||
char[] chars = Shared.Models.Stateless.Methods.IAge.GetChars();
|
||||
JsonSerializerOptions jsonSerializerOptions = new() { WriteIndented = true };
|
||||
string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A2_People), "{}");
|
||||
foreach ((string[] personDisplayDirectoryNames, PersonContainer personContainer) in possiblyNewPersonDisplayDirectoryNamesAndPersonContainer)
|
||||
{
|
||||
if (personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any())
|
||||
continue;
|
||||
personBirthday = personContainer.Birthdays[zero];
|
||||
personDisplayDirectoryName = personDisplayDirectoryNames[^1];
|
||||
personDisplayDirectory = Path.Combine(personDisplayDirectoryNames);
|
||||
personKeyFormatted = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(personBirthdayFormat, personBirthday);
|
||||
segments = personDisplayDirectoryName.Split(chars);
|
||||
if (segments.Length != 2)
|
||||
@char = '_';
|
||||
else
|
||||
@char = personDisplayDirectoryName[segments[zero].Length];
|
||||
checkPersonDisplayDirectory = Path.Combine(a2PeopleSingletonDirectory, @char.ToString(), personDisplayDirectoryName);
|
||||
checkPersonKeyFormattedDirectory = Path.Combine(checkPersonDisplayDirectory, personKeyFormatted);
|
||||
if (Directory.Exists(checkPersonKeyFormattedDirectory))
|
||||
continue;
|
||||
_ = Directory.CreateDirectory(checkPersonKeyFormattedDirectory);
|
||||
checkFile = Path.Combine(checkPersonKeyFormattedDirectory, $"{personKeyFormatted}.json");
|
||||
json = JsonSerializer.Serialize(personContainer.Person, jsonSerializerOptions);
|
||||
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true);
|
||||
if (!Directory.Exists(personDisplayDirectory))
|
||||
continue;
|
||||
files = Directory.GetFiles(personDisplayDirectory, $"*{facesFileNameExtension}", SearchOption.TopDirectoryOnly);
|
||||
foreach (string file in files)
|
||||
{
|
||||
checkFile = Path.Combine(checkPersonDisplayDirectory, Path.GetFileName(file));
|
||||
if (File.Exists(checkFile))
|
||||
continue;
|
||||
File.Copy(files[0], checkFile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -67,7 +67,7 @@ public class G2_Identify : Shared.Models.Properties.IIdentify, IIdentify
|
||||
return result;
|
||||
}
|
||||
|
||||
private void CheckLastWriteTimes(IsEnvironment isEnvironment, Property.Models.Configuration configuration, string facesFileNameExtension, FileInfo named, string g2IdentifySingletonDirectory)
|
||||
private void CheckLastWriteTimes(IsEnvironment isEnvironment, string facesFileNameExtension, FileInfo named, string g2IdentifySingletonDirectory)
|
||||
{
|
||||
string json;
|
||||
FileInfo fileInfo;
|
||||
@ -88,7 +88,13 @@ public class G2_Identify : Shared.Models.Properties.IIdentify, IIdentify
|
||||
}
|
||||
json = File.ReadAllText(named.FullName);
|
||||
Dictionary<string, string[]> resultKeyValuePairs = new();
|
||||
PersonContainer[] personContainers = A2_People.GetPersonContainers(_Configuration, configuration, facesFileNameExtension);
|
||||
string rootDirectory = _Configuration.PropertyConfiguration.RootDirectory;
|
||||
string peopleRootDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People));
|
||||
string rootResultsDirectory = Path.GetDirectoryName(Path.GetDirectoryName(peopleRootDirectory));
|
||||
if (rootResultsDirectory is null)
|
||||
throw new Exception();
|
||||
Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory);
|
||||
PersonContainer[] personContainers = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers(storage, _Configuration.LocationDigits, _Configuration.PersonBirthdayFormat, facesFileNameExtension);
|
||||
string[] peopleBirthDates = (from l in personContainers select Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, l.Person.Birthday)).ToArray();
|
||||
Dictionary<string, string[]> sourceKeyValuePairs = JsonSerializer.Deserialize<Dictionary<string, string[]>>(json);
|
||||
foreach (KeyValuePair<string, string[]> keyValuePair in sourceKeyValuePairs)
|
||||
@ -125,7 +131,7 @@ public class G2_Identify : Shared.Models.Properties.IIdentify, IIdentify
|
||||
string g2IdentifySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(G2_Identify), "[]");
|
||||
string jsonRootDirectory = Path.Combine(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, " - Copied"), string.Concat(directoryName, " - 4) Info"), _Configuration.PropertyConfiguration.DateGroup, "[]");
|
||||
if (named is not null && named.Exists)
|
||||
CheckLastWriteTimes(isEnvironment, configuration, facesFileNameExtension, named, g2IdentifySingletonDirectory);
|
||||
CheckLastWriteTimes(isEnvironment, facesFileNameExtension, named, g2IdentifySingletonDirectory);
|
||||
if (Directory.Exists(jsonRootDirectory))
|
||||
{
|
||||
jsonFiles = Directory.GetFiles(jsonRootDirectory, "*.json", SearchOption.AllDirectories);
|
||||
|
@ -53,7 +53,7 @@
|
||||
"CheckDFaceAndUpWriteDates": true,
|
||||
"CheckJsonForDistanceResults": false,
|
||||
"CrossDirectoryMaxItemsInDistanceCollection": 7,
|
||||
"DateGroup": "2022-09-15",
|
||||
"DateGroup": "2022-09-22",
|
||||
"DistanceFactor": 8,
|
||||
"FaceDistanceHiddenImageFactor": 2,
|
||||
"FaceDistanceMinimumConfidence": 0.8,
|
||||
@ -108,7 +108,7 @@
|
||||
"ResultSingleton": "{}",
|
||||
"Reverse": false,
|
||||
"xRootDirectory": "C:/Tmp/phares/Pictures",
|
||||
"RootDirectory": "C:/Tmp/Phares/Compare/Images 2022-09-15 - 7390c13 - III",
|
||||
"RootDirectory": "F:/Tmp/Phares/Compare/Images 2022-09-22 - fb1c68e - III",
|
||||
"SaveFullYearOfRandomFiles": true,
|
||||
"SaveResizedSubFiles": true,
|
||||
"SkipSearch": false,
|
||||
|
@ -53,7 +53,7 @@
|
||||
"CheckDFaceAndUpWriteDates": true,
|
||||
"CheckJsonForDistanceResults": false,
|
||||
"CrossDirectoryMaxItemsInDistanceCollection": 7,
|
||||
"DateGroup": "2022-09-15",
|
||||
"DateGroup": "2022-09-22",
|
||||
"DistanceFactor": 8,
|
||||
"FaceDistanceHiddenImageFactor": 2,
|
||||
"FaceDistanceMinimumConfidence": 0.8,
|
||||
|
@ -53,7 +53,7 @@
|
||||
"CheckDFaceAndUpWriteDates": true,
|
||||
"CheckJsonForDistanceResults": false,
|
||||
"CrossDirectoryMaxItemsInDistanceCollection": 7,
|
||||
"DateGroup": "2022-09-15",
|
||||
"DateGroup": "2022-09-22",
|
||||
"DistanceFactor": 8,
|
||||
"FaceDistanceHiddenImageFactor": 2,
|
||||
"FaceDistanceMinimumConfidence": 0.8,
|
||||
|
Reference in New Issue
Block a user