然后是调方法得到人脸数据,可以是多个脸,这里的把byte[]转Mat可是费了我好大功夫,最开始找不到简单的方法,只能傻乎乎生成图片到本地再去读取,效率低下,最终是在一个英语网站(讲真。。英语水平太低,都是蒙的)里边找到这个方法:
private static string FaceDetectionDetail(byte[] data, int plength)
{
StringBuilder sb = new StringBuilder();
sb.Append("[");
//把byte[]转成mat 找了好久找到的方法
Image img =Com.Other. GetImageByBytes(data);
Bitmap bmpImage = new Bitmap(img);
Emgu.CV.Image<Bgr, Byte> currentFrame = new Emgu.CV.Image<Bgr, Byte>(bmpImage);
Mat invert = new Mat();
CvInvoke.BitwiseAnd(currentFrame, currentFrame, invert);
if (invert != null)
{
Com.KingFaceDetect.faceDetectedObj faces = Run1(invert); //得到识别到的脸
for (int i = 0; i < faces.facesRectangle.Count; i++)
{
sb.AppendFormat("{{\"X\":{0},\"Y\":{1},\"W\":{2},\"H\":{3},\"N\":\"{4}\"}},", faces.facesRectangle[i].X, faces.facesRectangle[i].Y, faces.facesRectangle[i].Width, faces.facesRectangle[i].Height, faces.names[i]);
}
if (sb[sb.Length - 1] == ',')
{
sb.Remove(sb.Length - 1, 1);
}
}
sb.Append("]");
GC.Collect();
//AddLog((System.Environment.TickCount - aa).ToString()); //单位毫秒
return sb.ToString();
}
再来看一下Run1这个方法,返回值是一个faceDetectedObj类型的,这是自己封装的一个类KingFaceDetect中的东西,它包含了识别的的脸部的坐标和这个人的姓名,从之前提到的winform版本中提出来的,基本没改。可以看到这里用了一个Application,因为在创建KingFaceDetect的时候会去加载人脸样本库,比较耗内存把,第一次没用全局,然后服务器都被搞崩了。
static Com.KingFaceDetect.faceDetectedObj Run1(Mat image)
{
if (HttpContext.Current.Application["detect"] == null)
{
HttpContext.Current.Application["detect"] = new Com.KingFaceDetect(); //存入全局 否则好像会报内存错误
}
Com.KingFaceDetect detect = (Com.KingFaceDetect)HttpContext.Current.Application["detect"];
Com.KingFaceDetect.faceDetectedObj resut = detect.faceRecognize(image);
return resut;
}
接下来就是这个核心的类了,KingFaceDetect ,里边都有注释,懒得讲。。。。直接搬上来:,,在对比训练库得到姓名那一步,有个Distance,值越小越可能是同一个人,我自己改了下,大于4000就当没有,姓名返回“”。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.Util;
using Emgu.CV.Cuda;
using System.Diagnostics;
using Emgu.C