161 lines
6.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Drawing;
using System.Text.Json;
using View_by_Distance.Metadata.Models;
using View_by_Distance.Property.Models;
using View_by_Distance.Resize.Models;
using View_by_Distance.Shared.Models.Stateless;
namespace View_by_Distance.Instance.Models;
/// <summary>
// *.png
/// </summary>
internal class D2_FaceLandmarks
{
internal List<string> AngleBracketCollection { get; }
private readonly Serilog.ILogger? _Log;
private readonly Configuration _Configuration;
internal D2_FaceLandmarks(Configuration configuration)
{
_Configuration = configuration;
AngleBracketCollection = new List<string>();
_Log = Serilog.Log.ForContext<D2_FaceLandmarks>();
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
#pragma warning disable CA1416
private static Bitmap RotateBitmap(Image image, float angle)
{
Bitmap result;
Bitmap bitmap = new(image);
result = D_Face.RotateBitmap(bitmap, angle);
if (bitmap is not null)
bitmap.Dispose();
return result;
}
private static void SaveFaceLandmarkImages(List<D_Face> faceCollections, List<string[]> imageFiles, int pointSize, FileInfo resizedFileInfo)
{
int x;
int y;
D_Face face;
int width;
int height;
string imageFileFullName;
Bitmap rotated;
string rotatedImageFileFullName;
Shared.Models.FacePoint[] facePoints;
for (int i = 0; i < faceCollections.Count; i++)
{
if (!faceCollections[i].Populated)
continue;
face = faceCollections[i];
imageFileFullName = imageFiles[i][0];
rotatedImageFileFullName = imageFiles[i][1];
try
{
using (Image image = Image.FromFile(resizedFileInfo.FullName))
{
using Graphics graphic = Graphics.FromImage(image);
if (face.FaceLandmarks is null || !face.FaceLandmarks.Any())
{
width = face.Location.Right - face.Location.Left;
height = face.Location.Bottom - face.Location.Top;
graphic.DrawEllipse(Pens.Red, face.Location.Left, face.Location.Top, width, height);
}
else
{
foreach (KeyValuePair<string, Shared.Models.FacePoint[]> keyValuePair in face.FaceLandmarks)
{
facePoints = keyValuePair.Value.ToArray();
foreach (Shared.Models.FacePoint facePoint in facePoints)
graphic.DrawEllipse(Pens.GreenYellow, face.Location.Left + facePoint.X - pointSize, face.Location.Top + facePoint.Y - pointSize, pointSize * 2, pointSize * 2);
if (keyValuePair.Key == FacePart.Chin.ToString())
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();
graphic.DrawEllipse(Pens.Purple, face.Location.Left + x - pointSize, face.Location.Top + y - pointSize, pointSize * 2, pointSize * 2);
}
}
image.Save(imageFileFullName, System.Drawing.Imaging.ImageFormat.Png);
}
if (face.α.HasValue)
{
using Image image = Image.FromFile(resizedFileInfo.FullName);
rotated = RotateBitmap(image, (float)face.α.Value);
if (rotated is not null)
{
rotated.Save(rotatedImageFileFullName, System.Drawing.Imaging.ImageFormat.Png);
rotated.Dispose();
}
}
}
catch (Exception) { }
}
}
#pragma warning restore CA1416
internal void SaveFaceLandmarkImages(List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, string relativePath, string fileNameWithoutExtension, FileInfo resizedFileInfo, List<D_Face> faceCollections)
{
FileInfo fileInfo;
bool check = false;
string parentCheck;
const int pointSize = 2;
FileInfo rotatedFileInfo;
long ticks = DateTime.Now.Ticks;
List<string[]> imageFiles = new();
string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), fileNameWithoutExtension);
string[] changesFrom = new string[] { nameof(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);
for (int i = 0; i < faceCollections.Count; i++)
{
if (!faceCollections[i].Populated)
{
imageFiles.Add(Array.Empty<string>());
continue;
}
fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{i} - {fileNameWithoutExtension}.png"));
if (!fileInfo.Exists)
{
if (fileInfo.Directory?.Parent is null)
throw new Exception();
parentCheck = Path.Combine(fileInfo.Directory.Parent.FullName, fileInfo.Name);
if (File.Exists(parentCheck))
File.Delete(parentCheck);
}
if (string.IsNullOrEmpty(fileInfo.DirectoryName))
continue;
rotatedFileInfo = new FileInfo(Path.Combine(fileInfo.DirectoryName, string.Concat(Path.GetFileNameWithoutExtension(fileInfo.FullName), " - ", i, " - R", Path.GetExtension(fileInfo.FullName))));
imageFiles.Add(new string[] { fileInfo.FullName, rotatedFileInfo.FullName });
if (check)
continue;
if (_Configuration.OverrideForFaceLandmarkImages is null)
check = false;
else if (_Configuration.OverrideForFaceLandmarkImages.Value)
check = true;
else if (!fileInfo.Exists)
check = true;
else if (!rotatedFileInfo.Exists)
check = true;
else if (dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime)
check = true;
}
if (check)
SaveFaceLandmarkImages(faceCollections, imageFiles, pointSize, resizedFileInfo);
}
}