Split out classes

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

3
.txt
View File

@ -1,5 +1,8 @@
mklink /J "L:\Git\View-by-Distance-MKLink-Console\Compare" "L:\Git\View-by-Distance\Compare"
mklink /J "L:\Git\View-by-Distance-MKLink-Console\Date-Group" "L:\Git\View-by-Distance\Date-Group"
mklink /J "L:\Git\View-by-Distance-MKLink-Console\Distance" "L:\Git\View-by-Distance\Distance"
mklink /J "L:\Git\View-by-Distance-MKLink-Console\Face" "L:\Git\View-by-Distance\Face"
mklink /J "L:\Git\View-by-Distance-MKLink-Console\FaceParts" "L:\Git\View-by-Distance\FaceParts"
mklink /J "L:\Git\View-by-Distance-MKLink-Console\Instance" "L:\Git\View-by-Distance\Instance"
mklink /J "L:\Git\View-by-Distance-MKLink-Console\Metadata" "L:\Git\View-by-Distance\Metadata"
mklink /J "L:\Git\View-by-Distance-MKLink-Console\Not-Copy-Copy" "L:\Git\View-by-Distance\Not-Copy-Copy"

View File

@ -55,9 +55,10 @@ public class Compare
string outputExtension = ".jpg";
PredictorModel? predictorModel = null;
string eResultsFullGroupDirectory = string.Empty;
string a2PeopleSingletonDirectory = string.Empty;
Map.Models.Configuration? mapConfiguration = null;
Shared.Models.PersonContainer[] personContainers = Array.Empty<Shared.Models.PersonContainer>();
Map.Models.MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, propertyConfiguration, mapConfiguration, outputExtension, ticks, personContainers, eResultsFullGroupDirectory);
Map.Models.MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, propertyConfiguration, mapConfiguration, outputExtension, ticks, personContainers, a2PeopleSingletonDirectory, eResultsFullGroupDirectory);
A_Property propertyLogic = GetPropertyLogic(reverse, model, outputExtension, predictorModel, mapLogic);
foreach (string spelling in configuration.Spelling)
{

View File

@ -79,7 +79,7 @@
"/zzz Phares Slides/Slides 2015-06-10/Magazine 01"
],
"Configuration": {
"DateGroup": "2022-09-15",
"DateGroup": "2022-09-22",
"DiffPropertyDirectory": "",
"FileNameDirectorySeparator": ".Z.",
"ForcePropertyLastWriteTimeToCreationTime": false,
@ -87,20 +87,20 @@
"Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]",
"PopulatePropertyId": true,
"PropertiesChangedForProperty": false,
"RootDirectory": "C:/Tmp/Phares/Compare/Images 2022-09-15 - 7390c13 - III",
"RootDirectory": "C:/Tmp/Phares/Compare/Images 2022-09-22 - fb1c68e - III",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF"
],
"PropertyContentCollectionFiles": [
"/Images 2022-09-15 - 7390c13 - III - Results/A) Property/2022-09-15/[()]/637869381676042455.json",
"/Not-Copy-Copy/Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-09-15/[()]/637869733124119330.json",
"/Not-Copy-Copy/Images 2018-12-25 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-09-15/[()]/637869734240700328.json",
"/Not-Copy-Copy/Images 2018-05-12 - b01d4763d8853b6d6057a3870b2723449726da75 - Not-Copy-Copy - Results/A) Property/2022-09-15/[()]/637869734970730630.json",
"/Not-Copy-Copy/Images 2013-12-15 - d02c8791fa0b130c0bce2d39ee684e50f7ee7a97 - Not-Copy-Copy - Results/A) Property/2022-09-15/[()]/637869743752078399.json",
"/Not-Copy-Copy - Delta/Amazon Drive - Results/A) Property/2022-09-15/[()]/637869744751177715.json",
"/Not-Copy-Copy - Delta/Blackberry - Results/A) Property/2022-09-15/[()]/637869745134124462.json"
"/Images 2022-09-22 - fb1c68e - III - Results/A) Property/2022-09-22/[()]/637869381676042455.json",
"/Not-Copy-Copy/Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-09-22/[()]/637869733124119330.json",
"/Not-Copy-Copy/Images 2018-12-25 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-09-22/[()]/637869734240700328.json",
"/Not-Copy-Copy/Images 2018-05-12 - b01d4763d8853b6d6057a3870b2723449726da75 - Not-Copy-Copy - Results/A) Property/2022-09-22/[()]/637869734970730630.json",
"/Not-Copy-Copy/Images 2013-12-15 - d02c8791fa0b130c0bce2d39ee684e50f7ee7a97 - Not-Copy-Copy - Results/A) Property/2022-09-22/[()]/637869743752078399.json",
"/Not-Copy-Copy - Delta/Amazon Drive - Results/A) Property/2022-09-22/[()]/637869744751177715.json",
"/Not-Copy-Copy - Delta/Blackberry - Results/A) Property/2022-09-22/[()]/637869745134124462.json"
],
"ValidImageFormatExtensions": [
".bmp",

View File

@ -50,7 +50,7 @@
"WorkingDirectoryName": "PharesApps",
"Windows": {
"Configuration": {
"DateGroup": "2022-09-15",
"DateGroup": "2022-09-22",
"DiffPropertyDirectory": "",
"FileNameDirectorySeparator": ".Z.",
"ForcePropertyLastWriteTimeToCreationTime": false,
@ -94,13 +94,13 @@
".GIF"
],
"PropertyContentCollectionFiles": [
"/Images 2022-09-15 - 7390c13 - III - Results/A) Property/2022-09-15/[()]/637869381676042455.json",
"/Not-Copy-Copy/Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-09-15/[()]/637869733124119330.json",
"/Not-Copy-Copy/Images 2018-12-25 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-09-15/[()]/637869734240700328.json",
"/Not-Copy-Copy/Images 2018-05-12 - b01d4763d8853b6d6057a3870b2723449726da75 - Not-Copy-Copy - Results/A) Property/2022-09-15/[()]/637869734970730630.json",
"/Not-Copy-Copy/Images 2013-12-15 - d02c8791fa0b130c0bce2d39ee684e50f7ee7a97 - Not-Copy-Copy - Results/A) Property/2022-09-15/[()]/637869743752078399.json",
"/Not-Copy-Copy - Delta/Amazon Drive - Results/A) Property/2022-09-15/[()]/637869744751177715.json",
"/Not-Copy-Copy - Delta/Blackberry - Results/A) Property/2022-09-15/[()]/637869745134124462.json"
"/Images 2022-09-22 - fb1c68e - III - Results/A) Property/2022-09-22/[()]/637869381676042455.json",
"/Not-Copy-Copy/Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-09-22/[()]/637869733124119330.json",
"/Not-Copy-Copy/Images 2018-12-25 - 34a9240ac28b52da97428d7725153a80a757ee6b - Not-Copy-Copy - Results/A) Property/2022-09-22/[()]/637869734240700328.json",
"/Not-Copy-Copy/Images 2018-05-12 - b01d4763d8853b6d6057a3870b2723449726da75 - Not-Copy-Copy - Results/A) Property/2022-09-22/[()]/637869734970730630.json",
"/Not-Copy-Copy/Images 2013-12-15 - d02c8791fa0b130c0bce2d39ee684e50f7ee7a97 - Not-Copy-Copy - Results/A) Property/2022-09-22/[()]/637869743752078399.json",
"/Not-Copy-Copy - Delta/Amazon Drive - Results/A) Property/2022-09-22/[()]/637869744751177715.json",
"/Not-Copy-Copy - Delta/Blackberry - Results/A) Property/2022-09-22/[()]/637869745134124462.json"
],
"ValidImageFormatExtensions": [
".bmp",

View File

@ -55,7 +55,7 @@
"ByHash": false,
"BySeason": false,
"ByWeek": false,
"DateGroup": "2022-09-15",
"DateGroup": "2022-09-22",
"FileNameDirectorySeparator": ".Z.",
"ForcePropertyLastWriteTimeToCreationTime": false,
"KeepFullPath": false,
@ -63,7 +63,7 @@
"Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]",
"PopulatePropertyId": true,
"PropertiesChangedForProperty": false,
"RootDirectory": "C:/Tmp/Phares/Compare/Images 2022-09-15 - 7390c13 - III",
"RootDirectory": "C:/Tmp/Phares/Compare/Images 2022-09-22 - fb1c68e - III",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",

52
Distance/Distance.csproj Normal file
View File

@ -0,0 +1,52 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable>
<OutputType>library</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<PackageId>Phares.View.by.Distance.Distance</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>6.0.100.1</Version>
<Authors>Mike Phares</Authors>
<Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<PropertyGroup>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
</PropertyGroup>
<PropertyGroup Condition="'$(IsWindows)'=='true'">
<DefineConstants>Windows</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsOSX)'=='true'">
<DefineConstants>OSX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsLinux)'=='true'">
<DefineConstants>Linux</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'browser-wasm'">
<SupportedPlatform Include="browser" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.13.14" />
<PackageReference Include="MetadataExtractor" Version="2.7.1" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="ShellProgressBar" Version="5.1.0" />
<PackageReference Include="WindowsShortcutFactory" Version="1.0.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Text.Json" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
<ProjectReference Include="..\Map\Map.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,10 @@
namespace View_by_Distance.Distance.Models.Stateless;
internal static class SerilogExtensionMethods
{
internal static void Warn(this Serilog.ILogger log, string messageTemplate) => log.Warning(messageTemplate);
internal static void Info(this Serilog.ILogger log, string messageTemplate) => log.Information(messageTemplate);
}

View File

@ -5,12 +5,12 @@ 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;
namespace View_by_Distance.Distance.Models;
internal class E_Distance : Shared.Models.Methods.IFaceDistance
public class E_Distance : Shared.Models.Methods.IFaceDistance
{
internal static void SaveFaceDistances(Property.Models.Configuration propertyConfiguration, string eResultsFullGroupDirectory, SortingContainer[] sortingContainers)
public static void SaveFaceDistances(Property.Models.Configuration propertyConfiguration, string eResultsFullGroupDirectory, SortingContainer[] sortingContainers)
{
string eDistanceContentCollectionDirectory = Path.Combine(eResultsFullGroupDirectory, "([])");
if (!Directory.Exists(eDistanceContentCollectionDirectory))
@ -22,7 +22,7 @@ internal class E_Distance : Shared.Models.Methods.IFaceDistance
File.WriteAllLines(eDistanceContentFileName, results);
}
private static List<Sorting> GetSortingCollection(Map.Models.Configuration configuration, MapLogic mapLogic, List<FaceDistance> faceDistanceEncodings, int faceDistanceContainersLength, int i, FaceDistance faceDistanceEncoding)
private static List<Sorting> GetSortingCollection(Configuration configuration, MapLogic mapLogic, List<FaceDistance> faceDistanceEncodings, int faceDistanceContainersLength, int i, FaceDistance faceDistanceEncoding)
{
List<Sorting> results;
List<FaceDistance> faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncoding);
@ -33,7 +33,7 @@ internal class E_Distance : Shared.Models.Methods.IFaceDistance
return results;
}
private static List<SortingContainer> GetSortingContainers(Map.Models.Configuration configuration, Face face, FaceDistance faceDistanceEncoding, List<Sorting> sortingCollection)
private static List<SortingContainer> GetSortingContainers(Configuration configuration, Face face, FaceDistance faceDistanceEncoding, List<Sorting> sortingCollection)
{
List<SortingContainer> results = new();
SortingContainer sortingContainer;
@ -64,7 +64,29 @@ internal class E_Distance : Shared.Models.Methods.IFaceDistance
return faceDistanceEncodings;
}
internal static SortingContainer[] SetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, Map.Models.Configuration configuration, long ticks, MapLogic mapLogic, List<Face> selectedFilteredFaces)
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;
}
public static SortingContainer[] SetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, Configuration configuration, long ticks, MapLogic mapLogic, List<Face> selectedFilteredFaces)
{
SortingContainer[] results;
List<SortingContainer> collection = new();
@ -94,29 +116,7 @@ internal class E_Distance : Shared.Models.Methods.IFaceDistance
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)
public 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();
@ -124,7 +124,7 @@ internal class E_Distance : Shared.Models.Methods.IFaceDistance
return results;
}
internal static void SetFaceDistances(int maxDegreeOfParallelism, long ticks, List<Face> selectedFilteredFaces)
public 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 };
@ -186,7 +186,7 @@ internal class E_Distance : Shared.Models.Methods.IFaceDistance
return results;
}
void Shared.Models.Methods.IFaceDistance.SavePossiblyNewPersonContainers(IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, string facesFileNameExtension, Dictionary<long, PersonContainer> personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer)
void Shared.Models.Methods.IFaceDistance.SavePossiblyNewPersonContainers(IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, string facesFileNameExtension, string a2PeopleSingletonDirectory, Dictionary<long, PersonContainer> personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer)
{
char @char;
string json;
@ -202,7 +202,6 @@ internal class E_Distance : Shared.Models.Methods.IFaceDistance
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())

