public List <FaceInfo> ScanFaces(Bitmap bitmap) { List <FaceInfo> singleFaces = new List <FaceInfo>(); if (bitmap == null) { return(null); } //从视频帧中获取 多个人脸的矩形框位置 ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(pImageEngine, bitmap); //如果识别出人脸,且当前只有一个人脸 if (multiFaceInfo.faceNum == 1) { //将MultiFaceInfo结构体中的数据提取成单人脸数据并放入结构体中 for (int i = 0; i < multiFaceInfo.faceNum; i++) { FaceInfo faceInfo = new FaceInfo(); faceInfo.singleFaceInfo.faceRect = MemoryUtil.PtrToStructure <MRECT>(multiFaceInfo.faceRects + MemoryUtil.SizeOf <MRECT>() * i); faceInfo.singleFaceInfo.faceOrient = MemoryUtil.PtrToStructure <int>(multiFaceInfo.faceOrients + MemoryUtil.SizeOf <int>() * i); singleFaces.Add(faceInfo); } } else { LoggerService.logger.Info($"当前图片中含有多个人脸或没有人脸,请重新选择单人图片,进行特征提取"); if (bitmap != null) { bitmap.Dispose(); Console.WriteLine("释放成功"); } } return(singleFaces); }
//对每一帧的图片进行了处理,将该帧画面里检测到所有的人脸进行处理,然后进行显示 public void DetalDisplay(Image <Bgr, byte> nowFrame) { //如果有有效的bgr位图像则进行人工智能工作和picturView的显示 if (nowFrame != null) { using (Bitmap nowFrameBitmap = nowFrame.ToBitmap()) { //将每帧图片中的人脸信息位置获取出来给faceInfos集合,视频模式会多一个faceId来唯一标识人脸 List <FaceInfo> faceInfos = faceVideoRecognizer.ScanFaces(nowFrameBitmap); if (isRGBLock == false) { isRGBLock = true; for (int i = 0; i < faceInfos.Count; i++) { //faceInfo 是相机所检测到的人脸信息(带feceId)都会缓存在这个列表中,faceId不变的话,faceInfo可以找到,就把当前的脸的位置替换了, //但如果faceId变化了,就把新检测到的这张脸添加进列表 int findindex = faceInfo.FindIndex(temp => temp.faceId == faceInfos[i].faceId); //如果当前摄像设备之前没有侦测过任何人脸,或者在设备人脸缓存中未找到匹配的Faceid if (faceInfo.Count == 0 || findindex < 0) { FaceInfo tempFaceInfo = new FaceInfo(); faceInfos[i].getCopy(tempFaceInfo); tempFaceInfo.frameNum++; tempFaceInfo.dateTime = DateTime.Now.ToLocalTime(); faceInfo.Add(tempFaceInfo); } //如果在人脸缓存中有该faceid的对象 else { faceInfos[i].getCopy(faceInfo[findindex]); faceInfo[findindex].frameNum++; faceInfo[findindex].dateTime = DateTime.Now.ToLocalTime(); if (faceInfo[findindex].isFacePass == true) { faceInfos[i].studentId = faceInfo[findindex].studentId; } else { //如果没有比对成功,frameNum超过十次,等400ms再次提取特征值再比对,抽帧 if (faceInfo[findindex].frameNum % 10 == 0) { faceInfo[findindex].isGetFeature = false; if (faceInfo[findindex].faceFeature.feature != IntPtr.Zero) { faceInfo[findindex].freeFeature(); } } } } } for (int i = 0; i < faceInfo.Count; i++) { if ((DateTime.Now - faceInfo[i].dateTime).TotalSeconds > 5)//如果当前人脸未出现在视频中5秒则清除该人脸缓存信息 { faceInfo[i].Dispose(); faceInfo.RemoveAt(i); i--; continue; } //camera缓冲里的照片进行遍历,没有提取过特征或者没有比对成功过 if (faceInfo[i].isGetFeature == false || faceInfo[i].isFacePass == false) { FaceInfo tempFaceInfo = faceInfo[i]; //提取特征值 faceVideoRecognizer.ScanFaceFeature(nowFrameBitmap, tempFaceInfo); tempFaceInfo.isGetFeature = true; //创建一个线程放进这个线程池(资源系统自己维护),因为人脸对比消耗时间较多 //所以将每次需要人脸比对的操作都放进一个线程中 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { if (tempFaceInfo.isGetFeature == true) { tempFaceInfo.isFacePass = compareFeature(tempFaceInfo); //通过Http post方式 发送json数据 if (tempFaceInfo.isFacePass == true) { sendCheckIn(tempFaceInfo); } } })); } } for (int i = 0; i < faceInfos.Count; i++) { int x = faceInfos[i].singleFaceInfo.faceRect.left; int width = faceInfos[i].singleFaceInfo.faceRect.right - x; int y = faceInfos[i].singleFaceInfo.faceRect.top; int height = faceInfos[i].singleFaceInfo.faceRect.bottom - y; Rectangle rect = new Rectangle(x, y, width, height); CvInvoke.Rectangle(nowFrame, rect, new MCvScalar(0, 0, 255), 3); CvInvoke.PutText(nowFrame, $"FaceId: {faceInfos[i].faceId}, StudentId: {faceInfos[i].studentId}", new Point(x, y - 15), Emgu.CV.CvEnum.FontFace.HersheySimplex, 1, new MCvScalar(0, 0, 255), 3); } for (int i = 0; i < faceInfos.Count; i++) { faceInfos[i].Dispose(); faceInfos[i] = null; } faceInfos.Clear(); isRGBLock = false; } } //显示到屏幕中 if (PictrueBoxId != null) { PictrueBoxId.Invoke(new Action(() => { if (PictrueBoxId != null) { PictrueBoxId.Image = nowFrame; } PictrueBoxId.Refresh(); })); } } }