ReSaveFace

Removed GetLocationContainers
Split SetCreationTime and MoveToDecade
GetFilteredDistinctFileNameFirstSegments instead of GetFilteredDistinctIds for some
void Tick();
FaceFile
This commit is contained in:
2024-05-25 23:05:37 -07:00
parent 9a772f8dcc
commit 7f8b09e66c
18 changed files with 260 additions and 186 deletions

17
Shared/Models/FaceFile.cs Normal file
View File

@ -0,0 +1,17 @@
using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models;
public record FaceFile(DateTime DateTime,
string? DMS,
Dictionary<Stateless.FacePart, FacePoint[]>? FaceParts,
Location? Location,
string? Maker,
string? Model,
OutputResolution? OutputResolution);
[JsonSourceGenerationOptions(WriteIndented = false)]
[JsonSerializable(typeof(FaceFile))]
public partial class FaceFileGenerationContext : JsonSerializerContext
{
}

View File

@ -29,7 +29,7 @@ internal abstract class Container
return container.Items.Count == results.Count ? container.Items : new(results);
}
internal static List<Models.FilePair> GetFilePairs(Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string extension, string aPropertySingletonDirectory, ReadOnlyCollection<string[]> filesCollection)
internal static List<Models.FilePair> GetFilePairs(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string directorySearchFilter, string extension, string aPropertySingletonDirectory, ReadOnlyCollection<string[]> filesCollection)
{
int renamed;
const bool useCeilingAverage = true;
@ -37,16 +37,19 @@ internal abstract class Container
ReadOnlyCollection<string[]>? jsonFilesCollection = null;
IReadOnlyDictionary<string, List<string>>? compareFileNamesToFiles = null;
IReadOnlyDictionary<string, List<string>> fileNamesToFiles = XDirectory.GetFilesKeyValuePairs(filesCollection);
for (int i = 0; i < int.MaxValue; i++)
for (int i = 0; i < short.MaxValue; i++)
{
renamed = 0;
dlibDotNet?.Tick();
jsonFilesCollection = IDirectory.GetFilesCollection(aPropertySingletonDirectory, directorySearchFilter, extension, useCeilingAverage);
compareFileNamesToFiles = XDirectory.GetFilesKeyValuePairs(jsonFilesCollection);
renamed += XDirectory.LookForAbandoned(jsonFilesCollection, fileNamesToFiles, extension);
filePairs = XDirectory.GetFiles(filesCollection, fileNamesToFiles, extension, compareFileNamesToFiles);
filePairs = XDirectory.GetFiles(propertyConfiguration, filesCollection, fileNamesToFiles, extension, compareFileNamesToFiles);
renamed += XDirectory.MaybeMove(propertyConfiguration, filePairs, aPropertySingletonDirectory, extension);
if (renamed == 0)
break;
if (i > 10)
throw new NotImplementedException();
}
if (filePairs is null || jsonFilesCollection is null || compareFileNamesToFiles is null)
throw new NullReferenceException(nameof(filePairs));
@ -119,19 +122,19 @@ internal abstract class Container
results.Add(new(filePair.IsUnique, filePair.Collection, filePath, item));
}
private static List<FilePair> GetFilePairs(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection, string directorySearchFilter)
private static List<FilePair> GetFilePairs(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection, string directorySearchFilter)
{
List<FilePair> results = [];
const string extension = ".json";
int maxDegreeOfParallelism = Environment.ProcessorCount;
int filesCollectionDirectoryLength = filesCollectionDirectory.Length;
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
List<Models.FilePair> filePairs = GetFilePairs(propertyConfiguration, directorySearchFilter, extension, aPropertySingletonDirectory, filesCollection);
List<Models.FilePair> filePairs = GetFilePairs(dlibDotNet, propertyConfiguration, directorySearchFilter, extension, aPropertySingletonDirectory, filesCollection);
_ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) => ParallelFor(propertyConfiguration, aPropertySingletonDirectory, extension, filesCollectionDirectoryLength, filePairs[i], results));
return results;
}
private static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection, string directorySearchFilter)
private static (int, Models.Container[]) GetContainers(IDlibDotNet? dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection, string directorySearchFilter)
{
List<Models.Container> results = [];
string? directory;
@ -155,7 +158,7 @@ internal abstract class Container
throw new Exception();
}
}
List<FilePair> filePairs = GetFilePairs(propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filesCollection, directorySearchFilter);
List<FilePair> filePairs = GetFilePairs(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filesCollection, directorySearchFilter);
foreach (FilePair filePair in filePairs)
{
if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryName, out items))
@ -176,12 +179,12 @@ internal abstract class Container
return (filePairs.Count, results.ToArray());
}
internal static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection)
internal static (int, Models.Container[]) GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection)
{
int count;
Models.Container[] results;
const string directorySearchFilter = "*";
(count, results) = GetContainers(propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filesCollection, directorySearchFilter);
(count, results) = GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filesCollection, directorySearchFilter);
return (count, results);
}
@ -189,11 +192,12 @@ internal abstract class Container
{
int count;
Models.Container[] results;
IDlibDotNet? dlibDotNet = null;
const bool useCeilingAverage = true;
const string fileSearchFilter = "*";
const string directorySearchFilter = "*";
ReadOnlyCollection<string[]> filesCollection = IDirectory.GetFilesCollection(propertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
(count, results) = GetContainers(propertyConfiguration, aPropertySingletonDirectory, propertyConfiguration.RootDirectory, filesCollection, directorySearchFilter);
(count, results) = GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, propertyConfiguration.RootDirectory, filesCollection, directorySearchFilter);
return (count, results);
}
@ -220,6 +224,29 @@ internal abstract class Container
return results;
}
internal static List<string> GetFilteredDistinctFileNameFirstSegments(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers)
{
List<string> results = [];
ReadOnlyCollection<Models.Item> filteredItems;
foreach (Models.Container container in readOnlyContainers)
{
if (container.Items.Count == 0)
continue;
filteredItems = GetValidImageItems(propertyConfiguration, container);
if (filteredItems.Count == 0)
continue;
foreach (Models.Item item in filteredItems)
{
if (item.Property?.Id is null || item.ResizedFileHolder is null)
continue;
if (results.Contains(item.FilePath.FileNameFirstSegment))
continue;
results.Add(item.FilePath.FileNameFirstSegment);
}
}
return results;
}
internal static ReadOnlyCollection<Models.Item> GetValidImageItems(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> containers, bool distinctItems, bool filterItems)
{
List<Models.Item> results = [];

View File

@ -20,16 +20,21 @@ public interface IContainer
static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) =>
Container.GetContainers(propertyConfiguration, aPropertySingletonDirectory);
(int, Models.Container[]) TestStatic_GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection) =>
GetContainers(propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filesCollection);
static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection) =>
Container.GetContainers(propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filesCollection);
(int, Models.Container[]) TestStatic_GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection) =>
GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filesCollection);
static (int, Models.Container[]) GetContainers(IDlibDotNet dlibDotNet, Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection) =>
Container.GetContainers(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filesCollection);
List<int> TestStatic_GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
static List<int> GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
Container.GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
List<string> TestStatic_GetFilteredDistinctFileNameFirstSegments(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
GetFilteredDistinctFileNameFirstSegments(propertyConfiguration, readOnlyContainers);
static List<string> GetFilteredDistinctFileNameFirstSegments(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
Container.GetFilteredDistinctFileNameFirstSegments(propertyConfiguration, readOnlyContainers);
ReadOnlyCollection<Models.Item> TestStatic_GetValidImageItems(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> containers, bool distinctItems, bool filterItems) =>
GetValidImageItems(propertyConfiguration, containers, distinctItems, filterItems);
static ReadOnlyCollection<Models.Item> GetValidImageItems(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> containers, bool distinctItems, bool filterItems) =>

View File

@ -0,0 +1,8 @@
namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface IDlibDotNet
{
void Tick();
}

View File

@ -0,0 +1,9 @@
namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface IFaceD
{
public string FileNameExtension { get; }
void ReSaveFace(ExifDirectory exifDirectory, LocationContainer locationContainer, Models.Face face);
}

View File

@ -25,10 +25,10 @@ public interface ILocation
static Models.Location? GetLocation(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution) =>
Location.GetLocation(databaseFile, marker, outputResolution);
List<Models.Location> TestStatic_GetLocations(List<LocationContainer> locationContainers, List<Models.Face> faces, List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, float rectangleIntersectMinimum) =>
GetLocations(locationContainers, faces, mappingFromPhotoPrismCollection, rectangleIntersectMinimum);
static List<Models.Location> GetLocations(List<LocationContainer> locationContainers, List<Models.Face> faces, List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, float rectangleIntersectMinimum) =>
Location.GetLocations(locationContainers, faces, mappingFromPhotoPrismCollection, rectangleIntersectMinimum);
List<Models.Location> TestStatic_GetLocations(List<Models.Face> faces, List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, float rectangleIntersectMinimum) =>
GetLocations(faces, mappingFromPhotoPrismCollection, rectangleIntersectMinimum);
static List<Models.Location> GetLocations(List<Models.Face> faces, List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, float rectangleIntersectMinimum) =>
Location.GetLocations(faces, mappingFromPhotoPrismCollection, rectangleIntersectMinimum);
RectangleF? TestStatic_GetPercentagesRectangle(int locationDigits, int wholePercentages) =>
GetPercentagesRectangle(locationDigits, wholePercentages);

View File

@ -245,7 +245,7 @@ internal abstract class Location
return result;
}
internal static List<Models.Location> GetLocations(List<LocationContainer> locationContainers, List<Models.Face> faces, List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, float rectangleIntersectMinimum)
internal static List<Models.Location> GetLocations(List<Models.Face> faces, List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, float rectangleIntersectMinimum)
{
List<Models.Location> results = [];
bool any;
@ -266,12 +266,6 @@ internal abstract class Location
outputResolution ??= face.OutputResolution;
}
int before = results.Count;
foreach (LocationContainer locationContainer in locationContainers)
{
if (locationContainer.Location is null)
continue;
results.Add(locationContainer.Location);
}
foreach (MappingFromPhotoPrism mappingFromPhotoPrism in mappingFromPhotoPrismCollection)
{
if (outputResolution is null)
@ -289,19 +283,6 @@ internal abstract class Location
location = GetLocation(mappingFromPhotoPrism.DatabaseFile, marker, prismRectangle.Value);
if (location is null)
break;
foreach (LocationContainer locationContainer in locationContainers)
{
if (any)
continue;
if (locationContainer.Rectangle is null)
continue;
percent = GetIntersectPercent(prismRectangle.Value, prismArea, locationContainer.Rectangle.Value);
if (percent is null || percent < rectangleIntersectMinimum)
continue;
if (!any)
any = true;
break;
}
foreach (Models.Face face in faces)
{
if (any)

View File

@ -147,12 +147,13 @@ internal abstract partial class XDirectory
return result;
}
internal static List<FilePair> GetFiles(ReadOnlyCollection<string[]> filesCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension, IReadOnlyDictionary<string, List<string>> compareFileNamesToFiles)
internal static List<FilePair> GetFiles(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<string[]> filesCollection, IReadOnlyDictionary<string, List<string>> fileNamesToFiles, string extension, IReadOnlyDictionary<string, List<string>> compareFileNamesToFiles)
{
List<FilePair> results = [];
string? match;
string fileName;
bool uniqueFileName;
string fileExtension;
List<string>? collection;
bool? isNotUniqueAndNeedsReview;
foreach (string[] files in filesCollection)
@ -161,6 +162,9 @@ internal abstract partial class XDirectory
{
isNotUniqueAndNeedsReview = null;
fileName = Path.GetFileName(file);
fileExtension = Path.GetExtension(file);
if (propertyConfiguration.IgnoreExtensions.Contains(fileExtension))
continue;
if (!fileNamesToFiles.TryGetValue(fileName, out collection))
throw new Exception();
uniqueFileName = collection.Count == 1;
@ -260,7 +264,10 @@ internal abstract partial class XDirectory
continue;
checkFile = file.Replace(find, replace);
if (File.Exists(checkFile))
{
File.Delete(checkFile);
continue;
}
File.Move(file, checkFile);
}
}