161 lines
6.7 KiB
C#
161 lines
6.7 KiB
C#
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);
|
||
}
|
||
|
||
} |