/// <summary> /// RGB摄像头Paint事件,同步RGB人脸框,对比人脸框后进行IR活体检测 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public void IrVideoSource_Paint(object sender, PaintEventArgs e) { if (isDoubleShot && FRC.MainView._irVideoSource.IsRunning) { //如果双摄,且IR摄像头工作,获取IR摄像头图片 Bitmap irBitmap = FRC.MainView._irVideoSource.GetCurrentVideoFrame(); if (irBitmap == null) { return; } //得到Rect MRECT rect = new MRECT(); lock (rectLock) { rect = allRect; } float irOffsetX = FRC.MainView._irVideoSource.Width * 1f / irBitmap.Width; float irOffsetY = FRC.MainView._irVideoSource.Height * 1f / irBitmap.Height; float offsetX = FRC.MainView._irVideoSource.Width * 1f / FRC.MainView._rgbVideoSource.Width; float offsetY = FRC.MainView._irVideoSource.Height * 1f / FRC.MainView._rgbVideoSource.Height; //检测IR摄像头下最大人脸 Graphics g = e.Graphics; float x = rect.left * offsetX; float width = rect.right * offsetX - x; float y = rect.top * offsetY; float height = rect.bottom * offsetY - y; //根据Rect进行画框 g.DrawRectangle(Pens.Red, x, y, width, height); if (trackIRUnit.message != "" && x > 0 && y > 0) { //将上一帧检测结果显示到页面上 g.DrawString(trackIRUnit.message, font, trackIRUnit.message.Contains("活体") ? blueBrush : yellowBrush, x, y - 15); } //保证只检测一帧,防止页面卡顿以及出现其他内存被占用情况 if (isIRLock == false) { isIRLock = true; //异步处理提取特征值和比对,不然页面会比较卡 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { if (rect.left != 0 && rect.right != 0 && rect.top != 0 && rect.bottom != 0) { bool isLiveness = false; try { //得到当前摄像头下的图片 if (irBitmap != null) { //检测人脸,得到Rect框 ASF_MultiFaceInfo irMultiFaceInfo = UtilToolFace.DetectFace(pVideoIRImageEngine, irBitmap); if (irMultiFaceInfo.faceNum <= 0) { return; } //得到最大人脸 ASF_SingleFaceInfo irMaxFace = UtilToolFace.GetMaxFace(irMultiFaceInfo); //得到Rect MRECT irRect = irMaxFace.faceRect; //判断RGB图片检测的人脸框与IR摄像头检测的人脸框偏移量是否在误差允许范围内 if (JudgeInAllowErrorRange(rect.left * offsetX / irOffsetX, irRect.left) && JudgeInAllowErrorRange(rect.right * offsetX / irOffsetX, irRect.right) && JudgeInAllowErrorRange(rect.top * offsetY / irOffsetY, irRect.top) && JudgeInAllowErrorRange(rect.bottom * offsetY / irOffsetY, irRect.bottom)) { int retCode_Liveness = -1; //将图片进行灰度转换,然后获取图片数据 ImageInfo irImageInfo = UtilTool.ReadBMP_IR(irBitmap); if (irImageInfo == null) { return; } //IR活体检测 ASF_LivenessInfo liveInfo = UtilToolFace.LivenessInfo_IR(pVideoIRImageEngine, irImageInfo, irMultiFaceInfo, out retCode_Liveness); //判断检测结果 if (retCode_Liveness == 0 && liveInfo.num > 0) { int isLive = UtilToolMemory.PtrToStructure <int>(liveInfo.isLive); isLiveness = (isLive == 1) ? true : false; } if (irImageInfo != null) { UtilToolMemory.Free(irImageInfo.imgData); } } } } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { trackIRUnit.message = string.Format("IR{0}", isLiveness ? "活体" : "假体"); if (irBitmap != null) { irBitmap.Dispose(); } isIRLock = false; } } else { trackIRUnit.message = string.Empty; } isIRLock = false; })); } } }
/// <summary> /// RGB摄像头Paint事件,图像显示到窗体上,得到每一帧图像,并进行处理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public void VideoSource_Paint(object sender, PaintEventArgs e) { if (FRC.MainView._rgbVideoSource.IsRunning) { //得到当前RGB摄像头下的图片 Bitmap bitmap = FRC.MainView._rgbVideoSource.GetCurrentVideoFrame(); if (bitmap == null) { return; } //检测人脸,得到Rect框 ASF_MultiFaceInfo multiFaceInfo = UtilToolFace.DetectFace(pVideoEngine, bitmap); //得到最大人脸 ASF_SingleFaceInfo maxFace = UtilToolFace.GetMaxFace(multiFaceInfo); //得到Rect MRECT rect = maxFace.faceRect; //检测RGB摄像头下最大人脸 Graphics g = e.Graphics; float offsetX = FRC.MainView._rgbVideoSource.Width * 1f / bitmap.Width; float offsetY = FRC.MainView._rgbVideoSource.Height * 1f / bitmap.Height; float x = rect.left * offsetX; float width = rect.right * offsetX - x; float y = rect.top * offsetY; float height = rect.bottom * offsetY - y; //根据Rect进行画框 g.DrawRectangle(Pens.Red, x, y, width, height); if (trackRGBUnit.message != "" && x > 0 && y > 0) { //将上一帧检测结果显示到页面上 g.DrawString(trackRGBUnit.message, font, trackRGBUnit.message.Contains("活体") ? blueBrush : yellowBrush, x, y - 15); } //保证只检测一帧,防止页面卡顿以及出现其他内存被占用情况 if (isRGBLock == false) { isRGBLock = true; //异步处理提取特征值和比对,不然页面会比较卡 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { if (rect.left != 0 && rect.right != 0 && rect.top != 0 && rect.bottom != 0) { try { lock (rectLock) { allRect.left = (int)(rect.left * offsetX); allRect.top = (int)(rect.top * offsetY); allRect.right = (int)(rect.right * offsetX); allRect.bottom = (int)(rect.bottom * offsetY); } bool isLiveness = false; //调整图片数据,非常重要 ImageInfo imageInfo = UtilTool.ReadImage(bitmap); if (imageInfo == null) { return; } int retCode_Liveness = -1; //RGB活体检测 ASF_LivenessInfo liveInfo = UtilToolFace.LivenessInfo_RGB(pVideoRGBImageEngine, imageInfo, multiFaceInfo, out retCode_Liveness); //判断检测结果 if (retCode_Liveness == 0 && liveInfo.num > 0) { int isLive = UtilToolMemory.PtrToStructure <int>(liveInfo.isLive); isLiveness = (isLive == 1) ? true : false; } if (imageInfo != null) { UtilToolMemory.Free(imageInfo.imgData); } if (isLiveness) { //提取人脸特征 IntPtr feature = UtilToolFace.ExtractFaceFeature(pVideoRGBImageEngine, bitmap, maxFace); float similarity = 0f; //得到比对结果 int result = CompareFeature(feature, out similarity); UtilToolMemory.Free(feature); if (result > -1) { //将比对结果放到显示消息中,用于最新显示 trackRGBUnit.message = string.Format(" {0}号 {1},{2}", result, similarity, string.Format("RGB{0}", isLiveness ? "活体" : "假体")); } else { //显示消息 trackRGBUnit.message = string.Format("RGB{0}", isLiveness ? "活体" : "假体"); } } else { //显示消息 trackRGBUnit.message = string.Format("RGB{0}", isLiveness ? "活体" : "假体"); } } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { if (bitmap != null) { bitmap.Dispose(); } isRGBLock = false; } } else { lock (rectLock) { allRect.left = 0; allRect.top = 0; allRect.right = 0; allRect.bottom = 0; } } isRGBLock = false; })); } } }
/// <summary> /// 导入照片录入 /// </summary> /// <param name="IsOfflineRecord">是否为本地导入</param> public void ImportImgesFun(bool IsOfflineRecord) { lock (locker) { List <string> imagePathListTemp = ImportImages(IsOfflineRecord); if (imagePathListTemp.Count <= 0) { return; } FRC.PIVM.NaturalSourceImage = imagePathListTemp[0]; var numStart = ImagePathList.Count; int isGoodImage = 0; //人脸检测以及提取人脸特征 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { //人脸检测和剪裁 for (int i = 0; i < imagePathListTemp.Count; i++) { Image image = UtilTool.ReadImageFromFile(imagePathListTemp[i]); if (image == null) { continue; } if (image.Width > 1536 || image.Height > 1536) { image = UtilTool.ScaleImage(image, 1536, 1536); } if (image == null) { continue; } if (image.Width % 4 != 0) { image = UtilTool.ScaleImage(image, image.Width - (image.Width % 4), image.Height); } //人脸检测 ASF_MultiFaceInfo multiFaceInfo = UtilToolFace.DetectFace(pImageEngine, image); //判断检测结果 if (multiFaceInfo.faceNum > 0) { ImagePathList.Add(imagePathListTemp[i]); MRECT rect = UtilToolMemory.PtrToStructure <MRECT>(multiFaceInfo.faceRects); image = UtilTool.CutImage(image, rect.left, rect.top, rect.right, rect.bottom); } else { if (image != null) { image.Dispose(); } continue; } //显示人脸 FRC.MainView.Dispatcher.Invoke(new Action(delegate { if (image == null) { image = UtilTool.ReadImageFromFile(imagePathListTemp[i]); if (image.Width > 1536 || image.Height > 1536) { image = UtilTool.ScaleImage(image, 1536, 1536); } } //_imageLists.Images.Add(imagePathListTemp[i], image); //_imageList.Items.Add((numStart + isGoodImage) + "号", imagePathListTemp[i]); isGoodImage += 1; if (image != null) { image.Dispose(); } })); } //提取人脸特征 for (int i = numStart; i < ImagePathList.Count; i++) { ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo(); Image image = UtilTool.ReadImageFromFile(ImagePathList[i]); if (image == null) { continue; } IntPtr feature = UtilToolFace.ExtractFaceFeature(pImageEngine, image, out singleFaceInfo); FRC.PIVM.FaceCharacteristics = feature; FRC.MainView.Dispatcher.Invoke(new Action(delegate { if (singleFaceInfo.faceRect.left == 0 && singleFaceInfo.faceRect.right == 0) { AppendText(string.Format("{0}号未检测到人脸\r\n", i)); } else { AppendText(string.Format("已提取{0}号人脸特征值,[left:{1},right:{2},top:{3},bottom:{4},orient:{5}]\r\n", i, singleFaceInfo.faceRect.left, singleFaceInfo.faceRect.right, singleFaceInfo.faceRect.top, singleFaceInfo.faceRect.bottom, singleFaceInfo.faceOrient)); ImagesFeatureList.Add(feature); } })); if (image != null) { image.Dispose(); } } FRC.MainView.Dispatcher.Invoke(new Action(delegate { FRC.MainVM.IsCameraEnable = true; //FRC.MainVM.IsPGBtnEnable = true; FRC.MainVM.IsSIBtnEnable = true; //FRC.MainVM.IsPGIBtnEnable = true; FRC.MainVM.IsSIIBtnEnable = true; })); })); //保存个人信息数据 //FRC.UploadFaceRecord(); } }
/// <summary> /// “选择图片识别” /// </summary> public void ChooseImgeDistinguish(bool IsOffline) { //判断引擎是否初始化成功 if (pImageEngine == IntPtr.Zero) { //禁用相关功能按钮 FRC.MainVM.IsSIIBtnEnable = false; FRC.MainVM.IsPGIBtnEnable = false; //ControlsEnable(false, chooseMultiImgBtn, matchBtn, btnClearFaceList, chooseImgBtn); MessageBox.Show("请先初始化引擎!"); return; } List <string> imagePathList = ImportImages(IsOffline, false);//单张照片 if (imagePathList.Count <= 0) { return; } string selectedImagePath = imagePathList[0]; DateTime detectStartTime = DateTime.Now; AppendText(string.Format("------------------------------开始检测,时间:{0}------------------------------\n", detectStartTime.ToString("yyyy-MM-dd HH:mm:ss:ms"))); //获取文件,拒绝过大的图片 FileInfo fileInfo = new FileInfo(selectedImagePath); if (fileInfo.Length > MaxSize) { MessageBox.Show("图像文件最大为2MB,请压缩后再导入!"); AppendText(string.Format("------------------------------检测结束,时间:{0}------------------------------\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ms"))); AppendText("\n"); return; } Image srcImage = UtilTool.ReadImageFromFile(selectedImagePath); if (srcImage == null) { MessageBox.Show("图像数据获取失败,请稍后重试!"); AppendText(string.Format("------------------------------检测结束,时间:{0}------------------------------\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ms"))); AppendText("\n"); return; } if (srcImage.Width > 1536 || srcImage.Height > 1536) { srcImage = UtilTool.ScaleImage(srcImage, 1536, 1536); } if (srcImage == null) { MessageBox.Show("图像数据获取失败,请稍后重试!"); AppendText(string.Format("------------------------------检测结束,时间:{0}------------------------------\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ms"))); AppendText("\n"); return; } //调整图像宽度,需要宽度为4的倍数 if (srcImage.Width % 4 != 0) { srcImage = UtilTool.ScaleImage(srcImage, srcImage.Width - (srcImage.Width % 4), srcImage.Height); } //调整图片数据,非常重要 ImageInfo imageInfo = UtilTool.ReadImage(srcImage); if (imageInfo == null) { MessageBox.Show("图像数据获取失败,请稍后重试!"); AppendText(string.Format("------------------------------检测结束,时间:{0}------------------------------\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ms"))); AppendText("\n"); return; } //人脸检测 ASF_MultiFaceInfo multiFaceInfo = UtilToolFace.DetectFace(pImageEngine, imageInfo); //年龄检测 int retCode_Age = -1; ASF_AgeInfo ageInfo = UtilToolFace.DetectAge(pImageEngine, imageInfo, multiFaceInfo, out retCode_Age); //性别检测 int retCode_Gender = -1; ASF_GenderInfo genderInfo = UtilToolFace.DetectGender(pImageEngine, imageInfo, multiFaceInfo, out retCode_Gender); //3DAngle检测 int retCode_3DAngle = -1; ASF_Face3DAngle face3DAngleInfo = UtilToolFace.DetectFace3DAngle(pImageEngine, imageInfo, multiFaceInfo, out retCode_3DAngle); UtilToolMemory.Free(imageInfo.imgData); if (multiFaceInfo.faceNum < 1) { srcImage = UtilTool.ScaleImage(srcImage, (int)FRC.FIView._faceIdentificationImageBox.Width, (int)FRC.FIView._faceIdentificationImageBox.Height); ImageFeature = IntPtr.Zero; FRC.FIView._faceIdentificationImageBox.Source = UtilTool.BitmapToBitmapImage(srcImage); AppendText(string.Format("{0} - 未检测出人脸!\n\n", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"))); AppendText(string.Format("------------------------------检测结束,时间:{0}------------------------------\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ms"))); AppendText("\n"); return; } MRECT temp = new MRECT(); int ageTemp = 0; int genderTemp = 0; int rectTemp = 0; //标记出检测到的人脸 for (int i = 0; i < multiFaceInfo.faceNum; i++) { MRECT rect = UtilToolMemory.PtrToStructure <MRECT>(multiFaceInfo.faceRects + UtilToolMemory.SizeOf <MRECT>() * i); int orient = UtilToolMemory.PtrToStructure <int>(multiFaceInfo.faceOrients + UtilToolMemory.SizeOf <int>() * i); int age = 0; if (retCode_Age != 0) { AppendText(string.Format("年龄检测失败,返回{0}!\n\n", retCode_Age)); } else { age = UtilToolMemory.PtrToStructure <int>(ageInfo.ageArray + UtilToolMemory.SizeOf <int>() * i); } int gender = -1; if (retCode_Gender != 0) { AppendText(string.Format("性别检测失败,返回{0}!\n\n", retCode_Gender)); } else { gender = UtilToolMemory.PtrToStructure <int>(genderInfo.genderArray + UtilToolMemory.SizeOf <int>() * i); } int face3DStatus = -1; float roll = 0f; float pitch = 0f; float yaw = 0f; if (retCode_3DAngle != 0) { AppendText(string.Format("3DAngle检测失败,返回{0}!\n\n", retCode_3DAngle)); } else { //角度状态 非0表示人脸不可信 face3DStatus = UtilToolMemory.PtrToStructure <int>(face3DAngleInfo.status + UtilToolMemory.SizeOf <int>() * i); //roll为侧倾角,pitch为俯仰角,yaw为偏航角 roll = UtilToolMemory.PtrToStructure <float>(face3DAngleInfo.roll + UtilToolMemory.SizeOf <float>() * i); pitch = UtilToolMemory.PtrToStructure <float>(face3DAngleInfo.pitch + UtilToolMemory.SizeOf <float>() * i); yaw = UtilToolMemory.PtrToStructure <float>(face3DAngleInfo.yaw + UtilToolMemory.SizeOf <float>() * i); } int rectWidth = rect.right - rect.left; int rectHeight = rect.bottom - rect.top; //查找最大人脸 if (rectWidth * rectHeight > rectTemp) { rectTemp = rectWidth * rectHeight; temp = rect; ageTemp = age; genderTemp = gender; } AppendText(string.Format("{0} - 人脸坐标:[left:{1},top:{2},right:{3},bottom:{4},orient:{5},roll:{6},pitch:{7},yaw:{8},status:{11}] Age:{9} Gender:{10}\n", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), rect.left, rect.top, rect.right, rect.bottom, orient, roll, pitch, yaw, age, (gender >= 0 ? gender.ToString() : ""), face3DStatus)); } AppendText(string.Format("{0} - 人脸数量:{1}\n\n", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), multiFaceInfo.faceNum)); DateTime detectEndTime = DateTime.Now; AppendText(string.Format("------------------------------检测结束,时间:{0}------------------------------\n", detectEndTime.ToString("yyyy-MM-dd HH:mm:ss:ms"))); AppendText("\n"); ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo(); //提取人脸特征 ImageFeature = UtilToolFace.ExtractFaceFeature(pImageEngine, srcImage, out singleFaceInfo); //清空上次的匹配结果 for (int i = 0; i < ImagesFeatureList.Count; i++) { //_imageList.Items[i].Text = string.Format("{0}号", i); } //获取缩放比例 float scaleRate = UtilTool.GetWidthAndHeight(srcImage.Width, srcImage.Height, (int)FRC.FIView._faceIdentificationImageBox.Width, (int)FRC.FIView._faceIdentificationImageBox.Height); //缩放图片 srcImage = UtilTool.ScaleImage(srcImage, (int)FRC.FIView._faceIdentificationImageBox.Width, (int)FRC.FIView._faceIdentificationImageBox.Height); //添加标记 srcImage = UtilTool.MarkRectAndString(srcImage, (int)(temp.left * scaleRate), (int)(temp.top * scaleRate), (int)(temp.right * scaleRate) - (int)(temp.left * scaleRate), (int)(temp.bottom * scaleRate) - (int)(temp.top * scaleRate), ageTemp, genderTemp, (int)FRC.FIView._faceIdentificationImageBox.Width); //显示标记后的图像 FRC.FIView._faceIdentificationImageBox.Source = UtilTool.BitmapToBitmapImage(srcImage); MatchImage(); }
/// <summary> /// 将照片导入到路径集合 /// </summary> /// <param name="isOffline">是否为本地导入</param> /// <param name="IsMultiSelect">是否为多张导入</param> /// <returns> List<string>imageFileNames 路径集合</returns> private List <string> ImportImages(bool isOffline, bool IsMultiSelect = false) { List <string> imagePathLsit = new List <string>(); List <string> imagePathListTemp = new List <string>(); //本地导入图片 if (isOffline) { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Title = "选择图片"; openFileDialog.Filter = "图片文件|*.bmp;*.jpg;*.jpeg;*.png"; openFileDialog.Multiselect = IsMultiSelect; openFileDialog.FileName = string.Empty; if (openFileDialog.ShowDialog() == DialogResult.OK) { imagePathListTemp = openFileDialog.FileNames.ToList();; AppendText("本地导入成功!"); AppendText("\n"); } } //相机截图 else { Bitmap bitmap = null; try { bitmap = FRC.MainView._rgbVideoSource.GetCurrentVideoFrame(); } catch (Exception ex) { MessageBox.Show(ex.Message, @"Error while getting a snapshot"); } if (bitmap == null) { return(imagePathListTemp); } //截取图片 string imageName = DateTime.Now.Ticks.ToString() + ".png"; UtilTool.Save_BitmapImage_Into_File(UtilTool.BitmapToBitmapImage(bitmap), imageName, FRC.PersonInfoPath); AppendText("导入成功!"); AppendText("\n"); imagePathListTemp.Add(Path.Combine(FRC.PersonInfoPath, imageName)); } //保存图片路径并显示 foreach (var imageFileName in imagePathListTemp) { //图片格式判断 if (CheckImage(imageFileName)) { imagePathLsit.Add(imageFileName); } } return(imagePathLsit); }