49
Face/Face.csproj Normal file
View File

@ -0,0 +1,49 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable>
<OutputType>library</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<PackageId>Phares.View.by.Distance.Face</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>6.0.100.1</Version>
<Authors>Mike Phares</Authors>
<Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<PropertyGroup>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
</PropertyGroup>
<PropertyGroup Condition="'$(IsWindows)'=='true'">
<DefineConstants>Windows</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsOSX)'=='true'">
<DefineConstants>OSX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsLinux)'=='true'">
<DefineConstants>Linux</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'browser-wasm'">
<SupportedPlatform Include="browser" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="2.10.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Text.Json" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" />
<ProjectReference Include="..\Metadata\Metadata.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Resize\Resize.csproj" />
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,10 @@
namespace View_by_Distance.Face.Models.Stateless;
internal static class SerilogExtensionMethods
{
internal static void Warn(this Serilog.ILogger log, string messageTemplate) => log.Warning(messageTemplate);
internal static void Info(this Serilog.ILogger log, string messageTemplate) => log.Information(messageTemplate);
}

View File

@ -1,5 +1,4 @@
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Reflection;
using System.Text.Json;
@ -11,7 +10,7 @@ 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;
namespace View_by_Distance.Face.Models;
/// <summary>
// List<D_Faces>
@ -19,7 +18,7 @@ namespace View_by_Distance.Instance.Models;
public class D_Face
{
internal List<string> AngleBracketCollection { get; }
public List<string> AngleBracketCollection { get; }
protected readonly string _FileNameExtension;
public string FileNameExtension => _FileNameExtension;
@ -40,21 +39,60 @@ public class D_Face
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)
private readonly bool _CheckDFaceAndUpWriteDates;
private readonly int _FaceDistanceHiddenImageFactor;
private readonly bool _ForceFaceLastWriteTimeToCreationTime;
private readonly int _LocationDigits;
private readonly int _LocationFactor;
private readonly int _NumberOfJitters;
private readonly int _NumberOfTimesToUpsample;
private readonly bool _OverrideForFaceImages;
private readonly bool _PropertiesChangedForFaces;
public D_Face(
string argZero,
bool checkDFaceAndUpWriteDates,
Configuration configuration,
EncoderParameters encoderParameters,
int faceDistanceHiddenImageFactor,
string filenameExtension,
bool forceFaceLastWriteTimeToCreationTime,
EncoderParameters hiddenEncoderParameters,
string hiddenFileNameExtension,
ImageCodecInfo hiddenImageCodecInfo,
ImageCodecInfo imageCodecInfo,
int locationDigits,
int locationFactor,
Model model,
ModelParameter modelParameter,
int numberOfJitters,
int numberOfTimesToUpsample,
bool overrideForFaceImages,
PredictorModel predictorModel,
bool propertiesChangedForFaces)
{
_Model = model;
_ArgZero = argZero;
_Configuration = configuration;
_ImageCodecInfo = imageCodecInfo;
_LocationDigits = locationDigits;
_LocationFactor = locationFactor;
_ModelParameter = modelParameter;
_PredictorModel = predictorModel;
_NumberOfJitters = numberOfJitters;
_EncoderParameters = encoderParameters;
_FileNameExtension = filenameExtension;
_Log = Serilog.Log.ForContext<D_Face>();
AngleBracketCollection = new List<string>();
_HiddenImageCodecInfo = hiddenImageCodecInfo;
_OverrideForFaceImages = overrideForFaceImages;
_HiddenEncoderParameters = hiddenEncoderParameters;
_HiddenFileNameExtension = hiddenFileNameExtension;
_NumberOfTimesToUpsample = numberOfTimesToUpsample;
_CheckDFaceAndUpWriteDates = checkDFaceAndUpWriteDates;
_PropertiesChangedForFaces = propertiesChangedForFaces;
_FaceDistanceHiddenImageFactor = faceDistanceHiddenImageFactor;
_ForceFaceLastWriteTimeToCreationTime = forceFaceLastWriteTimeToCreationTime;
ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, Array.Empty<Type>(), null);
if (constructorInfo is null)
throw new Exception();
@ -62,25 +100,6 @@ public class D_Face
_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 });
@ -89,67 +108,6 @@ public class D_Face
#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];
@ -170,7 +128,7 @@ public class D_Face
return result;
}
private void SaveFaces(FileHolder resizedFileHolder, List<(Face, FileInfo?, string)> collection)
private void SaveFaces(FileHolder resizedFileHolder, List<(Shared.Models.Face, FileInfo?, string)> collection)
{
int pixel;
int width;
@ -181,23 +139,21 @@ public class D_Face
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)
foreach ((Shared.Models.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);
location = Shared.Models.Stateless.Methods.ILocation.GetLocation(face.Location, _LocationDigits, _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);
pixel = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(face.Location, _LocationDigits, _LocationFactor, face.OutputResolution);
rectangle = new Rectangle(location.Left, location.Top, width, height);
using (bitmap = new(width, height))
{
@ -205,15 +161,11 @@ public class D_Face
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);
location = Shared.Models.Stateless.Methods.ILocation.GetLocation(_FaceDistanceHiddenImageFactor, face.Location, _LocationDigits, _LocationFactor, source.Height, source.Width, collection.Count);
if (location is null)
continue;
width = location.Right - location.Left;
@ -229,9 +181,9 @@ public class D_Face
}
}
private List<Face> GetFaces(Item item, Shared.Models.Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation)
private List<Shared.Models.Face> GetFaces(Item item, Shared.Models.Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation)
{
List<Face> results = new();
List<Shared.Models.Face> results = new();
if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder));
if (item.ResizedFileHolder is null)
@ -251,14 +203,14 @@ public class D_Face
else
{
List<(int, Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary<FacePart, FacePoint[]>? FaceParts)> collection;
FaceRecognition faceRecognition = new(_Configuration.NumberOfTimesToUpsample, _Configuration.NumberOfJitters, _PredictorModel, _Model, _ModelParameter);
FaceRecognition faceRecognition = new(_NumberOfTimesToUpsample, _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.Face face;
Shared.Models.FaceEncoding convertedFaceEncoding;
foreach ((int locationIndex, Location location, FaceRecognitionDotNet.FaceEncoding? faceEncoding, Dictionary<FacePart, FacePoint[]>? faceParts) in collection)
{
@ -284,9 +236,9 @@ public class D_Face
#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)
public List<Shared.Models.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;
List<Shared.Models.Face>? results;
if (item.Property?.Id is null)
throw new NullReferenceException(nameof(item.Property.Id));
if (item.ImageFileHolder is null)
@ -299,7 +251,7 @@ public class D_Face
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");
string dCollectionFile = Path.Combine(dResultsFullGroupDirectory, "[]", _Configuration.ResultAllInOne, $"{item.Property.Id.Value}{item.ImageFileHolder.ExtensionLowered}.json");
FileInfo fileInfo = new(dCollectionFile);
if (!fileInfo.Exists)
{
@ -320,31 +272,31 @@ public class D_Face
}
}
}
if (_Configuration.ForceFaceLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete")))
if (_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)
if (_ForceFaceLastWriteTimeToCreationTime && fileInfo.Exists && fileInfo.LastWriteTime != fileInfo.CreationTime)
{
File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime);
fileInfo.Refresh();
}
if (_Configuration.PropertiesChangedForFaces)
if (_PropertiesChangedForFaces)
results = null;
else if (!fileInfo.Exists)
results = null;
else if (_Configuration.CheckDFaceAndUpWriteDates && dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime)
else if (_CheckDFaceAndUpWriteDates && dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime)
results = null;
else
{
json = Shared.Models.Stateless.Methods.IFace.GetJson(fileInfo.FullName);
try
{
results = JsonSerializer.Deserialize<List<Face>>(json);
results = JsonSerializer.Deserialize<List<Shared.Models.Face>>(json);
if (results is null)
throw new NullReferenceException(nameof(results));
if (!_Configuration.ForceFaceLastWriteTimeToCreationTime)
if (!_ForceFaceLastWriteTimeToCreationTime)
{
normalizedPixelPercentageCollection = Shared.Models.Stateless.Methods.IFace.GetInts(results);
normalizedPixelPercentageDistinctCount = normalizedPixelPercentageCollection.Distinct().Count();
@ -368,9 +320,9 @@ public class D_Face
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)
if (_ForceFaceLastWriteTimeToCreationTime)
{
results = (from l in results select new Face(_Configuration.LocationDigits, _Configuration.LocationFactor, results.Count, l)).ToList();
results = (from l in results select new Shared.Models.Face(_LocationDigits, _LocationFactor, results.Count, l)).ToList();
normalizedPixelPercentageCollection = Shared.Models.Stateless.Methods.IFace.GetInts(results);
normalizedPixelPercentageDistinctCount = normalizedPixelPercentageCollection.Distinct().Count();
if (normalizedPixelPercentageDistinctCount != normalizedPixelPercentageCollection.Length)
@ -388,7 +340,7 @@ public class D_Face
return results;
}
internal void SaveFaces(string dResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Item item, List<Face> faceCollection)
public void SaveFaces(string dResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Item item, List<Shared.Models.Face> faceCollection)
{
if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder));
@ -398,14 +350,13 @@ public class D_Face
bool check = false;
string parentCheck;
string deterministicHashCodeKeyDisplay;
List<(Face, FileInfo?, string)> collection = new();
List<(Shared.Models.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)
if (!Directory.Exists(facesDirectory))
_ = Directory.CreateDirectory(facesDirectory);
foreach (Face face in faceCollection)
foreach (Shared.Models.Face face in faceCollection)
{
if (item.Property?.Id is null || face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
{
@ -423,29 +374,15 @@ public class D_Face
File.Delete(parentCheck);
}
collection.Add(new(face, fileInfo, Path.Combine(facesDirectory, $"{deterministicHashCodeKeyDisplay}{item.ImageFileHolder.ExtensionLowered}{_HiddenFileNameExtension}")));
if (_Configuration.OverrideForFaceImages)
if (_OverrideForFaceImages)
check = true;
else if (!fileInfo.Exists)
check = true;
else if (_Configuration.CheckDFaceAndUpWriteDates && dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime)
else if (_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

@ -0,0 +1,50 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable>
<OutputType>library</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<PackageId>Phares.View.by.Distance.FaceParts</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>6.0.100.1</Version>
<Authors>Mike Phares</Authors>
<Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<PropertyGroup>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
</PropertyGroup>
<PropertyGroup Condition="'$(IsWindows)'=='true'">
<DefineConstants>Windows</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsOSX)'=='true'">
<DefineConstants>OSX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsLinux)'=='true'">
<DefineConstants>Linux</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'browser-wasm'">
<SupportedPlatform Include="browser" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="2.10.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Text.Json" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" />
<ProjectReference Include="..\Face\Face.csproj" />
<ProjectReference Include="..\Metadata\Metadata.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Resize\Resize.csproj" />
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,10 @@
namespace View_by_Distance.FaceParts.Models.Stateless;
internal static class SerilogExtensionMethods
{
internal static void Warn(this Serilog.ILogger log, string messageTemplate) => log.Warning(messageTemplate);
internal static void Info(this Serilog.ILogger log, string messageTemplate) => log.Information(messageTemplate);
}

View File

@ -1,35 +1,39 @@
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Text.Json;
using View_by_Distance.Face.Models;
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;
namespace View_by_Distance.FaceParts.Models;
/// <summary>
// *.png
/// </summary>
internal class D2_FaceParts
public 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 bool _CheckDFaceAndUpWriteDates;
private readonly bool _OverrideForFaceLandmarkImages;
private readonly EncoderParameters _EncoderParameters;
internal D2_FaceParts(Configuration configuration, ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension)
public D2_FaceParts(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension, bool checkDFaceAndUpWriteDates, bool overrideForFaceLandmarkImages)
{
_Configuration = configuration;
_ImageCodecInfo = imageCodecInfo;
_EncoderParameters = encoderParameters;
_FileNameExtension = filenameExtension;
_Log = Serilog.Log.ForContext<D2_FaceParts>();
_CheckDFaceAndUpWriteDates = checkDFaceAndUpWriteDates;
_OverrideForFaceLandmarkImages = overrideForFaceLandmarkImages;
}
public override string ToString()
@ -38,19 +42,99 @@ internal class D2_FaceParts
return result;
}
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;
}
}
#pragma warning disable CA1416
private 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 Bitmap RotateBitmap(Image image, float angle)
{
Bitmap result;
Bitmap bitmap = new(image);
result = D_Face.RotateBitmap(bitmap, angle);
result = 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)
private void SaveFaceParts(int pointSize, IFileHolder resizedFileHolder, bool saveRotated, List<(Shared.Models.Face, string, string)> collection)
{
int x;
int y;
@ -58,7 +142,7 @@ internal class D2_FaceParts
int width;
int height;
Bitmap rotated;
foreach ((Face face, string fileName, string rotatedFileName) in collection)
foreach ((Shared.Models.Face face, string fileName, string rotatedFileName) in collection)
{
if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
continue;
@ -118,7 +202,7 @@ internal class D2_FaceParts
#pragma warning restore CA1416
internal void SaveFaceLandmarkImages(string facesDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Item item, List<Face> faceCollection, bool saveRotated)
public void SaveFaceLandmarkImages(string facesDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Item item, List<Shared.Models.Face> faceCollection, bool saveRotated)
{
if (item.ImageFileHolder is null)
throw new NullReferenceException(nameof(item.ImageFileHolder));
@ -133,12 +217,12 @@ internal class D2_FaceParts
long ticks = DateTime.Now.Ticks;
bool updateDateWhenMatches = false;
string deterministicHashCodeKeyDisplay;
List<(Face, string, string)> collection = new();
List<(Shared.Models.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)
foreach (Shared.Models.Face face in faceCollection)
{
if (item.Property?.Id is null || face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null)
{
@ -161,13 +245,13 @@ internal class D2_FaceParts
collection.Add(new(face, fileInfo.FullName, rotatedFileInfo.FullName));
if (check)
continue;
else if (_Configuration.OverrideForFaceLandmarkImages)
else if (_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)
else if (_CheckDFaceAndUpWriteDates && dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime)
check = true;
if (check && !updateDateWhenMatches)
{

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

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

View File

@ -28,7 +28,7 @@ public class MapLogic
private readonly string _FacesHiddenFileNameExtension;
private readonly string _EDistanceContentTicksDirectory;
public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, string facesFileNameExtension, string facesHiddenFileNameExtension, string facePartsFileNameExtension, long ticks, PersonContainer[] personContainers, string eResultsFullGroupDirectory, List<Face> distinctFilteredFaces, Shared.Models.Methods.IFaceDistance? faceDistance)
public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, string facesFileNameExtension, string facesHiddenFileNameExtension, string facePartsFileNameExtension, long ticks, PersonContainer[] personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory, List<Face> distinctFilteredFaces, Shared.Models.Methods.IFaceDistance? faceDistance)
{
_Ticks = ticks;
_Configuration = configuration;
@ -49,7 +49,6 @@ public class MapLogic
Dictionary<int, List<int>> skipCollection = new();
List<PersonContainer> notMappedPersonContainers = new();
Dictionary<long, PersonContainer> personKeyToPersonContainer = new();
string eDistanceContentDirectory = Path.Combine(eResultsFullGroupDirectory, "()");
string? rootDirectoryParent = Path.GetDirectoryName(propertyConfiguration.RootDirectory);
Dictionary<long, (long LCL, long Minimum, long Maximum, long UCL)> personKeyToRanges = new();
string eDistanceContentTicksDirectory = Path.Combine(eDistanceContentDirectory, $"({ticks})");
@ -71,6 +70,7 @@ public class MapLogic
facesFileNameExtension,
ticks,
personContainerCollection,
a2PeopleSingletonDirectory,
eDistanceContentDirectory,
distinctFilteredFaces,
faceDistance,
@ -102,8 +102,8 @@ public class MapLogic
_IdThenNormalizedPixelPercentageToPersonContainers = idThenNormalizedPixelPercentageToPersonContainers;
}
public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, string outputExtension, long ticks, PersonContainer[] personContainers, string eResultsFullGroupDirectory) :
this(maxDegreeOfParallelism, propertyConfiguration, configuration, outputExtension, outputExtension, outputExtension, ticks, personContainers, eResultsFullGroupDirectory, new(), null)
public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, string outputExtension, long ticks, PersonContainer[] personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory) :
this(maxDegreeOfParallelism, propertyConfiguration, configuration, outputExtension, outputExtension, outputExtension, ticks, personContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory, new(), null)
{ }
public override string ToString()

View File

@ -612,7 +612,7 @@ internal abstract class MapLogic
}
}
internal static void Set(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, string facesFileNameExtension, long ticks, List<PersonContainer> personContainers, string eDistanceContentDirectory, List<Face> distinctFilteredFaces, Shared.Models.Methods.IFaceDistance faceDistance, Dictionary<long, PersonContainer> personKeyToPersonContainer, Dictionary<long, (long LCL, long Minimum, long Maximum, long UCL)> personKeyToRanges, List<PersonContainer> notMappedPersonContainers, Dictionary<int, List<int>> skipCollection, Dictionary<int, Dictionary<int, PersonContainer[]>> idThenNormalizedPixelPercentageToPersonContainers)
internal static void Set(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, string facesFileNameExtension, long ticks, List<PersonContainer> personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory, List<Face> distinctFilteredFaces, Shared.Models.Methods.IFaceDistance faceDistance, Dictionary<long, PersonContainer> personKeyToPersonContainer, Dictionary<long, (long LCL, long Minimum, long Maximum, long UCL)> personKeyToRanges, List<PersonContainer> notMappedPersonContainers, Dictionary<int, List<int>> skipCollection, Dictionary<int, Dictionary<int, PersonContainer[]>> idThenNormalizedPixelPercentageToPersonContainers)
{
if (configuration is null)
throw new NullReferenceException(nameof(configuration));
@ -696,6 +696,7 @@ internal abstract class MapLogic
propertyConfiguration,
configuration.PersonBirthdayFormat,
facesFileNameExtension,
a2PeopleSingletonDirectory,
personKeyToPersonContainer,
possiblyNewPersonDisplayDirectoryNamesAndPersonContainer);
}

View File

@ -44,8 +44,8 @@ public class B_Metadata
{
object? @object;
string? tagDescription;
int type = (int)IExif.Tags.Orientation;
List<string> tagNames = new();
int type = (int)IExif.Tags.Orientation;
string key = nameof(IExif.Tags.Orientation);
IReadOnlyList<MetadataExtractor.Directory> directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(subFile);
foreach (MetadataExtractor.Directory directory in directories)

View File

@ -50,7 +50,7 @@
"WorkingDirectoryName": "PharesApps",
"Windows": {
"Configuration": {
"DateGroup": "2022-09-15",
"DateGroup": "2022-09-22",
"FileNameDirectorySeparator": ".Z.",
"ForcePropertyLastWriteTimeToCreationTime": false,
"MaxImagesInDirectoryForTopLevelFirstPass": 10,

View File

@ -50,7 +50,7 @@
"WorkingDirectoryName": "PharesApps",
"Windows": {
"Configuration": {
"DateGroup": "2022-09-15",
"DateGroup": "2022-09-22",
"FileNameDirectorySeparator": ".Z.",
"ForcePropertyLastWriteTimeToCreationTime": false,
"KeepFullPath": false,

View File

@ -4,6 +4,6 @@ public interface IFaceDistance
{
List<Face> GetMatchingFaces(double faceDistanceTolerance, string checkFile, List<Face> faces);
void SavePossiblyNewPersonContainers(Properties.IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, string facesFileNameExtension, Dictionary<long, PersonContainer> personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer);
void SavePossiblyNewPersonContainers(Properties.IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, string facesFileNameExtension, string a2PeopleContentDirectory, Dictionary<long, PersonContainer> personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer);
}

View File

@ -31,6 +31,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Map", "Map\Map.csproj", "{9
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Instance", "Instance\Instance.csproj", "{8085C1EE-C4DB-43DE-8888-1C956D69CF91}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Distance", "Distance\Distance.csproj", "{8D444B55-933C-40CD-B7FC-226136F16138}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Face", "Face\Face.csproj", "{A12E19E5-59C0-40D4-B807-DF1334D4906D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FaceParts", "FaceParts\FaceParts.csproj", "{919525B1-60BA-40C6-BA66-6F7F4C526E01}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -96,5 +102,17 @@ Global
{8085C1EE-C4DB-43DE-8888-1C956D69CF91}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8085C1EE-C4DB-43DE-8888-1C956D69CF91}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8085C1EE-C4DB-43DE-8888-1C956D69CF91}.Release|Any CPU.Build.0 = Release|Any CPU
{8D444B55-933C-40CD-B7FC-226136F16138}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8D444B55-933C-40CD-B7FC-226136F16138}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D444B55-933C-40CD-B7FC-226136F16138}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8D444B55-933C-40CD-B7FC-226136F16138}.Release|Any CPU.Build.0 = Release|Any CPU
{A12E19E5-59C0-40D4-B807-DF1334D4906D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A12E19E5-59C0-40D4-B807-DF1334D4906D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A12E19E5-59C0-40D4-B807-DF1334D4906D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A12E19E5-59C0-40D4-B807-DF1334D4906D}.Release|Any CPU.Build.0 = Release|Any CPU
{919525B1-60BA-40C6-BA66-6F7F4C526E01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{919525B1-60BA-40C6-BA66-6F7F4C526E01}.Debug|Any CPU.Build.0 = Debug|Any CPU
{919525B1-60BA-40C6-BA66-6F7F4C526E01}.Release|Any CPU.ActiveCfg = Release|Any CPU
{919525B1-60BA-40C6-BA66-6F7F4C526E01}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal