C#人脸对比服务(基于虹软人脸识别SDKV4.1封装)
软件截图
项目截图
部分代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Nancy;
using NLog;
using System.Diagnostics;
using System.IO;
using System.Drawing;
using ArcFaceSDK.Entity;
using Newtonsoft.Json;
using ArcFaceSDK.SDKModels;
namespace ArcSoftFaceService.Controller
{
public class ViewFaceModule : NancyModule
{
private Logger _log = NLog.LogManager.GetCurrentClassLogger();
private readonly static object _locker = new object();
public ViewFaceModule()
: base("/faceApi")
{
After.AddItemToEndOfPipeline((ctx) => ctx.Response
.WithHeader("Access-Control-Allow-Origin", "*")
.WithHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS")
.WithHeader("Access-Control-Allow-Headers", "Accept, Origin, Content-type"));
Post["/faceRecognition"] = p =>
{
return FaceRecognizeByBase64();
};
}
private dynamic FaceRecognizeByBase64()
{
Stopwatch sw = Stopwatch.StartNew();
sw.Start();
AjaxReturn ar = new AjaxReturn();
ar.code = 0;
ar.message = "ok";
ar.similarity = 0;
string ContentType = Request.Headers.ContentType;
string base64str = null;
string base64str2 = null;
if (ContentType == "application/x-www-form-urlencoded")
{
base64str = Request.Form["zp1"];
base64str2 = Request.Form["zp2"];
}
else if (ContentType == "application/json")
{
string postData = Request.Body.AsString();
if (!string.IsNullOrEmpty(postData))
{
ReqPicParameter reqPic = JsonConvert.DeserializeObject<ReqPicParameter>(postData);
base64str = reqPic.zp1;
base64str2 = reqPic.zp2;
}
}
if (string.IsNullOrEmpty(base64str))
{
ar.code = 0;
ar.message = "参数[zp1]不能为空";
}
else if (string.IsNullOrEmpty(base64str2))
{
ar.code = 0;
ar.message = "参数[zp2]不能为空";
}
else
{
try
{
//TODO 图片大小判断??
Image srcImage1 = StringToImage(base64str);
//调整图像宽度,需要宽度为4的倍数
if (srcImage1.Width % 4 != 0)
{
srcImage1 = ImageUtil.ScaleImage(srcImage1, srcImage1.Width - (srcImage1.Width % 4), srcImage1.Height);
}
//人脸检测
MultiFaceInfo multiFaceInfo1;
int retCode = Program.imageEngine.ASFDetectFacesEx(srcImage1, out multiFaceInfo1);
if (retCode != 0)
{
ar.code = 0;
ar.message = "图像人脸检测失败,请稍后重试!";
ar.elapsedmilliseconds = sw.ElapsedMilliseconds;
_log.Info(JsonConvert.SerializeObject(ar));
sw.Stop();
return Response.AsJson<AjaxReturn>(ar);
}
if (multiFaceInfo1.faceNum < 1)
{
ar.code = 0;
ar.message = "图片1未检测出人脸";
ar.elapsedmilliseconds = sw.ElapsedMilliseconds;
_log.Info(JsonConvert.SerializeObject(ar));
sw.Stop();
return Response.AsJson<AjaxReturn>(ar);
}
if (multiFaceInfo1.faceNum >1)
{
ar.code = 0;
ar.message = "图片1检测出多张人脸";
ar.elapsedmilliseconds = sw.ElapsedMilliseconds;
_log.Info(JsonConvert.SerializeObject(ar));
sw.Stop();
return Response.AsJson<AjaxReturn>(ar);
}
SingleFaceInfo singleFaceInfo1;
bool isMask1;
string faceFeatureStr1 = string.Empty;
FaceFeature feature1 = FaceUtil.ExtractFeature(Program.imageEngine
, srcImage1
, Program.thresholdImgNoMask
, Program.thresholdImgMask
, ASF_RegisterOrNot.ASF_RECOGNITION
, out singleFaceInfo1
, out isMask1
, ref faceFeatureStr1
, out retCode
, 0);
if (feature1.featureSize == 0)
{
ar.code = 0;
ar.message = "图片1提取特征失败";
ar.elapsedmilliseconds = sw.ElapsedMilliseconds;
_log.Info(JsonConvert.SerializeObject(ar));
sw.Stop();
return Response.AsJson<AjaxReturn>(ar);
}
//活体检测
int retCodeLiveness1 = -1;
LivenessInfo liveInfo1 = FaceUtil.LivenessInfo_RGB(Program.imageEngine, srcImage1, singleFaceInfo1, out retCodeLiveness1);
//活体检测结果
if (retCodeLiveness1.Equals(0) && liveInfo1.num > 0)
{
if (liveInfo1.isLive[0]!=1)
{
string livenessResult = CommonUtil.TransLivenessResult(liveInfo1.isLive[0]);
ar.code = 0;
ar.message = "图片1活体结果:" + livenessResult;
ar.elapsedmilliseconds = sw.ElapsedMilliseconds;
_log.Info(JsonConvert.SerializeObject(ar));
sw.Stop();
return Response.AsJson<AjaxReturn>(ar);
}
}
else
{
ar.code = 0;
ar.message = "图片1活体检测失败";
ar.elapsedmilliseconds = sw.ElapsedMilliseconds;
_log.Info(JsonConvert.SerializeObject(ar));
sw.Stop();
return Response.AsJson<AjaxReturn>(ar);
}
Image srcImage2 = StringToImage(base64str2);
//调整图像宽度,需要宽度为4的倍数
if (srcImage2.Width % 4 != 0)
{
srcImage2 = ImageUtil.ScaleImage(srcImage2, srcImage2.Width - (srcImage2.Width % 4), srcImage2.Height);
}
//人脸检测
MultiFaceInfo multiFaceInfo2;
int retCode2 = Program.imageEngine.ASFDetectFacesEx(srcImage2, out multiFaceInfo2);
if (retCode2 != 0)
{
ar.code = 0;
ar.message = "图像人脸检测失败,请稍后重试!";
ar.elapsedmilliseconds = sw.ElapsedMilliseconds;
_log.Info(JsonConvert.SerializeObject(ar));
sw.Stop();
return Response.AsJson<AjaxReturn>(ar);
}
if (multiFaceInfo2.faceNum < 1)
{
ar.code = 0;
ar.message = "图片2未检测出人脸";
ar.elapsedmilliseconds = sw.ElapsedMilliseconds;
_log.Info(JsonConvert.SerializeObject(ar));
sw.Stop();
return Response.AsJson<AjaxReturn>(ar);
}
if (multiFaceInfo2.faceNum > 1)
{
ar.code = 0;
ar.message = "图片2检测出多张人脸";
ar.elapsedmilliseconds = sw.ElapsedMilliseconds;
_log.Info(JsonConvert.SerializeObject(ar));
sw.Stop();
return Response.AsJson<AjaxReturn>(ar);
}
SingleFaceInfo singleFaceInfo2;
bool isMask2;
string faceFeatureStr2 = string.Empty;
FaceFeature feature2 = FaceUtil.ExtractFeature(Program.imageEngine
, srcImage2
, Program.thresholdImgNoMask
, Program.thresholdImgMask
, ASF_RegisterOrNot.ASF_RECOGNITION
, out singleFaceInfo2
, out isMask2
, ref faceFeatureStr2
, out retCode2
, 0);
if (feature2.featureSize == 0)
{
ar.code = 0;
ar.message = "图片2提取特征失败";
ar.elapsedmilliseconds = sw.ElapsedMilliseconds;
_log.Info(JsonConvert.SerializeObject(ar));
sw.Stop();
return Response.AsJson<AjaxReturn>(ar);
}
//活体检测
int retCodeLiveness2 = -1;
LivenessInfo liveInfo2 = FaceUtil.LivenessInfo_RGB(Program.imageEngine, srcImage2, singleFaceInfo2, out retCodeLiveness2);
//活体检测结果
if (retCodeLiveness2.Equals(0) && liveInfo2.num > 0)
{
if (liveInfo2.isLive[0] != 1)
{
string livenessResult = CommonUtil.TransLivenessResult(liveInfo2.isLive[0]);
ar.code = 0;
ar.message = "图片2活体结果:" + livenessResult;
ar.elapsedmilliseconds = sw.ElapsedMilliseconds;
_log.Info(JsonConvert.SerializeObject(ar));
sw.Stop();
return Response.AsJson<AjaxReturn>(ar);
}
}
else
{
ar.code = 0;
ar.message = "图片2活体检测失败";
ar.elapsedmilliseconds = sw.ElapsedMilliseconds;
_log.Info(JsonConvert.SerializeObject(ar));
sw.Stop();
return Response.AsJson<AjaxReturn>(ar);
}
float similarity = 0f;
Program.imageEngine.ASFFaceFeatureCompare(feature1, feature2, out similarity, Program.compareModel);
//增加异常值处理
if (similarity.ToString().IndexOf("E") > -1)
{
similarity = 0f;
}
ar.code = 1;
ar.similarity = similarity;
ar.message = "ok";
srcImage1.Dispose();
srcImage2.Dispose();
}
catch (Exception ex)
{
ar.code = 0;
ar.message = "识别异常:" + ex.Message;
}
}
ar.elapsedmilliseconds = sw.ElapsedMilliseconds;
_log.Info(JsonConvert.SerializeObject(ar));
sw.Stop();
return Response.AsJson<AjaxReturn>(ar);
}
public Bitmap ByteToImage(byte[] bytes)
{
if (bytes == null)
{
return null;
}
using (MemoryStream ms = new MemoryStream(bytes))
{
Bitmap bmp = new Bitmap(ms);
SaveBitMap(bmp);
ms.Close();
return bmp;
}
}
public bool SaveBitMap(Bitmap bmp)
{
if (Program.saveImg == "0")
{
return true;
}
try
{
string path = System.Windows.Forms.Application.StartupPath + "\\img";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string filename = path + "\\" + DateTime.Now.ToString("yyyy-MM-dd HH-mmssffff") + ".jpeg";
bmp.Save(filename, System.Drawing.Imaging.ImageFormat.Jpeg);//保存到服务器路径
return true;
}
catch (Exception e)
{
_log.Error("SaveBitMap 保存图片出错", e);
return false;
}
}
/// <summary>
/// base64编码的文本转为图片
/// </summary>
/// <param name="inputStr"></param>
/// <returns></returns>
public Bitmap StringToImage(string inputStr)
{
if (string.IsNullOrEmpty(inputStr))
{
return null;
}
byte[] arr = Convert.FromBase64String(inputStr.Trim());
using (MemoryStream ms = new MemoryStream(arr))
{
Bitmap bmp = new Bitmap(ms);
SaveBitMap(bmp);
ms.Close();
return bmp;
}
}
}
}