commit 5e08f0b7d579515f348f8700ad9d6a81aae06285
Author: pscgyLancer <1971408908@qq.com>
Date: Mon Jun 13 17:41:33 2022 +0800
frist commit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..eab4de4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,343 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+# ASP.NET Core default setup: bower directory is configured as wwwroot/lib/ and bower restore is true
+**/wwwroot/lib/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+
diff --git a/ImageData/已戴/1.jpg b/ImageData/已戴/1.jpg
new file mode 100644
index 0000000..fe20834
Binary files /dev/null and b/ImageData/已戴/1.jpg differ
diff --git a/ImageData/已戴/2.png b/ImageData/已戴/2.png
new file mode 100644
index 0000000..676006a
Binary files /dev/null and b/ImageData/已戴/2.png differ
diff --git a/ImageData/已戴/3.jpg b/ImageData/已戴/3.jpg
new file mode 100644
index 0000000..9e791e5
Binary files /dev/null and b/ImageData/已戴/3.jpg differ
diff --git a/ImageData/已戴/4.jpg b/ImageData/已戴/4.jpg
new file mode 100644
index 0000000..a2e427c
Binary files /dev/null and b/ImageData/已戴/4.jpg differ
diff --git a/ImageData/已戴/5.jpg b/ImageData/已戴/5.jpg
new file mode 100644
index 0000000..ccbe5f3
Binary files /dev/null and b/ImageData/已戴/5.jpg differ
diff --git a/ImageData/已戴/6.png b/ImageData/已戴/6.png
new file mode 100644
index 0000000..1452445
Binary files /dev/null and b/ImageData/已戴/6.png differ
diff --git a/ImageData/已戴/7.jpg b/ImageData/已戴/7.jpg
new file mode 100644
index 0000000..dba7ee3
Binary files /dev/null and b/ImageData/已戴/7.jpg differ
diff --git a/ImageData/未戴/no1.jpg b/ImageData/未戴/no1.jpg
new file mode 100644
index 0000000..81ded0f
Binary files /dev/null and b/ImageData/未戴/no1.jpg differ
diff --git a/ImageData/未戴/no2.jpg b/ImageData/未戴/no2.jpg
new file mode 100644
index 0000000..7cdaa28
Binary files /dev/null and b/ImageData/未戴/no2.jpg differ
diff --git a/ImageData/未戴/no3.jpg b/ImageData/未戴/no3.jpg
new file mode 100644
index 0000000..3b087a5
Binary files /dev/null and b/ImageData/未戴/no3.jpg differ
diff --git a/ImageData/未戴/no4.jpg b/ImageData/未戴/no4.jpg
new file mode 100644
index 0000000..8f97c27
Binary files /dev/null and b/ImageData/未戴/no4.jpg differ
diff --git a/ImageData/未戴/no5.jpg b/ImageData/未戴/no5.jpg
new file mode 100644
index 0000000..d3c8d70
Binary files /dev/null and b/ImageData/未戴/no5.jpg differ
diff --git a/ImageData/未戴/no6.jpg b/ImageData/未戴/no6.jpg
new file mode 100644
index 0000000..284a1d4
Binary files /dev/null and b/ImageData/未戴/no6.jpg differ
diff --git a/Mask.ML.WebApi/Controllers/DiscernController.cs b/Mask.ML.WebApi/Controllers/DiscernController.cs
new file mode 100644
index 0000000..93c5271
--- /dev/null
+++ b/Mask.ML.WebApi/Controllers/DiscernController.cs
@@ -0,0 +1,78 @@
+using Mask_MLML.Model;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace Mask.ML.WebApi.Controllers
+{
+ [ApiController]
+ public class DiscernController : ControllerBase
+ {
+ ///
+ /// 上传文件:口罩验证
+ ///
+ ///
+ ///
+ [HttpPost("upload")]
+ [Route("api/discern/upload")]
+ public IActionResult UploadFile([FromForm] IFormCollection collection)
+ {
+ //申明返回的结果
+ string result = "";
+ FormFileCollection filelist = (FormFileCollection)collection.Files;
+ //检查是否有文件提交上来
+ if (filelist != null && filelist.Any())
+ {
+ //我们只做第一个文件的检查
+ IFormFile file = filelist[0];
+ //做随机数,用到文件夹名字上,防重名
+ Random random = new Random();
+ string r = "";
+ int i;
+ for (i = 1; i < 11; i++)
+ {
+ r += random.Next(0, 9).ToString();
+ }
+ //文件路径
+ string FilePath = AppDomain.CurrentDomain.BaseDirectory+"/TempFiles/";
+ string name = file.FileName;
+ string FileName = DateTime.Now.ToString("yyyyMMddHHmmssfff") + r;
+ //获取文件类型
+ string type = System.IO.Path.GetExtension(name);
+ DirectoryInfo di = new DirectoryInfo(FilePath);
+ if (!di.Exists)
+ {
+ di.Create();
+ }
+ //文件保存的路径
+ var filefullname = FilePath + FileName + type;
+ using (FileStream fs = System.IO.File.Create(filefullname))
+ {
+ // 复制文件
+ file.CopyTo(fs);
+ // 清空缓冲区数据
+ fs.Flush();
+ fs.Close();
+ fs.Dispose();
+ }
+ //成功提示赋值到返回结果中
+ //result = "文件上传成功";
+
+ // 创建样例数据的单个实例对模型输入数据集的第一行
+ ModelInput sampleData = new ModelInput()
+ {
+ ImageSource = filefullname,
+ };
+ // 获取预测结果
+ var predictionResult = ConsumeModel.Predict(sampleData);
+ //System.IO.File.Delete(filefullname);
+ return Ok(predictionResult.Prediction);
+ }
+ return NoContent();
+ }
+
+ }
+}
+
diff --git a/Mask.ML.WebApi/Mask.ML.WebApi.csproj b/Mask.ML.WebApi/Mask.ML.WebApi.csproj
new file mode 100644
index 0000000..bb1dd8b
--- /dev/null
+++ b/Mask.ML.WebApi/Mask.ML.WebApi.csproj
@@ -0,0 +1,15 @@
+
+
+
+ net5.0
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Mask.ML.WebApi/Program.cs b/Mask.ML.WebApi/Program.cs
new file mode 100644
index 0000000..ab444bf
--- /dev/null
+++ b/Mask.ML.WebApi/Program.cs
@@ -0,0 +1,26 @@
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Mask.ML.WebApi
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/Mask.ML.WebApi/Properties/launchSettings.json b/Mask.ML.WebApi/Properties/launchSettings.json
new file mode 100644
index 0000000..2c7c41e
--- /dev/null
+++ b/Mask.ML.WebApi/Properties/launchSettings.json
@@ -0,0 +1,23 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:16529",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "Mask.ML.WebApi": {
+ "commandName": "Project",
+ "dotnetRunMessages": "true",
+ "launchBrowser": true,
+ "launchUrl": "",
+ "applicationUrl": "http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/Mask.ML.WebApi/Startup.cs b/Mask.ML.WebApi/Startup.cs
new file mode 100644
index 0000000..74c6582
--- /dev/null
+++ b/Mask.ML.WebApi/Startup.cs
@@ -0,0 +1,50 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using Microsoft.OpenApi.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Mask.ML.WebApi
+{
+ public class Startup
+ {
+ public Startup(IConfiguration configuration)
+ {
+ Configuration = configuration;
+ }
+
+ public IConfiguration Configuration { get; }
+
+ // This method gets called by the runtime. Use this method to add services to the container.
+ public void ConfigureServices(IServiceCollection services)
+ {
+
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseAuthorization();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ });
+ }
+ }
+}
diff --git a/Mask.ML.WebApi/appsettings.Development.json b/Mask.ML.WebApi/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/Mask.ML.WebApi/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/Mask.ML.WebApi/appsettings.json b/Mask.ML.WebApi/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/Mask.ML.WebApi/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/Mask.ML.sln b/Mask.ML.sln
new file mode 100644
index 0000000..170a5f0
--- /dev/null
+++ b/Mask.ML.sln
@@ -0,0 +1,37 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31205.134
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mask.MLML.Model", "Mask.MLML.Model\Mask.MLML.Model.csproj", "{952B032F-6FFE-45E8-B7B0-5A806DDBD922}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mask.MLML.ConsoleApp", "Mask.MLML.ConsoleApp\Mask.MLML.ConsoleApp.csproj", "{B3C06518-648F-4430-815D-FEC905FE3DD7}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mask.ML.WebApi", "Mask.ML.WebApi\Mask.ML.WebApi.csproj", "{64704ACF-F0F9-4442-BEC5-3279C27B332C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {952B032F-6FFE-45E8-B7B0-5A806DDBD922}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {952B032F-6FFE-45E8-B7B0-5A806DDBD922}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {952B032F-6FFE-45E8-B7B0-5A806DDBD922}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {952B032F-6FFE-45E8-B7B0-5A806DDBD922}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B3C06518-648F-4430-815D-FEC905FE3DD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B3C06518-648F-4430-815D-FEC905FE3DD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B3C06518-648F-4430-815D-FEC905FE3DD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B3C06518-648F-4430-815D-FEC905FE3DD7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {64704ACF-F0F9-4442-BEC5-3279C27B332C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {64704ACF-F0F9-4442-BEC5-3279C27B332C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {64704ACF-F0F9-4442-BEC5-3279C27B332C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {64704ACF-F0F9-4442-BEC5-3279C27B332C}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {657EECC1-C95E-4F8E-BD19-7DEF54F69392}
+ EndGlobalSection
+EndGlobal
diff --git a/Mask.MLML.ConsoleApp/Mask.MLML.ConsoleApp.csproj b/Mask.MLML.ConsoleApp/Mask.MLML.ConsoleApp.csproj
new file mode 100644
index 0000000..ec6154d
--- /dev/null
+++ b/Mask.MLML.ConsoleApp/Mask.MLML.ConsoleApp.csproj
@@ -0,0 +1,20 @@
+
+
+
+ Exe
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Mask.MLML.ConsoleApp/ModelBuilder.cs b/Mask.MLML.ConsoleApp/ModelBuilder.cs
new file mode 100644
index 0000000..8b749c0
--- /dev/null
+++ b/Mask.MLML.ConsoleApp/ModelBuilder.cs
@@ -0,0 +1,161 @@
+// This file was auto-generated by ML.NET Model Builder.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Microsoft.ML;
+using Microsoft.ML.Data;
+using Mask_MLML.Model;
+using Microsoft.ML.Vision;
+
+namespace Mask_MLML.ConsoleApp
+{
+ public static class ModelBuilder
+ {
+ private static string TRAIN_DATA_FILEPATH = @"C:\Users\HUAWEI\AppData\Local\Temp\b441e20c-6f79-4437-a21a-be0014456e13.tsv";
+ private static string MODEL_FILEPATH = @"C:\Users\HUAWEI\AppData\Local\Temp\MLVSTools\Mask.MLML\Mask.MLML.Model\MLModel.zip";
+ // Create MLContext to be shared across the model creation workflow objects
+ // Set a random seed for repeatable/deterministic results across multiple trainings.
+ private static MLContext mlContext = new MLContext(seed: 1);
+
+ public static void CreateModel()
+ {
+ // Load Data
+ IDataView trainingDataView = mlContext.Data.LoadFromTextFile(
+ path: TRAIN_DATA_FILEPATH,
+ hasHeader: true,
+ separatorChar: '\t',
+ allowQuoting: true,
+ allowSparse: false);
+
+ // Build training pipeline
+ IEstimator trainingPipeline = BuildTrainingPipeline(mlContext);
+
+ // Train Model
+ ITransformer mlModel = TrainModel(mlContext, trainingDataView, trainingPipeline);
+
+ // Evaluate quality of Model
+ Evaluate(mlContext, trainingDataView, trainingPipeline);
+
+ // Save model
+ SaveModel(mlContext, mlModel, MODEL_FILEPATH, trainingDataView.Schema);
+ }
+
+ public static IEstimator BuildTrainingPipeline(MLContext mlContext)
+ {
+ // Data process configuration with pipeline data transformations
+ var dataProcessPipeline = mlContext.Transforms.Conversion.MapValueToKey("Label", "Label")
+ .Append(mlContext.Transforms.LoadRawImageBytes("ImageSource_featurized", null, "ImageSource"))
+ .Append(mlContext.Transforms.CopyColumns("Features", "ImageSource_featurized"));
+ // Set the training algorithm
+ var trainer = mlContext.MulticlassClassification.Trainers.ImageClassification(new ImageClassificationTrainer.Options() { LabelColumnName = "Label", FeatureColumnName = "Features" })
+ .Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel", "PredictedLabel"));
+
+ var trainingPipeline = dataProcessPipeline.Append(trainer);
+
+ return trainingPipeline;
+ }
+
+ public static ITransformer TrainModel(MLContext mlContext, IDataView trainingDataView, IEstimator trainingPipeline)
+ {
+ Console.WriteLine("=============== Training model ===============");
+
+ ITransformer model = trainingPipeline.Fit(trainingDataView);
+
+ Console.WriteLine("=============== End of training process ===============");
+ return model;
+ }
+
+ private static void Evaluate(MLContext mlContext, IDataView trainingDataView, IEstimator trainingPipeline)
+ {
+ // Cross-Validate with single dataset (since we don't have two datasets, one for training and for evaluate)
+ // in order to evaluate and get the model's accuracy metrics
+ Console.WriteLine("=============== Cross-validating to get model's accuracy metrics ===============");
+ var crossValidationResults = mlContext.MulticlassClassification.CrossValidate(trainingDataView, trainingPipeline, numberOfFolds: 5, labelColumnName: "Label");
+ PrintMulticlassClassificationFoldsAverageMetrics(crossValidationResults);
+ }
+
+ private static void SaveModel(MLContext mlContext, ITransformer mlModel, string modelRelativePath, DataViewSchema modelInputSchema)
+ {
+ // Save/persist the trained model to a .ZIP file
+ Console.WriteLine($"=============== Saving the model ===============");
+ mlContext.Model.Save(mlModel, modelInputSchema, GetAbsolutePath(modelRelativePath));
+ Console.WriteLine("The model is saved to {0}", GetAbsolutePath(modelRelativePath));
+ }
+
+ public static string GetAbsolutePath(string relativePath)
+ {
+ FileInfo _dataRoot = new FileInfo(typeof(Program).Assembly.Location);
+ string assemblyFolderPath = _dataRoot.Directory.FullName;
+
+ string fullPath = Path.Combine(assemblyFolderPath, relativePath);
+
+ return fullPath;
+ }
+
+ public static void PrintMulticlassClassificationMetrics(MulticlassClassificationMetrics metrics)
+ {
+ Console.WriteLine($"************************************************************");
+ Console.WriteLine($"* Metrics for multi-class classification model ");
+ Console.WriteLine($"*-----------------------------------------------------------");
+ Console.WriteLine($" MacroAccuracy = {metrics.MacroAccuracy:0.####}, a value between 0 and 1, the closer to 1, the better");
+ Console.WriteLine($" MicroAccuracy = {metrics.MicroAccuracy:0.####}, a value between 0 and 1, the closer to 1, the better");
+ Console.WriteLine($" LogLoss = {metrics.LogLoss:0.####}, the closer to 0, the better");
+ for (int i = 0; i < metrics.PerClassLogLoss.Count; i++)
+ {
+ Console.WriteLine($" LogLoss for class {i + 1} = {metrics.PerClassLogLoss[i]:0.####}, the closer to 0, the better");
+ }
+ Console.WriteLine($"************************************************************");
+ }
+
+ public static void PrintMulticlassClassificationFoldsAverageMetrics(IEnumerable> crossValResults)
+ {
+ var metricsInMultipleFolds = crossValResults.Select(r => r.Metrics);
+
+ var microAccuracyValues = metricsInMultipleFolds.Select(m => m.MicroAccuracy);
+ var microAccuracyAverage = microAccuracyValues.Average();
+ var microAccuraciesStdDeviation = CalculateStandardDeviation(microAccuracyValues);
+ var microAccuraciesConfidenceInterval95 = CalculateConfidenceInterval95(microAccuracyValues);
+
+ var macroAccuracyValues = metricsInMultipleFolds.Select(m => m.MacroAccuracy);
+ var macroAccuracyAverage = macroAccuracyValues.Average();
+ var macroAccuraciesStdDeviation = CalculateStandardDeviation(macroAccuracyValues);
+ var macroAccuraciesConfidenceInterval95 = CalculateConfidenceInterval95(macroAccuracyValues);
+
+ var logLossValues = metricsInMultipleFolds.Select(m => m.LogLoss);
+ var logLossAverage = logLossValues.Average();
+ var logLossStdDeviation = CalculateStandardDeviation(logLossValues);
+ var logLossConfidenceInterval95 = CalculateConfidenceInterval95(logLossValues);
+
+ var logLossReductionValues = metricsInMultipleFolds.Select(m => m.LogLossReduction);
+ var logLossReductionAverage = logLossReductionValues.Average();
+ var logLossReductionStdDeviation = CalculateStandardDeviation(logLossReductionValues);
+ var logLossReductionConfidenceInterval95 = CalculateConfidenceInterval95(logLossReductionValues);
+
+ Console.WriteLine($"*************************************************************************************************************");
+ Console.WriteLine($"* Metrics for Multi-class Classification model ");
+ Console.WriteLine($"*------------------------------------------------------------------------------------------------------------");
+ Console.WriteLine($"* Average MicroAccuracy: {microAccuracyAverage:0.###} - Standard deviation: ({microAccuraciesStdDeviation:#.###}) - Confidence Interval 95%: ({microAccuraciesConfidenceInterval95:#.###})");
+ Console.WriteLine($"* Average MacroAccuracy: {macroAccuracyAverage:0.###} - Standard deviation: ({macroAccuraciesStdDeviation:#.###}) - Confidence Interval 95%: ({macroAccuraciesConfidenceInterval95:#.###})");
+ Console.WriteLine($"* Average LogLoss: {logLossAverage:#.###} - Standard deviation: ({logLossStdDeviation:#.###}) - Confidence Interval 95%: ({logLossConfidenceInterval95:#.###})");
+ Console.WriteLine($"* Average LogLossReduction: {logLossReductionAverage:#.###} - Standard deviation: ({logLossReductionStdDeviation:#.###}) - Confidence Interval 95%: ({logLossReductionConfidenceInterval95:#.###})");
+ Console.WriteLine($"*************************************************************************************************************");
+
+ }
+
+ public static double CalculateStandardDeviation(IEnumerable values)
+ {
+ double average = values.Average();
+ double sumOfSquaresOfDifferences = values.Select(val => (val - average) * (val - average)).Sum();
+ double standardDeviation = Math.Sqrt(sumOfSquaresOfDifferences / (values.Count() - 1));
+ return standardDeviation;
+ }
+
+ public static double CalculateConfidenceInterval95(IEnumerable values)
+ {
+ double confidenceInterval95 = 1.96 * CalculateStandardDeviation(values) / Math.Sqrt((values.Count() - 1));
+ return confidenceInterval95;
+ }
+ }
+}
diff --git a/Mask.MLML.ConsoleApp/Program.cs b/Mask.MLML.ConsoleApp/Program.cs
new file mode 100644
index 0000000..6474a2a
--- /dev/null
+++ b/Mask.MLML.ConsoleApp/Program.cs
@@ -0,0 +1,28 @@
+// This file was auto-generated by ML.NET Model Builder.
+
+using System;
+using Mask_MLML.Model;
+
+namespace Mask_MLML.ConsoleApp
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ // Create single instance of sample data from first line of dataset for model input
+ ModelInput sampleData = new ModelInput()
+ {
+ ImageSource = @"D:\LancerProject\VsProject\Mask.ML\ImageData\已戴\1.jpg",
+ };
+
+ // Make a single prediction on the sample data and print results
+ var predictionResult = ConsumeModel.Predict(sampleData);
+
+ Console.WriteLine("Using model to make single prediction -- Comparing actual Label with predicted Label from sample data...\n\n");
+ Console.WriteLine($"ImageSource: {sampleData.ImageSource}");
+ Console.WriteLine($"\n\nPredicted Label value {predictionResult.Prediction} \nPredicted Label scores: [{String.Join(",", predictionResult.Score)}]\n\n");
+ Console.WriteLine("=============== End of process, hit any key to finish ===============");
+ Console.ReadKey();
+ }
+ }
+}
diff --git a/Mask.MLML.Model/ConsumeModel.cs b/Mask.MLML.Model/ConsumeModel.cs
new file mode 100644
index 0000000..f48f563
--- /dev/null
+++ b/Mask.MLML.Model/ConsumeModel.cs
@@ -0,0 +1,37 @@
+// This file was auto-generated by ML.NET Model Builder.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.ML;
+using Mask_MLML.Model;
+
+namespace Mask_MLML.Model
+{
+ public class ConsumeModel
+ {
+ private static Lazy> PredictionEngine = new Lazy>(CreatePredictionEngine);
+
+ // For more info on consuming ML.NET models, visit https://aka.ms/mlnet-consume
+ // Method for consuming model in your app
+ public static ModelOutput Predict(ModelInput input)
+ {
+ ModelOutput result = PredictionEngine.Value.Predict(input);
+ return result;
+ }
+
+ public static PredictionEngine CreatePredictionEngine()
+ {
+ // Create new MLContext
+ MLContext mlContext = new MLContext();
+
+ // Load model & create prediction engine
+ string modelPath = @"C:\Users\HUAWEI\AppData\Local\Temp\MLVSTools\Mask.MLML\Mask.MLML.Model\MLModel.zip";
+ ITransformer mlModel = mlContext.Model.Load(modelPath, out var modelInputSchema);
+ var predEngine = mlContext.Model.CreatePredictionEngine(mlModel);
+
+ return predEngine;
+ }
+ }
+}
diff --git a/Mask.MLML.Model/MLModel.zip b/Mask.MLML.Model/MLModel.zip
new file mode 100644
index 0000000..b182d4e
Binary files /dev/null and b/Mask.MLML.Model/MLModel.zip differ
diff --git a/Mask.MLML.Model/Mask.MLML.Model.csproj b/Mask.MLML.Model/Mask.MLML.Model.csproj
new file mode 100644
index 0000000..077eb17
--- /dev/null
+++ b/Mask.MLML.Model/Mask.MLML.Model.csproj
@@ -0,0 +1,22 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+
+
+
+
diff --git a/Mask.MLML.Model/ModelInput.cs b/Mask.MLML.Model/ModelInput.cs
new file mode 100644
index 0000000..d0f6d19
--- /dev/null
+++ b/Mask.MLML.Model/ModelInput.cs
@@ -0,0 +1,18 @@
+// This file was auto-generated by ML.NET Model Builder.
+
+using Microsoft.ML.Data;
+
+namespace Mask_MLML.Model
+{
+ public class ModelInput
+ {
+ [ColumnName("Label"), LoadColumn(0)]
+ public string Label { get; set; }
+
+
+ [ColumnName("ImageSource"), LoadColumn(1)]
+ public string ImageSource { get; set; }
+
+
+ }
+}
diff --git a/Mask.MLML.Model/ModelOutput.cs b/Mask.MLML.Model/ModelOutput.cs
new file mode 100644
index 0000000..cc20cde
--- /dev/null
+++ b/Mask.MLML.Model/ModelOutput.cs
@@ -0,0 +1,16 @@
+// This file was auto-generated by ML.NET Model Builder.
+
+using System;
+using Microsoft.ML.Data;
+
+namespace Mask_MLML.Model
+{
+ public class ModelOutput
+ {
+ // ColumnName attribute is used to change the column name from
+ // its default value, which is the name of the field.
+ [ColumnName("PredictedLabel")]
+ public String Prediction { get; set; }
+ public float[] Score { get; set; }
+ }
+}