IgnoreExtensions-nef
Config-LoadPhotoPrismLocations TestMethodIntersect
This commit is contained in:
parent
1d0506d74c
commit
6f22929136
@ -13,6 +13,9 @@ completedColumns:
|
||||
|
||||
## Todo
|
||||
|
||||
- [nef-support](tasks/nef-support.md)
|
||||
- [determine-if-location-container-collection-is-needed-in-get-faces](tasks/determine-if-location-container-collection-is-needed-in-get-faces.md)
|
||||
- [use-eyes-to-find-orientation](tasks/use-eyes-to-find-orientation.md)
|
||||
- [use-photo-prism-to-map](tasks/use-photo-prism-to-map.md)
|
||||
- [import-face-region-metadata](tasks/import-face-region-metadata.md)
|
||||
|
||||
|
@ -0,0 +1,17 @@
|
||||
---
|
||||
created: 2023-06-12T15:44:11.932Z
|
||||
updated: 2023-06-12T15:45:59.891Z
|
||||
assigned: ""
|
||||
progress: 0
|
||||
tags: []
|
||||
---
|
||||
|
||||
# determine-if-location-container-collection-is-needed-in-get-faces
|
||||
|
||||
```c#
|
||||
locations = Shared.Models.Stateless.Methods.ILocation.GetLocations(collection, results, mappingFromPhotoPrismCollection, _RectangleIntersectMinimum);
|
||||
```
|
||||
|
||||
## Sub-tasks
|
||||
|
||||
- [ ] See code above
|
13
.kanbn/tasks/nef-support.md
Normal file
13
.kanbn/tasks/nef-support.md
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
created: 2023-06-12T15:44:11.932Z
|
||||
updated: 2023-06-12T15:45:59.891Z
|
||||
assigned: ""
|
||||
progress: 0
|
||||
tags: []
|
||||
---
|
||||
|
||||
# nef-support
|
||||
|
||||
## Sub-tasks
|
||||
|
||||
- [ ] asdf
|
13
.kanbn/tasks/use-eyes-to-find-orientation.md
Normal file
13
.kanbn/tasks/use-eyes-to-find-orientation.md
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
created: 2023-06-12T15:44:11.932Z
|
||||
updated: 2023-06-12T15:45:59.891Z
|
||||
assigned: ""
|
||||
progress: 0
|
||||
tags: []
|
||||
---
|
||||
|
||||
# use-eyes-to-find-orientation
|
||||
|
||||
## Sub-tasks
|
||||
|
||||
- [ ] asdf
|
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@ -18,6 +18,7 @@
|
||||
"Greyscale",
|
||||
"Hasher",
|
||||
"jfif",
|
||||
"JOSN",
|
||||
"mmod",
|
||||
"Nicéphore",
|
||||
"Niépce",
|
||||
@ -42,5 +43,8 @@
|
||||
"**/.git": false
|
||||
},
|
||||
"coverage-gutters.coverageBaseDir": "./.vscode/ReportGenerator/Cobertura/*",
|
||||
"extensions.ignoreRecommendations": true
|
||||
"extensions.ignoreRecommendations": true,
|
||||
"[markdown]": {
|
||||
"editor.wordWrap": "off"
|
||||
}
|
||||
}
|
@ -92,6 +92,8 @@
|
||||
"IgnoreExtensions": [
|
||||
".gif",
|
||||
".GIF",
|
||||
".nef",
|
||||
".NEF",
|
||||
".pdf",
|
||||
".PDF"
|
||||
],
|
||||
|
@ -72,6 +72,8 @@
|
||||
"IgnoreExtensions": [
|
||||
".gif",
|
||||
".GIF",
|
||||
".nef",
|
||||
".NEF",
|
||||
".pdf",
|
||||
".PDF"
|
||||
],
|
||||
|
@ -72,6 +72,8 @@
|
||||
"IgnoreExtensions": [
|
||||
".gif",
|
||||
".GIF",
|
||||
".nef",
|
||||
".NEF",
|
||||
".pdf",
|
||||
".PDF"
|
||||
],
|
||||
|
@ -74,6 +74,8 @@
|
||||
"IgnoreExtensions": [
|
||||
".gif",
|
||||
".GIF",
|
||||
".nef",
|
||||
".NEF",
|
||||
".pdf",
|
||||
".PDF"
|
||||
],
|
||||
|
@ -69,6 +69,8 @@
|
||||
"IgnoreExtensions": [
|
||||
".gif",
|
||||
".GIF",
|
||||
".nef",
|
||||
".NEF",
|
||||
".pdf",
|
||||
".PDF"
|
||||
],
|
||||
|
@ -23,7 +23,7 @@ public partial class E_Distance
|
||||
private readonly double _RangeDistanceToleranceAverage;
|
||||
private readonly List<string> _DuplicateMappedFaceFiles;
|
||||
|
||||
public E_Distance(bool distanceMoveUnableToMatch, bool distanceRenameToMatch, int faceConfidencePercent, float[] rangeDistanceTolerance, float[] rangeFaceConfidence, float[] rectangleIntersectMinimum)
|
||||
public E_Distance(bool distanceMoveUnableToMatch, bool distanceRenameToMatch, int faceConfidencePercent, float[] rangeDistanceTolerance, float[] rangeFaceConfidence, float[] rectangleIntersectMinimums)
|
||||
{
|
||||
_Debug = new();
|
||||
_Moved = new();
|
||||
@ -36,7 +36,7 @@ public partial class E_Distance
|
||||
_DistanceRenameToMatch = distanceRenameToMatch;
|
||||
_FaceConfidencePercent = faceConfidencePercent;
|
||||
_DistanceMoveUnableToMatch = distanceMoveUnableToMatch;
|
||||
_RectangleIntersectMinimum = rectangleIntersectMinimum.Max();
|
||||
_RectangleIntersectMinimum = rectangleIntersectMinimums.Max();
|
||||
_RangeDistanceToleranceAverage = rangeDistanceTolerance.Average();
|
||||
}
|
||||
|
||||
@ -199,7 +199,7 @@ public partial class E_Distance
|
||||
}
|
||||
}
|
||||
|
||||
public void LookForMatchFacesAndPossiblyRename(string facesFileNameExtension, MappingFromItem mappingFromItem, List<Face> faces, List<LocationContainer<MetadataExtractor.Directory>> collection)
|
||||
public void LookForMatchFacesAndPossiblyRename(string facesFileNameExtension, MappingFromItem mappingFromItem, List<Face> faces, List<LocationContainer<MetadataExtractor.Directory>> locationContainers)
|
||||
{
|
||||
string? json;
|
||||
string fileName;
|
||||
@ -211,7 +211,7 @@ public partial class E_Distance
|
||||
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 (LocationContainer<MetadataExtractor.Directory>? locationContainer in collection)
|
||||
foreach (LocationContainer<MetadataExtractor.Directory>? locationContainer in locationContainers)
|
||||
{
|
||||
if (_Renamed.Contains(locationContainer.File))
|
||||
continue;
|
||||
|
@ -71,6 +71,8 @@
|
||||
"IgnoreExtensions": [
|
||||
".gif",
|
||||
".GIF",
|
||||
".nef",
|
||||
".NEF",
|
||||
".pdf",
|
||||
".PDF"
|
||||
],
|
||||
|
@ -34,12 +34,14 @@ public class D_Face
|
||||
private readonly Serilog.ILogger? _Log;
|
||||
private readonly bool _OverrideForFaceImages;
|
||||
private readonly Configuration _Configuration;
|
||||
private readonly bool _LoadPhotoPrismLocations;
|
||||
private readonly ImageCodecInfo _ImageCodecInfo;
|
||||
private readonly ModelParameter _ModelParameter;
|
||||
private readonly PredictorModel _PredictorModel;
|
||||
private readonly bool _CheckDFaceAndUpWriteDates;
|
||||
private readonly bool _PropertiesChangedForFaces;
|
||||
private readonly ConstructorInfo _ConstructorInfo;
|
||||
private readonly float _RectangleIntersectMinimum;
|
||||
private readonly int _FaceDistanceHiddenImageFactor;
|
||||
private readonly EncoderParameters _EncoderParameters;
|
||||
private readonly ImageCodecInfo _HiddenImageCodecInfo;
|
||||
@ -59,11 +61,13 @@ public class D_Face
|
||||
string hiddenFileNameExtension,
|
||||
ImageCodecInfo hiddenImageCodecInfo,
|
||||
ImageCodecInfo imageCodecInfo,
|
||||
bool loadPhotoPrismLocations,
|
||||
string modelDirectory,
|
||||
string modelName,
|
||||
bool overrideForFaceImages,
|
||||
string predictorModelName,
|
||||
bool propertiesChangedForFaces)
|
||||
bool propertiesChangedForFaces,
|
||||
float[] rectangleIntersectMinimums)
|
||||
{
|
||||
_ArgZero = argZero;
|
||||
_Configuration = configuration;
|
||||
@ -76,17 +80,17 @@ public class D_Face
|
||||
_OverrideForFaceImages = overrideForFaceImages;
|
||||
_HiddenEncoderParameters = hiddenEncoderParameters;
|
||||
_HiddenFileNameExtension = hiddenFileNameExtension;
|
||||
_LoadPhotoPrismLocations = loadPhotoPrismLocations;
|
||||
_CheckDFaceAndUpWriteDates = checkDFaceAndUpWriteDates;
|
||||
_PropertiesChangedForFaces = propertiesChangedForFaces;
|
||||
_RectangleIntersectMinimum = rectangleIntersectMinimums.Min();
|
||||
_FaceDistanceHiddenImageFactor = faceDistanceHiddenImageFactor;
|
||||
_ForceFaceLastWriteTimeToCreationTime = forceFaceLastWriteTimeToCreationTime;
|
||||
(Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(modelDirectory, modelName, predictorModelName);
|
||||
_Model = model;
|
||||
_PredictorModel = predictorModel;
|
||||
_ModelParameter = modelParameter;
|
||||
ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, Array.Empty<Type>(), null);
|
||||
if (constructorInfo is null)
|
||||
throw new Exception();
|
||||
ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, Array.Empty<Type>(), null) ?? throw new Exception();
|
||||
_ConstructorInfo = constructorInfo;
|
||||
_WriteIndentedAndWhenWritingNull = new JsonSerializerOptions { WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull };
|
||||
}
|
||||
@ -294,7 +298,7 @@ public class D_Face
|
||||
|
||||
#pragma warning restore CA1416
|
||||
|
||||
private static List<LocationContainer<MetadataExtractor.Directory>> GetCollection(string outputResolution, List<LocationContainer<MetadataExtractor.Directory>> collection, Dictionary<string, int[]> outputResolutionToResize, List<Shared.Models.Face> faces)
|
||||
private static List<LocationContainer<MetadataExtractor.Directory>> GetLocationContainers(string outputResolution, List<LocationContainer<MetadataExtractor.Directory>> locationContainers, Dictionary<string, int[]> outputResolutionToResize, List<Shared.Models.Face> faces)
|
||||
{
|
||||
List<LocationContainer<MetadataExtractor.Directory>> results = new();
|
||||
string? json;
|
||||
@ -309,7 +313,7 @@ public class D_Face
|
||||
continue;
|
||||
skip.Add(Shared.Models.Stateless.Methods.ILocation.GetWholePercentages(face.Location, ILocation.Digits, face.OutputResolution));
|
||||
}
|
||||
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in collection)
|
||||
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers)
|
||||
{
|
||||
if (locationContainer.Directories is null)
|
||||
continue;
|
||||
@ -340,7 +344,7 @@ public class D_Face
|
||||
return results;
|
||||
}
|
||||
|
||||
public List<Shared.Models.Face> GetFaces(string outputResolution, string dResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize, List<LocationContainer<MetadataExtractor.Directory>>? collection, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection)
|
||||
public List<Shared.Models.Face> GetFaces(string outputResolution, string dResultsFullGroupDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize, List<LocationContainer<MetadataExtractor.Directory>>? locationContainers, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection)
|
||||
{
|
||||
List<Shared.Models.Face>? results;
|
||||
if (string.IsNullOrEmpty(dResultsFullGroupDirectory))
|
||||
@ -383,15 +387,15 @@ public class D_Face
|
||||
parseExceptions.Add(nameof(D_Face));
|
||||
}
|
||||
}
|
||||
List<LocationContainer<MetadataExtractor.Directory>> locationContainers;
|
||||
if (results is null || collection is null)
|
||||
locationContainers = new();
|
||||
List<LocationContainer<MetadataExtractor.Directory>> collection;
|
||||
if (results is null || locationContainers is null)
|
||||
collection = new();
|
||||
else
|
||||
locationContainers = GetCollection(outputResolution, collection, outputResolutionToResize, results);
|
||||
if (mappingFromPhotoPrismCollection is null || results is null)
|
||||
locations = (from l in locationContainers where l is not null select l.Location).ToList();
|
||||
collection = GetLocationContainers(outputResolution, locationContainers, outputResolutionToResize, results);
|
||||
if (!_LoadPhotoPrismLocations || mappingFromPhotoPrismCollection is null || results is null)
|
||||
locations = (from l in collection where l is not null select l.Location).ToList();
|
||||
else
|
||||
locations = Shared.Models.Stateless.Methods.ILocation.GetLocations(mappingFromPhotoPrismCollection, results, locationContainers);
|
||||
locations = Shared.Models.Stateless.Methods.ILocation.GetLocations(collection, results, mappingFromPhotoPrismCollection, _RectangleIntersectMinimum);
|
||||
if (results is null || (locations is not null && locations.Any()))
|
||||
{
|
||||
results = GetFaces(outputResolution, property, mappingFromItem, outputResolutionToResize, locations);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/// <summary>
|
||||
/// Represents an ordered pair of integer x- and y-coordinates that defines a point in a two-dimensional plane.
|
||||
/// </summary>
|
||||
public struct Point : IEquatable<Point>
|
||||
public readonly struct Point : IEquatable<Point>
|
||||
{
|
||||
|
||||
#region Constructors
|
||||
@ -73,7 +73,9 @@ public struct Point : IEquatable<Point>
|
||||
/// Returns the hash code for this <see cref="Point"/>.
|
||||
/// </summary>
|
||||
/// <returns>The hash code for this <see cref="Point"/> structure.</returns>
|
||||
#pragma warning disable IDE0070
|
||||
public override int GetHashCode()
|
||||
#pragma warning restore IDE0070
|
||||
{
|
||||
int hashCode = 1861411795;
|
||||
hashCode = hashCode * -1521134295 + X.GetHashCode();
|
||||
|
@ -95,11 +95,13 @@ public partial class DlibDotNet
|
||||
hiddenFileNameExtension,
|
||||
hiddenImageCodecInfo,
|
||||
imageCodecInfo,
|
||||
configuration.LoadPhotoPrismLocations,
|
||||
configuration.ModelDirectory,
|
||||
configuration.ModelName,
|
||||
configuration.OverrideForFaceImages,
|
||||
configuration.PredictorModelName,
|
||||
configuration.PropertiesChangedForFaces);
|
||||
configuration.PropertiesChangedForFaces,
|
||||
configuration.RectangleIntersectMinimums);
|
||||
}
|
||||
{
|
||||
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetGifLowQuality();
|
||||
@ -456,14 +458,14 @@ public partial class DlibDotNet
|
||||
else
|
||||
{
|
||||
List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection;
|
||||
List<LocationContainer<MetadataExtractor.Directory>>? collection;
|
||||
List<LocationContainer<MetadataExtractor.Directory>>? locationContainers;
|
||||
if (item.Property?.Id is null)
|
||||
collection = null;
|
||||
locationContainers = null;
|
||||
else
|
||||
_ = idToLocationContainers.TryGetValue(item.Property.Id.Value, out collection);
|
||||
_ = idToLocationContainers.TryGetValue(item.Property.Id.Value, out locationContainers);
|
||||
if (!fileNameToCollection.TryGetValue(mappingFromItem.Id, out mappingFromPhotoPrismCollection))
|
||||
mappingFromPhotoPrismCollection = null;
|
||||
faces = _Faces.GetFaces(outputResolution, dResultsFullGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionToResize, collection, mappingFromPhotoPrismCollection);
|
||||
faces = _Faces.GetFaces(outputResolution, dResultsFullGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionToResize, locationContainers, mappingFromPhotoPrismCollection);
|
||||
if (_AppSettings.MaxDegreeOfParallelism < 2)
|
||||
ticks = LogDelta(ticks, nameof(D_Face.GetFaces));
|
||||
List<(Shared.Models.Face, FileInfo?, string, bool Saved)> faceCollection = _Faces.SaveFaces(_FaceParts.FileNameExtension, dResultsFullGroupDirectory, subFileTuples, parseExceptions, mappingFromItem, facesDirectory, faces);
|
||||
@ -474,8 +476,8 @@ public partial class DlibDotNet
|
||||
ticks = LogDelta(ticks, nameof(D_Face.SaveFaces));
|
||||
if ((_Configuration.DistanceMoveUnableToMatch || _Configuration.DistanceRenameToMatch)
|
||||
&& _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)
|
||||
&& collection is not null && faceCollection.All(l => !l.Saved))
|
||||
_Distance.LookForMatchFacesAndPossiblyRename(_Faces.FileNameExtension, mappingFromItem, faces, collection);
|
||||
&& locationContainers is not null && faceCollection.All(l => !l.Saved))
|
||||
_Distance.LookForMatchFacesAndPossiblyRename(_Faces.FileNameExtension, mappingFromItem, faces, locationContainers);
|
||||
if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution))
|
||||
{
|
||||
bool saveRotated = false;
|
||||
@ -881,11 +883,11 @@ public partial class DlibDotNet
|
||||
private static void LookForAbandoned(ReadOnlyDictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers, List<int> distinctFilteredIds)
|
||||
{
|
||||
List<string> renameCollection = new();
|
||||
foreach (KeyValuePair<int, List<LocationContainer<MetadataExtractor.Directory>>> idToCollection in idToLocationContainers)
|
||||
foreach (KeyValuePair<int, List<LocationContainer<MetadataExtractor.Directory>>> keyValuePair in idToLocationContainers)
|
||||
{
|
||||
if (distinctFilteredIds.Contains(idToCollection.Key))
|
||||
if (distinctFilteredIds.Contains(keyValuePair.Key))
|
||||
continue;
|
||||
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in idToCollection.Value)
|
||||
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in keyValuePair.Value)
|
||||
{
|
||||
if (locationContainer.File.Contains('!'))
|
||||
continue;
|
||||
|
@ -34,6 +34,7 @@ public class Configuration
|
||||
[Display(Name = "Julie Phares Copy Birthdays"), Required] public string[] JLinks { get; set; }
|
||||
[Display(Name = "Load Or Create Then Save Distance Results"), Required] public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { get; set; }
|
||||
[Display(Name = "Load Or Create Then Save Image Faces Results"), Required] public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; }
|
||||
[Display(Name = "Load PhotoPrism Locations"), Required] public bool? LoadPhotoPrismLocations { get; set; }
|
||||
[Display(Name = "Location Digits"), Required] public int? LocationDigits { get; set; }
|
||||
[Display(Name = "Location Factor"), Required] public int? LocationFactor { get; set; }
|
||||
[Display(Name = "Look for Abandoned"), Required] public bool? LookForAbandoned { get; set; }
|
||||
@ -145,6 +146,8 @@ public class Configuration
|
||||
configuration.IgnoreRelativePaths ??= Array.Empty<string>();
|
||||
configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions ??= Array.Empty<string>();
|
||||
configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions ??= Array.Empty<string>();
|
||||
if (configuration.LoadPhotoPrismLocations is null)
|
||||
throw new NullReferenceException(nameof(configuration.LoadPhotoPrismLocations));
|
||||
if (configuration.LocationDigits is null)
|
||||
throw new NullReferenceException(nameof(configuration.LocationDigits));
|
||||
if (configuration.LocationFactor is null)
|
||||
@ -261,6 +264,7 @@ public class Configuration
|
||||
configuration.JLinks,
|
||||
configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions,
|
||||
configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions,
|
||||
configuration.LoadPhotoPrismLocations.Value,
|
||||
configuration.LocationDigits.Value,
|
||||
configuration.LocationFactor.Value,
|
||||
configuration.LookForAbandoned.Value,
|
||||
|
@ -33,6 +33,7 @@ public class Configuration
|
||||
public string[] JLinks { init; get; }
|
||||
public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { init; get; }
|
||||
public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { init; get; }
|
||||
public bool LoadPhotoPrismLocations { init; get; }
|
||||
public int LocationDigits { init; get; }
|
||||
public int LocationFactor { init; get; }
|
||||
public bool LookForAbandoned { init; get; }
|
||||
@ -112,6 +113,7 @@ public class Configuration
|
||||
string[] jLinks,
|
||||
string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions,
|
||||
string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions,
|
||||
bool loadPhotoPrismLocations,
|
||||
int locationDigits,
|
||||
int locationFactor,
|
||||
bool lookForAbandoned,
|
||||
@ -190,6 +192,7 @@ public class Configuration
|
||||
JLinks = jLinks;
|
||||
LoadOrCreateThenSaveDistanceResultsForOutputResolutions = loadOrCreateThenSaveDistanceResultsForOutputResolutions;
|
||||
LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = loadOrCreateThenSaveImageFacesResultsForOutputResolutions;
|
||||
LoadPhotoPrismLocations = loadPhotoPrismLocations;
|
||||
LocationDigits = locationDigits;
|
||||
LocationFactor = locationFactor;
|
||||
LookForAbandoned = lookForAbandoned;
|
||||
|
@ -71,6 +71,7 @@
|
||||
"FocusDirectory": "",
|
||||
"FocusModel": "",
|
||||
"GenealogicalDataCommunicationFile": "",
|
||||
"LoadPhotoPrismLocations": false,
|
||||
"LocationDigits": 9,
|
||||
"LocationFactor": 10000,
|
||||
"LookForAbandoned": true,
|
||||
|
@ -607,7 +607,7 @@ internal abstract class MapLogic
|
||||
return results;
|
||||
}
|
||||
|
||||
private static void ParallelFor(Configuration configuration, string eDistanceContentDirectory, List<LocationContainer<MetadataExtractor.Directory>> collection, long personKey, string file)
|
||||
private static void ParallelFor(Configuration configuration, string eDistanceContentDirectory, List<LocationContainer<MetadataExtractor.Directory>> locationContainers, long personKey, string file)
|
||||
{
|
||||
const string lnk = ".lnk";
|
||||
int? id, wholePercentages;
|
||||
@ -623,29 +623,29 @@ internal abstract class MapLogic
|
||||
directories = new List<MetadataExtractor.Directory>();
|
||||
else
|
||||
directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(file);
|
||||
Rectangle? rectangle = ILocation.GetWholePercentages(configuration.LocationDigits, wholePercentages.Value);
|
||||
lock (collection)
|
||||
collection.Add(new(fromDistanceContent, file, personKey, id.Value, wholePercentages.Value, directories, rectangle, null));
|
||||
RectangleF? rectangle = ILocation.GetPercentagesRectangle(configuration.LocationDigits, wholePercentages.Value);
|
||||
lock (locationContainers)
|
||||
locationContainers.Add(new(fromDistanceContent, file, personKey, id.Value, wholePercentages.Value, directories, rectangle, null));
|
||||
}
|
||||
|
||||
private static void OpenPossibleDuplicates(Configuration configuration, List<(long, int, string, double?)> duplicates)
|
||||
private static void OpenPossibleDuplicates(Configuration configuration, List<(long, int, string, float?)> duplicates)
|
||||
{
|
||||
string personKeyFormatted;
|
||||
foreach ((long personKey, int id, string file, double? percent) in duplicates)
|
||||
foreach ((long personKey, int id, string file, float? percent) in duplicates)
|
||||
{
|
||||
if (percent is null)
|
||||
continue;
|
||||
_ = Process.Start("explorer.exe", string.Concat("\"", Path.GetDirectoryName(file), "\""));
|
||||
personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, personKey);
|
||||
}
|
||||
foreach ((long personKey, int id, string file, double? percent) in duplicates)
|
||||
foreach ((long personKey, int id, string file, float? percent) in duplicates)
|
||||
{
|
||||
if (percent is not null && percent.Value == 0)
|
||||
continue;
|
||||
_ = Process.Start("explorer.exe", string.Concat("\"", Path.GetDirectoryName(file), "\""));
|
||||
personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, personKey);
|
||||
}
|
||||
foreach ((long personKey, int id, string file, double? percent) in duplicates)
|
||||
foreach ((long personKey, int id, string file, float? percent) in duplicates)
|
||||
{
|
||||
if (percent is not null && percent.Value > 0)
|
||||
continue;
|
||||
@ -654,35 +654,30 @@ internal abstract class MapLogic
|
||||
}
|
||||
}
|
||||
|
||||
private static void LookForPossibleDuplicates(Configuration configuration, List<LocationContainer<MetadataExtractor.Directory>> collection)
|
||||
private static void LookForPossibleDuplicates(Configuration configuration, List<LocationContainer<MetadataExtractor.Directory>> locationContainers)
|
||||
{
|
||||
string key;
|
||||
double? percent;
|
||||
Rectangle? rectangle;
|
||||
float? percent;
|
||||
float itemPercentagesArea;
|
||||
List<string> delete = new();
|
||||
Rectangle intersectRectangle;
|
||||
RectangleF? itemPercentagesRectangle;
|
||||
(string File, int WholePercentages) item;
|
||||
Dictionary<string, (string, int)> distinct = new();
|
||||
List<(long, int, string, double?)> duplicates = new();
|
||||
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in collection)
|
||||
List<(long, int, string, float?)> duplicates = new();
|
||||
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers)
|
||||
{
|
||||
key = string.Concat(locationContainer.PersonKey, locationContainer.Id);
|
||||
if (distinct.TryGetValue(key, out item))
|
||||
{
|
||||
if (item.WholePercentages == locationContainer.WholePercentages)
|
||||
continue;
|
||||
if (locationContainer.Rectangle is null)
|
||||
itemPercentagesRectangle = ILocation.GetPercentagesRectangle(configuration.LocationDigits, item.WholePercentages);
|
||||
if (itemPercentagesRectangle is null || locationContainer.Rectangle is null)
|
||||
percent = null;
|
||||
else
|
||||
{
|
||||
rectangle = ILocation.GetWholePercentages(configuration.LocationDigits, item.WholePercentages);
|
||||
if (locationContainer.Rectangle is null || rectangle is null)
|
||||
percent = null;
|
||||
else
|
||||
{
|
||||
intersectRectangle = Rectangle.Intersect(locationContainer.Rectangle.Value, rectangle.Value);
|
||||
percent = intersectRectangle.Width * intersectRectangle.Height;
|
||||
}
|
||||
itemPercentagesArea = itemPercentagesRectangle.Value.Width * itemPercentagesRectangle.Value.Height;
|
||||
percent = ILocation.GetIntersectPercent(itemPercentagesRectangle.Value, itemPercentagesArea, locationContainer.Rectangle.Value);
|
||||
}
|
||||
delete.Add(item.File);
|
||||
delete.Add(locationContainer.File);
|
||||
|
@ -72,6 +72,8 @@
|
||||
"IgnoreExtensions": [
|
||||
".gif",
|
||||
".GIF",
|
||||
".nef",
|
||||
".NEF",
|
||||
".pdf",
|
||||
".PDF"
|
||||
],
|
||||
|
@ -22,6 +22,8 @@
|
||||
"IgnoreExtensions": [
|
||||
".gif",
|
||||
".GIF",
|
||||
".nef",
|
||||
".NEF",
|
||||
".pdf",
|
||||
".PDF"
|
||||
],
|
||||
@ -137,6 +139,8 @@
|
||||
"IgnoreExtensions": [
|
||||
".gif",
|
||||
".GIF",
|
||||
".nef",
|
||||
".NEF",
|
||||
".pdf",
|
||||
".PDF"
|
||||
],
|
||||
|
@ -30,7 +30,7 @@ public record Marker(
|
||||
internal static Shared.Models.Marker Map(Marker marker)
|
||||
{
|
||||
Shared.Models.Marker result;
|
||||
(double x, double y, double w, double h, double score) = (double.Parse(marker.X), double.Parse(marker.Y), double.Parse(marker.W), double.Parse(marker.H), double.Parse(marker.Score));
|
||||
(float x, float y, float w, float h, float score) = (float.Parse(marker.X), float.Parse(marker.Y), float.Parse(marker.W), float.Parse(marker.H), float.Parse(marker.Score));
|
||||
result = new(
|
||||
F_PhotoPrism.HexStringToString(marker.MarkerUid),
|
||||
F_PhotoPrism.HexStringToString(marker.FileUid),
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using View_by_Distance.Shared.Models;
|
||||
@ -139,14 +140,14 @@ public class F_PhotoPrism
|
||||
return results;
|
||||
}
|
||||
|
||||
private static void PopulateSubjects(string mappingDefaultName, string personBirthdayFormat, List<string> subjects, StringBuilder stringBuilder, PersonContainer[] personContainers, (MappingFromPhotoPrism MappingFromPhotoPrism, Shared.Models.Marker Marker, double Percent)[] sortedCollection)
|
||||
private static void PopulateSubjects(string mappingDefaultName, string personBirthdayFormat, List<string> subjects, StringBuilder stringBuilder, PersonContainer[] personContainers, (MappingFromPhotoPrism MappingFromPhotoPrism, Shared.Models.Marker Marker, float Percent)[] sortedCollection)
|
||||
{
|
||||
long? personKey;
|
||||
string personName;
|
||||
const int zero = 0;
|
||||
string personKeyFormatted;
|
||||
PersonBirthday personBirthday;
|
||||
foreach ((MappingFromPhotoPrism mappingFromPhotoPrism, Shared.Models.Marker marker, double percent) in sortedCollection)
|
||||
foreach ((MappingFromPhotoPrism mappingFromPhotoPrism, Shared.Models.Marker marker, float percent) in sortedCollection)
|
||||
{
|
||||
foreach (PersonContainer personContainer in personContainers)
|
||||
{
|
||||
@ -173,18 +174,22 @@ public class F_PhotoPrism
|
||||
{
|
||||
string file;
|
||||
string text;
|
||||
double percent;
|
||||
float dlibArea;
|
||||
float? percent;
|
||||
string directory;
|
||||
int width, height;
|
||||
int? wholePercentages;
|
||||
RectangleF? prismRectangle;
|
||||
List<string> subjects = new();
|
||||
DateTime dateTime = new(ticks);
|
||||
int dlibLocationWholePercentages;
|
||||
PersonContainer[]? personContainers;
|
||||
StringBuilder stringBuilder = new();
|
||||
System.Drawing.Rectangle dlibRectangle;
|
||||
System.Drawing.Rectangle? prismRectangle;
|
||||
System.Drawing.Rectangle intersectRectangle;
|
||||
RectangleF? dlibPercentagesRectangle;
|
||||
float rectangleIntersectMinimum = rectangleIntersectMinimums.Min();
|
||||
Dictionary<int, PersonContainer[]>? wholePercentagesToPersonContainers;
|
||||
(MappingFromPhotoPrism MappingFromPhotoPrism, Shared.Models.Marker Marker, double Percent)[] sortedCollection;
|
||||
List<(MappingFromPhotoPrism MappingFromPhotoPrism, Shared.Models.Marker Marker, double Percent)> collection = new();
|
||||
(MappingFromPhotoPrism MappingFromPhotoPrism, Shared.Models.Marker Marker, float Percent)[] sortedCollection;
|
||||
List<(MappingFromPhotoPrism MappingFromPhotoPrism, Shared.Models.Marker Marker, float Percent)> collection = new();
|
||||
foreach (Face face in distinctFilteredFaces)
|
||||
{
|
||||
collection.Clear();
|
||||
@ -198,21 +203,23 @@ public class F_PhotoPrism
|
||||
(_, wholePercentagesToPersonContainers) = mapLogic.GetWholePercentagesToPersonContainers(face.Mapping.MappingFromItem.Id);
|
||||
if (wholePercentagesToPersonContainers is null || !wholePercentagesToPersonContainers.TryGetValue(wholePercentages.Value, out personContainers))
|
||||
continue;
|
||||
dlibRectangle = new(face.Location.Left, face.Location.Top, face.Location.Right - face.Location.Left, face.Location.Bottom - face.Location.Top);
|
||||
(width, height) = IOutputResolution.Get(face.OutputResolution);
|
||||
dlibLocationWholePercentages = ILocation.GetWholePercentages(height, face.Location, Shared.Models.Stateless.ILocation.Digits, width);
|
||||
dlibPercentagesRectangle = ILocation.GetPercentagesRectangle(Shared.Models.Stateless.ILocation.Digits, dlibLocationWholePercentages);
|
||||
if (dlibPercentagesRectangle is null)
|
||||
continue;
|
||||
dlibArea = dlibPercentagesRectangle.Value.Width * dlibPercentagesRectangle.Value.Height;
|
||||
foreach (MappingFromPhotoPrism mappingFromPhotoPrism in face.Mapping.MappingFromPhotoPrismCollection)
|
||||
{
|
||||
foreach (Shared.Models.Marker marker in mappingFromPhotoPrism.Markers)
|
||||
{
|
||||
prismRectangle = ILocation.GetRectangle(mappingFromPhotoPrism.DatabaseFile, marker, face.OutputResolution);
|
||||
prismRectangle = ILocation.GetPercentagesRectangle(mappingFromPhotoPrism.DatabaseFile, marker, face.OutputResolution);
|
||||
if (prismRectangle is null)
|
||||
continue;
|
||||
intersectRectangle = System.Drawing.Rectangle.Intersect(dlibRectangle, prismRectangle.Value);
|
||||
if (intersectRectangle.Width == 0 || intersectRectangle.Height == 0)
|
||||
percent = ILocation.GetIntersectPercent(dlibPercentagesRectangle.Value, dlibArea, prismRectangle.Value);
|
||||
if (percent is null || percent < rectangleIntersectMinimum)
|
||||
continue;
|
||||
percent = (double)intersectRectangle.Width * intersectRectangle.Height / (dlibRectangle.Width * dlibRectangle.Height);
|
||||
if (percent < rectangleIntersectMinimum)
|
||||
continue;
|
||||
collection.Add(new(mappingFromPhotoPrism, marker, percent));
|
||||
collection.Add(new(mappingFromPhotoPrism, marker, percent.Value));
|
||||
}
|
||||
}
|
||||
if (!collection.Any())
|
||||
@ -222,10 +229,13 @@ public class F_PhotoPrism
|
||||
}
|
||||
if (subjects.Any())
|
||||
{
|
||||
file = Path.Combine(fPhotoPrismContentDirectory, $"{ticks}-{rectangleIntersectMinimum}-subject_alias_update.sql");
|
||||
directory = Path.Combine(fPhotoPrismContentDirectory, dateTime.ToString("yyyy-MM-dd"));
|
||||
if (!Directory.Exists(directory))
|
||||
_ = Directory.CreateDirectory(directory);
|
||||
file = Path.Combine(directory, $"{ticks}-{rectangleIntersectMinimum}-subject_alias_update.sql");
|
||||
text = string.Join(Environment.NewLine, subjects.Distinct());
|
||||
_ = IPath.WriteAllText(file, text, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
|
||||
file = Path.Combine(fPhotoPrismContentDirectory, $"{ticks}-{rectangleIntersectMinimum}-marker_name_update.sql");
|
||||
file = Path.Combine(directory, $"{ticks}-{rectangleIntersectMinimum}-marker_name_update.sql");
|
||||
text = stringBuilder.ToString();
|
||||
_ = IPath.WriteAllText(file, text, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
|
||||
}
|
||||
|
@ -63,6 +63,8 @@
|
||||
"IgnoreExtensions": [
|
||||
".gif",
|
||||
".GIF",
|
||||
".nef",
|
||||
".NEF",
|
||||
".pdf",
|
||||
".PDF"
|
||||
],
|
||||
|
@ -73,6 +73,8 @@
|
||||
"IgnoreExtensions": [
|
||||
".gif",
|
||||
".GIF",
|
||||
".nef",
|
||||
".NEF",
|
||||
".pdf",
|
||||
".PDF"
|
||||
],
|
||||
|
@ -37,7 +37,9 @@ public class FacePoint : Properties.IFacePoint
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0070
|
||||
public override int GetHashCode()
|
||||
#pragma warning restore IDE0070
|
||||
{
|
||||
int hashCode = 1861411795;
|
||||
hashCode = hashCode * -1521134295 + _Point.GetHashCode();
|
||||
|
@ -74,7 +74,9 @@ public class Location : Properties.ILocation, IEquatable<Location>
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0070
|
||||
public override int GetHashCode()
|
||||
#pragma warning restore IDE0070
|
||||
{
|
||||
int hashCode = -773114317;
|
||||
hashCode = hashCode * -1521134295 + Bottom.GetHashCode();
|
||||
|
@ -2,5 +2,5 @@ using System.Drawing;
|
||||
|
||||
namespace View_by_Distance.Shared.Models;
|
||||
|
||||
public record LocationContainer<T>(bool FromDistanceContent, string File, long PersonKey, int Id, int WholePercentages, IReadOnlyList<T> Directories, Rectangle? Rectangle, Location? Location)
|
||||
public record LocationContainer<T>(bool FromDistanceContent, string File, long PersonKey, int Id, int WholePercentages, IReadOnlyList<T> Directories, RectangleF? Rectangle, Location? Location)
|
||||
{ }
|
@ -12,13 +12,13 @@ public record Marker(
|
||||
string? SubjSrc,
|
||||
string? FaceId,
|
||||
string FaceDist,
|
||||
double X,
|
||||
double Y,
|
||||
double W,
|
||||
double H,
|
||||
float X,
|
||||
float Y,
|
||||
float W,
|
||||
float H,
|
||||
string Q,
|
||||
string Size,
|
||||
double Score,
|
||||
float Score,
|
||||
string? Thumb,
|
||||
string MatchedAt,
|
||||
string CreatedAt,
|
||||
|
@ -31,9 +31,7 @@ internal abstract class Face
|
||||
private static JsonElement[] GetJsonElements(string jsonFileFullName)
|
||||
{
|
||||
string json = GetJson(jsonFileFullName);
|
||||
JsonElement[]? jsonElements = JsonSerializer.Deserialize<JsonElement[]>(json);
|
||||
if (jsonElements is null)
|
||||
throw new Exception();
|
||||
JsonElement[]? jsonElements = JsonSerializer.Deserialize<JsonElement[]>(json) ?? throw new Exception();
|
||||
return jsonElements;
|
||||
}
|
||||
|
||||
|
@ -15,25 +15,25 @@ public interface ILocation
|
||||
static List<Models.Face> FilterByIntersect(Models.Face[] faces, float rectangleIntersectMinimum, int wholePercentages) =>
|
||||
Location.FilterByIntersect(faces, rectangleIntersectMinimum, wholePercentages);
|
||||
|
||||
Rectangle? TestStatic_GetRectangle(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution) =>
|
||||
GetRectangle(databaseFile, marker, outputResolution);
|
||||
static Rectangle? GetRectangle(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution) =>
|
||||
Location.GetRectangle(databaseFile, marker, outputResolution);
|
||||
RectangleF? TestStatic_GetPercentagesRectangle(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution) =>
|
||||
GetPercentagesRectangle(databaseFile, marker, outputResolution);
|
||||
static RectangleF? GetPercentagesRectangle(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution) =>
|
||||
Location.GetPercentagesRectangle(databaseFile, marker, outputResolution);
|
||||
|
||||
Models.Location? TestStatic_GetLocation(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution) =>
|
||||
GetLocation(databaseFile, marker, outputResolution);
|
||||
static Models.Location? GetLocation(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution) =>
|
||||
Location.GetLocation(databaseFile, marker, outputResolution);
|
||||
|
||||
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);
|
||||
List<Models.Location> TestStatic_GetLocations<T>(List<LocationContainer<T>> locationContainers, List<Models.Face> faces, List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, float rectangleIntersectMinimum) =>
|
||||
GetLocations(locationContainers, faces, mappingFromPhotoPrismCollection, rectangleIntersectMinimum);
|
||||
static List<Models.Location> GetLocations<T>(List<LocationContainer<T>> locationContainers, List<Models.Face> faces, List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, float rectangleIntersectMinimum) =>
|
||||
Location.GetLocations(locationContainers, faces, mappingFromPhotoPrismCollection, rectangleIntersectMinimum);
|
||||
|
||||
Rectangle? TestStatic_GetWholePercentages(int locationDigits, int wholePercentages) =>
|
||||
GetWholePercentages(locationDigits, wholePercentages);
|
||||
static Rectangle? GetWholePercentages(int locationDigits, int wholePercentages) =>
|
||||
Location.GetWholePercentages(locationDigits, wholePercentages.ToString());
|
||||
RectangleF? TestStatic_GetPercentagesRectangle(int locationDigits, int wholePercentages) =>
|
||||
GetPercentagesRectangle(locationDigits, wholePercentages);
|
||||
static RectangleF? GetPercentagesRectangle(int locationDigits, int wholePercentages) =>
|
||||
Location.GetPercentagesRectangle(locationDigits, wholePercentages.ToString());
|
||||
|
||||
Rectangle? TestStatic_GetRectangle(int locationDigits, Models.OutputResolution outputResolution, int wholePercentages) =>
|
||||
GetRectangle(locationDigits, outputResolution, wholePercentages);
|
||||
@ -90,6 +90,11 @@ public interface ILocation
|
||||
static int GetWholePercentages(int locationDigits) =>
|
||||
Location.GetWholePercentages(1, 1, 0, locationDigits, 1, 0, 1, zCount: 1);
|
||||
|
||||
int TestStatic_GetWholePercentages(int height, Models.Location location, int locationDigits, int width) =>
|
||||
GetWholePercentages(height, location, locationDigits, width);
|
||||
static int GetWholePercentages(int height, Models.Location location, int locationDigits, int width) =>
|
||||
Location.GetWholePercentages(height, location, locationDigits, width);
|
||||
|
||||
int TestStatic_GetWholePercentages(int bottom, int height, int left, int locationDigits, int right, int top, int width) =>
|
||||
GetWholePercentages(bottom, height, left, locationDigits, right, top, width);
|
||||
static int GetWholePercentages(int bottom, int height, int left, int locationDigits, int right, int top, int width) =>
|
||||
@ -109,4 +114,9 @@ public interface ILocation
|
||||
width,
|
||||
facesCount);
|
||||
|
||||
float? TestStatic_GetIntersectPercent(RectangleF rectangleA, float? areaA, RectangleF rectangleB) =>
|
||||
GetIntersectPercent(rectangleA, areaA, rectangleB);
|
||||
static float? GetIntersectPercent(RectangleF rectangleA, float? areaA, RectangleF rectangleB) =>
|
||||
Location.GetIntersectPercent(rectangleA, areaA, rectangleB);
|
||||
|
||||
}
|
@ -3,6 +3,11 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
||||
public interface IOutputResolution
|
||||
{ // ...
|
||||
|
||||
(int, int) TestStatic_Get(Models.OutputResolution outputResolution) =>
|
||||
Get(outputResolution);
|
||||
static (int, int) Get(Models.OutputResolution outputResolution) =>
|
||||
OutputResolution.Get(outputResolution);
|
||||
|
||||
int TestStatic_GetHeight(Models.OutputResolution outputResolution) =>
|
||||
GetHeight(outputResolution);
|
||||
static int GetHeight(Models.OutputResolution outputResolution) =>
|
||||
|
@ -108,15 +108,21 @@ internal abstract class Location
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static int GetWholePercentages(int height, Models.Location location, int locationDigits, int width)
|
||||
{
|
||||
int result = GetWholePercentages(location.Bottom, height, location.Left, locationDigits, location.Right, location.Top, width, zCount: 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static int GetConfidencePercent(int faceConfidencePercent, float[] rangeFaceConfidence, double confidence)
|
||||
{
|
||||
int result = (int)(confidence / rangeFaceConfidence[1] * faceConfidencePercent);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static Rectangle? GetWholePercentages(int locationDigits, string wholePercentages)
|
||||
internal static RectangleF? GetPercentagesRectangle(int locationDigits, string wholePercentages)
|
||||
{
|
||||
Rectangle? result;
|
||||
RectangleF? result;
|
||||
int length = (locationDigits - 1) / 4;
|
||||
string[] segments = new string[]
|
||||
{
|
||||
@ -133,7 +139,10 @@ internal abstract class Location
|
||||
if (!int.TryParse(segments[1], out int xWholePercent) || !int.TryParse(segments[2], out int yWholePercent) || !int.TryParse(segments[3], out int wWholePercent) || !int.TryParse(segments[4], out int hWholePercent))
|
||||
result = null;
|
||||
else
|
||||
result = new(xWholePercent, yWholePercent, wWholePercent, hWholePercent);
|
||||
{
|
||||
float factor = 100;
|
||||
result = new(xWholePercent / factor, yWholePercent / factor, wWholePercent / factor, hWholePercent / factor);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -143,14 +152,13 @@ internal abstract class Location
|
||||
Rectangle? result;
|
||||
if (wholePercentages.Length != locationDigits || wholePercentages[0] is not '4' and not '8')
|
||||
throw new NotSupportedException("Old way has been removed!");
|
||||
(int width, int height) = OutputResolution.Get(outputResolution);
|
||||
Rectangle? rectangle = GetWholePercentages(locationDigits, wholePercentages);
|
||||
(int width, int height) = OutputResolution.Get(outputResolution);
|
||||
RectangleF? rectangle = GetPercentagesRectangle(locationDigits, wholePercentages);
|
||||
if (rectangle is null)
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
decimal factor = 100;
|
||||
result = new((int)(rectangle.Value.X / factor * width), (int)(rectangle.Value.Y / factor * height), (int)(rectangle.Value.Width / factor * width), (int)(rectangle.Value.Height / factor * height));
|
||||
result = new((int)(rectangle.Value.X * width), (int)(rectangle.Value.Y * height), (int)(rectangle.Value.Width * width), (int)(rectangle.Value.Height * height));
|
||||
}
|
||||
if (result is null)
|
||||
throw new NullReferenceException(nameof(result));
|
||||
@ -163,25 +171,29 @@ internal abstract class Location
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static Rectangle? GetRectangle(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution)
|
||||
internal static RectangleF? GetPercentagesRectangle(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution)
|
||||
{
|
||||
Rectangle? result;
|
||||
RectangleF? result;
|
||||
bool matches = Matches(outputResolution, databaseFile);
|
||||
if (!matches)
|
||||
result = null;
|
||||
else
|
||||
result = new((int)Math.Ceiling(marker.X * databaseFile.FileWidth), (int)Math.Ceiling(marker.Y * databaseFile.FileHeight), (int)Math.Ceiling(marker.W * databaseFile.FileWidth), (int)Math.Ceiling(marker.H * databaseFile.FileHeight));
|
||||
result = new(marker.X, marker.Y, marker.W, marker.H);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Models.Location? GetLocation(DatabaseFile databaseFile, Marker marker, Rectangle rectangle)
|
||||
private static Models.Location? GetLocation(DatabaseFile databaseFile, Marker marker, RectangleF rectangle)
|
||||
{
|
||||
Models.Location? result;
|
||||
bool verified = Check(rectangle.Bottom, databaseFile.FileHeight, rectangle.Left, rectangle.Right, rectangle.Top, databaseFile.FileWidth, zCount: 1, throwException: false);
|
||||
int top = (int)Math.Ceiling(rectangle.Top * databaseFile.FileHeight);
|
||||
int left = (int)Math.Ceiling(rectangle.Left * databaseFile.FileWidth);
|
||||
int right = (int)Math.Ceiling(rectangle.Right * databaseFile.FileWidth);
|
||||
int bottom = (int)Math.Ceiling(rectangle.Bottom * databaseFile.FileHeight);
|
||||
bool verified = Check(bottom, databaseFile.FileHeight, left, right, top, databaseFile.FileWidth, zCount: 1, throwException: false);
|
||||
if (!verified)
|
||||
result = null;
|
||||
else
|
||||
result = new(rectangle.Bottom, marker.Score / 100, rectangle.Left, rectangle.Right, rectangle.Top);
|
||||
result = new(bottom, marker.Score / 100, left, right, top);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -200,7 +212,7 @@ internal abstract class Location
|
||||
internal static Models.Location? GetLocation(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution)
|
||||
{
|
||||
Models.Location? result;
|
||||
Rectangle? rectangle = GetRectangle(databaseFile, marker, outputResolution);
|
||||
RectangleF? rectangle = GetPercentagesRectangle(databaseFile, marker, outputResolution);
|
||||
if (rectangle is null)
|
||||
result = null;
|
||||
else
|
||||
@ -208,15 +220,43 @@ internal abstract class Location
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static List<Models.Location> GetLocations<T>(List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, List<Models.Face> faces, List<LocationContainer<T>> containers)
|
||||
internal static float? GetIntersectPercent(RectangleF rectangleA, float? areaA, RectangleF rectangleB)
|
||||
{
|
||||
float? result;
|
||||
if (rectangleA.Equals(rectangleB))
|
||||
result = 1;
|
||||
else
|
||||
{
|
||||
float intersectArea;
|
||||
RectangleF intersectRectangle;
|
||||
areaA ??= rectangleA.Width * rectangleA.Height;
|
||||
float areaB = rectangleB.Width * rectangleB.Height;
|
||||
bool check = areaA > areaB;
|
||||
if (check)
|
||||
intersectRectangle = RectangleF.Intersect(rectangleB, rectangleA);
|
||||
else
|
||||
intersectRectangle = RectangleF.Intersect(rectangleA, rectangleB);
|
||||
intersectArea = intersectRectangle.Width * intersectRectangle.Height;
|
||||
if (check)
|
||||
result = intersectArea / areaA;
|
||||
else
|
||||
result = intersectArea / areaB;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static List<Models.Location> GetLocations<T>(List<LocationContainer<T>> locationContainers, List<Models.Face> faces, List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, float rectangleIntersectMinimum)
|
||||
{
|
||||
List<Models.Location> results = new();
|
||||
bool any;
|
||||
bool matches;
|
||||
Rectangle dlibRectangle;
|
||||
Rectangle? prismRectangle;
|
||||
float? percent;
|
||||
float prismArea;
|
||||
int width, height;
|
||||
Models.Location? location;
|
||||
Rectangle intersectRectangle;
|
||||
RectangleF? prismRectangle;
|
||||
int dlibLocationWholePercentages;
|
||||
RectangleF? dlibPercentagesRectangle;
|
||||
Models.OutputResolution? outputResolution = null;
|
||||
foreach (Models.Face face in faces)
|
||||
{
|
||||
@ -226,7 +266,7 @@ internal abstract class Location
|
||||
outputResolution ??= face.OutputResolution;
|
||||
}
|
||||
int before = results.Count;
|
||||
foreach (LocationContainer<T> locationContainer in containers)
|
||||
foreach (LocationContainer<T> locationContainer in locationContainers)
|
||||
{
|
||||
if (locationContainer.Location is null)
|
||||
continue;
|
||||
@ -242,23 +282,24 @@ internal abstract class Location
|
||||
foreach (Marker marker in mappingFromPhotoPrism.Markers)
|
||||
{
|
||||
any = false;
|
||||
prismRectangle = GetRectangle(mappingFromPhotoPrism.DatabaseFile, marker, outputResolution);
|
||||
prismRectangle = GetPercentagesRectangle(mappingFromPhotoPrism.DatabaseFile, marker, outputResolution);
|
||||
if (prismRectangle is null)
|
||||
break;
|
||||
prismArea = prismRectangle.Value.Width * prismRectangle.Value.Height;
|
||||
location = GetLocation(mappingFromPhotoPrism.DatabaseFile, marker, prismRectangle.Value);
|
||||
if (location is null)
|
||||
break;
|
||||
foreach (LocationContainer<T> locationContainer in containers)
|
||||
foreach (LocationContainer<T> locationContainer in locationContainers)
|
||||
{
|
||||
if (any)
|
||||
continue;
|
||||
if (locationContainer.Location is null)
|
||||
if (locationContainer.Rectangle 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)
|
||||
percent = GetIntersectPercent(prismRectangle.Value, prismArea, locationContainer.Rectangle.Value);
|
||||
if (percent is null || percent < rectangleIntersectMinimum)
|
||||
continue;
|
||||
any = true;
|
||||
if (!any)
|
||||
any = true;
|
||||
break;
|
||||
}
|
||||
foreach (Models.Face face in faces)
|
||||
@ -267,11 +308,16 @@ internal abstract class Location
|
||||
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(prismRectangle.Value, dlibRectangle);
|
||||
if (intersectRectangle.Width == 0 && intersectRectangle.Height == 0)
|
||||
(width, height) = OutputResolution.Get(face.OutputResolution);
|
||||
dlibLocationWholePercentages = GetWholePercentages(height, face.Location, Stateless.ILocation.Digits, width);
|
||||
dlibPercentagesRectangle = GetPercentagesRectangle(Stateless.ILocation.Digits, dlibLocationWholePercentages.ToString());
|
||||
if (dlibPercentagesRectangle is null)
|
||||
continue;
|
||||
any = true;
|
||||
percent = GetIntersectPercent(prismRectangle.Value, prismArea, dlibPercentagesRectangle.Value);
|
||||
if (percent is null || percent < rectangleIntersectMinimum)
|
||||
continue;
|
||||
if (!any)
|
||||
any = true;
|
||||
break;
|
||||
}
|
||||
if (!any)
|
||||
@ -283,31 +329,28 @@ internal abstract class Location
|
||||
return results;
|
||||
}
|
||||
|
||||
// private static double GP(OutputResolution outputResolution,Location location, ){
|
||||
// double result;
|
||||
// return result;
|
||||
// }
|
||||
|
||||
internal static List<Models.Face> FilterByIntersect(Models.Face[] faces, float rectangleIntersectMinimum, int wholePercentages)
|
||||
{
|
||||
List<Models.Face> results = new();
|
||||
double? percent;
|
||||
Rectangle checkRectangle;
|
||||
Rectangle? sourceRectangle;
|
||||
Rectangle intersectRectangle;
|
||||
float? percent;
|
||||
int width, height;
|
||||
int faceLocationWholePercentages;
|
||||
RectangleF? facePercentagesRectangle;
|
||||
RectangleF? sourceRectangle = GetPercentagesRectangle(Stateless.ILocation.Digits, wholePercentages.ToString());
|
||||
float? sourceArea = sourceRectangle is null ? null : sourceRectangle.Value.Width * sourceRectangle.Value.Height;
|
||||
foreach (Models.Face face in faces)
|
||||
{
|
||||
if (sourceRectangle is null || sourceArea is null)
|
||||
continue;
|
||||
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);
|
||||
sourceRectangle = GetRectangle(Stateless.ILocation.Digits, face.OutputResolution, wholePercentages.ToString());
|
||||
if (sourceRectangle is null)
|
||||
(width, height) = OutputResolution.Get(face.OutputResolution);
|
||||
faceLocationWholePercentages = GetWholePercentages(height, face.Location, Stateless.ILocation.Digits, width);
|
||||
facePercentagesRectangle = GetPercentagesRectangle(Stateless.ILocation.Digits, faceLocationWholePercentages.ToString());
|
||||
if (facePercentagesRectangle 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 < rectangleIntersectMinimum)
|
||||
percent = GetIntersectPercent(sourceRectangle.Value, sourceArea.Value, facePercentagesRectangle.Value);
|
||||
if (percent is null || percent < rectangleIntersectMinimum)
|
||||
continue;
|
||||
results.Add(face);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Phares.Shared;
|
||||
using Serilog;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Reflection;
|
||||
using View_by_Distance.Shared.Models;
|
||||
using View_by_Distance.Shared.Models.Stateless.Methods;
|
||||
@ -307,4 +308,74 @@ public partial class UnitTestCalculations
|
||||
NonThrowTryCatch();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestMethodIntersect()
|
||||
{
|
||||
float? percent;
|
||||
float? areaA = null;
|
||||
RectangleF rectangleA;
|
||||
RectangleF rectangleB;
|
||||
rectangleA = new(0, 0, 4, 4);
|
||||
rectangleB = new(0, 0, 4, 4);
|
||||
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
|
||||
Assert.IsNotNull(percent);
|
||||
Assert.IsTrue(percent.Value == 1);
|
||||
rectangleA = new(0, 0, 4, 4);
|
||||
rectangleB = new(0, 0, 2, 2);
|
||||
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
|
||||
Assert.IsNotNull(percent);
|
||||
Assert.IsTrue(percent.Value == .25);
|
||||
rectangleA = new(0, 0, 4, 4);
|
||||
rectangleB = new(0, 0, 4, 2);
|
||||
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
|
||||
Assert.IsNotNull(percent);
|
||||
Assert.IsTrue(percent.Value == .5);
|
||||
rectangleA = new(0, 0, 4, 4);
|
||||
rectangleB = new(2, 2, 4, 4);
|
||||
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
|
||||
Assert.IsNotNull(percent);
|
||||
Assert.IsTrue(percent.Value == .25);
|
||||
rectangleA = new(0, 0, 4, 4);
|
||||
rectangleB = new(2, 0, 4, 4);
|
||||
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
|
||||
Assert.IsNotNull(percent);
|
||||
Assert.IsTrue(percent.Value == .5);
|
||||
rectangleA = new(0, 0, 4, 4);
|
||||
rectangleB = new(2, 4, 4, 4);
|
||||
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
|
||||
Assert.IsNotNull(percent);
|
||||
Assert.IsTrue(percent.Value == 0);
|
||||
rectangleB = new(0, 0, 4, 4);
|
||||
rectangleA = new(0, 0, 4, 4);
|
||||
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
|
||||
Assert.IsNotNull(percent);
|
||||
Assert.IsTrue(percent.Value == 1);
|
||||
rectangleB = new(0, 0, 4, 4);
|
||||
rectangleA = new(0, 0, 2, 2);
|
||||
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
|
||||
Assert.IsNotNull(percent);
|
||||
Assert.IsTrue(percent.Value == .25);
|
||||
rectangleB = new(0, 0, 4, 4);
|
||||
rectangleA = new(0, 0, 4, 2);
|
||||
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
|
||||
Assert.IsNotNull(percent);
|
||||
Assert.IsTrue(percent.Value == .5);
|
||||
rectangleB = new(0, 0, 4, 4);
|
||||
rectangleA = new(2, 2, 4, 4);
|
||||
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
|
||||
Assert.IsNotNull(percent);
|
||||
Assert.IsTrue(percent.Value == .25);
|
||||
rectangleB = new(0, 0, 4, 4);
|
||||
rectangleA = new(2, 0, 4, 4);
|
||||
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
|
||||
Assert.IsNotNull(percent);
|
||||
Assert.IsTrue(percent.Value == .5);
|
||||
rectangleB = new(0, 0, 4, 4);
|
||||
rectangleA = new(2, 4, 4, 4);
|
||||
percent = ILocation.GetIntersectPercent(rectangleA, areaA, rectangleB);
|
||||
Assert.IsNotNull(percent);
|
||||
Assert.IsTrue(percent.Value == 0);
|
||||
NonThrowTryCatch();
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user