From c48a30f42fbda984b51401bdfb55691af69a50ce Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Thu, 23 Mar 2023 18:22:37 -0700 Subject: [PATCH] facePartsCollectionDirectory --- FaceParts/Models/_D2_FaceParts.cs | 81 +++++++++++++++++++++++++++++-- Instance/DlibDotNet.cs | 7 +-- 2 files changed, 81 insertions(+), 7 deletions(-) diff --git a/FaceParts/Models/_D2_FaceParts.cs b/FaceParts/Models/_D2_FaceParts.cs index 3887bfc..a4cb721 100644 --- a/FaceParts/Models/_D2_FaceParts.cs +++ b/FaceParts/Models/_D2_FaceParts.cs @@ -57,7 +57,7 @@ public class D2_FaceParts converted: true)); } - public string GetFacePartsDirectory(Property.Models.Configuration configuration, string dResultsFullGroupDirectory, Item item) + public string GetFacePartsDirectory(Property.Models.Configuration configuration, string dResultsFullGroupDirectory, Item item, bool includeNameWithoutExtension) { string result; bool angleBracketCollectionAny = _AngleBracketCollection.Any(); @@ -67,7 +67,10 @@ public class D2_FaceParts throw new NullReferenceException(nameof(item.ImageFileHolder.DirectoryName)); SetAngleBracketCollection(configuration, dResultsFullGroupDirectory, item.ImageFileHolder.DirectoryName); } - result = Path.Combine(_AngleBracketCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension); + if (!includeNameWithoutExtension) + result = _AngleBracketCollection[0].Replace("<>", "[()]"); + else + result = Path.Combine(_AngleBracketCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension); if (!angleBracketCollectionAny) _AngleBracketCollection.Clear(); return result; @@ -230,12 +233,51 @@ public class D2_FaceParts } } + private void SaveFaceParts(int pointSize, IFileHolder resizedFileHolder, List<(Shared.Models.Face, string, string)> collection) + { + int x; + int y; + string? firstFileName = null; + using Image image = Image.FromFile(resizedFileHolder.FullName); + using Graphics graphic = Graphics.FromImage(image); + foreach ((Shared.Models.Face face, string fileName, string _) in collection) + { + firstFileName ??= fileName; + try + { + if (face.FaceParts is null || !face.FaceParts.Any()) + continue; + foreach ((FacePart facePart, FacePoint[] facePoints) in face.FaceParts) + { + foreach (FacePoint facePoint in facePoints) + { + if (face.Location is null) + continue; + graphic.DrawEllipse(Pens.GreenYellow, facePoint.X - pointSize, facePoint.Y - pointSize, pointSize * 2, pointSize * 2); + } + if (facePart == FacePart.Chin) + continue; + if (facePoints.Length < 3) + continue; + x = (int)(from l in facePoints select l.X).Average(); + y = (int)(from l in facePoints select l.Y).Average(); + if (face.Location is null) + continue; + graphic.DrawEllipse(Pens.Purple, x - pointSize, y - pointSize, pointSize * 2, pointSize * 2); + } + } + catch (Exception) { } + } + if (!string.IsNullOrEmpty(firstFileName)) + image.Save(firstFileName, _ImageCodecInfo, _EncoderParameters); + } + #pragma warning restore CA1416 - public void SaveFaceLandmarkImages(Property.Models.Configuration configuration, string facePartsDirectory, List> subFileTuples, List parseExceptions, MappingFromItem mappingFromItem, List faces, bool saveRotated) + public void SaveFaceLandmarkImages(Property.Models.Configuration configuration, string facePartsDirectory, string facePartsCollectionDirectory, List> subFileTuples, List parseExceptions, MappingFromItem mappingFromItem, List faces, bool saveRotated) { + bool check; FileInfo fileInfo; - bool check = false; const int pointSize = 2; FileInfo rotatedFileInfo; DateTime? dateTime = null; @@ -247,6 +289,37 @@ public class D2_FaceParts List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); if (!Directory.Exists(facePartsDirectory)) _ = Directory.CreateDirectory(facePartsDirectory); + if (!Directory.Exists(facePartsCollectionDirectory)) + _ = Directory.CreateDirectory(facePartsCollectionDirectory); + fileInfo = new FileInfo(Path.Combine(facePartsCollectionDirectory, $"{mappingFromItem.ImageFileHolder.Name}{_FileNameExtension}")); + if (_OverrideForFaceLandmarkImages) + check = true; + else if (!fileInfo.Exists) + check = true; + else if (_CheckDFaceAndUpWriteDates && dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime) + check = true; + else + check = false; + if (check && !updateDateWhenMatches) + { + updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; + dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); + } + if (check) + { + foreach (Shared.Models.Face face in faces) + { + if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) + continue; + if (face.FaceParts is null || !face.FaceParts.Any()) + continue; + collection.Add(new(face, fileInfo.FullName, string.Empty)); + } + } + if (check && collection.Any()) + SaveFaceParts(pointSize, mappingFromItem.ResizedFileHolder, collection); + check = false; + collection.Clear(); foreach (Shared.Models.Face face in faces) { if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null) diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index 9e2e467..7e92bec 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -325,7 +325,8 @@ public partial class DlibDotNet FileHolder resizedFileHolder = _Resize.GetResizedFileHolder(item); 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) : string.Empty; + string facePartsDirectory = _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution) ? _FaceParts.GetFacePartsDirectory(_Configuration.PropertyConfiguration, dResultsFullGroupDirectory, item, includeNameWithoutExtension: true) : string.Empty; + string facePartsCollectionDirectory = _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution) ? _FaceParts.GetFacePartsDirectory(_Configuration.PropertyConfiguration, dResultsFullGroupDirectory, item, includeNameWithoutExtension: false) : string.Empty; MappingFromItem mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder); (int metadataGroups, metadataCollection) = metadata.GetMetadataCollection(subFileTuples, parseExceptions, mappingFromItem); if (_AppSettings.MaxDegreeOfParallelism < 2) @@ -365,9 +366,9 @@ public partial class DlibDotNet _Distance.LookForMatchFacesAndPossiblyRename(_Faces.FileNameExtension, eDistanceContentDirectory, mappingFromItem, faces, collection); if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) { - bool saveRotated = !_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution); + bool saveRotated = false; string sourceDirectorySegment = Property.Models.Stateless.IResult.GetRelativePath(_Configuration.PropertyConfiguration, container.SourceDirectory); - _FaceParts.SaveFaceLandmarkImages(_Configuration.PropertyConfiguration, facePartsDirectory, subFileTuples, parseExceptions, mappingFromItem, faces, saveRotated); + _FaceParts.SaveFaceLandmarkImages(_Configuration.PropertyConfiguration, facePartsDirectory, facePartsCollectionDirectory, subFileTuples, parseExceptions, mappingFromItem, faces, saveRotated); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(D2_FaceParts.SaveFaceLandmarkImages)); }