Rename-isWrongYear

EyeThreshold
This commit is contained in:
Mike Phares 2023-06-24 09:07:11 -07:00
parent b4c1a05869
commit ddcb5b479a
12 changed files with 100 additions and 26 deletions

View File

@ -15,7 +15,6 @@ completedColumns:
- [nef-support](tasks/nef-support.md)
- [determine-if-location-container-collection-is-needed-in-get-faces](tasks/determine-if-location-container-collection-is-needed-in-get-faces.md)
- [use-eyes-to-find-orientation](tasks/use-eyes-to-find-orientation.md)
- [use-photo-prism-to-map](tasks/use-photo-prism-to-map.md)
- [import-face-region-metadata](tasks/import-face-region-metadata.md)
@ -26,6 +25,7 @@ completedColumns:
- [run-scan-originals](tasks/run-scan-originals.md)
- [find-incorrectly-mapped-faces](tasks/find-incorrectly-mapped-faces.md)
- [shrink-percent](tasks/shrink-percent.md)
- [use-eyes-to-find-orientation](tasks/use-eyes-to-find-orientation.md)
## Done

View File

@ -10,4 +10,4 @@ tags: []
## Sub-tasks
- [ ] asdf
- [ ] 1006207980

View File

@ -216,7 +216,7 @@ public class D2_FaceParts
}
if (saveRotated && face.FaceParts is not null)
{
α = Shared.Models.Stateless.Methods.IFace.Getα(face.FaceParts);
(_, α) = Shared.Models.Stateless.Methods.IFace.GetEyeα(face.FaceParts);
if (α is null)
continue;
using Image image = Image.FromFile(resizedFileHolder.FullName);

View File

@ -290,6 +290,9 @@ public partial class DlibDotNet
private void SetMapping(MapLogic mapLogic, Item item, bool? isFocusRelativePath, bool? isIgnoreRelativePath, MappingFromItem mappingFromItem, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection, List<Shared.Models.Face> faces)
{
double? α;
int? eyeα;
bool? eyeReview;
Mapping mapping;
int faceAreaPermyriad;
int confidencePercent;
@ -309,11 +312,18 @@ public partial class DlibDotNet
}
else
{
if (face.FaceParts is null)
(eyeα, eyeReview) = (null, null);
else
{
(eyeReview, α) = Shared.Models.Stateless.Methods.IFace.GetEyeα(face.FaceParts);
eyeα = α is null ? null : (int)Math.Round(Math.Abs(α.Value));
}
confidencePercent = Shared.Models.Stateless.Methods.ILocation.GetConfidencePercent(_Configuration.FaceConfidencePercent, _Configuration.RangeFaceConfidence, face.Location.Confidence);
faceAreaPermyriad = Shared.Models.Stateless.Methods.IMapping.GetAreaPermyriad(_Configuration.FaceAreaPermyriad, face.Location, face.OutputResolution);
wholePercentRectangle = Shared.Models.Stateless.Methods.ILocation.GetWholePercentages(face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution);
deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution);
mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, wholePercentRectangle);
mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, eyeα, eyeReview, wholePercentRectangle);
inSkipCollection = mapLogic.InSkipCollection(item.Property.Id.Value, mappingFromLocation);
mappingFromFilter = new(isFocusModel, isFocusRelativePath, isIgnoreRelativePath, inSkipCollection);
}
@ -326,6 +336,8 @@ public partial class DlibDotNet
private Mapping GetMapping(MapLogic mapLogic, Item item, bool? isFocusRelativePath, bool? isIgnoreRelativePath, MappingFromItem mappingFromItem)
{
Mapping result;
int? eyeα = null;
bool? eyeReview = null;
bool? inSkipCollection;
int wholePercentRectangle;
int faceAreaPermyriad = 0;
@ -344,7 +356,7 @@ public partial class DlibDotNet
{
wholePercentRectangle = Shared.Models.Stateless.Methods.ILocation.GetWholePercentages(Shared.Models.Stateless.ILocation.Digits);
deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, Shared.Models.Stateless.ILocation.Digits);
mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, wholePercentRectangle);
mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, eyeα, eyeReview, wholePercentRectangle);
inSkipCollection = mapLogic.InSkipCollection(item.Property.Id.Value, mappingFromLocation);
mappingFromFilter = new(isFocusModel, isFocusRelativePath, isIgnoreRelativePath, inSkipCollection);
}
@ -381,6 +393,7 @@ public partial class DlibDotNet
string outputResolution,
string cResultsFullGroupDirectory,
string dResultsFullGroupDirectory,
string d2ResultsFullGroupDirectory,
List<Tuple<string, DateTime>> sourceDirectoryChanges,
Dictionary<int, List<MappingFromPhotoPrism>> fileNameToCollection,
Container container,
@ -436,8 +449,8 @@ public partial class DlibDotNet
if (property is null || item.Property is null)
throw new NullReferenceException(nameof(property));
item.SetResizedFileHolder(_Resize.FileNameExtension, resizedFileHolder);
string facesDirectory = _Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution) ? _Faces.GetFacesDirectory(dResultsFullGroupDirectory, item) : string.Empty;
string facePartsDirectory = _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution) ? _FaceParts.GetFacePartsDirectory(_Configuration.PropertyConfiguration, dResultsFullGroupDirectory, item, includeNameWithoutExtension: true) : string.Empty;
string? facesDirectory = !_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution) ? null : _Faces.GetFacesDirectory(dResultsFullGroupDirectory, item);
string? facePartsDirectory = !_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution) ? null : _FaceParts.GetFacePartsDirectory(_Configuration.PropertyConfiguration, dResultsFullGroupDirectory, item, includeNameWithoutExtension: true);
MappingFromItem mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder);
(int metadataGroups, metadataCollection) = metadata.GetMetadataCollection(subFileTuples, parseExceptions, mappingFromItem);
if (_AppSettings.MaxDegreeOfParallelism < 2)
@ -451,9 +464,9 @@ public partial class DlibDotNet
if (_AppSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(C_Resize.SaveResizedSubfile));
}
if (!mappingFromItem.ResizedFileHolder.Exists && !File.Exists(mappingFromItem.ResizedFileHolder.FullName))
if (facesDirectory is null)
faces = new();
else if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution))
else if (!mappingFromItem.ResizedFileHolder.Exists && !File.Exists(mappingFromItem.ResizedFileHolder.FullName))
faces = new();
else
{
@ -468,8 +481,8 @@ public partial class DlibDotNet
faces = _Faces.GetFaces(outputResolution, dResultsFullGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionToResize, locationContainers, mappingFromPhotoPrismCollection);
if (_AppSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(D_Face.GetFaces));
List<(Shared.Models.Face, FileInfo?, string, bool Saved)> faceCollection = _Faces.SaveFaces(_FaceParts.FileNameExtension, dResultsFullGroupDirectory, subFileTuples, parseExceptions, mappingFromItem, facesDirectory, faces);
SetMapping(mapLogic, item, isFocusRelativePath, isIgnoreRelativePath, mappingFromItem, mappingFromPhotoPrismCollection, faces);
List<(Shared.Models.Face, FileInfo?, string, bool Saved)> faceCollection = _Faces.SaveFaces(_FaceParts.FileNameExtension, dResultsFullGroupDirectory, subFileTuples, parseExceptions, mappingFromItem, facesDirectory, faces);
if (_Configuration.CopyFacesAndSaveFaceLandmarkForOutputResolutions.Contains(outputResolution))
_FaceParts.CopyFacesAndSaveFaceLandmarkImage(facePartsCollectionDirectory, mappingFromItem, faceCollection);
if (_AppSettings.MaxDegreeOfParallelism < 2)
@ -478,10 +491,14 @@ public partial class DlibDotNet
&& _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)
&& locationContainers is not null && faceCollection.All(l => !l.Saved))
_Distance.LookForMatchFacesAndPossiblyRename(_Faces.FileNameExtension, mappingFromItem, faces, locationContainers);
if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution))
(bool review, int[] eyesCollection) = Shared.Models.Stateless.Methods.IFace.GetEyeCollection(_Configuration.EyeThreshold, faces);
if (review || _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution))
{
bool saveRotated = false;
if (!_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution))
_FaceParts.SetAngleBracketCollection(_Configuration.PropertyConfiguration, d2ResultsFullGroupDirectory, container.SourceDirectory);
string sourceDirectorySegment = Property.Models.Stateless.IResult.GetRelativePath(_Configuration.PropertyConfiguration, container.SourceDirectory);
facePartsDirectory ??= _FaceParts.GetFacePartsDirectory(_Configuration.PropertyConfiguration, dResultsFullGroupDirectory, item, includeNameWithoutExtension: true);
_FaceParts.SaveFaceLandmarkImages(_Configuration.PropertyConfiguration, facePartsDirectory, subFileTuples, parseExceptions, mappingFromItem, faces, saveRotated);
if (_AppSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(D2_FaceParts.SaveFaceLandmarkImages));
@ -517,8 +534,8 @@ public partial class DlibDotNet
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
string focusRelativePath = Path.GetFullPath(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, _Configuration.FocusDirectory));
bool? isFocusRelativePath = string.IsNullOrEmpty(_Configuration.FocusDirectory) ? null : container.SourceDirectory.StartsWith(focusRelativePath);
string facePartsCollectionDirectory = _Configuration.CopyFacesAndSaveFaceLandmarkForOutputResolutions.Contains(outputResolution) ? _FaceParts.GetFacePartsDirectory(_Configuration.PropertyConfiguration, d2ResultsFullGroupDirectory, item: filteredItems.First(), includeNameWithoutExtension: false) : string.Empty;
bool? isIgnoreRelativePath = !_Configuration.IgnoreRelativePaths.Any() ? null : _Configuration.IgnoreRelativePaths.Any(l => container.SourceDirectory.Contains(l)) && Shared.Models.Stateless.Methods.IContainer.IsIgnoreRelativePath(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, container.SourceDirectory);
string facePartsCollectionDirectory = _Configuration.CopyFacesAndSaveFaceLandmarkForOutputResolutions.Contains(outputResolution) || _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution) ? _FaceParts.GetFacePartsDirectory(_Configuration.PropertyConfiguration, d2ResultsFullGroupDirectory, item: filteredItems.First(), includeNameWithoutExtension: false) : string.Empty;
using ProgressBar progressBar = new(filteredItems.Length, message, options);
_ = Parallel.For(0, filteredItems.Length, parallelOptions, (i, state) =>
{
@ -531,6 +548,7 @@ public partial class DlibDotNet
outputResolution,
cResultsFullGroupDirectory,
dResultsFullGroupDirectory,
d2ResultsFullGroupDirectory,
sourceDirectoryChanges,
fileNameToCollection,
container,

View File

@ -19,6 +19,7 @@ public class Configuration
[Display(Name = "Distance Move Unable to Match by 1 Tick"), Required] public bool? DistanceMoveUnableToMatch { get; set; }
[Display(Name = "Distance Pixel Distance Tolerance"), Required] public int? DistancePixelDistanceTolerance { get; set; }
[Display(Name = "Distance Rename to Match"), Required] public bool? DistanceRenameToMatch { get; set; }
[Display(Name = "Eye Threshold"), Required] public int? EyeThreshold { get; set; }
[Display(Name = "Face Area Permille"), Required] public int? FaceAreaPermyriad { get; set; }
[Display(Name = "Face Distance Hidden Image Factor"), Required] public int? FaceDistanceHiddenImageFactor { get; set; }
[Display(Name = "Face Confidence Percent"), Required] public int? FaceConfidencePercent { get; set; }
@ -121,6 +122,8 @@ public class Configuration
throw new NullReferenceException(nameof(configuration.DistancePixelDistanceTolerance));
if (configuration.DistanceRenameToMatch is null)
throw new NullReferenceException(nameof(configuration.DistanceRenameToMatch));
if (configuration.EyeThreshold is null)
throw new NullReferenceException(nameof(configuration.EyeThreshold));
if (configuration.FaceAreaPermyriad is null)
throw new NullReferenceException(nameof(configuration.FaceAreaPermyriad));
if (configuration.FaceDistanceHiddenImageFactor is null)
@ -249,6 +252,7 @@ public class Configuration
configuration.DistanceMoveUnableToMatch.Value,
configuration.DistancePixelDistanceTolerance.Value,
configuration.DistanceRenameToMatch.Value,
configuration.EyeThreshold.Value,
configuration.FaceAreaPermyriad.Value,
configuration.FaceConfidencePercent.Value,
configuration.FaceDistanceHiddenImageFactor.Value,

View File

@ -7,6 +7,7 @@ public class Configuration
{
protected Property.Models.Configuration _PropertyConfiguration;
public Property.Models.Configuration PropertyConfiguration => _PropertyConfiguration;
public bool CheckDFaceAndUpWriteDates { init; get; }
@ -18,6 +19,7 @@ public class Configuration
public bool DistanceMoveUnableToMatch { init; get; }
public int DistancePixelDistanceTolerance { init; get; }
public bool DistanceRenameToMatch { init; get; }
public int EyeThreshold { init; get; }
public int FaceAreaPermyriad { init; get; }
public int FaceDistanceHiddenImageFactor { init; get; }
public int FaceConfidencePercent { init; get; }
@ -98,6 +100,7 @@ public class Configuration
bool distanceMoveUnableToMatch,
int distancePixelDistanceTolerance,
bool distanceRenameToMatch,
int eyeThreshold,
int faceAreaPermyriad,
int faceConfidencePercent,
int faceDistanceHiddenImageFactor,
@ -177,6 +180,7 @@ public class Configuration
DistanceMoveUnableToMatch = distanceMoveUnableToMatch;
DistancePixelDistanceTolerance = distancePixelDistanceTolerance;
DistanceRenameToMatch = distanceRenameToMatch;
EyeThreshold = eyeThreshold;
FaceAreaPermyriad = faceAreaPermyriad;
FaceDistanceHiddenImageFactor = faceDistanceHiddenImageFactor;
FaceConfidencePercent = faceConfidencePercent;

View File

@ -59,6 +59,7 @@
"DistanceMoveUnableToMatch": false,
"DistancePixelDistanceTolerance": 1,
"DistanceRenameToMatch": false,
"EyeThreshold": 33,
"FaceAreaPermyriad": 10000,
"FaceDistanceHiddenImageFactor": 2,
"FaceConfidencePercent": 100,

View File

@ -154,12 +154,14 @@ public class Rename
DateTime dateTime;
string seasonName;
string? directory;
bool? isWrongYear;
TimeSpan? timeSpan;
string directoryName;
DateTime?[] dateTimes;
FileHolder fileHolder;
string[]? ffmpegFiles;
string seasonDirectory;
bool isIgnoreExtension;
string? seasonDirectory;
const string jpg = ".jpg";
DateTime? minimumDateTime;
string checkFileExtension;
@ -167,6 +169,7 @@ public class Rename
DateTime? dateTimeOriginal;
const string jpeg = ".jpeg";
List<string> distinct = new();
string[] directoryNameSegments;
bool isValidImageFormatExtension;
bool nameWithoutExtensionIsIdFormat;
DateTime? metadataMinimumDateTime = null;
@ -272,7 +275,10 @@ public class Rename
if (minimumDateTime is null)
break;
if (dateTimeOriginal is not null && dateTimeFromName is not null)
timeSpan = new(Math.Abs(minimumDateTime.Value.Ticks - new long[] { dateTimeOriginal.Value.Ticks, dateTimeFromName.Value.Ticks }.Min()));
{
timeSpan = new(Math.Abs(dateTimeOriginal.Value.Ticks - dateTimeFromName.Value.Ticks));
timeSpan = timeSpan.Value.TotalMinutes > _AppSettings.MaxMinutesDelta ? null : new(Math.Abs(minimumDateTime.Value.Ticks - new long[] { dateTimeOriginal.Value.Ticks, dateTimeFromName.Value.Ticks }.Min()));
}
else if (dateTimeFromName is not null)
timeSpan = new(Math.Abs(minimumDateTime.Value.Ticks - dateTimeFromName.Value.Ticks));
else if (dateTimeOriginal is not null)
@ -290,7 +296,18 @@ public class Rename
else
timeSpan = new(Math.Abs(minimumDateTime.Value.Ticks - metadataMinimumDateTime.Value.Ticks));
}
if (timeSpan is null || timeSpan.Value.TotalMinutes >= _AppSettings.MaxMinutesDelta)
if (timeSpan is null || timeSpan.Value.TotalMinutes > _AppSettings.MaxMinutesDelta)
(isWrongYear, seasonDirectory) = (null, null);
else
{
directoryName = Path.GetFileName(fileHolder.DirectoryName);
directoryNameSegments = directoryName.Split(' ');
(isWrongYear, _) = Shared.Models.Stateless.Methods.IProperty.IsWrongYear(directoryNameSegments, string.Empty);
dateTime = minimumDateTime.Value.AddTicks(timeSpan.Value.Ticks);
(season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
seasonDirectory = Path.Combine(fileHolder.DirectoryName, $"{dateTime.Year}.{season} {seasonName}");
}
if (seasonDirectory is null || isWrongYear is null || isWrongYear.Value)
{
if (metadataMinimumDateTime is null)
break;
@ -312,9 +329,6 @@ public class Rename
{
if (id is null)
continue;
dateTime = minimumDateTime.Value.AddTicks(timeSpan.Value.Ticks);
(season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
seasonDirectory = Path.Combine(fileHolder.DirectoryName, $"{dateTime.Year}.{season} {seasonName}");
if (ffmpegFiles is not null)
{
foreach (string ffmpegFile in ffmpegFiles)

View File

@ -9,14 +9,18 @@ public class MappingFromLocation : Properties.IMappingFromLocation
public int AreaPermyriad { init; get; }
public int ConfidencePercent { init; get; }
public string DeterministicHashCodeKey { init; get; }
public int? Eyeα { init; get; }
public bool? EyeReview { init; get; }
public int WholePercentages { init; get; }
[JsonConstructor]
public MappingFromLocation(int areaPermyriad, int confidencePercent, string deterministicHashCodeKey, int wholePercentages)
public MappingFromLocation(int areaPermyriad, int confidencePercent, string deterministicHashCodeKey, int? eyeα, bool? eyeReview, int wholePercentages)
{
AreaPermyriad = areaPermyriad;
ConfidencePercent = confidencePercent;
DeterministicHashCodeKey = deterministicHashCodeKey;
Eyeα = eyeα;
EyeReview = eyeReview;
WholePercentages = wholePercentages;
}

View File

@ -6,6 +6,8 @@ public interface IMappingFromLocation
public int AreaPermyriad { init; get; }
public int ConfidencePercent { init; get; }
public string DeterministicHashCodeKey { init; get; }
public int? Eyeα { init; get; }
public bool? EyeReview { init; get; }
public int WholePercentages { init; get; }
}

View File

@ -94,9 +94,11 @@ internal abstract class Face
return result;
}
internal static double? Getα(Dictionary<FacePart, Models.FacePoint[]> faceParts)
internal static (bool?, double?) GetEyeα(Dictionary<FacePart, Models.FacePoint[]> faceParts)
{
bool? review;
double? result;
int? lipY = null;
int? leftEyeX = null;
int? leftEyeY = null;
int? rightEyeX = null;
@ -115,12 +117,32 @@ internal abstract class Face
rightEyeX = (int)(from l in facePoints select l.X).Average();
rightEyeY = (int)(from l in facePoints select l.Y).Average();
}
if (facePart is FacePart.BottomLip or FacePart.TopLip)
lipY ??= (int)(from l in facePoints select l.X).Average();
}
if (rightEyeX is null || leftEyeX is null || rightEyeY is null || leftEyeY is null)
result = null;
(result, review) = (null, null);
else
{
review = lipY < rightEyeY || lipY < leftEyeY;
result = Getα(rightEyeX.Value, leftEyeX.Value, rightEyeY.Value, leftEyeY.Value);
return result;
}
return (review, result);
}
internal static (bool, int[]) GetEyeCollection(int threshold, List<Shared.Models.Face> faces)
{
bool result = false;
List<int> results = new();
foreach (Shared.Models.Face face in faces)
{
if (face.Mapping?.MappingFromLocation?.Eyeα is null || face.Mapping.MappingFromLocation.EyeReview is null)
continue;
results.Add(face.Mapping.MappingFromLocation.Eyeα.Value);
if (!result && face.Mapping.MappingFromLocation.EyeReview.Value || face.Mapping.MappingFromLocation.Eyeα.Value > threshold)
result = true;
}
return (result, results.ToArray());
}
}

View File

@ -23,9 +23,14 @@ public interface IFace
static Models.Face[] GetFaces(string jsonFileFullName) =>
Face.GetFaces(jsonFileFullName);
double? TestStatic_Getα(Dictionary<FacePart, Models.FacePoint[]> faceParts) =>
Getα(faceParts);
static double? Getα(Dictionary<FacePart, Models.FacePoint[]> faceParts) =>
Face.Getα(faceParts);
(bool?, double?) TestStatic_Getα(Dictionary<FacePart, Models.FacePoint[]> faceParts) =>
GetEyeα(faceParts);
static (bool?, double?) GetEyeα(Dictionary<FacePart, Models.FacePoint[]> faceParts) =>
Face.GetEyeα(faceParts);
(bool, int[]) TestStatic_GetEyeCollection(int threshold, List<Shared.Models.Face> faces) =>
GetEyeCollection(threshold, faces);
static (bool, int[]) GetEyeCollection(int threshold, List<Shared.Models.Face> faces) =>
Face.GetEyeCollection(threshold, faces);
}