
主要思路
OpenCV是机器视觉领域最流行的开源视觉图像处理算法框架,在C#中使用OpenCV进行人脸识别,最主流且成熟的选择是OpenCVSharp,它是OpenCV的一个.NET封装。让你可以在C#中直接调用OpenCV丰富的图像处理和识别算法,轻松玩转各种常见的图像处理、图像分析、图像测量算子。
回到本文分享的例子,OpenCV从4.7版本以后支持深度学习方式的人脸识别,主要是基于两个人脸模型,分别是人脸检测模型、人脸识别模型。人脸检测模型负责找到人脸在哪儿;人脸识别模型负责判定这个人是谁,就这样就可以完成人脸识别。为了降低大家学习成本,快速上手人脸识别案例,我已经把这些都封装在一个C++类中,然后导出了C#支持的接口。简单易用,支持快速实现人脸识别。
实践步骤
第一步:环境搭建
在Visual Studio2022中新建一个C# 控制台项目后,通过NuGet包管理器安装核心库,图示如下:

第二步:人脸检测(找脸)
人脸检测是第一步,基于OpenCV官方提供的人脸检测模型yunet,它是一个轻量化人脸检测模型。你需要在项目中包含OpenCV提供的模型文件。通过OpenCV DNN相关的接口SDK加载即可。
第三步:人脸识别(识人)
找到人脸后,下一步是识别身份。OpenCV的人脸识别算法来自北邮邓伟洪教授团队贡献,SFace模型大小为37MB,属于轻量级的人脸识别模型,输出特征维度是128维。然后使用L2或者余弦相似函数进行比对,根据比对结果判定人脸识别结果。

完整流程图示如下:

代码实践与演示
第一步:构建C# SDK支持,C++部分已经编译程dll支持库,一键下载即可,对应OpenCV版本为4.10。
using System.Runtime.InteropServices;
namespace opencvxuetang_csharp
{
class FaceRecogHelper
{
[DllImport("face_recog_demo.dll", CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr faceRecogClassInit2(); //创建人脸
[DllImport("face_recog_demo.dll", CallingConvention = CallingConvention.StdCall)]
public static extern void delefaceRecogInstance(IntPtr p);//删除人脸
[DllImport("face_recog_demo.dll")]
public static extern bool initFaceModels(IntPtr p, char[] detect_path, char[] recog_path, char[] db_path);//加载到工作流(参数1 图像处理工作流路径,参数2:权限ID)
[DllImport("face_recog_demo.dll")]
public static extern void detectFace(IntPtr p, IntPtr da, [In, Out] BoxInfoWapper[] boxes, int w, int h);//运行工作流(参数 工作流对象,输入图像指针,输出图像指针,输出宽,高)
[DllImport("face_recog_demo.dll")]
public static extern void matchFace(IntPtr p, IntPtr da, [In, Out] BoxInfoWapper[] boxes, int w, int h);//运行工作流(参数 工作流对象,输入图像指针,输出图像指针,输出宽,高)
public struct BoxInfoWapper
{
public int userid;
public int x;
public int y;
public int width;
public int height;
};
}
}第二步:构建客户端调用代码
using System;
using csharp_opencv410;
using OpenCvSharp;
using opencvxuetang_csharp;
class OpenCVWorkFlowDemo
{
static void Main(string[] args)
{
// create face data base from image files.
Dictionary<int, string> map = new Dictionary<int, string>();
map.Add(0, "123");
map.Add(1, "fbb");
map.Add(2, "zhigang");
IntPtr myInstance = FaceRecogHelper.faceRecogClassInit2();
bool succ = FaceRecogHelper.initFaceModels(myInstance,
"D:/face_detection_yunet_2023mar.onnx".ToCharArray(),
"D:/face_recognizer_fast.onnx".ToCharArray(),
"D:/images/facedb".ToCharArray());
// please check and replace your image file path
Mat src = Cv2.ImRead("D:/images/black_zg.jpg");
Mat dst = new Mat(src.Size(), src.Type());
int w = src.Cols;
int h = src.Rows;
FaceRecogHelper.BoxInfoWapper[] boxes =
new FaceRecogHelper.BoxInfoWapper[10];
FaceRecogHelper.matchFace(myInstance, src.CvPtr, boxes, w, h);
for (int i = 0; i < 1; i++)
{
int x = boxes[i].x;
int y = boxes[i].y;
int width = boxes[i].width;
int height = boxes[i].height;
Rect box = new Rect(x, y, width, height);
Cv2.Rectangle(src, box, new Scalar(0, 0, 255), 2, LineTypes.Link8);
string value = map[boxes[i].userid];
Cv2.PutText(src, value, box.TopLeft, HersheyFonts.HersheySimplex, 1.0, new Scalar(255, 0, 0), 2, LineTypes.Link8);
}
Cv2.ImShow("OpenCV学堂-人脸检测", src);
Cv2.WaitKey(0);
Cv2.DestroyAllWindows();
}
}运行与演示效果:
