.config
.vscode
BlurHash
BlurHash.Core
BlurHash.System.Drawing.Common
Compare
Copy-Distinct
Date-Group
Delete-By-Distinct
Delete-By-Relative
Distance
Drag-Drop-Explorer
Drag-Drop-Move
Drag-Drop-Search
Drag-Drop-Set-Property-Item
Duplicate-Search
Face
FaceParts
FaceRecognitionDotNet
Instance
Map
Metadata
Metadata-Query
Mirror-Length
Move-By-Id
Offset-Date-Time-Original
PhotoPrism
PrepareForOld
Property
Property-Compare
Rename
Resize
Set-Created-Date
Shared
.foam
.kanbn
.vscode
Models
Methods
Properties
Stateless
Methods
%ClassName%.cs .ai
Age.cs
Container.cs
DistanceHolder.cs
Face.cs
FaceDistance.cs
FaceDistanceContainer.cs
FaceFileSystem.cs
FacePoint.cs
FileHolder.cs
FileSystem.cs
I%ClassName%.cs .ai
IAge.cs
IBackgroundPage.cs
IContainer.cs
IDirectory.cs
IDirectoryFileSystem.cs
IDistanceHolder.cs
IFace.cs
IFaceDistance.cs
IFaceDistanceContainer.cs
IFaceFileSystem.cs
IFacePoint.cs
IFileHolder.cs
IFileSystem.cs
IIndex.cs
IItem.cs
ILocation.cs
IMapping.cs
IMappingFromItem.cs
IMetadataFile.cs
IMetadataFileCollection.cs
IMetadataFileId.cs
IMethodName.cs
IOutputResolution.cs
IPath.cs
IPerson.cs
IPersonBirthday.cs
IPersonContainer.cs
IProperty.cs
IRelativePaths.cs
ISorting.cs
ISortingContainer.cs
IStorage.cs
IWorkingDirectory.cs
ImageHelper.cs
Index.cs
Item.cs
Location.cs
Mapping.cs
MetadataFile.cs
MetadataFileCollection.cs
MetadataFileId.cs
OutputResolution.cs
PersonBirthday.cs
PersonContainer.cs
Property.cs
RelativePaths.cs
Sorting.cs
SortingContainer.cs
Storage.cs
WorkingDirectory.cs
XDirectory.cs
XPath.cs
FacePart.cs
IExif.cs
ILocation.cs
IMapLogic.cs
ImageFormat.cs
Mode.cs
Model.cs
PredictorModel.cs
%ClassName%.cs .ai
Console.cs
Container.cs
DatabaseFile.cs
DirectoryFileSystem.cs
DistanceHolder.cs
Face.cs
FaceDistance.cs
FaceDistanceContainer.cs
FaceEncoding.cs
FaceFileSystem.cs
FacePoint.cs
FileHolder.cs
FilePair.cs
FileSystem.cs
Item.cs
Location.cs
LocationContainer.cs
Mapping.cs
MappingFromFilter.cs
MappingFromItem.cs
MappingFromLocation.cs
MappingFromPerson.cs
MappingFromPhotoPrism.cs
Marker.cs
MatchNginx.cs
MetadataFile.cs
MetadataFileCollection.cs
MetadataFileId.cs
OutputResolution.cs
PersonBirthday.cs
PersonContainer.cs
PersonDirectory.cs
Property.cs
RelativeLocation.cs
RelativePaths.cs
SaveContainer.cs
SaveShortcutsForOutputResolutions.cs
Sorting.cs
SortingContainer.cs
Storage.cs
XPath.cs
Phares
Sample-Data
View-by-Distance.Shared.csproj
Tests
TestsWithFaceRecognitionDotNet
ThumbHash
.editorconfig
.gitattributes
.gitignore
.prettierignore
.txt
View-by-Distance-MKLink-Console.sln
package-lock.json
package.json
148 lines
5.2 KiB
C#
148 lines
5.2 KiB
C#
using System.Text.Json;
|
||
|
||
namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
||
|
||
internal abstract class Face
|
||
{
|
||
|
||
internal static string GetJson(string jsonFileFullName)
|
||
{
|
||
string result;
|
||
FileInfo fileInfo;
|
||
string fileSegment = "FileSegment";
|
||
result = File.ReadAllText(jsonFileFullName);
|
||
if (result.Contains(fileSegment))
|
||
{
|
||
fileInfo = new FileInfo(jsonFileFullName);
|
||
result = result.Replace(fileSegment, nameof(Properties.IIndex.RelativePaths)).Replace("\\\\", "/");
|
||
File.WriteAllText(fileInfo.FullName, result);
|
||
File.SetLastWriteTime(fileInfo.FullName, fileInfo.LastWriteTime);
|
||
}
|
||
if (result.Contains("/u0"))
|
||
{
|
||
fileInfo = new FileInfo(jsonFileFullName);
|
||
result = result.Replace("/u0", "\\u0");
|
||
File.WriteAllText(fileInfo.FullName, result);
|
||
File.SetLastWriteTime(fileInfo.FullName, fileInfo.LastWriteTime);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
private static JsonElement[] GetJsonElements(string jsonFileFullName)
|
||
{
|
||
string json = GetJson(jsonFileFullName);
|
||
JsonElement[]? jsonElements = JsonSerializer.Deserialize<JsonElement[]>(json) ?? throw new Exception();
|
||
return jsonElements;
|
||
}
|
||
|
||
private static List<Models.Face> GetFaces(string jsonFileFullName, int? maximum)
|
||
{
|
||
List<Models.Face> results = new();
|
||
Tuple<Models.Face, string>? tuple;
|
||
JsonElement[] jsonElements = GetJsonElements(jsonFileFullName);
|
||
foreach (JsonElement jsonElement in jsonElements)
|
||
{
|
||
tuple = JsonSerializer.Deserialize<Tuple<Models.Face, string>>(jsonElement.ToString());
|
||
if (tuple is null || tuple.Item1 is null || string.IsNullOrEmpty("tuple.Item1.RelativePath"))
|
||
continue;
|
||
results.Add(tuple.Item1);
|
||
if (maximum.HasValue && results.Count >= maximum)
|
||
break;
|
||
}
|
||
return results;
|
||
}
|
||
|
||
internal static Models.Face GetFace(string jsonFileFullName)
|
||
{
|
||
Models.Face? result;
|
||
List<Models.Face> results = GetFaces(jsonFileFullName, maximum: 1);
|
||
if (results.Count == 0)
|
||
throw new Exception();
|
||
result = results[0];
|
||
return result;
|
||
}
|
||
|
||
internal static Models.Face[] GetFaces(string jsonFileFullName)
|
||
{
|
||
List<Models.Face> results = GetFaces(jsonFileFullName, maximum: null);
|
||
return results.ToArray();
|
||
}
|
||
|
||
internal static double Getα(int x1, int x2, int y1, int y2)
|
||
{
|
||
double result;
|
||
if (y1 == y2)
|
||
result = 0;
|
||
else
|
||
{
|
||
int b;
|
||
if (x1 > x2)
|
||
b = x1 - x2;
|
||
else
|
||
b = x2 - x1;
|
||
int a;
|
||
if (y1 > y2)
|
||
a = y1 - y2;
|
||
else
|
||
a = y2 - y1;
|
||
double c = Math.Sqrt(Math.Pow(a, 2) + Math.Pow(b, 2));
|
||
if (y1 < y2)
|
||
result = 180 / Math.PI * Math.Asin(a / c);
|
||
else
|
||
result = 180 / Math.PI * Math.Asin(a / c) * -1;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
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;
|
||
int? rightEyeY = null;
|
||
foreach ((FacePart facePart, Models.FacePoint[] facePoints) in faceParts)
|
||
{
|
||
if (facePart is not FacePart.LeftEye and not FacePart.RightEye)
|
||
continue;
|
||
if (facePart is FacePart.LeftEye)
|
||
{
|
||
leftEyeX = (int)(from l in facePoints select l.X).Average();
|
||
leftEyeY = (int)(from l in facePoints select l.Y).Average();
|
||
}
|
||
if (facePart is FacePart.RightEye)
|
||
{
|
||
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, review) = (null, null);
|
||
else
|
||
{
|
||
review = lipY < rightEyeY || lipY < leftEyeY;
|
||
result = Getα(rightEyeX.Value, leftEyeX.Value, rightEyeY.Value, leftEyeY.Value);
|
||
}
|
||
return (review, result);
|
||
}
|
||
|
||
internal static (bool, int[]) GetEyeCollection(int threshold, List<Models.Face> faces)
|
||
{
|
||
bool result = false;
|
||
List<int> results = new();
|
||
foreach (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());
|
||
}
|
||
|
||
} |