Skip to content

Commit

Permalink
merge
Browse files Browse the repository at this point in the history
  • Loading branch information
withsalt committed Sep 3, 2022
2 parents ffd5a76 + ef69c62 commit 1b1acb5
Show file tree
Hide file tree
Showing 21 changed files with 1,097 additions and 198 deletions.
783 changes: 676 additions & 107 deletions README.md

Large diffs are not rendered by default.

75 changes: 74 additions & 1 deletion src/Examples/ViewFaceCore.Demo.ConsoleApp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using ViewFaceCore.Configs;
using ViewFaceCore.Core;
using ViewFaceCore.Extensions;
using ViewFaceCore.Model;

namespace ViewFaceCore.Example.ConsoleApp
Expand All @@ -16,11 +18,14 @@ internal class Program

static void Main(string[] args)
{
Console.WriteLine("Hello, ViewFaceCore!");
Console.WriteLine("Hello, ViewFaceCore!\n");

//人脸识别Demo
FaceDetectorDemo();

//关键点标记
FaceMarkDemo();

//戴口罩识别Demo
MaskDetectorDemo();

Expand All @@ -30,6 +35,9 @@ static void Main(string[] args)
//活体检测Demo
AntiSpoofingDemo();

//提取并对比特征值
FaceRecognizerDemo();

Console.ReadKey();
}

Expand Down Expand Up @@ -74,6 +82,26 @@ static void MaskDetectorDemo()
Console.WriteLine();
}

static void FaceMarkDemo()
{
using var bitmap0 = SKBitmap.Decode(imagePath0);
using var faceImage = bitmap0.ToFaceImage();
using FaceDetector faceDetector = new FaceDetector();
using FaceLandmarker faceMark = new FaceLandmarker();
Stopwatch sw = new Stopwatch();

var infos = faceDetector.Detect(faceImage);
var markPoints = faceMark.Mark(faceImage, infos[0]);

sw.Stop();
Console.WriteLine($"识别到的关键点个数:{markPoints.Length},耗时:{sw.ElapsedMilliseconds}ms");
foreach (var item in markPoints)
{
Console.WriteLine($"X:{item.X}\tY:{item.Y}");
}
Console.WriteLine();
}

static void FaceQualityDemo()
{
using var bitmap = SKBitmap.Decode(imagePath0);
Expand Down Expand Up @@ -134,5 +162,50 @@ static void AntiSpoofingDemo()
sw.Stop();
Console.WriteLine();
}

static void FaceRecognizerDemo()
{
Stopwatch sw = Stopwatch.StartNew();

using var faceImage0 = SKBitmap.Decode(imagePath0).ToFaceImage();
using var faceImage1 = SKBitmap.Decode(imagePath1).ToFaceImage();
//检测人脸信息
using FaceDetector faceDetector = new FaceDetector();
FaceInfo[] infos0 = faceDetector.Detect(faceImage0);
FaceInfo[] infos1 = faceDetector.Detect(faceImage1);
//标记人脸位置
using FaceLandmarker faceMark = new FaceLandmarker();
FaceMarkPoint[] points0 = faceMark.Mark(faceImage0, infos0[0]);
FaceMarkPoint[] points1 = faceMark.Mark(faceImage1, infos1[0]);
//提取特征值
using FaceRecognizer faceRecognizer = new FaceRecognizer();
float[] data0 = faceRecognizer.Extract(faceImage0, points0);
float[] data1 = faceRecognizer.Extract(faceImage1, points1);
//对比特征值
bool isSelf = faceRecognizer.IsSelf(data0, data1);

Console.WriteLine($"识别到的人脸是否为同一人:{isSelf},对比耗时:{sw.ElapsedMilliseconds}ms");
Console.WriteLine();
sw.Stop();
}

