@ -1,14 +1,15 @@
using FaceRecognitionDotNet ;
using System.Drawing ;
using System.Drawing.Drawing2D ;
using System.Text.Json ;
using System.Text.Json.Serialization ;
using System.Text.RegularExpressions ;
using View_by_Distance.FaceRecognitionDotNet ;
using View_by_Distance.Metadata.Models ;
using View_by_Distance.Property.Models ;
using View_by_Distance.Resize.Models ;
using View_by_Distance.Shared.Models ;
using View_by_Distance.Shared.Models.Methods ;
using View_by_Distance.Shared.Models.Stateless ;
using WindowsShortcutFactory ;
namespace View_by_Distance.Instance.Models ;
@ -32,8 +33,8 @@ public class D_Face : Shared.Models.Properties.IFace, IFace
protected double? _Α ;
protected DateTime _DateTime ;
protected Shared . Models . FaceEncoding _FaceEncoding ;
protected Dictionary < string , Shared . Models . FacePoint[ ] > _FaceLandmarks ;
protected Shared . Models . Location _Location ;
protected Dictionary < string , FacePoint [ ] > _FaceLandmarks ;
protected Location _Location ;
protected int? _LocationIndex ;
protected OutputResolution _OutputResolution ;
protected bool _Populated ;
@ -41,9 +42,9 @@ public class D_Face : Shared.Models.Properties.IFace, IFace
public double? α = > _Α ;
public DateTime DateTime = > _DateTime ;
public Shared . Models . FaceEncoding FaceEncoding = > _FaceEncoding ;
public Dictionary < string , Shared . Models . FacePoint[ ] > FaceLandmarks = > _FaceLandmarks ;
public Dictionary < string , FacePoint [ ] > FaceLandmarks = > _FaceLandmarks ;
public OutputResolution OutputResolution = > _OutputResolution ;
public Shared . Models . Location Location = > _Location ;
public Location Location = > _Location ;
public int? LocationIndex = > _LocationIndex ;
public bool Populated = > _Populated ;
public string RelativePath = > _RelativePath ;
@ -51,7 +52,7 @@ public class D_Face : Shared.Models.Properties.IFace, IFace
#nullable disable
[JsonConstructor]
public D_Face ( double? α , DateTime dateTime , Shared . Models . FaceEncoding faceEncoding , Dictionary < string , Shared . Models . FacePoint[ ] > faceLandmarks , Shared . Models . Location location , int? locationIndex , OutputResolution outputResolution , bool populated , string relativePath )
public D_Face ( double? α , DateTime dateTime , Shared . Models . FaceEncoding faceEncoding , Dictionary < string , FacePoint [ ] > faceLandmarks , Location location , int? locationIndex , OutputResolution outputResolution , bool populated , string relativePath )
{
_Α = α ;
_DateTime = dateTime ;
@ -76,7 +77,7 @@ public class D_Face : Shared.Models.Properties.IFace, IFace
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true } ;
}
private D_Face ( Shared . Models . Location location )
private D_Face ( Location location )
{
_Α = α ;
_DateTime = DateTime . MinValue ;
@ -102,12 +103,12 @@ public class D_Face : Shared.Models.Properties.IFace, IFace
_RelativePath = string . Empty ;
}
private D_Face ( A_Property property , int outputResolutionWidth , int outputResolutionHeight , int outputResolutionOrientation , string relativePath , int? i , Shared . Models . Location location )
private D_Face ( A_Property property , int outputResolutionWidth , int outputResolutionHeight , int outputResolutionOrientation , string relativePath , int? i , Location location )
{
DateTime ? [ ] dateTimes ;
dateTimes = new DateTime ? [ ] { property . CreationTime , property . LastWriteTime , property . DateTime , property . DateTimeDigitized , property . DateTimeOriginal , property . GPSDateStamp } ;
_DateTime = ( from l in dateTimes where l . HasValue select l . Value ) . Min ( ) ;
_FaceLandmarks = new Dictionary < string , Shared . Models . FacePoint[ ] > ( ) ;
_FaceLandmarks = new Dictionary < string , FacePoint [ ] > ( ) ;
_OutputResolution = new ( outputResolutionHeight , outputResolutionOrientation , outputResolutionWidth ) ;
_Location = location ;
_LocationIndex = i ;
@ -223,15 +224,15 @@ public class D_Face : Shared.Models.Properties.IFace, IFace
int width ;
int height ;
Graphics graphics ;
Rectangle rectangle ;
Location location ;
Bitmap preRotated ;
Shared . Models . Location location ;
Rectangle rectangle ;
using Bitmap source = new ( resizedFileInfo . FullName ) ;
for ( int i = 0 ; i < faceCollection . Count ; i + + )
{
if ( ! faceCollection [ i ] . Populated | | faceCollection [ i ] ? . Location is null )
continue ;
location = new Shared . Models . Location( faceCollection [ i ] . Location . Confidence ,
location = new Location ( faceCollection [ i ] . Location . Confidence ,
faceCollection [ i ] . Location . Bottom ,
faceCollection [ i ] . Location . Left ,
faceCollection [ i ] . Location . Right ,
@ -255,7 +256,7 @@ public class D_Face : Shared.Models.Properties.IFace, IFace
throw new Exception ( ) ;
if ( _Configuration . NumJitters is null )
throw new Exception ( ) ;
FaceRecognitionDotNet . Location[ ] locations ;
Location [ ] locations ;
const int numberOfTimesToUpSample = 1 ;
FaceRecognitionDotNet . Image ? unknownImage = null ;
if ( resizedFileInfo . Exists )
@ -284,18 +285,18 @@ public class D_Face : Shared.Models.Properties.IFace, IFace
int rightEyeY ;
Bitmap rotated ;
string faceFile ;
Location location ;
Bitmap preRotated ;
Graphics graphics ;
D_Face ? face = null ;
Rectangle rectangle ;
double [ ] rawEncoding ;
Shared . Models . Location location ;
FaceRecognitionDotNet . Image known Image ;
FaceRecognitionDotNet . Image ? knownImage ;
FaceRecognitionDotNet . Image ? rotated Image;
Shared . Models . FaceEncoding faceEncoding ;
FaceRecognitionDotNet . Image rotatedImage ;
FaceRecognitionDotNet . FaceEncoding [ ] faceEncodings ;
IEnumerable < FaceRecognitionDotNet . FacePoint> facePoints ;
IDictionary < FacePart , IEnumerable < FaceRecognitionDotNet . FacePoint> > [ ] faceLandmarks ;
IEnumerable < FacePoint > facePoints ;
IDictionary < FacePart , IEnumerable < FacePoint > > [ ] faceLandmarks ;
using Bitmap source = unknownImage . ToBitmap ( ) ;
padding = ( int ) ( ( source . Width + source . Height ) / 2 * . 01 ) ;
for ( int i = 0 ; i < locations . Length ; i + + )
@ -319,27 +320,31 @@ public class D_Face : Shared.Models.Properties.IFace, IFace
// source.Save(Path.Combine(_Configuration.RootDirectory, "source.jpg"));
// preRotated.Save(Path.Combine(_Configuration.RootDirectory, $"{p} - preRotated.jpg"));
using ( knownImage = FaceRecognition . LoadImage ( preRotated ) )
faceLandmarks = faceRecognition . FaceLandmark ( knownImage , faceLocations : null , _PredictorModel , _Model ) . ToArray ( ) ;
if ( knownImage is null )
throw new Exception ( $"{nameof(knownImage)} is null" ) ;
faceLandmarks = faceRecognition . FaceLandmark ( knownImage , faceLocations : null , _PredictorModel , _Model ) . ToArray ( ) ;
if ( faceLandmarks . Length = = 0 & & p < _Configuration . PaddingLoops . Value )
continue ;
else if ( faceLandmarks . Length ! = 1 )
continue ;
foreach ( KeyValuePair < FacePart , IEnumerable < FaceRecognitionDotNet . FacePoint> > keyValuePair in faceLandmarks [ 0 ] )
face . FaceLandmarks . Add ( keyValuePair . Key . ToString ( ) , ( from l in keyValuePair . Value select new Shared . Models . FacePoint ( l . Index , l . Point . X , l . Point . Y ) ) . ToArray ( ) ) ;
foreach ( KeyValuePair < FacePart , IEnumerable < FacePoint > > keyValuePair in faceLandmarks [ 0 ] )
face . FaceLandmarks . Add ( keyValuePair . Key . ToString ( ) , keyValuePair . Value . ToArray ( ) ) ;
if ( ! faceLandmarks [ 0 ] . ContainsKey ( FacePart . LeftEye ) | | ! faceLandmarks [ 0 ] . ContainsKey ( FacePart . RightEye ) )
continue ;
facePoints = faceLandmarks [ 0 ] [ FacePart . LeftEye ] ;
leftEyeX = ( int ) ( from l in facePoints select l . Point . X) . Average ( ) ;
leftEyeY = ( int ) ( from l in facePoints select l . Point . Y) . Average ( ) ;
leftEyeX = ( int ) ( from l in facePoints select l . X ) . Average ( ) ;
leftEyeY = ( int ) ( from l in facePoints select l . Y ) . Average ( ) ;
facePoints = faceLandmarks [ 0 ] [ FacePart . RightEye ] ;
rightEyeX = ( int ) ( from l in facePoints select l . Point . X) . Average ( ) ;
rightEyeY = ( int ) ( from l in facePoints select l . Point . Y) . Average ( ) ;
rightEyeX = ( int ) ( from l in facePoints select l . X ) . Average ( ) ;
rightEyeY = ( int ) ( from l in facePoints select l . Y ) . Average ( ) ;
α = Shared . Models . Stateless . Methods . IFace . Getα ( rightEyeX , leftEyeX , rightEyeY , leftEyeY ) ;
using ( rotated = RotateBitmap ( preRotated , ( float ) α . Value ) )
{
// rotated.Save(Path.Combine(_Configuration.RootDirectory, $"{p} - rotated.jpg"));
using ( rotatedImage = FaceRecognition . LoadImage ( rotated ) )
faceEncodings = faceRecognition . FaceEncodings ( rotatedImage , knownFaceLocation : null , _Configuration . NumJitters . Value , _PredictorModel , _Model ) . ToArray ( ) ;
if ( rotatedImage is null )
throw new Exception ( $"{nameof(rotatedImage)} is null" ) ;
faceEncodings = faceRecognition . FaceEncodings ( rotatedImage , knownFaceLocation : null , _Configuration . NumJitters . Value , _PredictorModel , _Model ) . ToArray ( ) ;
if ( faceEncodings . Length = = 0 & & p < _Configuration . PaddingLoops . Value )
continue ;
else if ( faceEncodings . Length ! = 1 )
@ -495,29 +500,26 @@ public class D_Face : Shared.Models.Properties.IFace, IFace
SaveFaces ( faceCollection , resizedFileInfo , imageFiles ) ;
}
internal void SaveShortcuts ( Property . Models . Configuration configuration , string [ ] juliePhares , Model model , PredictorModel predictorModel , Person [ ] pe ople , PropertyLogic pr opertyLogic , string outputResolution , PropertyHolder [ ] filteredPropertyHolderCollection , List < A_Property > propertyCollection , List < List < D_Face > > faceCollections )
internal void SaveShortcuts ( Property . Models . Configuration configuration , string [ ] juliePhares , Model model , PredictorModel predictorModel , PropertyLogic pr opertyLogic , Dictionary < string , List < Person > > pe opleCollection , string outputResolution , PropertyHolder [ ] filteredPropertyHolderCollection , List < A_Property > propertyCollection , List < List < D_Face > > faceCollections )
{
int oldIndex ;
string [ ] keys ;
string fileName ;
string fullName ;
string personKey ;
string directory ;
bool? isWrongYear ;
FileInfo fileInfo ;
TimeSpan timeSpan ;
DateTime ? birthDate ;
string copyDirectory ;
string? relativePath ;
string isWrongYearFlag ;
string subDirectoryName ;
DateTime minimumDateTime ;
List < D_Face > faceCollection ;
PropertyHolder propertyHolder ;
WindowsShortcut windowsShortcut ;
const string pattern = @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]" ;
Dictionary < string , List < Person > > peopleCollection = new ( ) ;
foreach ( Person person in people )
{
personKey = Shared . Models . Stateless . Methods . IPersonBirthday . GetFormatted ( person . Birthday ) ;
if ( ! peopleCollection . ContainsKey ( personKey ) )
peopleCollection . Add ( personKey , new List < Person > ( ) ) ;
peopleCollection [ personKey ] . Add ( person ) ;
}
string dFacesContentDirectory = Path . Combine ( Property . Models . Stateless . IResult . GetResultsFullGroupDirectory ( configuration , model . ToString ( ) , predictorModel . ToString ( ) , nameof ( D_Face ) , outputResolution , includeResizeGroup : true , includeModel : true , includePredictorModel : true ) , "(_)" ) ;
for ( int i = 0 ; i < filteredPropertyHolderCollection . Length ; i + + )
{
@ -532,37 +534,42 @@ public class D_Face : Shared.Models.Properties.IFace, IFace
continue ;
if ( propertyHolder . Property ? . Id is null | | propertyHolder . MinimumDateTime is null | | propertyHolder . ResizedFileInfo is null )
continue ;
if ( propertyHolder . Property . Indices . Length < 2 )
directory = Path . Combine ( dFacesContentDirectory , $"New {relativePath[2..]}" ) ;
if ( ! propertyLogic . NamedFaceInfoDeterministicHashCodeIndices . ContainsKey ( propertyHolder . Property . Id . Value ) )
directory = Path . Combine ( dFacesContentDirectory , $"Unnamed {relativePath[2..]}" ) ;
else
{
oldIndex = propertyHolder . Property . Indice s[ 1 ] ;
if ( ! propertyLogic . NamedFaceInfo. ContainsKey ( oldIndex ) )
directory = Path . Combine ( dFacesContentDirectory , $"Unnamed{relativePath[2..]}" ) ;
faceCollection = faceCollection s[ i ] ;
keys = propertyLogic . NamedFaceInfoDeterministicHashCodeIndices [ propertyHolder . Property . Id . Value ] ;
minimumDateTime = Property . Models . Stateless . A_Property . GetMinimumDateTime ( propertyHolder . Property ) ;
( isWrongYear , _ ) = propertyHolder . Property . IsWrongYear ( propertyHolder . ImageFileInfo . FullName , minimumDateTime ) ;
isWrongYearFlag = isWrongYear is null ? "#" : isWrongYear . Value ? "~" : "=" ;
subDirectoryName = $"{isWrongYearFlag}{minimumDateTime:yyyy}" ;
if ( ! faceCollection . Any ( ) )
directory = Path . Combine ( dFacesContentDirectory , $"None{relativePath[2..]}" , subDirectoryName ) ;
else if ( keys . Length ! = 1 )
directory = Path . Combine ( dFacesContentDirectory , $"Not Supported{relativePath[2..]}" , subDirectoryName ) ;
else if ( faceCollection . Count ! = 1 )
directory = Path . Combine ( dFacesContentDirectory , $"Many{relativePath[2..]}" , subDirectoryName ) ;
else
{
faceCollection = faceCollection s[ i ] ;
keys = propertyLogic . NamedFaceInfo [ oldIndex ] ;
if ( ! faceCollection . Any ( ) )
directory = Path . Combine ( dFacesContentDirectory , $"None{relativePath[2..]}" ) ;
else if ( keys . Length ! = 1 )
directory = Path . Combine ( dFacesContentDirectory , $"Not Supported{relativePath[2..]}" ) ;
else if ( faceCollection . Count = = 1 )
personKey = key s[ 0 ] ;
if ( isWrongYear is not null & & ! isWrongYear . Value & & personKey [ . . 2 ] is "19" or "20" )
{
personKey = keys [ 0 ] ;
if ( juliePhares . Contains ( personKey ) )
copyDirectory = Path . Combine ( dFacesContentDirectory , "Named Images" ) ;
directory = Path . Combine ( dFacesContentDirectory , "Named Shortcuts" , personKey ) ;
birthDate = Shared . Models . Stateless . Methods . IPersonBirthday . Get ( personKey ) ;
if ( birthDate . HasValue )
{
if ( minimumDateTime < birthDate . Value )
subDirectoryName = "!---" ;
else
{
timeSpan = new ( minimumDateTime . Ticks - birthDate . Value . Ticks ) ;
subDirectoryName = $"^{Math.Floor(timeSpan.TotalDays / 365):000}" ;
}
}
}
else if ( ( from l in f aceCollection where HasLeftAndRight ( l . FaceLandmarks ) select true ) . Count ( ) = = 1 )
{
personKey = k eys [ 0 ] ;
if ( juliePhares . Contains ( personKey ) )
copyDirectory = Path . Combine ( dFacesContentDirectory , "Named Images^" ) ;
directory = Path . Combine ( dFacesContentDirectory , "Named Shortcuts" , $"{personKey}^" ) ;
}
else
directory = Path . Combine ( dFacesContentDirectory , $"Many{relativePath[2..]}" ) ;
directory = Path . Combine ( dF aces ContentDirectory , "Named Shortcuts" , personKey , subDirectoryName ) ;
if ( juliePhares . Contains ( personKey ) )
copyDirectory = Path . Combine ( dFacesContentDirectory , "Named Images" , personK ey, subDirectoryName ) ;
}
}
if ( ! Directory . Exists ( directory ) )
@ -603,7 +610,7 @@ public class D_Face : Shared.Models.Properties.IFace, IFace
Face [ ] Shared . Models . Stateless . Methods . IFace . TestStatic_GetFaces ( string jsonFileFullName ) = > throw new NotImplementedException ( ) ;
private static bool HasLeftAndRight ( Dictionary < string , Shared . Models . FacePoint[ ] > faceLandmarks )
private static bool HasLeftAndRight ( Dictionary < string , FacePoint [ ] > faceLandmarks )
{
bool result = true ;
if ( ! faceLandmarks . ContainsKey ( FacePart . LeftEye . ToString ( ) ) )