Commit f21ed7f6 by 何阳

NEW:1. 增加系统登陆功能 2. 增加拉在线人脸功能 3. 增加配置文件

parent 51d5d01d
......@@ -11,46 +11,78 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServerTest", "ServerTest\Se
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClientTest", "ClientTest\ClientTest.csproj", "{DC69BE48-99DE-4533-B15D-FF9109CF1614}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FaceServerTests", "FaceServerTests\FaceServerTests.csproj", "{906E22CF-F9D5-4AAC-9165-6C8987388B31}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{269111C4-EDB6-485D-B47E-C62AE703021C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{269111C4-EDB6-485D-B47E-C62AE703021C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{269111C4-EDB6-485D-B47E-C62AE703021C}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{269111C4-EDB6-485D-B47E-C62AE703021C}.Debug|ARM64.Build.0 = Debug|Any CPU
{269111C4-EDB6-485D-B47E-C62AE703021C}.Debug|x64.ActiveCfg = Debug|x64
{269111C4-EDB6-485D-B47E-C62AE703021C}.Debug|x64.Build.0 = Debug|x64
{269111C4-EDB6-485D-B47E-C62AE703021C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{269111C4-EDB6-485D-B47E-C62AE703021C}.Release|Any CPU.Build.0 = Release|Any CPU
{269111C4-EDB6-485D-B47E-C62AE703021C}.Release|ARM64.ActiveCfg = Release|Any CPU
{269111C4-EDB6-485D-B47E-C62AE703021C}.Release|ARM64.Build.0 = Release|Any CPU
{269111C4-EDB6-485D-B47E-C62AE703021C}.Release|x64.ActiveCfg = Release|x64
{269111C4-EDB6-485D-B47E-C62AE703021C}.Release|x64.Build.0 = Release|x64
{1A20E2DE-F5FD-4555-93CE-AC9CEE9E8FA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A20E2DE-F5FD-4555-93CE-AC9CEE9E8FA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A20E2DE-F5FD-4555-93CE-AC9CEE9E8FA2}.Debug|ARM64.ActiveCfg = Debug|x64
{1A20E2DE-F5FD-4555-93CE-AC9CEE9E8FA2}.Debug|ARM64.Build.0 = Debug|x64
{1A20E2DE-F5FD-4555-93CE-AC9CEE9E8FA2}.Debug|x64.ActiveCfg = Debug|x64
{1A20E2DE-F5FD-4555-93CE-AC9CEE9E8FA2}.Debug|x64.Build.0 = Debug|x64
{1A20E2DE-F5FD-4555-93CE-AC9CEE9E8FA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A20E2DE-F5FD-4555-93CE-AC9CEE9E8FA2}.Release|Any CPU.Build.0 = Release|Any CPU
{1A20E2DE-F5FD-4555-93CE-AC9CEE9E8FA2}.Release|ARM64.ActiveCfg = Release|Any CPU
{1A20E2DE-F5FD-4555-93CE-AC9CEE9E8FA2}.Release|ARM64.Build.0 = Release|Any CPU
{1A20E2DE-F5FD-4555-93CE-AC9CEE9E8FA2}.Release|x64.ActiveCfg = Release|x64
{1A20E2DE-F5FD-4555-93CE-AC9CEE9E8FA2}.Release|x64.Build.0 = Release|x64
{0A3C84AF-FF06-4770-B00D-F938A1431D42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0A3C84AF-FF06-4770-B00D-F938A1431D42}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0A3C84AF-FF06-4770-B00D-F938A1431D42}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{0A3C84AF-FF06-4770-B00D-F938A1431D42}.Debug|ARM64.Build.0 = Debug|Any CPU
{0A3C84AF-FF06-4770-B00D-F938A1431D42}.Debug|x64.ActiveCfg = Debug|Any CPU
{0A3C84AF-FF06-4770-B00D-F938A1431D42}.Debug|x64.Build.0 = Debug|Any CPU
{0A3C84AF-FF06-4770-B00D-F938A1431D42}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0A3C84AF-FF06-4770-B00D-F938A1431D42}.Release|Any CPU.Build.0 = Release|Any CPU
{0A3C84AF-FF06-4770-B00D-F938A1431D42}.Release|ARM64.ActiveCfg = Release|Any CPU
{0A3C84AF-FF06-4770-B00D-F938A1431D42}.Release|ARM64.Build.0 = Release|Any CPU
{0A3C84AF-FF06-4770-B00D-F938A1431D42}.Release|x64.ActiveCfg = Release|Any CPU
{0A3C84AF-FF06-4770-B00D-F938A1431D42}.Release|x64.Build.0 = Release|Any CPU
{DC69BE48-99DE-4533-B15D-FF9109CF1614}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DC69BE48-99DE-4533-B15D-FF9109CF1614}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DC69BE48-99DE-4533-B15D-FF9109CF1614}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{DC69BE48-99DE-4533-B15D-FF9109CF1614}.Debug|ARM64.Build.0 = Debug|Any CPU
{DC69BE48-99DE-4533-B15D-FF9109CF1614}.Debug|x64.ActiveCfg = Debug|Any CPU
{DC69BE48-99DE-4533-B15D-FF9109CF1614}.Debug|x64.Build.0 = Debug|Any CPU
{DC69BE48-99DE-4533-B15D-FF9109CF1614}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DC69BE48-99DE-4533-B15D-FF9109CF1614}.Release|Any CPU.Build.0 = Release|Any CPU
{DC69BE48-99DE-4533-B15D-FF9109CF1614}.Release|ARM64.ActiveCfg = Release|Any CPU
{DC69BE48-99DE-4533-B15D-FF9109CF1614}.Release|ARM64.Build.0 = Release|Any CPU
{DC69BE48-99DE-4533-B15D-FF9109CF1614}.Release|x64.ActiveCfg = Release|Any CPU
{DC69BE48-99DE-4533-B15D-FF9109CF1614}.Release|x64.Build.0 = Release|Any CPU
{906E22CF-F9D5-4AAC-9165-6C8987388B31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{906E22CF-F9D5-4AAC-9165-6C8987388B31}.Debug|Any CPU.Build.0 = Debug|Any CPU
{906E22CF-F9D5-4AAC-9165-6C8987388B31}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{906E22CF-F9D5-4AAC-9165-6C8987388B31}.Debug|ARM64.Build.0 = Debug|Any CPU
{906E22CF-F9D5-4AAC-9165-6C8987388B31}.Debug|x64.ActiveCfg = Debug|Any CPU
{906E22CF-F9D5-4AAC-9165-6C8987388B31}.Debug|x64.Build.0 = Debug|Any CPU
{906E22CF-F9D5-4AAC-9165-6C8987388B31}.Release|Any CPU.ActiveCfg = Release|Any CPU
{906E22CF-F9D5-4AAC-9165-6C8987388B31}.Release|Any CPU.Build.0 = Release|Any CPU
{906E22CF-F9D5-4AAC-9165-6C8987388B31}.Release|ARM64.ActiveCfg = Release|Any CPU
{906E22CF-F9D5-4AAC-9165-6C8987388B31}.Release|ARM64.Build.0 = Release|Any CPU
{906E22CF-F9D5-4AAC-9165-6C8987388B31}.Release|x64.ActiveCfg = Release|Any CPU
{906E22CF-F9D5-4AAC-9165-6C8987388B31}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......
using SharpConfig;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FaceServer
{
public static class Config
{
static Configuration settings;
public static Section Api;
public static void Load(string filename)
{
settings = Configuration.LoadFromFile(filename);
Api = settings["api"];
User = Api["User"].GetValueOrDefault("15995200590");
Passwd = Api["Passwd"].GetValueOrDefault("123456");
BaseUrl = Api["BaseUrl"].GetValueOrDefault("https://saas-uat.guke.tech");
LoginUrl = Api["LoginUrl"].GetValueOrDefault("/api/ucpm/console/token");
Test = Api["Test"].GetValueOrDefault(100);
}
public static string User { get; set; }
public static string Passwd { get; set; }
public static string BaseUrl { get; set; }
public static string LoginUrl { get; set; }
public static int Test { get; set; }
public static string OMP_TOKEN { get; internal set; }
public static string TENANT_ID { get; internal set; }
}
}
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FaceServer.DTO
{
public class OssFile
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("filePath")]
public string FilePath { get; set; }
[JsonProperty("fileName")]
public string FileName { get; set; }
[JsonIgnore]
public User Owner { get; set; }
}
}
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FaceServer.DTO
{
public class User
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("accountId")]
public string AccountId { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("username")]
public string Username { get; set; }
[JsonProperty("weChatNo")]
public string WeChatNo { get; set; }
[JsonProperty("tenantId")]
public string TenantId { get; set; }
[JsonProperty("faceFileId")]
public string FaceFileId { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FaceServer.DTO
{
public class UserLoginVo
{
public string username { get; set; }
public string password { get; set; }
public string grantType { get; set; }
}
}
......@@ -64,6 +64,9 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="CSharpFunctionalExtensions, Version=2.40.3.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\CSharpFunctionalExtensions.2.40.3\lib\net461\CSharpFunctionalExtensions.dll</HintPath>
</Reference>
<Reference Include="DlibDotNet, Version=19.21.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\DlibDotNet.19.21.0.20220724\lib\netstandard2.0\DlibDotNet.dll</HintPath>
</Reference>
......@@ -79,12 +82,18 @@
<Reference Include="MessagePack.ImmutableCollection, Version=2.5.0.0, Culture=neutral, PublicKeyToken=b4a0369545f0a1be, processorArchitecture=MSIL">
<HintPath>..\packages\MessagePack.ImmutableCollection.2.5.140\lib\netstandard2.0\MessagePack.ImmutableCollection.dll</HintPath>
</Reference>
<Reference Include="MetadataExtractor, Version=2.8.1.0, Culture=neutral, PublicKeyToken=b66b5ccaf776c301, processorArchitecture=MSIL">
<HintPath>..\packages\MetadataExtractor.2.8.1\lib\net45\MetadataExtractor.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.6.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
</Reference>
<Reference Include="Microsoft.NET.StringTools, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.NET.StringTools.17.6.3\lib\net472\Microsoft.NET.StringTools.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="OpenCvSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6adad1e807fea099, processorArchitecture=MSIL">
<HintPath>..\packages\OpenCvSharp4.4.9.0.20240103\lib\net48\OpenCvSharp.dll</HintPath>
</Reference>
......@@ -114,6 +123,9 @@
<Reference Include="Serilog.Sinks.Trace, Version=3.0.0.0, Culture=neutral, PublicKeyToken=24c2f752a8e58a10, processorArchitecture=MSIL">
<HintPath>..\packages\Serilog.Sinks.Trace.3.0.0\lib\net45\Serilog.Sinks.Trace.dll</HintPath>
</Reference>
<Reference Include="SharpConfig, Version=3.2.9.1, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\SharpConfig.3.2.9.1\lib\net461\SharpConfig.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
......@@ -154,8 +166,16 @@
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
<Reference Include="XmpCore, Version=6.1.10.1, Culture=neutral, PublicKeyToken=961f4f366277b80e, processorArchitecture=MSIL">
<HintPath>..\packages\XmpCore.6.1.10.1\lib\net35\XmpCore.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Config.cs" />
<Compile Include="DTO\OssFile.cs" />
<Compile Include="DTO\UserInfo.cs" />
<Compile Include="DTO\UserLoginVo.cs" />
<Compile Include="Server\FaceDataSet.cs" />
<Compile Include="Util\ConvertEx.cs" />
<Compile Include="Util\FaceRecognitionThread.cs" />
<Compile Include="Util\FaceUtil.cs" />
......@@ -171,6 +191,8 @@
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TextBoxSink.cs" />
<Compile Include="Util\ImageHash.cs" />
<Compile Include="Util\MetadataHelper.cs" />
<EmbeddedResource Include="Main.resx">
<DependentUpon>Main.cs</DependentUpon>
</EmbeddedResource>
......@@ -183,6 +205,9 @@
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="config.ini">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Model\dlib_face_recognition_resnet_model_v1.dat">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
......@@ -213,13 +238,12 @@
<Content Include="App.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Face\何阳.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Face\何阳.jpg" />
</ItemGroup>
<ItemGroup>
<Analyzer Include="..\packages\MessagePackAnalyzer.2.5.140\analyzers\dotnet\MessagePackAnalyzer.dll" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
......
......@@ -25,13 +25,29 @@ namespace FaceServer
rollingInterval: RollingInterval.Day,
fileSizeLimitBytes: 1_000_000,
rollOnFileSizeLimit: true,
outputTemplate: "[{Timestamp:HH:mm:ss.fff}] [{Level}] [{ThreadId}] [{SourceContext}] {Message:lj}{NewLine}{Code} {Exception}") // 文件日志,每天滚动
.WriteTo.Trace(outputTemplate: "[{Timestamp:HH:mm:ss.fff}] [{Level}] [{ThreadId}] [{SourceContext}] {Message:lj}{NewLine}{Code} {Exception}")
.WriteTo.Sink(new TextBoxSink(textBox, "[{Timestamp:HH:mm:ss.fff}] [{Level}] [{ThreadId}] [{SourceContext}] {Message:lj}{NewLine}{Exception}")) // 自定义 TextBox Sink
outputTemplate: "[{Timestamp:HH:mm:ss.fff}] [{Level}] [{ThreadId}]{Message:lj}{NewLine}{Code} {Exception}") // 文件日志,每天滚动
.WriteTo.Trace(outputTemplate: "[{Timestamp:HH:mm:ss.fff}] [{Level}] [{ThreadId}]{Message:lj}{NewLine}{Code} {Exception}")
.WriteTo.Sink(new TextBoxSink(textBox, "[{Timestamp:HH:mm:ss.fff}] [{Level}] [{ThreadId}]{Message:lj}{NewLine}{Exception}")) // 自定义 TextBox Sink
.CreateLogger();
_logger = Log.Logger;
Serilog.Debugging.SelfLog.Enable(Console.Error);
}
public static void Init()
{
// 配置 Serilog
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.With(new ThreadIdEnricher()) // 丰富器,包括线程号
.WriteTo.File(
path: "log/log-.log",
rollingInterval: RollingInterval.Day,
fileSizeLimitBytes: 1_000_000,
rollOnFileSizeLimit: true,
outputTemplate: "[{Timestamp:HH:mm:ss.fff}] [{Level}] [{ThreadId}] {Message:lj}{NewLine}{Code} {Exception}") // 文件日志,每天滚动
.WriteTo.Trace(outputTemplate: "[{Timestamp:HH:mm:ss.fff}] [{Level}] [{ThreadId}] {Message:lj}{NewLine}{Code} {Exception}")
.CreateLogger();
_logger = Log.Logger;
Serilog.Debugging.SelfLog.Enable(Console.Error);
}
}
}
......@@ -39,13 +39,14 @@
this.tbLog.Location = new System.Drawing.Point(12, 12);
this.tbLog.Multiline = true;
this.tbLog.Name = "tbLog";
this.tbLog.Size = new System.Drawing.Size(776, 377);
this.tbLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.tbLog.Size = new System.Drawing.Size(1214, 431);
this.tbLog.TabIndex = 0;
//
// cbPowerOn
//
this.cbPowerOn.AutoSize = true;
this.cbPowerOn.Location = new System.Drawing.Point(12, 422);
this.cbPowerOn.Location = new System.Drawing.Point(10, 476);
this.cbPowerOn.Name = "cbPowerOn";
this.cbPowerOn.Size = new System.Drawing.Size(72, 16);
this.cbPowerOn.TabIndex = 1;
......@@ -55,7 +56,7 @@
//
// tbROI
//
this.tbROI.Location = new System.Drawing.Point(65, 395);
this.tbROI.Location = new System.Drawing.Point(63, 449);
this.tbROI.Name = "tbROI";
this.tbROI.Size = new System.Drawing.Size(100, 21);
this.tbROI.TabIndex = 2;
......@@ -63,7 +64,7 @@
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 404);
this.label1.Location = new System.Drawing.Point(10, 458);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(47, 12);
this.label1.TabIndex = 3;
......@@ -73,15 +74,16 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.ClientSize = new System.Drawing.Size(1238, 499);
this.Controls.Add(this.label1);
this.Controls.Add(this.tbROI);
this.Controls.Add(this.cbPowerOn);
this.Controls.Add(this.tbLog);
this.Name = "Main";
this.Text = "Form1";
this.Text = "人脸识别服务";
this.Load += new System.EventHandler(this.Main_Load);
this.Shown += new System.EventHandler(this.Main_Shown);
this.Resize += new System.EventHandler(this.Main_Resize);
this.ResumeLayout(false);
this.PerformLayout();
......
using Microsoft.Win32;
using FaceServer.DTO;
using FaceServer.Server;
using Microsoft.Win32;
using Serilog;
using System;
using System.Collections.Generic;
......@@ -23,6 +25,7 @@ namespace FaceServer
InitializeTrayIcon();
trayIcon.MouseDoubleClick += TrayIcon_MouseDoubleClick;
this.ShowInTaskbar = false;//任务栏中显示标志
Config.Load("config.ini");
}
private void TrayIcon_MouseDoubleClick(object sender, MouseEventArgs e)
......@@ -36,6 +39,7 @@ namespace FaceServer
// 创建右键菜单项
trayMenu = new ContextMenu();
trayMenu.MenuItems.Add("打开", OnTrayIconOpenClicked);
trayMenu.MenuItems.Add("更新", OnRefrechClicked);
trayMenu.MenuItems.Add("退出", OnTrayIconExitClicked);
// 创建系统托盘图标
......@@ -49,6 +53,66 @@ namespace FaceServer
// 显示图标
trayIcon.Visible = true;
}
private async void OnRefrechClicked(object sender, EventArgs e)
{
FaceDataSet.InitApi();
var loginResponse = await FaceDataSet.Login();
if (loginResponse.IsFailure)
{
MessageBox.Show("连接系统失败: " + loginResponse.Error);
return;
}
var usersResponse = await FaceDataSet.GetUserListAsync();
if (usersResponse.IsFailure)
{
MessageBox.Show("获取用户名单失败: "+usersResponse.Error);
return;
}
var users = usersResponse.Value.Where(u => u.FaceFileId != null);
var ossFiles = new List<OssFile>();
foreach (var usr in users)
{
var fileResponse = await FaceDataSet.QueryFileAsync(usr);
if (fileResponse.IsFailure)
{
Log.Warning($"查询文件失败: {fileResponse.Error}");
continue;
}
ossFiles.Add(fileResponse.Value);
}
if (ossFiles.Count == 0)
{
MessageBox.Show("更新照片失败,没有拉到图片!");
return;
}
var downResponse = await FaceDataSet.Download(ossFiles, "Face");
if (downResponse.IsFailure)
{
MessageBox.Show("更新照片失败: " + downResponse.Error);
return;
}
await Task.Run(() =>
{
Log.Information("重新初始化人脸服务");
Server = new FaceRecognitionServer("Face", "Model");
Server.RoiSize = 480;
Log.Information("人脸服务初始化成功");
});
MessageBox.Show("更新成功");
}
private Icon ConvertImageToIcon(string imagePath)
{
using (Image image = Image.FromFile(imagePath))
......@@ -251,5 +315,15 @@ namespace FaceServer
}
}
}
private void Main_Resize(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
// 在窗体最小化时执行您的操作
// 例如,可以隐藏窗体、显示通知图标等
this.Hide();
}
}
}
}
......@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.0.0.1")]
[assembly: AssemblyFileVersion("1.0.0.1")]
using CSharpFunctionalExtensions;
using FaceServer.DTO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Serilog;
using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using MetadataExtractor;
using Directory = System.IO.Directory;
using FaceServer.Util;
namespace FaceServer.Server
{
public static class FaceDataSet
{
static HttpClient client;
public static void InitApi()
{
client = new HttpClient();
client.DefaultRequestHeaders.Add("Client-Code", "console");
}
public static async Task<Result<JToken,string>> PostJsonAsync(string url, string data)
{
var content = new StringContent(data.ToString(), Encoding.UTF8, "application/json");
var respond = await client.PostAsync(url, content);
var res = await respond.Content.ReadAsStringAsync();
JObject jo = (JObject)JsonConvert.DeserializeObject(res);
if ((int)respond.StatusCode == 401)
{
await Login();
return await PostJsonAsync( url, data);
}
if (respond.StatusCode != System.Net.HttpStatusCode.OK)
{
return $"登陆失败:Code:{jo["code"]},msg:{jo["msg"]}";
}
return jo["data"];
}
public static async Task<Result<JToken, string>> GetJsonList(string url)
{
var respond = await client.GetAsync(url);
var raw = await respond.Content.ReadAsStringAsync();
JObject jo = (JObject)JsonConvert.DeserializeObject(raw);
if ((int)respond.StatusCode == 401)
{
await Login();
return await GetJsonList(url);
}
if (respond.StatusCode != System.Net.HttpStatusCode.OK)
{
return $"Code:{jo["code"]},msg:{jo["msg"]}";
}
return jo["data"]["records"];
}
public static async Task<Result<byte[], string>> GetImage(string imageUrl)
{
var respond = await client.GetAsync(imageUrl);
if (respond.StatusCode != System.Net.HttpStatusCode.OK)
{
var rawError = await respond.Content.ReadAsStringAsync();
JObject errorObject = (JObject)JsonConvert.DeserializeObject(rawError);
return $"Failed to get image. Code:{errorObject["code"]}, msg:{errorObject["msg"]}";
}
var imageBytes = await respond.Content.ReadAsByteArrayAsync();
return imageBytes;
}
public static async Task<Result<OssFile,string>> QueryFileAsync(User usr)
{
Log.Information($"查询{usr.Name} 照片");
var url = Config.BaseUrl + "api/ucpm/oss/queryBatchById";
var data = new JObject()
{
["ids" ] = new JArray() { usr.FaceFileId }
};
var res = await PostJsonAsync(url, data.ToString());
if (res.IsFailure)
{
return res.Error;
}
var files = res.Value.ToObject<List<OssFile>>();
var file = files.First();
file.Owner = usr;
return file;
}
public static async Task< UnitResult< string> > Download(List<OssFile> files, string dir)
{
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
var errs = new List<string>();
foreach (var file in files)
{
Log.Information($"下载图片:{file.FileName} 所属:{file.Owner.Name}");
var result = await GetImage(file.FilePath);
if (result.IsFailure)
{
var msg = $"Failed to download image for file {file.FileName}. Error: {result.Error}";
errs.Add(msg);
}
else
{
var hash = ImageHash.CalculateImageHashWithSalt(result.Value, file.Owner.Name);
string filePath = Path.Combine(dir, $"{file.Owner.Name}_{file.Owner.AccountId}_{hash}.jpg");
File.WriteAllBytes(filePath, result.Value);
Log.Information($"文件哈希:{hash}");
}
}
if (errs.Count == 0)
{
return Result.Success();
}
var str = errs.Aggregate((sum, cur) => sum + "/n" + cur);
return UnitResult.Failure(str);
}
public static async Task<UnitResult<string>> Login()
{
UserLoginVo user = new UserLoginVo();
user.grantType = "password";
user.username = Config.User;
user.password = Config.Passwd;
Log.Information($"登陆管理账号:{user.username}");
var content = new StringContent(JsonConvert.SerializeObject(user), Encoding.UTF8, "application/json");
var respond = await client.PostAsync(Config.BaseUrl + "api/ucpm/token", content);
var res = await respond.Content.ReadAsStringAsync();
Log.Information($"登陆结果:{res}");
JObject jo = (JObject)JsonConvert.DeserializeObject(res);
if (respond.StatusCode != System.Net.HttpStatusCode.OK)
{
return $"登陆失败:Code:{jo["code"]},msg:{jo["msg"]}";
}
Config.OMP_TOKEN = jo["data"]["token"].ToString();
Config.TENANT_ID = jo["data"]["identityId"].ToString();
client.DefaultRequestHeaders.Add("Access-Token", Config.OMP_TOKEN);
Log.Information("登陆成功!");
return Result.Success();
}
public static async Task<Result<List<User>,string>> GetUserListAsync()
{
Log.Information($"获取用户列表");
var url = Config.BaseUrl + "api/ucpm/identity/employee/page" + "?pageNo=1&pageSize=9999";
var raw = await GetJsonList(url);
if (raw.IsFailure)
{
return $"获取用户列表失败:{raw.Error}";
}
var data = raw.Value.ToObject<List<User>>();
return data;
}
}
}
......@@ -20,11 +20,11 @@ public static class ConvertEx
writer.Write(faceData.FaceRect.Height);
byte[] nameBytes = Encoding.UTF8.GetBytes(faceData.Name);
if (nameBytes.Length > 50)
if (nameBytes.Length > 255)
{
throw new ArgumentException("Name is too long to serialize");
}
byte[] paddedNameBytes = new byte[50]; // 固定长度的字节数组
byte[] paddedNameBytes = new byte[255]; // 固定长度的字节数组
Array.Copy(nameBytes, paddedNameBytes, nameBytes.Length); // 复制字符串的字节数组到固定长度的字节数组
writer.Write(paddedNameBytes);
......
......@@ -11,11 +11,12 @@ using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using System.Text;
using Serilog;
using FaceServer.Util;
public class FaceRecognitionServer
{
private static FaceRecognition FaceRecognition = null;
private static Dictionary<string, FaceEncoding> KnownFaceEncodings = null;
private FaceRecognition FaceRecognition = null;
private Dictionary<string, FaceEncoding> KnownFaceEncodings = null;
public Rectangle Roi { set; get; } = default;
public int RoiSize { set; get; } = default;
public FaceRecognitionServer(string faceDataPath, string modelPath)
......@@ -104,6 +105,12 @@ public class FaceRecognitionServer
var knownFaceEncodings = new Dictionary<string, FaceEncoding>();
foreach (var imagePath in Directory.GetFiles(faceDataPath, "*.jpg"))
{
if (!ImageHash.Test(imagePath))
{
Log.Warning($"{imagePath} 文件哈希校验失败!");
continue;
}
var name = Path.GetFileNameWithoutExtension(imagePath);
var image = FaceRecognition.LoadImageFile(imagePath);
var faceEncoding = faceRecognition.FaceEncodings(image).FirstOrDefault();
......
using CSharpFunctionalExtensions;
using Serilog;
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
namespace FaceServer.Util
{
public class ImageHash
{
public static string CalculateImageHashWithSalt(byte[] imageBytes, string salt)
{
// 将图片数据和盐拼接
byte[] saltBytes = Encoding.UTF8.GetBytes(salt);
byte[] combinedBytes = new byte[imageBytes.Length + saltBytes.Length];
Buffer.BlockCopy(imageBytes, 0, combinedBytes, 0, imageBytes.Length);
Buffer.BlockCopy(saltBytes, 0, combinedBytes, imageBytes.Length, saltBytes.Length);
// 计算SHA-256哈希
using (SHA256 sha256 = SHA256.Create())
{
byte[] hashBytes = sha256.ComputeHash(combinedBytes);
// 将哈希值转换为16进制字符串
StringBuilder sb = new StringBuilder();
foreach (byte b in hashBytes)
{
sb.Append(b.ToString("x2"));
}
return sb.ToString();
}
}
public static bool Test(string filename)
{
var meta = Path.GetFileNameWithoutExtension(filename);
var parts = meta.Split('_'); // 将字符串分割为数组
var name = parts[0];
var id = parts[1];
var hash = parts[2];
Log.Information($"file:{filename}");
var cal = CalculateImageHashWithSalt(filename, name);
Log.Information($"cal:{cal}");
return hash == cal;
}
public static string CalculateImageHashWithSalt(string imagePath, string salt)
{
// 读取文件尾部的1KB数据
byte[] imageBytes = File.ReadAllBytes(imagePath);
// 将图片数据和盐拼接
byte[] saltBytes = Encoding.UTF8.GetBytes(salt);
byte[] combinedBytes = new byte[imageBytes.Length + saltBytes.Length];
Buffer.BlockCopy(imageBytes, 0, combinedBytes, 0, imageBytes.Length);
Buffer.BlockCopy(saltBytes, 0, combinedBytes, imageBytes.Length, saltBytes.Length);
// 计算SHA-256哈希
using (SHA256 sha256 = SHA256.Create())
{
byte[] hashBytes = sha256.ComputeHash(combinedBytes);
// 将哈希值转换为16进制字符串
StringBuilder sb = new StringBuilder();
foreach (byte b in hashBytes)
{
sb.Append(b.ToString("x2"));
}
return sb.ToString();
}
}
}
}
using MetadataExtractor;
using MetadataExtractor.Formats.Exif;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
namespace FaceServer.Util
{
public static class MetadataHelper
{
public static void AddMetadata(string filePath, string name, string accountId, string hash)
{
byte[] fileBytes = File.ReadAllBytes(filePath);
using (var ms = new MemoryStream(fileBytes))
using (var image = Image.FromStream(ms))
{
var propItems = image.PropertyItems;
var encoder = Encoding.GetEncoding("unicode");
var data = $"{name}:{accountId}:{hash}";
SetProperty(0x9c9c, encoder.GetBytes(data), image, propItems);
// 保存更改到新的内存流
using (var newMs = new MemoryStream())
{
image.Save(newMs, ImageFormat.Jpeg);
File.WriteAllBytes(filePath, newMs.ToArray());
}
}
}
public static string GetMetadata(string filePath)
{
using (var image = Image.FromFile(filePath))
{
var metadata = GetProperty(0x9c9c, image);
var encoder = Encoding.GetEncoding("unicode");
var data = encoder.GetString(metadata);
return data;
}
}
private static void SetProperty(int id, byte[] value, Image image, PropertyItem[] propItems)
{
PropertyItem pi = propItems[0];
pi.Id = id;
pi.Type = 1;
pi.Value = value;
pi.Len = pi.Value.Length;
image.SetPropertyItem(pi);
}
private static byte[] GetProperty(int id, Image image)
{
PropertyItem pi = image.PropertyItems.First(p => p.Id == id);
return pi.Value;
}
}
}
[api]
User=15995200590
Passwd=123456
BaseUrl=https://saas-test.guke.tech/
LoginUrl=api/ucpm/console/token
Test=100
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="CSharpFunctionalExtensions" version="2.40.3" targetFramework="net48" />
<package id="DlibDotNet" version="19.21.0.20220724" targetFramework="net48" />
<package id="FaceRecognitionDotNet" version="1.3.0.7" targetFramework="net48" />
<package id="MessagePack" version="2.5.140" targetFramework="net48" />
<package id="MessagePack.Annotations" version="2.5.140" targetFramework="net48" />
<package id="MessagePack.ImmutableCollection" version="2.5.140" targetFramework="net48" />
<package id="MessagePackAnalyzer" version="2.5.140" targetFramework="net48" developmentDependency="true" />
<package id="MetadataExtractor" version="2.8.1" targetFramework="net48" />
<package id="Microsoft.Bcl.AsyncInterfaces" version="6.0.0" targetFramework="net48" />
<package id="Microsoft.NET.StringTools" version="17.6.3" targetFramework="net48" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
<package id="OpenCvSharp4" version="4.9.0.20240103" targetFramework="net48" />
<package id="OpenCvSharp4.Extensions" version="4.9.0.20240103" targetFramework="net48" />
<package id="OpenCvSharp4.runtime.win" version="4.9.0.20240103" targetFramework="net48" />
......@@ -19,6 +22,7 @@
<package id="Serilog.Enrichers.Thread" version="3.1.0" targetFramework="net48" />
<package id="Serilog.Sinks.File" version="5.0.0" targetFramework="net48" />
<package id="Serilog.Sinks.Trace" version="3.0.0" targetFramework="net48" />
<package id="SharpConfig" version="3.2.9.1" targetFramework="net48" />
<package id="System.Buffers" version="4.5.1" targetFramework="net48" />
<package id="System.Collections.Immutable" version="7.0.0" targetFramework="net48" />
<package id="System.Drawing.Common" version="7.0.0" targetFramework="net48" />
......@@ -29,4 +33,5 @@
<package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net48" />
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net48" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net48" />
<package id="XmpCore" version="6.1.10.1" targetFramework="net48" />
</packages>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{906E22CF-F9D5-4AAC-9165-6C8987388B31}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>FaceServerTests</RootNamespace>
<AssemblyName>FaceServerTests</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="CSharpFunctionalExtensions, Version=2.40.3.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\CSharpFunctionalExtensions.2.40.3\lib\net461\CSharpFunctionalExtensions.dll</HintPath>
</Reference>
<Reference Include="GroupDocs.Metadata, Version=24.1.0.0, Culture=neutral, PublicKeyToken=716fcc553a201e56, processorArchitecture=MSIL">
<HintPath>..\packages\GroupDocs.Metadata.24.1.0\lib\net472\GroupDocs.Metadata.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.6.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Serilog, Version=2.0.0.0, Culture=neutral, PublicKeyToken=24c2f752a8e58a10, processorArchitecture=MSIL">
<HintPath>..\packages\Serilog.3.1.1\lib\net471\Serilog.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Diagnostics.DiagnosticSource, Version=7.0.0.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Diagnostics.DiagnosticSource.7.0.2\lib\net462\System.Diagnostics.DiagnosticSource.dll</HintPath>
</Reference>
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Text.Encoding.CodePages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Encoding.CodePages.6.0.0\lib\net461\System.Text.Encoding.CodePages.dll</HintPath>
</Reference>
<Reference Include="System.Text.Encodings.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Encodings.Web.6.0.0\lib\net461\System.Text.Encodings.Web.dll</HintPath>
</Reference>
<Reference Include="System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Json.6.0.0\lib\net461\System.Text.Json.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Forms" />
</ItemGroup>
<Choose>
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
</ItemGroup>
</Otherwise>
</Choose>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Server\FaceDataSetTests.cs" />
<Compile Include="Util\ImageHashTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FaceServer\FaceServer.csproj">
<Project>{1A20E2DE-F5FD-4555-93CE-AC9CEE9E8FA2}</Project>
<Name>FaceServer</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
</ItemGroup>
</When>
</Choose>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\System.Text.Json.6.0.0\build\System.Text.Json.targets" Condition="Exists('..\packages\System.Text.Json.6.0.0\build\System.Text.Json.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\System.Text.Json.6.0.0\build\System.Text.Json.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\System.Text.Json.6.0.0\build\System.Text.Json.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("FaceServerTests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FaceServerTests")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//将 ComVisible 设置为 false 将使此程序集中的类型
//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("906e22cf-f9d5-4aac-9165-6c8987388b31")]
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
using Microsoft.VisualStudio.TestTools.UnitTesting;
using FaceServer.Server;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using Newtonsoft.Json;
using FaceServer.DTO;
using CSharpFunctionalExtensions;
using System.IO;
namespace FaceServer.Server.Tests
{
[TestClass()]
public class FaceDataSetTests
{
[TestInitialize]
public void Initialize()
{
Logging.Init();
Config.Load("config.ini");
FaceDataSet.InitApi();
var res = FaceDataSet.Login().Result;
Assert.IsTrue(res.IsSuccess);
Assert.IsFalse(string.IsNullOrEmpty(Config.OMP_TOKEN));
}
[TestMethod()]
public void GetUserListAsyncTest()
{
var usrs = FaceDataSet.GetUserListAsync().Result;
Assert.IsTrue(usrs.IsSuccess);
Assert.IsTrue(usrs.Value.Count != 0);
foreach (var u in usrs.Value)
{
Console.WriteLine(JsonConvert.SerializeObject(u));
}
}
[TestMethod()]
public void QueryFileAsyncTest()
{
List<User> usersWithFaceFiles = GetUsersWithFaceFiles();
Assert.IsTrue(usersWithFaceFiles.Count != 0);
foreach (var user in usersWithFaceFiles)
{
var fileResult = FaceDataSet.QueryFileAsync(user).Result;
if (fileResult.IsFailure)
{
Assert.Fail($"Failed to query file for user {user.Name}. Error: {fileResult.Error}");
}
else
{
Console.WriteLine($"File data for user {user.Name}: {JsonConvert.SerializeObject(fileResult.Value)}");
}
}
Assert.IsTrue(true);
}
private List<User> GetUsersWithFaceFiles()
{
var usersResponse = FaceDataSet.GetUserListAsync().Result;
if (usersResponse.IsSuccess)
{
return usersResponse.Value.Where(u => u.FaceFileId != null).ToList();
}
else
{
Assert.Fail($"Failed to get user list. Error: {usersResponse.Error}");
return new List<User>();
}
}
[TestMethod()]
public void DownloadTest()
{
var usrs = GetUsersWithFaceFiles();
var files = usrs.Select(u => FaceDataSet.QueryFileAsync(u).Result.Value).ToList();
var res = FaceDataSet.Download(files, "Image").Result;
if (res.IsFailure)
{
Console.WriteLine($"Error: {res.Error}");
Assert.Fail();
}
// 打开文件夹
Process.Start("explorer.exe", $"\"{Path.Combine( AppDomain.CurrentDomain.BaseDirectory, "Image")}\"");
Assert.IsTrue(true);
}
}
}
\ No newline at end of file
using Microsoft.VisualStudio.TestTools.UnitTesting;
using FaceServer.Util;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using FaceServer.Server;
using FaceServer.DTO;
using Serilog;
namespace FaceServer.Util.Tests
{
[TestClass()]
public class ImageHashTests
{
[TestInitialize]
public void Initialize()
{
Logging.Init();
Config.Load("config.ini");
FaceDataSet.InitApi();
var res = FaceDataSet.Login().Result;
Assert.IsTrue(res.IsSuccess);
Assert.IsFalse(string.IsNullOrEmpty(Config.OMP_TOKEN));
}
private List<User> GetUsersWithFaceFiles()
{
var usersResponse = FaceDataSet.GetUserListAsync().Result;
if (usersResponse.IsSuccess)
{
return usersResponse.Value.Where(u => u.FaceFileId != null).ToList();
}
else
{
Assert.Fail($"Failed to get user list. Error: {usersResponse.Error}");
return new List<User>();
}
}
[TestMethod()]
public void CalculateImageHashWithSaltTest()
{
var usrs = GetUsersWithFaceFiles();
var ossfiles = usrs.Select(u => FaceDataSet.QueryFileAsync(u).Result.Value).ToList();
try
{
var res = FaceDataSet.Download(ossfiles, "Image").Result;
}
catch (AggregateException ex)
{
Log.Error(ex.InnerException, "下载失败");
Assert.Fail();
}
var files = Directory.GetFiles("Image");
foreach (var file in files)
{
var meta = Path.GetFileNameWithoutExtension(file);
var parts = meta.Split('-'); // 将字符串分割为数组
var name = parts[0];
var id = parts[1];
var hash = parts[2];
Log.Information($"file:{file}");
var cal = ImageHash.CalculateImageHashWithSalt(file, name);
Log.Information($"cal:{cal}");
Assert.IsTrue(hash == cal);
}
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="CSharpFunctionalExtensions" version="2.40.3" targetFramework="net48" />
<package id="GroupDocs.Metadata" version="24.1.0" targetFramework="net48" />
<package id="Microsoft.Bcl.AsyncInterfaces" version="6.0.0" targetFramework="net48" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
<package id="Serilog" version="3.1.1" targetFramework="net48" />
<package id="System.Buffers" version="4.5.1" targetFramework="net48" />
<package id="System.Diagnostics.DiagnosticSource" version="7.0.2" targetFramework="net48" />
<package id="System.Memory" version="4.5.5" targetFramework="net48" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net48" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net48" />
<package id="System.Text.Encoding.CodePages" version="6.0.0" targetFramework="net48" />
<package id="System.Text.Encodings.Web" version="6.0.0" targetFramework="net48" />
<package id="System.Text.Json" version="6.0.0" targetFramework="net48" />
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net48" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net48" />
</packages>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment