Split out classes

This commit is contained in:
2022-09-23 09:26:15 -07:00
parent fb1c68e1f5
commit e64c713926
30 changed files with 823 additions and 320 deletions

View File

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

View File

@ -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" />

View File

@ -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;
}
}
{ }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,

View File

@ -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,

View File

@ -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,