static void FaceTrackDemo()
{
using var faceImage = SKBitmap.Decode(imagePath0).ToFaceImage();
using FaceLandmarker faceMark = new FaceLandmarker();
using FaceTracker faceTrack = new FaceTracker(new FaceTrackerConfig(faceImage.Width, faceImage.Height));
var result = faceTrack.Track(faceImage);
if (result == null || !result.Any())
{
Console.WriteLine("未追踪到任何人脸!");
return;
}
foreach (var item in result)
{
FaceInfo faceInfo = item.ToFaceInfo();
//标记人脸
var points = faceMark.Mark(faceImage, faceInfo);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using System.Runtime.CompilerServices;
using ViewFaceCore.Model;

namespace ViewFaceCore
namespace ViewFaceCore.Core
{
public static class ViewFaceImageSharpExtension
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using ViewFaceCore.Core;
using ViewFaceCore.Exceptions;
using ViewFaceCore.Model;

namespace ViewFaceCore
namespace ViewFaceCore.Core
{
/// <summary>
/// 异步扩展,对于 CPU 绑定的操作直接使用 <see cref="Task.Run(Action)"/> 进行包装。
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
using System;
using ViewFaceCore.Core;
using ViewFaceCore.Model;


namespace ViewFaceCore
namespace ViewFaceCore.Core
{
public static class ViewFaceCoreExtension
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using System;
using ViewFaceCore.Model;

namespace ViewFaceCore
namespace ViewFaceCore.Core
{
public static class ViewFaceSkiaSharpExtension
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using System.Runtime.InteropServices;
using ViewFaceCore.Model;

namespace ViewFaceCore
namespace ViewFaceCore.Core
{
public static class ViewFaceSystemDrawingExtension
{
Expand Down
13 changes: 13 additions & 0 deletions src/ViewFaceCore/Configs/FaceLandmarkConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,19 @@ namespace ViewFaceCore.Configs
{
public class FaceLandmarkConfig : BaseConfig
{
/// <summary>
/// 关键点类型
/// </summary>
public MarkType MarkType { get; set; } = MarkType.Light;

public FaceLandmarkConfig()
{

}

public FaceLandmarkConfig(MarkType markType)
{
MarkType = markType;
}
}
}
26 changes: 25 additions & 1 deletion src/ViewFaceCore/Configs/FaceRecognizeConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ public FaceRecognizeConfig(FaceType faceType)
/// <returns></returns>
public float GetThreshold(FaceType type) => Threshold[type];

/// <summary>
/// 获取默认人脸识别模型的相似度阈值。
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public float GetThreshold() => Threshold[this.FaceType];

/// <summary>
/// 设置指定人脸识别模型的相似度阈值。
/// <para>
Expand All @@ -55,6 +62,23 @@ public FaceRecognizeConfig(FaceType faceType)
/// </summary>
/// <param name="type">指定的人脸识别模型</param>
/// <param name="score">相似度阈值</param>
public void SetThreshold(FaceType type, float score) => Threshold[type] = score;
public FaceRecognizeConfig SetThreshold(FaceType type, float score)
{
Threshold[type] = score;
return this;
}

/// <summary>
/// 设置指定人脸识别模型的相似度阈值。
/// <para>
/// 默认阈值是一般场景使用的推荐阈值。一般来说1比1的场景下,该阈值会对应偏低,1比N场景会对应偏高。
/// </para>
/// </summary>
/// <param name="score">相似度阈值</param>
public FaceRecognizeConfig SetThreshold(float score)
{
Threshold[this.FaceType] = score;
return this;
}
}
}
61 changes: 59 additions & 2 deletions src/ViewFaceCore/Configs/FaceTrackerConfig.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace ViewFaceCore.Configs
using System;

namespace ViewFaceCore.Configs
{
/// <summary>
/// 人脸跟踪器配置
Expand All @@ -23,16 +25,19 @@ public class FaceTrackerConfig : BaseConfig
/// 如果最小人脸参数设置为 <see langword="80"/> 的话,从检测能力上,可以将原图缩小的原来的 <see langword="1/4"/> ,这样从计算复杂度上,能够比最小人脸设置为 <see langword="20"/> 时,提速到 <see langword="16"/> 倍。
/// </para>
/// </summary>
public int FaceSize { get; set; } = 20;
public int MinFaceSize { get; set; } = 20;

/// <summary>
/// 检测器阈值。
/// <para>默认值是0.9,合理范围为[0, 1]。这个值一般不进行调整,除了用来处理一些极端情况。这个值设置的越小,漏检的概率越小,同时误检的概率会提高。</para>
/// </summary>
public float Threshold { get; set; } = 0.9f;

/// <summary>
/// 是否进行检测结果的帧间平滑,使得检测结果从视觉上更好一些。
/// </summary>
public bool Stable { get; set; } = false;

/// <summary>
/// 检测间隔
/// <para>
Expand All @@ -46,5 +51,57 @@ public FaceTrackerConfig(int width, int height)
this.Width = width;
this.Height = height;
}

/// <summary>
/// 设置是否进行检测结果的帧间平滑
/// </summary>
/// <param name="stable"></param>
/// <returns></returns>
public FaceTrackerConfig SetStable(bool stable)
{
this.Stable = stable;
return this;
}

/// <summary>
/// 设置最小检测人脸
/// </summary>
/// <param name="minFaceSize"></param>
/// <returns></returns>
public FaceTrackerConfig SetMinFaceSize(int minFaceSize)
{
if (minFaceSize < 5 || minFaceSize > Math.Min(Width, Height))
{
throw new ArgumentException($"MinFaceSize value range from {5} to {Math.Min(Width, Height)}", nameof(minFaceSize));
}
this.MinFaceSize = minFaceSize;
return this;
}

/// <summary>
/// 设置检测器阈值
/// </summary>
/// <param name="threshold">阈值</param>
/// <returns></returns>
public FaceTrackerConfig SetThreshold(float threshold)
{
if (threshold <= 0 || threshold >= 1f)
{
throw new ArgumentException($"Threshold value range from 0 to 1", nameof(threshold));
}
this.Threshold = threshold;
return this;
}

/// <summary>
/// 设置检测间隔
/// </summary>
/// <param name="interval"></param>
/// <returns></returns>
public FaceTrackerConfig SetInterval(int interval)
{
this.Interval = interval;
return this;
}
}
}
81 changes: 81 additions & 0 deletions src/ViewFaceCore/Configs/GlobalConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace ViewFaceCore.Configs
{
public static class GlobalConfig
{
#region Log

public static Action<string> LogEvent { get; private set; }

/// <summary>
/// 绑定log event
/// </summary>
/// <param name="action"></param>
public static void SetLog(Action<string> action)
{
if (action == null) return;
if (LogEvent != null) return;
LogEvent = action;
}

/// <summary>
/// 对外写日志
/// </summary>
/// <param name="log"></param>
internal static void WriteLog(string log)
{
if (LogEvent != null)
{
LogEvent(log);
}
}

#endregion

#region Instruction

private static bool _isSetX86Instruction = false;

private static readonly object _setX86InstructionLocker = new object();

/// <summary>
/// 在x86环境下支持的指令集
/// </summary>
public static X86Instruction X86Instruction { get; private set; } = X86Instruction.AVX2 | X86Instruction.SSE2 | X86Instruction.FMA;

/// <summary>
/// 设置支持的指令集
/// </summary>
/// <param name="instruction"></param>
public static void SetX86Instruction(X86Instruction instruction)
{
if (_isSetX86Instruction)
return;
if (RuntimeInformation.ProcessArchitecture != Architecture.X86 && RuntimeInformation.ProcessArchitecture != Architecture.X64)
return;
lock (_setX86InstructionLocker)
{
if (_isSetX86Instruction)
return;
_isSetX86Instruction = true;
X86Instruction = instruction;
}
}

#endregion
}

public enum X86Instruction
{
AVX2 = 1 << 0,

SSE2 = 1 << 1,

FMA = 1 << 2,
}
}
Loading

0 comments on commit 1b1acb5

Please sign in to comment.