using Microsoft.Extensions.Configuration; using Microsoft.VisualStudio.TestTools.UnitTesting; using Phares.Shared; using Serilog; using System.Diagnostics; using System.Drawing.Imaging; using System.Reflection; using View_by_Distance.FaceRecognitionDotNet; using View_by_Distance.Metadata.Models; using View_by_Distance.Property.Models; using View_by_Distance.Resize.Models; using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models.Stateless; using View_by_Distance.Shared.Models.Stateless.Methods; using View_by_Distance.Tests.Models; namespace View_by_Distance.Tests; [TestClass] public class UnitTestFace { private readonly ILogger _Logger; private readonly AppSettings _AppSettings; private readonly string _WorkingDirectory; private readonly IsEnvironment _IsEnvironment; private readonly Models.Configuration _Configuration; private readonly IConfigurationRoot _ConfigurationRoot; private readonly Property.Models.Configuration _PropertyConfiguration; public UnitTestFace() { ILogger logger; AppSettings appSettings; string workingDirectory; IsEnvironment isEnvironment; Models.Configuration configuration; IConfigurationRoot configurationRoot; LoggerConfiguration loggerConfiguration = new(); Property.Models.Configuration propertyConfiguration; Assembly assembly = Assembly.GetExecutingAssembly(); bool debuggerWasAttachedAtLineZero = Debugger.IsAttached || assembly.Location.Contains(@"\bin\Debug"); isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero); IConfigurationBuilder configurationBuilder = new ConfigurationBuilder() .AddEnvironmentVariables() .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true); configurationRoot = configurationBuilder.Build(); appSettings = Models.Binder.AppSettings.Get(configurationRoot); if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) throw new Exception("Working directory name must have a value!"); workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName); Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory); _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot); Log.Logger = loggerConfiguration.CreateLogger(); logger = Log.ForContext(); propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot); configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration); logger.Information("Complete"); _Logger = logger; _AppSettings = appSettings; _Configuration = configuration; _IsEnvironment = isEnvironment; _WorkingDirectory = workingDirectory; _ConfigurationRoot = configurationRoot; _PropertyConfiguration = propertyConfiguration; } [TestMethod] public void TestConfiguration() { if (_Configuration.LocationDigits != Shared.Models.Stateless.ILocation.Digits) throw new Exception("Configuration has to match interface!"); if (_Configuration.LocationFactor != Shared.Models.Stateless.ILocation.Factor) throw new Exception("Configuration has to match interface!"); } [TestMethod] public void TestMethodNull() { Assert.IsFalse(_Logger is null); Assert.IsFalse(_AppSettings is null); Assert.IsFalse(_Configuration is null); Assert.IsFalse(_IsEnvironment is null); Assert.IsFalse(_WorkingDirectory is null); Assert.IsFalse(_ConfigurationRoot is null); Assert.IsFalse(_PropertyConfiguration is null); } private A_Property GetPropertyLogic(bool reverse, string aResultsFullGroupDirectory) { A_Property result; if (_Configuration?.PropertyConfiguration is null) throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration)); result = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Configuration.OutputExtension, reverse, aResultsFullGroupDirectory); return result; } private static (Model model, PredictorModel predictorModel, ModelParameter modelParameter) GetModel(Models.Configuration configuration) { (Model, PredictorModel, ModelParameter) result; Array array; Model? model = null; PredictorModel? predictorModel = null; array = Enum.GetValues(typeof(Model)); foreach (Model check in array) { if (configuration.ModelName.Contains(check.ToString())) { model = check; break; } } if (model is null) throw new Exception("Destination directory must have Model name!"); model = model.Value; array = Enum.GetValues(typeof(PredictorModel)); foreach (PredictorModel check in array) { if (configuration.PredictorModelName.Contains(check.ToString())) { predictorModel = check; break; } } if (predictorModel is null) throw new Exception("Destination directory must have Predictor Model name!"); predictorModel = predictorModel.Value; ModelParameter modelParameter = new() { CnnFaceDetectorModel = File.ReadAllBytes(Path.Combine(configuration.ModelDirectory, "mmod_human_face_detector.dat")), FaceRecognitionModel = File.ReadAllBytes(Path.Combine(configuration.ModelDirectory, "dlib_face_recognition_resnet_model_v1.dat")), PosePredictor5FaceLandmarksModel = File.ReadAllBytes(Path.Combine(configuration.ModelDirectory, "shape_predictor_5_face_landmarks.dat")), PosePredictor68FaceLandmarksModel = File.ReadAllBytes(Path.Combine(configuration.ModelDirectory, "shape_predictor_68_face_landmarks.dat")) }; result = new(model.Value, predictorModel.Value, modelParameter); return result; } [TestMethod] public void TestMethodRoundB() { const int DistanceDigits = 3; const int DistanceFactor = 1000; const int ToleranceAfterFactor = 600; Assert.IsTrue(DistanceDigits == 3); Assert.IsTrue(DistanceFactor == 1000); Assert.IsTrue(_Configuration.RangeDistanceTolerance[1] == 0.6d); Assert.IsTrue(ToleranceAfterFactor == 600); double valueA = 0.00001d; int checkA = (int)(Math.Round(valueA, _Configuration.LocationDigits) * _Configuration.LocationFactor); Assert.IsTrue(checkA == 0); double valueB = 0.01d; int checkB = (int)(Math.Round(valueB, _Configuration.LocationDigits) * _Configuration.LocationFactor); Assert.IsTrue(checkB == 100); Assert.IsTrue(checkB > checkA); int checkC = (int)(_Configuration.RangeDistanceTolerance[1] * DistanceFactor); Assert.IsTrue(checkC == ToleranceAfterFactor); } private (string, string) GetResultsFullGroupDirectories() { string aResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( _Configuration.PropertyConfiguration, nameof(A_Property), string.Empty, includeResizeGroup: false, includeModel: false, includePredictorModel: false); string bResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( _Configuration.PropertyConfiguration, nameof(B_Metadata), string.Empty, includeResizeGroup: false, includeModel: false, includePredictorModel: false); return new(aResultsFullGroupDirectory, bResultsFullGroupDirectory); } private (string, string, string) GetResultsFullGroupDirectories(string outputResolution) { string cResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory( _Configuration.PropertyConfiguration, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false); string dResultsFullGroupDirectory = string.Empty; string d2ResultsFullGroupDirectory = string.Empty; return new(cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory); } [TestMethod] public void TestMethodFace() { // string sourceFileName = "IMG_0067.jpg"; // string sourceDirectoryName = "Mackenzie Prom 2017"; // string sourceFileName = "Fall 2005 (113).jpg"; // string sourceDirectoryName = "=2005.3 Fall"; // string sourceFileName = "DSCN0534.jpg"; // string sourceDirectoryName = "Logan Swimming Lessons 2013"; // string sourceFileName = "DSC_4913.jpg"; // string sourceDirectoryName = "Disneyland 2014"; // string sourceFileName = "Logan Michael Sept 08 (193).jpg"; // string sourceDirectoryName = "=2008.2 Summer Logan Michael"; // string sourceFileName = "Halloween 2006 (112).jpg"; // string sourceDirectoryName = "Halloween 2006"; string sourceFileName = "1384160978.jpg"; string sourceDirectoryName = "zzz Portrait Innovations Files 2007"; Item item; bool reverse = false; FileHolder resizedFileHolder; List parseExceptions = new(); const bool isIgnoreRelativePath = false; Shared.Models.Property? property = null; const bool isValidImageFormatExtension = true; Dictionary outputResolutionToResize; List> subFileTuples = new(); List> metadataCollection; int length = _PropertyConfiguration.RootDirectory.Length; string outputResolution = _Configuration.OutputResolutions[0]; (string cResultsFullGroupDirectory, _, _) = GetResultsFullGroupDirectories(outputResolution); string sourceDirectory = Path.Combine(_PropertyConfiguration.RootDirectory, sourceDirectoryName); (string aResultsFullGroupDirectory, string bResultsFullGroupDirectory) = GetResultsFullGroupDirectories(); _Logger.Information(_Configuration.ModelDirectory); A_Property propertyLogic = GetPropertyLogic(reverse, aResultsFullGroupDirectory); string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, "{}"); if (!Directory.Exists(aPropertySingletonDirectory)) _ = Directory.CreateDirectory(aPropertySingletonDirectory); (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetTuple(_Configuration.OutputExtension, _Configuration.OutputQuality); B_Metadata metadata = new(_Configuration.PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, bResultsFullGroupDirectory); _ = metadata.ToString(); C_Resize resize = new(_Configuration.ForceResizeLastWriteTimeToCreationTime, _Configuration.OverrideForResizeImages, _Configuration.PropertiesChangedForResize, _Configuration.ValidResolutions, imageCodecInfo, encoderParameters, filenameExtension); _ = resize.ToString(); bool? isUniqueFileName = null; bool anyNullOrNoIsUniqueFileName = true; FileHolder sourceDirectoryFileHolder = new(".json"); FileHolder fileHolder = new(Path.Combine(sourceDirectory, sourceFileName)); string relativePath = IPath.GetRelativePath(fileHolder.FullName, length); sourceDirectory = Path.Combine(aPropertySingletonDirectory, sourceDirectoryName); propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, sourceDirectory, anyNullOrNoIsUniqueFileName); resize.SetAngleBracketCollection(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, sourceDirectory); item = new(sourceDirectoryFileHolder, relativePath, fileHolder, isUniqueFileName, isValidImageFormatExtension, property, false, false, false); Assert.IsNotNull(item.ImageFileHolder); if (item.Property is null) { property = propertyLogic.GetProperty(item, subFileTuples, parseExceptions); item.Update(property); } if (property is null || item.Property is null) throw new NullReferenceException(nameof(property)); resizedFileHolder = resize.GetResizedFileHolder(item); item.SetResizedFileHolder(resize.FileNameExtension, resizedFileHolder); MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(item, isIgnoreRelativePath); (int _, metadataCollection) = metadata.GetMetadataCollection(subFileTuples, parseExceptions, mappingFromItem); outputResolutionToResize = resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, subFileTuples, parseExceptions, metadataCollection, item.Property, mappingFromItem); Assert.IsNotNull(mappingFromItem.ResizedFileHolder); resize.SaveResizedSubfile(_Configuration.PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, outputResolutionToResize); Image image = FaceRecognition.LoadImageFile(mappingFromItem.ResizedFileHolder.FullName); Assert.IsNotNull(image); (Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(_Configuration); FaceRecognition faceRecognition = new(_Configuration.NumberOfJitters, _Configuration.NumberOfTimesToUpsample, model, modelParameter, predictorModel); List<(Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary? FaceParts)> collection; collection = faceRecognition.GetCollection(image, locations: new(), includeFaceEncoding: true, includeFaceParts: true); Assert.IsTrue(collection.Count == 2); List faceDistanceEncodings = (from l in collection where l.FaceEncoding is not null select new FaceDistance(l.FaceEncoding)).ToList(); List faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncodings[0]); Assert.IsTrue(faceDistanceLengths.Count == 2); Assert.IsNotNull(sourceFileName); } }