public static ASF_MultiFaceInfo DetectFace(IntPtr pEngine, Image image) { lock (locks) { ASF_MultiFaceInfo multiFaceInfo = new ASF_MultiFaceInfo(); if (image != null) { if (image == null) { return(multiFaceInfo); } ImageInfo imageInfo = UtilTool.ReadImage(image); if (imageInfo == null) { return(multiFaceInfo); } multiFaceInfo = DetectFace(pEngine, imageInfo); UtilToolMemory.Free(imageInfo.imgData); return(multiFaceInfo); } else { return(multiFaceInfo); } } }
/// <summary> /// 单人脸性别检测 /// </summary> /// <param name="pEngine">引擎Handle</param> /// <param name="image">图片</param> /// <param name="singleFaceInfo">单人脸信息</param> /// <returns>性别估计结果</returns> public static ASF_GenderInfo DetectGender(IntPtr pEngine, Image image, ASF_SingleFaceInfo singleFaceInfo) { ImageInfo imageInfo = UtilTool.ReadImage(image); if (imageInfo == null) { return(new ASF_GenderInfo()); } ASF_MultiFaceInfo multiFaceInfo = new ASF_MultiFaceInfo(); multiFaceInfo.faceRects = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <MRECT>()); UtilToolMemory.StructureToPtr <MRECT>(singleFaceInfo.faceRect, multiFaceInfo.faceRects); multiFaceInfo.faceOrients = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <int>()); UtilToolMemory.StructureToPtr <int>(singleFaceInfo.faceOrient, multiFaceInfo.faceOrients); multiFaceInfo.faceNum = 1; ASF_GenderInfo genderInfo = DetectGender(pEngine, imageInfo, multiFaceInfo); UtilToolMemory.Free(imageInfo.imgData); return(genderInfo); }
/// <summary> /// 提取人脸特征 /// </summary> /// <param name="pEngine">引擎Handle</param> /// <param name="image">图像</param> /// <returns>保存人脸特征结构体指针</returns> public static IntPtr ExtractFaceFeature(IntPtr pEngine, Image image, out ASF_SingleFaceInfo singleFaceInfo) { if (image.Width > 1536 || image.Height > 1536) { image = UtilTool.ScaleImage(image, 1536, 1536); } else { image = UtilTool.ScaleImage(image, image.Width, image.Height); } if (image == null) { singleFaceInfo = new ASF_SingleFaceInfo(); ASF_FaceFeature emptyFeature = new ASF_FaceFeature(); IntPtr pEmptyFeature = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_FaceFeature>()); UtilToolMemory.StructureToPtr(emptyFeature, pEmptyFeature); return(pEmptyFeature); } ImageInfo imageInfo = UtilTool.ReadImage(image); if (imageInfo == null) { singleFaceInfo = new ASF_SingleFaceInfo(); ASF_FaceFeature emptyFeature = new ASF_FaceFeature(); IntPtr pEmptyFeature = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_FaceFeature>()); UtilToolMemory.StructureToPtr(emptyFeature, pEmptyFeature); return(pEmptyFeature); } ASF_MultiFaceInfo multiFaceInfo = DetectFace(pEngine, imageInfo); singleFaceInfo = new ASF_SingleFaceInfo(); IntPtr pFaceModel = ExtractFaceFeature(pEngine, imageInfo, multiFaceInfo, out singleFaceInfo); UtilToolMemory.Free(imageInfo.imgData); return(pFaceModel); }
/// <summary> /// 提取单人脸特征 /// </summary> /// <param name="pEngine">人脸识别引擎</param> /// <param name="image">图片</param> /// <param name="singleFaceInfo">单人脸信息</param> /// <returns>单人脸特征</returns> public static IntPtr ExtractFaceFeature(IntPtr pEngine, Image image, ASF_SingleFaceInfo singleFaceInfo) { ImageInfo imageInfo = UtilTool.ReadImage(image); if (imageInfo == null) { ASF_FaceFeature emptyFeature = new ASF_FaceFeature(); IntPtr pEmptyFeature = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_FaceFeature>()); UtilToolMemory.StructureToPtr(emptyFeature, pEmptyFeature); return(pEmptyFeature); } IntPtr pSingleFaceInfo = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_SingleFaceInfo>()); UtilToolMemory.StructureToPtr(singleFaceInfo, pSingleFaceInfo); IntPtr pFaceFeature = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_FaceFeature>()); int retCode = -1; try { retCode = ASFFunctions.ASFFaceFeatureExtract(pEngine, imageInfo.width, imageInfo.height, imageInfo.format, imageInfo.imgData, pSingleFaceInfo, pFaceFeature); } catch (Exception e) { Console.WriteLine(e.Message); } Console.WriteLine("FR Extract Feature result:" + retCode); if (retCode != 0) { //释放指针 UtilToolMemory.Free(pSingleFaceInfo); UtilToolMemory.Free(pFaceFeature); UtilToolMemory.Free(imageInfo.imgData); ASF_FaceFeature emptyFeature = new ASF_FaceFeature(); IntPtr pEmptyFeature = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_FaceFeature>()); UtilToolMemory.StructureToPtr(emptyFeature, pEmptyFeature); return(pEmptyFeature); } //人脸特征feature过滤 ASF_FaceFeature faceFeature = UtilToolMemory.PtrToStructure <ASF_FaceFeature>(pFaceFeature); byte[] feature = new byte[faceFeature.featureSize]; UtilToolMemory.Copy(faceFeature.feature, feature, 0, faceFeature.featureSize); ASF_FaceFeature localFeature = new ASF_FaceFeature(); localFeature.feature = UtilToolMemory.Malloc(feature.Length); UtilToolMemory.Copy(feature, 0, localFeature.feature, feature.Length); localFeature.featureSize = feature.Length; IntPtr pLocalFeature = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_FaceFeature>()); UtilToolMemory.StructureToPtr(localFeature, pLocalFeature); //释放指针 UtilToolMemory.Free(pSingleFaceInfo); UtilToolMemory.Free(pFaceFeature); UtilToolMemory.Free(imageInfo.imgData); return(pLocalFeature); }
/// <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> 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(); }