LocationContainer
This commit is contained in:
parent
681b2fdf3c
commit
26edd826d5
@ -38,53 +38,14 @@ public partial class E_Distance
|
||||
_DistanceMoveUnableToMatch = distanceMoveUnableToMatch;
|
||||
}
|
||||
|
||||
private void MoveUnableToMatch(string eDistanceContentDirectory, string file, string fileName)
|
||||
private static void MoveUnableToMatch(string file)
|
||||
{
|
||||
bool check;
|
||||
string? directoryName = Path.GetDirectoryName(file);
|
||||
if (fileName is null || directoryName is null)
|
||||
check = false;
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(directoryName) || string.IsNullOrEmpty(directoryName) || !directoryName.Contains(eDistanceContentDirectory))
|
||||
check = false;
|
||||
else
|
||||
{
|
||||
List<string> directoryNames = new();
|
||||
string? checkDirectoryName = directoryName;
|
||||
for (int i = 0; i < int.MaxValue; i++)
|
||||
{
|
||||
if (string.IsNullOrEmpty(checkDirectoryName))
|
||||
continue;
|
||||
directoryNames.Add(Path.GetFileName(checkDirectoryName));
|
||||
checkDirectoryName = Path.GetDirectoryName(checkDirectoryName);
|
||||
if (string.IsNullOrEmpty(checkDirectoryName))
|
||||
continue;
|
||||
if (checkDirectoryName == eDistanceContentDirectory)
|
||||
break;
|
||||
}
|
||||
if (string.IsNullOrEmpty(checkDirectoryName) || !directoryNames.Any() || !long.TryParse(directoryNames[^1][1..^1], out long directoryTicks))
|
||||
{
|
||||
check = false;
|
||||
File.Delete(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
checkDirectoryName = Path.Combine(checkDirectoryName, $"({directoryTicks}_{string.Join('-', _RangeDistanceTolerance)})");
|
||||
for (int i = directoryNames.Count - 1 - 1; i > -1; i--)
|
||||
checkDirectoryName = Path.Combine(checkDirectoryName, directoryNames[i]);
|
||||
if (!Directory.Exists(checkDirectoryName))
|
||||
_ = Directory.CreateDirectory(checkDirectoryName);
|
||||
File.Move(file, Path.Combine(checkDirectoryName, fileName));
|
||||
check = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (check)
|
||||
_Moved.Add(file);
|
||||
string checkFile = string.Concat(file, ".unk");
|
||||
if (File.Exists(file) && !File.Exists(checkFile))
|
||||
File.Move(file, checkFile);
|
||||
}
|
||||
|
||||
private FaceDistanceContainer[] GetFaceDistanceContainers(MappingFromItem mappingFromItem, List<Face> filteredFaces)
|
||||
private FaceDistanceContainer[] GetFaceDistanceContainers(MappingFromItem mappingFromItem, List<Face> intersectFaces)
|
||||
{
|
||||
FaceDistanceContainer[] results;
|
||||
int confidencePercent;
|
||||
@ -92,7 +53,7 @@ public partial class E_Distance
|
||||
FaceDistance faceDistance;
|
||||
FaceDistanceContainer faceDistanceContainer;
|
||||
List<FaceDistanceContainer> collection = new();
|
||||
foreach (Face face in filteredFaces)
|
||||
foreach (Face face in intersectFaces)
|
||||
{
|
||||
if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null)
|
||||
throw new NotSupportedException();
|
||||
@ -104,7 +65,7 @@ public partial class E_Distance
|
||||
{
|
||||
faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
|
||||
faceDistance = new(confidencePercent, faceEncoding, mappingFromItem.Id, mappingFromItem.IsWrongYear, mappingFromItem.MinimumDateTime, normalizedRectangle);
|
||||
lock (filteredFaces)
|
||||
lock (intersectFaces)
|
||||
face.SetFaceDistance(faceDistance);
|
||||
}
|
||||
faceDistanceContainer = new(face, faceDistance);
|
||||
@ -126,42 +87,38 @@ public partial class E_Distance
|
||||
return faceDistanceEncodings;
|
||||
}
|
||||
|
||||
private List<(Face Face, double? Length)> GetValues(MappingFromItem mappingFromItem, Face[] faces, Shared.Models.FaceEncoding modelsFaceEncoding, int normalizedRectangle)
|
||||
private List<(Face Face, double? Length)> GetValues(MappingFromItem mappingFromItem, List<Face> intersectFaces, Shared.Models.FaceEncoding modelsFaceEncoding)
|
||||
{
|
||||
List<(Face Face, double? Length)> results = new();
|
||||
Face face;
|
||||
FaceDistance faceDistanceLength;
|
||||
List<Face> filteredFaces = FilterByIntersect(faces, normalizedRectangle);
|
||||
if (filteredFaces.Any())
|
||||
{
|
||||
FaceRecognitionDotNet.FaceEncoding faceRecognitionDotNetFaceEncoding = FaceRecognition.LoadFaceEncoding(modelsFaceEncoding.RawEncoding);
|
||||
FaceDistance faceDistanceEncoding = new(faceRecognitionDotNetFaceEncoding);
|
||||
FaceDistanceContainer[] faceDistanceContainers = GetFaceDistanceContainers(mappingFromItem, filteredFaces);
|
||||
FaceDistanceContainer[] faceDistanceContainers = GetFaceDistanceContainers(mappingFromItem, intersectFaces);
|
||||
int faceDistanceContainersLength = faceDistanceContainers.Length;
|
||||
if (faceDistanceContainersLength != filteredFaces.Count)
|
||||
if (faceDistanceContainersLength != intersectFaces.Count)
|
||||
throw new NotSupportedException();
|
||||
List<FaceDistance> faceDistanceEncodings = GetFaceDistanceEncodings(faceDistanceContainers);
|
||||
if (faceDistanceEncodings.Count != filteredFaces.Count)
|
||||
if (faceDistanceEncodings.Count != intersectFaces.Count)
|
||||
throw new NotSupportedException();
|
||||
List<FaceDistance> faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncoding);
|
||||
if (faceDistanceLengths.Count != faceDistanceContainersLength)
|
||||
throw new NotSupportedException();
|
||||
for (int i = 0; i < filteredFaces.Count; i++)
|
||||
for (int i = 0; i < intersectFaces.Count; i++)
|
||||
{
|
||||
face = filteredFaces[i];
|
||||
face = intersectFaces[i];
|
||||
faceDistanceLength = faceDistanceLengths[i];
|
||||
if (faceDistanceLength.Length is null)
|
||||
throw new NotSupportedException();
|
||||
results.Add(new(face, faceDistanceLength.Length.Value));
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private (Face, double?)[] GetClosestFaceByDistanceIgnoringTolerance(MappingFromItem mappingFromItem, int normalizedRectangle, Face[] filteredFaces, Shared.Models.FaceEncoding modelsFaceEncoding)
|
||||
private (Face, double?)[] GetClosestFaceByDistanceIgnoringTolerance(MappingFromItem mappingFromItem, List<Face> intersectFaces, Shared.Models.FaceEncoding modelsFaceEncoding)
|
||||
{
|
||||
(Face, double?)[] results;
|
||||
List<(Face Face, double? Length)> collection = GetValues(mappingFromItem, filteredFaces, modelsFaceEncoding, normalizedRectangle);
|
||||
List<(Face Face, double? Length)> collection = GetValues(mappingFromItem, intersectFaces, modelsFaceEncoding);
|
||||
results = (from l in collection orderby l.Length select l).Take(1).ToArray();
|
||||
if (results.Any())
|
||||
{
|
||||
@ -240,69 +197,40 @@ public partial class E_Distance
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Face> FilterByIntersect(Face[] faces, int normalizedRectangle)
|
||||
{
|
||||
List<Face> results = new();
|
||||
bool useOldWay;
|
||||
double? percent;
|
||||
System.Drawing.Rectangle checkRectangle;
|
||||
System.Drawing.Rectangle sourceRectangle;
|
||||
System.Drawing.Rectangle intersectRectangle;
|
||||
foreach (Face face in faces)
|
||||
{
|
||||
if (face.Location is null || face.OutputResolution is null)
|
||||
continue;
|
||||
checkRectangle = new(face.Location.Left, face.Location.Top, face.Location.Right - face.Location.Left, face.Location.Bottom - face.Location.Top);
|
||||
for (int i = 1; i < 3; i++)
|
||||
{
|
||||
useOldWay = i == 1;
|
||||
sourceRectangle = Shared.Models.Stateless.Methods.ILocation.GetRectangle(checkRectangle, Shared.Models.Stateless.ILocation.Digits, Shared.Models.Stateless.ILocation.Factor, normalizedRectangle, face.OutputResolution, useOldWay);
|
||||
intersectRectangle = System.Drawing.Rectangle.Intersect(checkRectangle, sourceRectangle);
|
||||
if (intersectRectangle.Width == 0 || intersectRectangle.Height == 0)
|
||||
continue;
|
||||
percent = (double)intersectRectangle.Width * intersectRectangle.Height / (checkRectangle.Width * checkRectangle.Height);
|
||||
if (percent < 0.000001)
|
||||
continue;
|
||||
results.Add(face);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public void LookForMatchFacesAndPossiblyRename(string facesFileNameExtension, string eDistanceContentDirectory, MappingFromItem mappingFromItem, List<Face> faces, List<(bool c, string File, int NormalizedRectangle, IReadOnlyList<MetadataExtractor.Directory>? Directories)> collection)
|
||||
public void LookForMatchFacesAndPossiblyRename(string facesFileNameExtension, string eDistanceContentDirectory, MappingFromItem mappingFromItem, List<Face> faces, List<LocationContainer<MetadataExtractor.Directory>> collection)
|
||||
{
|
||||
string? json;
|
||||
string fileName;
|
||||
string[] matches;
|
||||
FileInfo? fileInfo;
|
||||
List<Face> intersectFaces;
|
||||
List<(Face, double?)> checkFaces = new();
|
||||
Shared.Models.FaceEncoding? modelsFaceEncoding;
|
||||
Face[] filteredFaces = (from l in faces where l.FaceEncoding is not null && l.Location is not null && l.OutputResolution is not null select l).ToArray();
|
||||
if (filteredFaces.Length != faces.Count)
|
||||
checkFaces.Clear();
|
||||
foreach ((bool fromDistanceContent, string file, int normalizedRectangle, IReadOnlyList<MetadataExtractor.Directory>? directories) in collection)
|
||||
foreach (LocationContainer<MetadataExtractor.Directory>? locationContainer in collection)
|
||||
{
|
||||
if (!filteredFaces.Any())
|
||||
break;
|
||||
if (_Renamed.Contains(file))
|
||||
if (_Renamed.Contains(locationContainer.File))
|
||||
continue;
|
||||
fileName = Path.GetFileName(file);
|
||||
if (fromDistanceContent && _DuplicateMappedFaceFiles.Contains(fileName))
|
||||
fileName = Path.GetFileName(locationContainer.File);
|
||||
if (locationContainer.FromDistanceContent && _DuplicateMappedFaceFiles.Contains(fileName))
|
||||
continue;
|
||||
checkFaces.Clear();
|
||||
if (directories is null)
|
||||
if (!locationContainer.Directories.Any())
|
||||
{
|
||||
if (fromDistanceContent)
|
||||
throw new NullReferenceException(nameof(directories));
|
||||
if (locationContainer.FromDistanceContent)
|
||||
throw new NullReferenceException(nameof(locationContainer.Directories));
|
||||
continue;
|
||||
}
|
||||
json = Metadata.Models.Stateless.IMetadata.GetFaceEncoding(directories);
|
||||
json = Metadata.Models.Stateless.IMetadata.GetFaceEncoding(locationContainer.Directories);
|
||||
if (json is null)
|
||||
{
|
||||
if (_DistanceMoveUnableToMatch)
|
||||
MoveUnableToMatch(eDistanceContentDirectory, file, fileName);
|
||||
MoveUnableToMatch(locationContainer.File);
|
||||
continue;
|
||||
}
|
||||
if (filteredFaces.Any())
|
||||
checkFaces.AddRange(GetMatchingFacesByFaceEncoding(filteredFaces, json));
|
||||
if (checkFaces.Count == 1)
|
||||
_Debug.Add(0);
|
||||
@ -312,44 +240,49 @@ public partial class E_Distance
|
||||
modelsFaceEncoding = JsonSerializer.Deserialize<Shared.Models.FaceEncoding>(json);
|
||||
if (modelsFaceEncoding is null)
|
||||
throw new NotSupportedException();
|
||||
checkFaces.AddRange(GetClosestFaceByDistanceIgnoringTolerance(mappingFromItem, normalizedRectangle, filteredFaces, modelsFaceEncoding));
|
||||
if (filteredFaces.Any())
|
||||
{
|
||||
intersectFaces = Shared.Models.Stateless.Methods.ILocation.FilterByIntersect(filteredFaces, locationContainer.NormalizedRectangle);
|
||||
if (intersectFaces.Any())
|
||||
checkFaces.AddRange(GetClosestFaceByDistanceIgnoringTolerance(mappingFromItem, intersectFaces, modelsFaceEncoding));
|
||||
}
|
||||
}
|
||||
if (!checkFaces.Any())
|
||||
{
|
||||
if (_DistanceMoveUnableToMatch)
|
||||
MoveUnableToMatch(eDistanceContentDirectory, file, fileName);
|
||||
MoveUnableToMatch(locationContainer.File);
|
||||
continue;
|
||||
}
|
||||
if (checkFaces.Count != 1)
|
||||
{
|
||||
if (_DistanceMoveUnableToMatch)
|
||||
MoveUnableToMatch(eDistanceContentDirectory, file, fileName);
|
||||
MoveUnableToMatch(locationContainer.File);
|
||||
continue;
|
||||
}
|
||||
fileInfo = CheckFileThenGetFileInfo(facesFileNameExtension, mappingFromItem, file, checkFaces);
|
||||
fileInfo = CheckFileThenGetFileInfo(facesFileNameExtension, mappingFromItem, locationContainer.File, checkFaces);
|
||||
if (fileInfo is not null)
|
||||
{
|
||||
if (_DistanceRenameToMatch && fileInfo is not null)
|
||||
{
|
||||
if (fileInfo.Exists)
|
||||
File.Delete(file);
|
||||
File.Delete(locationContainer.File);
|
||||
else
|
||||
File.Move(file, fileInfo.FullName);
|
||||
_Renamed.Add(file);
|
||||
File.Move(locationContainer.File, fileInfo.FullName);
|
||||
_Renamed.Add(locationContainer.File);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (_AllMappedFaceFileNames.Contains(fileName))
|
||||
{
|
||||
lock (_AllMappedFaceFiles)
|
||||
matches = (from l in _AllMappedFaceFiles where l != file && Path.GetFileName(l) == fileName select l).ToArray();
|
||||
if (fromDistanceContent && matches.Any())
|
||||
AppendMatchingDuplicates(file, matches);
|
||||
matches = (from l in _AllMappedFaceFiles where l != locationContainer.File && Path.GetFileName(l) == fileName select l).ToArray();
|
||||
if (locationContainer.FromDistanceContent && matches.Any())
|
||||
AppendMatchingDuplicates(locationContainer.File, matches);
|
||||
}
|
||||
if (!fromDistanceContent)
|
||||
if (!locationContainer.FromDistanceContent)
|
||||
continue;
|
||||
lock (_AllMappedFaceFiles)
|
||||
_AllMappedFaceFiles.Add(file);
|
||||
_AllMappedFaceFiles.Add(locationContainer.File);
|
||||
lock (_AllMappedFaceFileNames)
|
||||
_AllMappedFaceFileNames.Add(fileName);
|
||||
}
|
||||
|
@ -140,6 +140,12 @@ public class D_Face
|
||||
|
||||
#pragma warning disable CA1416
|
||||
|
||||
private static (int width, int height) Get(string file)
|
||||
{
|
||||
using Bitmap source = new(file);
|
||||
return new(source.Width, source.Height);
|
||||
}
|
||||
|
||||
private PropertyItem GetPropertyItem(int id, string value)
|
||||
{
|
||||
PropertyItem result = (PropertyItem)_ConstructorInfo.Invoke(null);
|
||||
@ -291,12 +297,60 @@ public class D_Face
|
||||
|
||||
#pragma warning restore CA1416
|
||||
|
||||
public List<Shared.Models.Face> GetFaces(string dResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection)
|
||||
private static List<LocationContainer<MetadataExtractor.Directory>> GetCollection(int outputResolutionWidth, int outputResolutionHeight, List<LocationContainer<MetadataExtractor.Directory>> collection, List<Shared.Models.Face> faces)
|
||||
{
|
||||
List<LocationContainer<MetadataExtractor.Directory>> results = new();
|
||||
string? json;
|
||||
int width, height;
|
||||
Location? location;
|
||||
Rectangle? rectangle;
|
||||
List<int> skip = new();
|
||||
OutputResolution? outputResolution = null;
|
||||
foreach (Shared.Models.Face face in faces)
|
||||
{
|
||||
if (face.Location is null || face.OutputResolution is null)
|
||||
continue;
|
||||
skip.Add(Shared.Models.Stateless.Methods.ILocation.GetNormalizedRectangle(face.Location, ILocation.Digits, face.OutputResolution));
|
||||
}
|
||||
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in collection)
|
||||
{
|
||||
if (locationContainer.Directories is null)
|
||||
continue;
|
||||
if (skip.Contains(locationContainer.NormalizedRectangle))
|
||||
continue;
|
||||
foreach (Shared.Models.Face face in faces)
|
||||
{
|
||||
if (face.Location is not null && face.OutputResolution is not null)
|
||||
continue;
|
||||
json = Metadata.Models.Stateless.IMetadata.GetOutputResolution(locationContainer.Directories);
|
||||
if (json is not null)
|
||||
{
|
||||
outputResolution = JsonSerializer.Deserialize<OutputResolution>(json);
|
||||
if (outputResolution is not null && (outputResolution.Width != outputResolutionWidth || outputResolution.Height != outputResolutionHeight))
|
||||
continue;
|
||||
}
|
||||
(width, height) = Get(locationContainer.File);
|
||||
rectangle = Shared.Models.Stateless.Methods.ILocation.GetRectangle(height, ILocation.Digits, ILocation.Factor, locationContainer.NormalizedRectangle, outputResolutionHeight, outputResolutionWidth, width);
|
||||
if (rectangle is null)
|
||||
continue;
|
||||
location = Shared.Models.Stateless.Methods.ILocation.GetLocation(outputResolutionHeight, rectangle.Value, outputResolutionWidth);
|
||||
if (location is null)
|
||||
continue;
|
||||
if (!results.Any(l => l.NormalizedRectangle == locationContainer.NormalizedRectangle))
|
||||
results.Add(new(locationContainer.FromDistanceContent, locationContainer.File, locationContainer.NormalizedRectangle, locationContainer.Directories, rectangle.Value, location));
|
||||
}
|
||||
}
|
||||
if (results.Any())
|
||||
outputResolution = null;
|
||||
return results;
|
||||
}
|
||||
|
||||
public List<Shared.Models.Face> GetFaces(string dResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, List<LocationContainer<MetadataExtractor.Directory>>? collection, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection)
|
||||
{
|
||||
List<Shared.Models.Face>? results;
|
||||
if (string.IsNullOrEmpty(dResultsFullGroupDirectory))
|
||||
throw new NullReferenceException(nameof(dResultsFullGroupDirectory));
|
||||
string json;
|
||||
string? json;
|
||||
List<Location>? locations;
|
||||
string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) };
|
||||
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
|
||||
@ -334,10 +388,15 @@ public class D_Face
|
||||
parseExceptions.Add(nameof(D_Face));
|
||||
}
|
||||
}
|
||||
if (mappingFromPhotoPrismCollection is null || results is null)
|
||||
locations = null;
|
||||
List<LocationContainer<MetadataExtractor.Directory>> containers;
|
||||
if (results is null || collection is null)
|
||||
containers = new();
|
||||
else
|
||||
locations = Shared.Models.Stateless.Methods.ILocation.GetLocations(mappingFromPhotoPrismCollection, results);
|
||||
containers = GetCollection(outputResolutionWidth, outputResolutionHeight, collection, results);
|
||||
if (mappingFromPhotoPrismCollection is null || results is null)
|
||||
locations = (from l in containers where l is not null select l.Location).ToList();
|
||||
else
|
||||
locations = Shared.Models.Stateless.Methods.ILocation.GetLocations(mappingFromPhotoPrismCollection, results, containers);
|
||||
if (results is null || (locations is not null && locations.Any()))
|
||||
{
|
||||
results = GetFaces(property, mappingFromItem, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, locations);
|
||||
|
@ -283,7 +283,7 @@ public partial class DlibDotNet
|
||||
return result;
|
||||
}
|
||||
|
||||
private void FullParallelForWork(A_Property propertyLogic, Dictionary<int, List<(bool, string, int, IReadOnlyList<MetadataExtractor.Directory>?)>> idToMappedFaceFilesWithCollection, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsDateGroupDirectory, string dResultsFullGroupDirectory, string eDistanceContentDirectory, List<Tuple<string, DateTime>> sourceDirectoryChanges, List<FileHolder?> propertyFileHolderCollection, List<Shared.Models.Property?> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollections, List<Dictionary<string, int[]>> resizeKeyValuePairs, List<List<Shared.Models.Face>> imageFaceCollections, Container container, int index, Item item, DateTime[] containerDateTimes)
|
||||
private void FullParallelForWork(A_Property propertyLogic, Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToMappedFaceFilesWithCollection, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsDateGroupDirectory, string dResultsFullGroupDirectory, string eDistanceContentDirectory, List<Tuple<string, DateTime>> sourceDirectoryChanges, List<FileHolder?> propertyFileHolderCollection, List<Shared.Models.Property?> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollections, List<Dictionary<string, int[]>> resizeKeyValuePairs, List<List<Shared.Models.Face>> imageFaceCollections, Container container, int index, Item item, DateTime[] containerDateTimes)
|
||||
{
|
||||
if (_Log is null)
|
||||
throw new NullReferenceException(nameof(_Log));
|
||||
@ -369,10 +369,14 @@ public partial class DlibDotNet
|
||||
int outputResolutionHeight = outputResolutionCollection[1];
|
||||
int outputResolutionOrientation = outputResolutionCollection[2];
|
||||
List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection;
|
||||
List<(bool, string, int, IReadOnlyList<MetadataExtractor.Directory>?)>? collection;
|
||||
List<LocationContainer<MetadataExtractor.Directory>>? collection;
|
||||
if (item.Property?.Id is null)
|
||||
collection = null;
|
||||
else
|
||||
_ = idToMappedFaceFilesWithCollection.TryGetValue(item.Property.Id.Value, out collection);
|
||||
if (!_FileNameToCollection.TryGetValue(mappingFromItem.RelativePath[1..], out mappingFromPhotoPrismCollection))
|
||||
mappingFromPhotoPrismCollection = null;
|
||||
faces = _Faces.GetFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, mappingFromPhotoPrismCollection);
|
||||
faces = _Faces.GetFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, collection, mappingFromPhotoPrismCollection);
|
||||
if (_AppSettings.MaxDegreeOfParallelism < 2)
|
||||
ticks = LogDelta(ticks, nameof(D_Face.GetFaces));
|
||||
bool anyFacesSaved = _Faces.SaveFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, mappingFromItem, facesDirectory, faces);
|
||||
@ -380,8 +384,7 @@ public partial class DlibDotNet
|
||||
ticks = LogDelta(ticks, nameof(D_Face.SaveFaces));
|
||||
if ((_Configuration.DistanceMoveUnableToMatch || _Configuration.DistanceRenameToMatch)
|
||||
&& _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)
|
||||
&& !anyFacesSaved && item.Property?.Id is not null
|
||||
&& idToMappedFaceFilesWithCollection.TryGetValue(item.Property.Id.Value, out collection))
|
||||
&& !anyFacesSaved && collection is not null)
|
||||
_Distance.LookForMatchFacesAndPossiblyRename(_Faces.FileNameExtension, eDistanceContentDirectory, mappingFromItem, faces, collection);
|
||||
if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution))
|
||||
{
|
||||
@ -405,7 +408,7 @@ public partial class DlibDotNet
|
||||
|
||||
private int FullParallelWork(int maxDegreeOfParallelism,
|
||||
A_Property propertyLogic,
|
||||
Dictionary<int, List<(bool, string, int, IReadOnlyList<MetadataExtractor.Directory>?)>> idToMappedFaceFilesWithCollection,
|
||||
Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToMappedFaceFilesWithCollection,
|
||||
string outputResolution,
|
||||
string bResultsFullGroupDirectory,
|
||||
string cResultsFullGroupDirectory,
|
||||
@ -658,7 +661,7 @@ public partial class DlibDotNet
|
||||
int maxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism;
|
||||
List<Shared.Models.Property?> nullablePropertyCollection = new();
|
||||
List<List<KeyValuePair<string, string>>> metadataCollection = new();
|
||||
Dictionary<int, List<(bool, string, int, IReadOnlyList<MetadataExtractor.Directory>?)>> idToMappedFaceFilesWithCollection = GetDictionary(ticks, a2PeopleContentDirectory, eDistanceContentDirectory);
|
||||
Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToMappedFaceFilesWithCollection = GetDictionary(ticks, a2PeopleContentDirectory, eDistanceContentDirectory);
|
||||
string dResultsDateGroupDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(D_Face));
|
||||
foreach (string outputResolution in _Configuration.OutputResolutions)
|
||||
{
|
||||
@ -874,7 +877,7 @@ public partial class DlibDotNet
|
||||
List<Item> filteredItems = GetItems(argZero, containers);
|
||||
mapLogic.SaveShortcutsForOutputResolutions(filteredItems, mappingCollection, personKeyToCount);
|
||||
}
|
||||
if (_Configuration.PersonCharactersToCopyTo.Length == 1)
|
||||
if (_Configuration.PersonCharactersToCopyTo.Length == 1 && _Configuration.PersonCharacters.ToArray().Contains(_Configuration.PersonCharactersToCopyTo[0]))
|
||||
mapLogic.CopyAtLeastOneMappedFiles(_Configuration.PersonCharactersToCopyTo[0], dFacesContentDirectory, a2PeopleSingletonDirectory, mappingCollection);
|
||||
Dictionary<int, Dictionary<int, Mapping>> idToNormalizedRectangleToMapping = MapLogicSupport.GetIdToNormalizedRectangleToFace(mappingCollection);
|
||||
mapLogic.CopyManualFiles(dFacesContentDirectory, idToNormalizedRectangleToMapping);
|
||||
@ -1008,11 +1011,11 @@ public partial class DlibDotNet
|
||||
return results;
|
||||
}
|
||||
|
||||
private void ParallelFor(string eDistanceContentDirectory, List<(bool, string, int, int, IReadOnlyList<MetadataExtractor.Directory>?)> collection, string file)
|
||||
private void ParallelFor(string eDistanceContentDirectory, List<(bool, string, int, int, IReadOnlyList<MetadataExtractor.Directory>)> collection, string file)
|
||||
{
|
||||
const string lnk = ".lnk";
|
||||
int? id, normalizedRectangle;
|
||||
IReadOnlyList<MetadataExtractor.Directory>? directories;
|
||||
IReadOnlyList<MetadataExtractor.Directory> directories;
|
||||
bool fromDistanceContent = !file.EndsWith(lnk) && file.Contains(eDistanceContentDirectory);
|
||||
if (!file.EndsWith(lnk))
|
||||
(id, normalizedRectangle) = Shared.Models.Stateless.Methods.IMapping.GetConverted(_MapConfiguration.FacesFileNameExtension, file);
|
||||
@ -1021,52 +1024,58 @@ public partial class DlibDotNet
|
||||
if (id is null || normalizedRectangle is null)
|
||||
return;
|
||||
if (file.EndsWith(lnk) || (!_Configuration.DistanceMoveUnableToMatch && !_Configuration.DistanceRenameToMatch))
|
||||
directories = null;
|
||||
directories = new List<MetadataExtractor.Directory>();
|
||||
else
|
||||
directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(file);
|
||||
lock (collection)
|
||||
collection.Add(new(fromDistanceContent, file, id.Value, normalizedRectangle.Value, directories));
|
||||
}
|
||||
|
||||
private List<(bool, string, int, int, IReadOnlyList<MetadataExtractor.Directory>?)> GetCollection(long ticks, string? a2PeopleContentDirectory, string eDistanceContentDirectory)
|
||||
private List<(bool, string, int, int, IReadOnlyList<MetadataExtractor.Directory>)> GetCollection(long ticks, string? a2PeopleContentDirectory, string eDistanceContentDirectory)
|
||||
{
|
||||
string file;
|
||||
List<string> files = new();
|
||||
List<(bool, string, int, int, IReadOnlyList<MetadataExtractor.Directory>?)> results = new();
|
||||
List<(bool, string, int, int, IReadOnlyList<MetadataExtractor.Directory>)> results = new();
|
||||
files.AddRange(Map.Models.Stateless.Methods.IMapLogic.GetDisplayDirectoryAllFiles(_PersonContainers));
|
||||
files.AddRange(Map.Models.Stateless.Methods.IMapLogic.DeleteEmptyDirectoriesAndGetMappedFaceFiles(_MapConfiguration, _PersonContainers, ticks, a2PeopleContentDirectory, eDistanceContentDirectory));
|
||||
// foreach (string file in files)
|
||||
// {
|
||||
// if (!file.EndsWith(".dup"))
|
||||
// continue;
|
||||
// if (!File.Exists(file))
|
||||
// continue;
|
||||
// File.Move(file, file[..^4]);
|
||||
// }
|
||||
if (files.Any() && (_Configuration.DistanceMoveUnableToMatch || _Configuration.DistanceRenameToMatch))
|
||||
for (int i = 0; i < files.Count; i++)
|
||||
{
|
||||
file = files[i];
|
||||
if (!file.EndsWith(".dup") && !file.EndsWith(".unk"))
|
||||
continue;
|
||||
if (!File.Exists(file))
|
||||
continue;
|
||||
File.Move(file, file[..^4]);
|
||||
files[i] = file[..^4];
|
||||
}
|
||||
string[] distictFiles = files.Distinct().ToArray();
|
||||
if (distictFiles.Any() && (_Configuration.DistanceMoveUnableToMatch || _Configuration.DistanceRenameToMatch))
|
||||
{
|
||||
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||
string message = $") Building Mapped Face Files Collection - {totalSeconds} total second(s)";
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism };
|
||||
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||
using ProgressBar progressBar = new(files.Count, message, options);
|
||||
_ = Parallel.For(0, files.Count, parallelOptions, (i, state) =>
|
||||
using ProgressBar progressBar = new(distictFiles.Length, message, options);
|
||||
_ = Parallel.For(0, distictFiles.Length, parallelOptions, (i, state) =>
|
||||
{
|
||||
progressBar.Tick();
|
||||
ParallelFor(eDistanceContentDirectory, results, files[i]);
|
||||
ParallelFor(eDistanceContentDirectory, results, distictFiles[i]);
|
||||
});
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private Dictionary<int, List<(bool, string, int, IReadOnlyList<MetadataExtractor.Directory>?)>> GetDictionary(long ticks, string? a2PeopleContentDirectory, string eDistanceContentDirectory)
|
||||
private Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> GetDictionary(long ticks, string? a2PeopleContentDirectory, string eDistanceContentDirectory)
|
||||
{
|
||||
Dictionary<int, List<(bool, string, int, IReadOnlyList<MetadataExtractor.Directory>?)>> results = new();
|
||||
List<(bool, string, int, int, IReadOnlyList<MetadataExtractor.Directory>?)> collection = GetCollection(ticks, a2PeopleContentDirectory, eDistanceContentDirectory);
|
||||
foreach ((bool fromDistanceContent, string file, int id, int normalizedRectangle, IReadOnlyList<MetadataExtractor.Directory>? directories) in collection)
|
||||
Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> results = new();
|
||||
LocationContainer<MetadataExtractor.Directory> noob;
|
||||
List<(bool, string, int, int, IReadOnlyList<MetadataExtractor.Directory>)> collection = GetCollection(ticks, a2PeopleContentDirectory, eDistanceContentDirectory);
|
||||
foreach ((bool fromDistanceContent, string file, int id, int normalizedRectangle, IReadOnlyList<MetadataExtractor.Directory> directories) in collection)
|
||||
{
|
||||
if (!results.ContainsKey(id))
|
||||
results.Add(id, new());
|
||||
results[id].Add(new(fromDistanceContent, file, normalizedRectangle, directories));
|
||||
noob = new LocationContainer<MetadataExtractor.Directory>(fromDistanceContent, file, normalizedRectangle, directories, null, null);
|
||||
results[id].Add(noob);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
@ -915,7 +915,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
|
||||
collection.Clear();
|
||||
windowsShortcut = WindowsShortcut.Load(file);
|
||||
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file);
|
||||
if (windowsShortcut.Path is null)
|
||||
if (string.IsNullOrEmpty(windowsShortcut.Path))
|
||||
continue;
|
||||
if (!Directory.Exists(windowsShortcut.Path))
|
||||
{
|
||||
|
@ -233,7 +233,7 @@ internal abstract class MapLogic
|
||||
if (!string.IsNullOrEmpty(a2PeopleContentDirectory))
|
||||
File.WriteAllLines(Path.Combine(a2PeopleContentDirectory, "People - C.tsv"), from l in lines select l.Line);
|
||||
List<(string, string[], string)> collection = DeleteEmptyDirectoriesAndGetCollection(configuration, personKeyFormattedCollection, ticksDirectories, message);
|
||||
foreach ((string personKeyFormatted, string[] personDisplayDirectoryNames, string mappedFaceFile) in collection)
|
||||
foreach ((_, _, string mappedFaceFile) in collection)
|
||||
results.Add(mappedFaceFile);
|
||||
return results;
|
||||
}
|
||||
|
@ -8,9 +8,9 @@ public interface IMetadata
|
||||
static string? GetFaceEncoding(IReadOnlyList<MetadataExtractor.Directory> directories) =>
|
||||
Metadata.GetFaceEncoding(directories);
|
||||
|
||||
string? TestStatic_GetFaceX(IReadOnlyList<MetadataExtractor.Directory> directories) =>
|
||||
GetFaceX(directories);
|
||||
static string? GetFaceX(IReadOnlyList<MetadataExtractor.Directory> directories) =>
|
||||
Metadata.GetFaceX(directories);
|
||||
string? TestStatic_GetOutputResolution(IReadOnlyList<MetadataExtractor.Directory> directories) =>
|
||||
GetOutputResolution(directories);
|
||||
static string? GetOutputResolution(IReadOnlyList<MetadataExtractor.Directory> directories) =>
|
||||
Metadata.GetOutputResolution(directories);
|
||||
|
||||
}
|
@ -25,7 +25,7 @@ internal class Metadata
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static string? GetFaceX(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
internal static string? GetOutputResolution(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
{
|
||||
string? result;
|
||||
List<string> results = new();
|
||||
|
@ -64,6 +64,32 @@ public class A_Property
|
||||
|
||||
#pragma warning disable CA1416
|
||||
|
||||
private static List<DateTime> GetMetadataDateTimesByPattern(string dateTimeFormat, FileHolder fileHolder)
|
||||
{
|
||||
List<DateTime> results = new();
|
||||
try
|
||||
{
|
||||
DateTime checkDateTime;
|
||||
DateTime kristy = new(1976, 3, 8);
|
||||
IReadOnlyList<MetadataExtractor.Directory> directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(fileHolder.FullName);
|
||||
foreach (MetadataExtractor.Directory directory in directories)
|
||||
{
|
||||
foreach (MetadataExtractor.Tag tag in directory.Tags)
|
||||
{
|
||||
if (string.IsNullOrEmpty(tag.Description) || tag.Description.Length != dateTimeFormat.Length)
|
||||
continue;
|
||||
if (!DateTime.TryParseExact(tag.Description, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
|
||||
continue;
|
||||
if (checkDateTime < kristy)
|
||||
continue;
|
||||
results.Add(checkDateTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception) { }
|
||||
return results;
|
||||
}
|
||||
|
||||
private Shared.Models.Property GetImageProperty(FileHolder fileHolder, Shared.Models.Property? property, bool populateId, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions, int? id)
|
||||
{
|
||||
Shared.Models.Property result;
|
||||
@ -90,7 +116,7 @@ public class A_Property
|
||||
if (!isValidImageFormatExtension && isValidMetadataExtensions && fileHolder.Exists)
|
||||
{
|
||||
dateTimeFormat = "ddd MMM dd HH:mm:ss yyyy";
|
||||
List<DateTime> dateTimes = Shared.Models.Stateless.Methods.IProperty.GetMetadataDateTimesByPattern(dateTimeFormat, fileHolder);
|
||||
List<DateTime> dateTimes = GetMetadataDateTimesByPattern(dateTimeFormat, fileHolder);
|
||||
if (dateTimes.Any())
|
||||
dateTimeOriginal = dateTimes.Min();
|
||||
}
|
||||
|
6
Shared/Models/LocationContainer.cs
Normal file
6
Shared/Models/LocationContainer.cs
Normal file
@ -0,0 +1,6 @@
|
||||
using System.Drawing;
|
||||
|
||||
namespace View_by_Distance.Shared.Models;
|
||||
|
||||
public record LocationContainer<T>(bool FromDistanceContent, string File, int NormalizedRectangle, IReadOnlyList<T> Directories, Rectangle? Rectangle, Location? Location)
|
||||
{ }
|
@ -5,6 +5,16 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
||||
public interface ILocation
|
||||
{ // ...
|
||||
|
||||
Models.Location? TestStatic_GetLocation(int height, Rectangle rectangle, int width) =>
|
||||
GetLocation(height, rectangle, width);
|
||||
static Models.Location? GetLocation(int height, Rectangle rectangle, int width) =>
|
||||
Location.GetLocation(height, rectangle, width);
|
||||
|
||||
List<Models.Face> TestStatic_FilterByIntersect(Models.Face[] faces, int normalizedRectangle) =>
|
||||
FilterByIntersect(faces, normalizedRectangle);
|
||||
static List<Models.Face> FilterByIntersect(Models.Face[] faces, int normalizedRectangle) =>
|
||||
Location.FilterByIntersect(faces, normalizedRectangle);
|
||||
|
||||
Rectangle? TestStatic_GetRectangle(Models.OutputResolution outputResolution, DatabaseFile databaseFile, Marker marker) =>
|
||||
GetRectangle(outputResolution, databaseFile, marker);
|
||||
static Rectangle? GetRectangle(Models.OutputResolution outputResolution, DatabaseFile databaseFile, Marker marker) =>
|
||||
@ -15,15 +25,20 @@ public interface ILocation
|
||||
static Models.Location? GetLocation(Models.OutputResolution outputResolution, DatabaseFile databaseFile, Marker marker) =>
|
||||
Location.GetLocation(outputResolution, databaseFile, marker);
|
||||
|
||||
List<Models.Location> TestStatic_GetLocations(List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, List<Models.Face> faces) =>
|
||||
GetLocations(mappingFromPhotoPrismCollection, faces);
|
||||
static List<Models.Location> GetLocations(List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, List<Models.Face> faces) =>
|
||||
Location.GetLocations(mappingFromPhotoPrismCollection, faces);
|
||||
List<Models.Location> TestStatic_GetLocations<T>(List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, List<Models.Face> faces, List<LocationContainer<T>> containers) =>
|
||||
GetLocations(mappingFromPhotoPrismCollection, faces, containers);
|
||||
static List<Models.Location> GetLocations<T>(List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, List<Models.Face> faces, List<LocationContainer<T>> containers) =>
|
||||
Location.GetLocations(mappingFromPhotoPrismCollection, faces, containers);
|
||||
|
||||
Rectangle TestStatic_GetRectangle(Rectangle checkRectangle, int locationDigits, int locationFactor, int normalizedRectangle, Models.OutputResolution outputResolution, bool useOldWay) =>
|
||||
Rectangle? TestStatic_GetRectangle(Rectangle checkRectangle, int locationDigits, int locationFactor, int normalizedRectangle, Models.OutputResolution outputResolution, bool useOldWay) =>
|
||||
GetRectangle(checkRectangle, locationDigits, locationFactor, normalizedRectangle, outputResolution, useOldWay);
|
||||
static Rectangle GetRectangle(Rectangle checkRectangle, int locationDigits, int locationFactor, int normalizedRectangle, Models.OutputResolution outputResolution, bool useOldWay) =>
|
||||
Location.GetRectangle(checkRectangle, locationDigits, locationFactor, normalizedRectangle, OutputResolution.Get(outputResolution).Height, OutputResolution.Get(outputResolution).Width, useOldWay);
|
||||
static Rectangle? GetRectangle(Rectangle checkRectangle, int locationDigits, int locationFactor, int normalizedRectangle, Models.OutputResolution outputResolution, bool useOldWay) =>
|
||||
Location.GetRectangle(checkRectangle, OutputResolution.Get(outputResolution).Height, locationDigits, locationFactor, normalizedRectangle.ToString(), OutputResolution.Get(outputResolution).Width, useOldWay);
|
||||
|
||||
Rectangle? TestStatic_GetRectangle(int height, int locationDigits, int locationFactor, int normalizedRectangle, int outputResolutionHeight, int outputResolutionWidth, int width) =>
|
||||
GetRectangle(height, locationDigits, locationFactor, normalizedRectangle, outputResolutionHeight, outputResolutionWidth, width);
|
||||
static Rectangle? GetRectangle(int height, int locationDigits, int locationFactor, int normalizedRectangle, int outputResolutionHeight, int outputResolutionWidth, int width) =>
|
||||
Location.GetRectangle(height, locationDigits, locationFactor, normalizedRectangle.ToString(), outputResolutionHeight, outputResolutionWidth, width);
|
||||
|
||||
string TestStatic_GetLeftPadded(int locationDigits, string value) =>
|
||||
GetLeftPadded(locationDigits, value);
|
||||
|
@ -11,11 +11,6 @@ public interface IProperty
|
||||
static int GetDeterministicHashCode(byte[] value) =>
|
||||
Property.GetDeterministicHashCode(value);
|
||||
|
||||
List<DateTime> TestStatic_GetMetadataDateTimesByPattern(string dateTimeFormat, Models.FileHolder fileHolder) =>
|
||||
GetMetadataDateTimesByPattern(dateTimeFormat, fileHolder);
|
||||
static List<DateTime> GetMetadataDateTimesByPattern(string dateTimeFormat, Models.FileHolder fileHolder) =>
|
||||
Property.GetMetadataDateTimesByPattern(dateTimeFormat, fileHolder.FullName);
|
||||
|
||||
int TestStatic_GetDeterministicHashCode(string value) =>
|
||||
GetDeterministicHashCode(value);
|
||||
static int GetDeterministicHashCode(string value) =>
|
||||
|
@ -167,26 +167,43 @@ internal abstract class Location
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static Rectangle GetRectangle(Rectangle checkRectangle, int locationDigits, int locationFactor, int normalizedRectangleValue, int height, int width, bool useOldWay)
|
||||
internal static Rectangle? GetRectangle(Rectangle checkRectangle, int height, int locationDigits, int locationFactor, string normalizedRectangle, int width, bool useOldWay)
|
||||
{
|
||||
Rectangle? result;
|
||||
string normalizedRectangle = normalizedRectangleValue.ToString();
|
||||
if (normalizedRectangle.Length != locationDigits)
|
||||
throw new NotImplementedException();
|
||||
if (!useOldWay)
|
||||
{
|
||||
result = GetRectangle(locationDigits, height, normalizedRectangle, width);
|
||||
if (result is null)
|
||||
throw new NullReferenceException(nameof(result));
|
||||
}
|
||||
else
|
||||
if (useOldWay)
|
||||
{
|
||||
(int? x, int? y) = GetXY(locationDigits, locationFactor, width, height, normalizedRectangle);
|
||||
if (x is null || y is null)
|
||||
throw new Exception();
|
||||
result = new(x.Value - (checkRectangle.Width / 2), y.Value - (checkRectangle.Height / 2), checkRectangle.Width, checkRectangle.Height);
|
||||
}
|
||||
return result.Value;
|
||||
else
|
||||
{
|
||||
if (normalizedRectangle.Length != locationDigits)
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
result = GetRectangle(locationDigits, height, normalizedRectangle, width);
|
||||
if (result is null)
|
||||
throw new NullReferenceException(nameof(result));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static Rectangle? GetRectangle(int height, int locationDigits, int locationFactor, string normalizedRectangle, int outputResolutionHeight, int outputResolutionWidth, int width)
|
||||
{
|
||||
Rectangle? result;
|
||||
if (normalizedRectangle.Length == locationDigits && normalizedRectangle[0] is '4' or '8')
|
||||
result = GetRectangle(locationDigits, outputResolutionHeight, normalizedRectangle, outputResolutionWidth);
|
||||
else
|
||||
{
|
||||
(int? x, int? y) = GetXY(locationDigits, locationFactor, outputResolutionWidth, outputResolutionHeight, normalizedRectangle);
|
||||
if (x is null || y is null)
|
||||
throw new Exception();
|
||||
result = new(x.Value - (width / 2), y.Value - (height / 2), width, height);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static bool Matches(Models.OutputResolution outputResolution, DatabaseFile databaseFile)
|
||||
@ -217,6 +234,18 @@ internal abstract class Location
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static Models.Location? GetLocation(int height, Rectangle rectangle, int width)
|
||||
{
|
||||
Models.Location? result;
|
||||
double confidence = 0;
|
||||
bool verified = Check(rectangle.Bottom, height, rectangle.Left, rectangle.Right, rectangle.Top, width, zCount: 1, throwException: false);
|
||||
if (!verified)
|
||||
result = null;
|
||||
else
|
||||
result = new(rectangle.Bottom, confidence, rectangle.Left, rectangle.Right, rectangle.Top);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static Models.Location? GetLocation(Models.OutputResolution outputResolution, DatabaseFile databaseFile, Marker marker)
|
||||
{
|
||||
Models.Location? result;
|
||||
@ -228,7 +257,7 @@ internal abstract class Location
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static List<Models.Location> GetLocations(List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, List<Models.Face> faces)
|
||||
internal static List<Models.Location> GetLocations<T>(List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, List<Models.Face> faces, List<LocationContainer<T>> containers)
|
||||
{
|
||||
List<Models.Location> results = new();
|
||||
bool any;
|
||||
@ -246,6 +275,12 @@ internal abstract class Location
|
||||
outputResolution ??= face.OutputResolution;
|
||||
}
|
||||
int before = results.Count;
|
||||
foreach (LocationContainer<T> locationContainer in containers)
|
||||
{
|
||||
if (locationContainer.Location is null)
|
||||
continue;
|
||||
results.Add(locationContainer.Location);
|
||||
}
|
||||
foreach (MappingFromPhotoPrism mappingFromPhotoPrism in mappingFromPhotoPrismCollection)
|
||||
{
|
||||
if (outputResolution is null)
|
||||
@ -262,12 +297,27 @@ internal abstract class Location
|
||||
location = GetLocation(mappingFromPhotoPrism.DatabaseFile, marker, prismRectangle.Value);
|
||||
if (location is null)
|
||||
break;
|
||||
foreach (LocationContainer<T> locationContainer in containers)
|
||||
{
|
||||
if (any)
|
||||
continue;
|
||||
if (locationContainer.Location is null)
|
||||
continue;
|
||||
dlibRectangle = new(locationContainer.Location.Left, locationContainer.Location.Top, locationContainer.Location.Right - locationContainer.Location.Left, locationContainer.Location.Bottom - locationContainer.Location.Top);
|
||||
intersectRectangle = Rectangle.Intersect(prismRectangle.Value, dlibRectangle);
|
||||
if (intersectRectangle.Width == 0 && intersectRectangle.Height == 0)
|
||||
continue;
|
||||
any = true;
|
||||
break;
|
||||
}
|
||||
foreach (Models.Face face in faces)
|
||||
{
|
||||
if (any)
|
||||
continue;
|
||||
if (face.Location is null || face.OutputResolution is null)
|
||||
continue;
|
||||
dlibRectangle = new(face.Location.Left, face.Location.Top, face.Location.Right - face.Location.Left, face.Location.Bottom - face.Location.Top);
|
||||
intersectRectangle = Rectangle.Intersect(dlibRectangle, prismRectangle.Value);
|
||||
intersectRectangle = Rectangle.Intersect(prismRectangle.Value, dlibRectangle);
|
||||
if (intersectRectangle.Width == 0 && intersectRectangle.Height == 0)
|
||||
continue;
|
||||
any = true;
|
||||
@ -282,4 +332,35 @@ internal abstract class Location
|
||||
return results;
|
||||
}
|
||||
|
||||
internal static List<Models.Face> FilterByIntersect(Models.Face[] faces, int normalizedRectangle)
|
||||
{
|
||||
List<Models.Face> results = new();
|
||||
bool useOldWay;
|
||||
double? percent;
|
||||
Rectangle checkRectangle;
|
||||
Rectangle? sourceRectangle;
|
||||
Rectangle intersectRectangle;
|
||||
foreach (Models.Face face in faces)
|
||||
{
|
||||
if (face.Location is null || face.OutputResolution is null)
|
||||
continue;
|
||||
checkRectangle = new(face.Location.Left, face.Location.Top, face.Location.Right - face.Location.Left, face.Location.Bottom - face.Location.Top);
|
||||
for (int i = 1; i < 3; i++)
|
||||
{
|
||||
useOldWay = i == 1;
|
||||
sourceRectangle = ILocation.GetRectangle(checkRectangle, Stateless.ILocation.Digits, Stateless.ILocation.Factor, normalizedRectangle, face.OutputResolution, useOldWay);
|
||||
if (sourceRectangle is null)
|
||||
continue;
|
||||
intersectRectangle = Rectangle.Intersect(checkRectangle, sourceRectangle.Value);
|
||||
if (intersectRectangle.Width == 0 || intersectRectangle.Height == 0)
|
||||
continue;
|
||||
percent = (double)intersectRectangle.Width * intersectRectangle.Height / (checkRectangle.Width * checkRectangle.Height);
|
||||
if (percent < 0.000001)
|
||||
continue;
|
||||
results.Add(face);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
@ -343,32 +343,6 @@ internal abstract class Property
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static List<DateTime> GetMetadataDateTimesByPattern(string dateTimeFormat, string sourceDirectoryFile)
|
||||
{
|
||||
List<DateTime> results = new();
|
||||
try
|
||||
{
|
||||
DateTime checkDateTime;
|
||||
DateTime kristy = new(1976, 3, 8);
|
||||
IReadOnlyList<MetadataExtractor.Directory> directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(sourceDirectoryFile);
|
||||
foreach (MetadataExtractor.Directory directory in directories)
|
||||
{
|
||||
foreach (MetadataExtractor.Tag tag in directory.Tags)
|
||||
{
|
||||
if (string.IsNullOrEmpty(tag.Description) || tag.Description.Length != dateTimeFormat.Length)
|
||||
continue;
|
||||
if (!DateTime.TryParseExact(tag.Description, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
|
||||
continue;
|
||||
if (checkDateTime < kristy)
|
||||
continue;
|
||||
results.Add(checkDateTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception) { }
|
||||
return results;
|
||||
}
|
||||
|
||||
#pragma warning disable CA1416
|
||||
|
||||
internal static (DateTime?, int?, string?) Get(Models.FileHolder fileHolder)
|
||||
|
@ -35,6 +35,5 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="7.0.1" />
|
||||
<PackageReference Include="MetadataExtractor" Version="2.7.2" />
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
x
Reference in New Issue
Block a user