赞
踩
目录
github地址:https://github.com/ViewFaceCore/ViewFaceCore
C# 超简单的离线人脸识别库。( 基于 SeetaFace6 )
一个基于 SeetaFace6 的 .NET 人脸识别解决方案
本项目受到了 SeetaFaceEngine.Net 的启发
开源、免费、跨平台 (win/linux)
目标框架 最低版本 操作系统
.NET Framework 4.0 win ( x64/x86 )
.NET Standard 2.0 win ( x64/x86 )
.NET / .NET Core 3.1、5.0、6.0、7.0 win ( x64/x86 )、linux ( arm/arm64/x64 )
以 Windows x64平台 为例,一个简单的人脸检测Demo。
1、使用 nuget 安装依赖
包名称 说明
ViewFaceCore ViewFaceCore .NET 核心库
ViewFaceCore.all_models 人脸检测的模型支持(图省事可以直接安装这个)
ViewFaceCore.runtime.win.x64 Windows-x64 的本机运行时,其它平台自行选择安装,可安装多个
ViewFaceCore.Extension.SkiaSharp SkiaSharp图像处理扩展,ImageSharp、SkiaSharp、System.Drawing三选一
2、获取人脸信息
using SkiaSharp;
using System;
using ViewFaceCore.Core;
using ViewFaceCore.Model;
namespace ViewFaceCore.Demo.ConsoleApp
{
internal class Program
{
private readonly static string imagePath = @"images/Jay_3.jpg";
static void Main(string[] args)
{
using var bitmap = SKBitmap.Decode(imagePath);
using FaceDetector faceDetector = new FaceDetector();
FaceInfo[] infos = faceDetector.Detect(bitmap);
Console.WriteLine($"识别到的人脸数量:{infos.Length} 个人脸信息:\n");
Console.WriteLine($"No.\t人脸置信度\t位置信息");
for (int i = 0; i < infos.Length; i++)
{
Console.WriteLine($"{i}\t{infos[i].Score:f8}\t{infos[i].Location}");
}
Console.ReadKey();
}
}
}
- using SkiaSharp;
- using System;
- using ViewFaceCore.Core;
- using ViewFaceCore.Model;
-
- namespace ViewFaceCore.Demo.ConsoleApp
- {
- internal class Program
- {
- private readonly static string imagePath = @"images/Jay_3.jpg";
-
- static void Main(string[] args)
- {
- using var bitmap = SKBitmap.Decode(imagePath);
- using FaceDetector faceDetector = new FaceDetector();
- FaceInfo[] infos = faceDetector.Detect(bitmap);
- Console.WriteLine($"识别到的人脸数量:{infos.Length} 个人脸信息:\n");
- Console.WriteLine($"No.\t人脸置信度\t位置信息");
- for (int i = 0; i < infos.Length; i++)
- {
- Console.WriteLine($"{i}\t{infos[i].Score:f8}\t{infos[i].Location}");
- }
- Console.ReadKey();
- }
- }
- }
为了兼容各个平台,我们分别编号好了各个平台的SeetaFace6以及ViewFaceBridge(用于通过C#调用C++写的SeetaFace6)。并打包好,发布到nuget上面。使用时,按需安装对应平台的nuget包。比如windows x64平台,安装对应的nuget包ViewFaceCore.runtime.win.x64
。runtime可以同时安装多个平台,但是不能不安装,至少需要安装一个当前平台对应的runtime。
支持的平台以及nuget包如下表所示:
Nuget包名 | 输出目录 | 说明 |
ViewFaceCore.runtime.win.x64 | viewfacecore/win/x64 | Windows,x64 |
ViewFaceCore.runtime.win.x86 | viewfacecore/win/x86 | Windows,x86 |
ViewFaceCore.runtime.ubuntu.20.04.x64 | viewfacecore/linux/x64 | Linux,x64;支持Ubuntu20.04+、Debian10+、Deepin20+等较新的debian系Linux系统 |
ViewFaceCore.runtime.linux.arm | viewfacecore/linux/arm | Linux,armhf;支持树莓派,nanopi等 |
ViewFaceCore.runtime.linux.arm64 | viewfacecore/linux/arm64 | Linux,arm64;支持树莓派,nanopi等 |
Nuget包名 | 说明 |
ViewFaceCore.all_models | 包含全部模型。不知道装哪一个时,装这个就行了,但是包特别大(300多MB) |
ViewFaceCore.model.age_predictor | 年龄预测 |
ViewFaceCore.model.eye_state | 眼睛状态检测 |
ViewFaceCore.model.gender_predictor | 性别预测 |
ViewFaceCore.model.face_detector | 人脸检测 |
ViewFaceCore.model.mask_detector | 口罩检测 |
ViewFaceCore.model.face_landmarker_mask_pts5 | 戴口罩关键定定位,5个关键点 |
ViewFaceCore.model.face_landmarker_pts5 | 关键定定位,5个关键点 |
ViewFaceCore.model.face_landmarker_pts68 | 关键定定位,68个关键点 |
ViewFaceCore.model.face_recognizer | 人脸识别,68个关键点 |
ViewFaceCore.model.face_recognizer_light | 人脸识别,5个关键点 |
ViewFaceCore.model.face_recognizer_mask | 人脸识别,戴口罩 |
ViewFaceCore.model.fas_first | 活体检测,局部 |
ViewFaceCore.model.fas_second | 活体检测,全局 |
ViewFaceCore.model.pose_estimation | 姿态检测 |
ViewFaceCore.model.quality_lbn | 质量检测 |
这里的对象的生命周期指的是人脸识别中各个功能对象的生命周期,并不是C#中GC和对象的生命周期。虽然也和C#中对象生命周期密不可分,但是这并不是这一小节的主题,这里不会过多的解释C#语言本身的特性。
用FaceDetector举个例子。在FaceDetector的构造函数中
public FaceDetector(FaceDetectConfig config = null)
{
this.DetectConfig = config ?? new FaceDetectConfig();
_handle = ViewFaceNative.GetFaceDetectorHandler(this.DetectConfig.FaceSize
, this.DetectConfig.Threshold
, this.DetectConfig.MaxWidth
, this.DetectConfig.MaxHeight
, (int)this.DetectConfig.DeviceType);
if (_handle == IntPtr.Zero)
{
throw new Exception("Get face detector handler failed.");
}
}
通过Native调用的方式,调用C++项目ViewFaceBridge中的函数GetFaceDetectorHandler获取SeetaFace6中seeta::v6::FaceDetector对象的IntPtr句柄。
ViewFaceBridge中的函数GetFaceDetectorHandler函数代码如下:
View_Api seeta::v6::FaceDetector *GetFaceDetectorHandler(const double faceSize = 20, const double threshold = 0.9, const double maxWidth = 2000, const double maxHeight = 2000, const SeetaDevice deviceType = SEETA_DEVICE_AUTO)
{
seeta::v6::FaceDetector *faceDetector = new seeta::v6::FaceDetector(ModelSetting(modelPath + "face_detector.csta", deviceType));
faceDetector->set(FaceDetector::Property::PROPERTY_MIN_FACE_SIZE, faceSize);
faceDetector->set(FaceDetector::Property::PROPERTY_THRESHOLD, threshold);
faceDetector->set(FaceDetector::Property::PROPERTY_MAX_IMAGE_WIDTH, maxWidth);
faceDetector->set(FaceDetector::Property::PROPERTY_MAX_IMAGE_HEIGHT, maxHeight);
return faceDetector;
}
当对象使用完毕后,FaceDetector中Dispose方法中通过Native调用DisposeFaceDetector函数,释放掉seeta::v6::FaceDetector对象。
View_Api void DisposeFaceDetector(seeta::v6::FaceDetector *handler)
{
_dispose(handler);
}
综上所述,在编写代码的过程中,一定要使用using语句或在结束后调用Dispose释放掉对象。且SeetaFace6对象的构造和释放会比较耗时,其中涉及到模型加载、计算等,建议尽可能的复用对象以及在需要频繁使用新对象的场景中使用对象池。
对象复用,又涉及到线程安全的问题。更多关于线程安全的细节,请继续阅读下一节。
线程安全也是开发中需要重点关注的特性。然而,线程安全在不同的上下文解释中总会有不同解释。为了避免理解的偏差,这里用几种不同的用例去解释识别器的使用。
1. 对象可以跨线程传递。线程1构造的识别器,可以在线程2中调用。
2. 对象的构造可以并发构造,即可以多个线程同时构造识别器。
3. 单个对象的接口调用不可以并发调用,即单个对象,在多个线程同时使用是被禁止的。
来源:入门教程 1.5 线程安全性 http://leanote.com/blog/post/5e7d6cecab64412ae60016ef#title-11
因为SeetaFace6本身不支持多线程调用,所以在这个库设计的时候,在每个不支持并发操作的功能中通过加锁限制并发调用。可以认为,在单个对象的不同操作中,是线程安全的。
在一些场景下,比如不支持AVX2指令集、需要拿取内部日志等场景下,默认设置并不能满足要求。为此,我们提供了一个全局配置项:GlobalConfig,下面的小节将具体介绍支持的特性。
在生产环境或者某些不方便调试场景下,又出现一些莫名其妙的问题的时候,不妨看看内部日志,说不定有不一样的收获。
static void Config()
{
//打印内部日志
GlobalConfig.SetLog((msg) =>
{
Console.WriteLine($"[内部日志]{msg}");
});
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。