PhotoPrism

This commit is contained in:
2022-12-27 08:57:12 -07:00
parent d08cffe50d
commit e5dc8c1c05
25 changed files with 318 additions and 228 deletions

7
PhotoPrism/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
"cSpell.words": [
"dlib",
"Exif",
"Serilog"
]
}

View File

@ -0,0 +1,10 @@
namespace View_by_Distance.PhotoPrism.Models.Stateless;
internal static class SerilogExtensionMethods
{
internal static void Warn(this Serilog.ILogger log, string messageTemplate) => log.Warning(messageTemplate);
internal static void Info(this Serilog.ILogger log, string messageTemplate) => log.Information(messageTemplate);
}

View File

@ -0,0 +1,154 @@
using System.Text;
using System.Text.Json;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Stateless.Methods;
namespace View_by_Distance.PhotoPrism.Models;
public class F_PhotoPrism
{
private static JsonProperty[] GetJsonProperty(string fileName)
{
JsonProperty[] results;
string json = File.ReadAllText(fileName);
JsonElement? jsonElement = JsonSerializer.Deserialize<JsonElement>(json);
results = jsonElement.Value.EnumerateObject().ToArray();
return results;
}
private static Marker[]? GetMarkers(string photoPrismDirectory)
{
Marker[]? results;
string file = Path.Combine(photoPrismDirectory, "markers.json");
JsonProperty[] jsonProperties = GetJsonProperty(file);
results = JsonSerializer.Deserialize<Marker[]>(jsonProperties[1].Value);
return results;
}
private static Dictionary<string, List<Marker>> GetFileUIdToMarkers(string photoPrismDirectory)
{
Dictionary<string, List<Marker>> results = new();
Marker[]? markers = GetMarkers(photoPrismDirectory);
if (markers is null)
throw new NullReferenceException(nameof(markers));
foreach (Marker marker in markers)
{
if (!results.ContainsKey(marker.FileUid))
results.Add(marker.FileUid, new());
results[marker.FileUid].Add(marker);
}
return results;
}
private static DatabaseFile[]? GetDatabaseFiles(string photoPrismDirectory)
{
DatabaseFile[]? results;
string file = Path.Combine(photoPrismDirectory, "files.json");
JsonProperty[] jsonProperties = GetJsonProperty(file);
results = JsonSerializer.Deserialize<DatabaseFile[]>(jsonProperties[1].Value);
return results;
}
public static Dictionary<string, List<MappingFromPhotoPrism>> GetFileNameToCollection(string photoPrismDirectory)
{
Dictionary<string, List<MappingFromPhotoPrism>> results = new();
List<Marker>? makers;
MappingFromPhotoPrism mappingFromPhotoPrism;
List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection;
DatabaseFile[]? databaseFiles = GetDatabaseFiles(photoPrismDirectory);
if (databaseFiles is null)
throw new NullReferenceException(nameof(databaseFiles));
Dictionary<string, List<Marker>> fileUIdToMarkers = GetFileUIdToMarkers(photoPrismDirectory);
foreach (DatabaseFile databaseFile in databaseFiles)
{
if (!results.TryGetValue(databaseFile.FileName, out mappingFromPhotoPrismCollection))
{
results.Add(databaseFile.FileName, new());
if (!results.TryGetValue(databaseFile.FileName, out mappingFromPhotoPrismCollection))
throw new Exception();
}
if (!fileUIdToMarkers.TryGetValue(databaseFile.FileUid, out makers))
mappingFromPhotoPrism = new(databaseFile, new());
else
mappingFromPhotoPrism = new(databaseFile, makers);
mappingFromPhotoPrismCollection.Add(mappingFromPhotoPrism);
}
return results;
}
public static void WriteMatches(string photoPrismDirectory, string personBirthdayFormat, long ticks, Face[] distinctFilteredFaces, Shared.Models.Methods.IMapLogic mapLogic)
{
long? personKey;
const int zero = 0;
int? normalizedRectangle;
string personKeyFormatted;
List<string> subjects = new();
PersonBirthday personBirthday;
string personDisplayDirectoryName;
StringBuilder stringBuilder = new();
PersonContainer[]? personContainers;
System.Drawing.Rectangle dlibRectangle;
System.Drawing.Rectangle? prismRectangle;
System.Drawing.Rectangle intersectRectangle;
Dictionary<int, PersonContainer[]>? normalizedRectangleToPersonContainers;
(MappingFromPhotoPrism MappingFromPhotoPrism, Marker Marker, double Percent)[] sortedCollection;
List<(MappingFromPhotoPrism MappingFromPhotoPrism, Marker Marker, double Percent)> collection = new();
foreach (Face face in distinctFilteredFaces)
{
collection.Clear();
normalizedRectangle = face.Mapping?.MappingFromLocation.NormalizedRectangle;
if (normalizedRectangle is null)
continue;
if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null || face.Mapping is null)
continue;
if (face.Mapping.MappingFromPhotoPrismCollection is null)
continue;
(_, normalizedRectangleToPersonContainers) = mapLogic.GetNormalizedRectangleToPersonContainers(face.Mapping.MappingFromItem.Id);
if (normalizedRectangleToPersonContainers is null || !normalizedRectangleToPersonContainers.TryGetValue(normalizedRectangle.Value, out personContainers))
continue;
dlibRectangle = new(face.Location.Left, face.Location.Top, face.Location.Right - face.Location.Left, face.Location.Bottom - face.Location.Top);
foreach (MappingFromPhotoPrism mappingFromPhotoPrism in face.Mapping.MappingFromPhotoPrismCollection)
{
foreach (Marker marker in mappingFromPhotoPrism.Markers)
{
prismRectangle = ILocation.GetRectangle(face.OutputResolution, mappingFromPhotoPrism.DatabaseFile, marker);
if (prismRectangle is null)
continue;
intersectRectangle = System.Drawing.Rectangle.Intersect(dlibRectangle, prismRectangle.Value);
if (intersectRectangle.Width == 0 || intersectRectangle.Height == 0)
continue;
double percent = (double)intersectRectangle.Width * intersectRectangle.Height / (dlibRectangle.Width * dlibRectangle.Height);
if (percent < 0.000001)
continue;
collection.Add(new(mappingFromPhotoPrism, marker, percent));
}
}
if (!collection.Any())
continue;
sortedCollection = collection.OrderByDescending(l => l.Percent).ToArray();
foreach ((MappingFromPhotoPrism mappingFromPhotoPrism, Marker marker, double percent) in sortedCollection)
{
foreach (PersonContainer personContainer in personContainers)
{
if (personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any())
continue;
personBirthday = personContainer.Birthdays[zero];
personKey = personBirthday.Value.Ticks;
personDisplayDirectoryName = personContainer.DisplayDirectoryName;
personKeyFormatted = IPersonBirthday.GetFormatted(personBirthdayFormat, personBirthday);
subjects.Add($"update `subjects` set subj_alias = '{personKeyFormatted}' where subj_name = '{personDisplayDirectoryName}';");
_ = stringBuilder.
Append("update `markers` set subj_src = 'manual', marker_name = '").
Append(personDisplayDirectoryName).
Append("' where marker_uid = '").
Append(marker.MarkerUid).
AppendLine("';");
}
}
}
File.WriteAllLines(Path.Combine(photoPrismDirectory, $"{ticks}-subject_alias_update.sql"), subjects.Distinct());
File.WriteAllText(Path.Combine(photoPrismDirectory, $"{ticks}-marker_name_update.sql"), stringBuilder.ToString());
}
}

View File

@ -0,0 +1,47 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable>
<OutputType>library</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<PackageId>Phares.View.by.Distance.PhotoPrism</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>6.0.100.1</Version>
<Authors>Mike Phares</Authors>
<Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<PropertyGroup>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
</PropertyGroup>
<PropertyGroup Condition="'$(IsWindows)'=='true'">
<DefineConstants>Windows</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsOSX)'=='true'">
<DefineConstants>OSX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsLinux)'=='true'">
<DefineConstants>Linux</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'browser-wasm'">
<SupportedPlatform Include="browser" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="MetadataExtractor" Version="2.7.2" />
<PackageReference Include="Serilog" Version="2.12.0" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="WindowsShortcutFactory" Version="1.1.0" />
<PackageReference Include="System.Text.Json" Version="7.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
</ItemGroup>
</Project>