static void DrawRect(Graphics graphics, MRECT rect, Color color, int width) { Point point = new Point(rect.left, rect.top); Size size = new Size(Math.Abs(rect.right - rect.left), Math.Abs(rect.bottom - rect.top)); DrawRect(graphics, new Rectangle(point, size), color, width); }
/// <summary> /// 从Image图片中提取特征 /// </summary> /// <param name="img"></param> /// <returns></returns> private IntPtr GetFeatureFromImage(Image img) { Image image = img; if (image.Width % 4 != 0) { image = ImageUtil.ScaleImage(image, image.Width - (image.Width % 4), image.Height); } ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(pImageEngine, image); if (multiFaceInfo.faceNum > 0) { //裁剪照片到识别人脸的框的大小 MRECT rect = MemoryUtil.PtrToStructure <MRECT>(multiFaceInfo.faceRects); image = ImageUtil.CutImage(image, rect.left, rect.top, rect.right, rect.bottom); } //提取人脸特征 ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo(); IntPtr feature = FaceUtil.ExtractFeature(pImageEngine, image, out singleFaceInfo); if (singleFaceInfo.faceRect.left == 0 && singleFaceInfo.faceRect.right == 0) { //messageBox.AppendText("无法提取身份证件照特征...\n"); //无法提取身份证件照特征.. } else { //成功提取到的图像特征值 return(feature); } return(IntPtr.Zero); }
static public Bitmap DrawRect(this Bitmap bitmap, MRECT rect, Color color, int width) { Graphics graphics = Graphics.FromImage(bitmap); DrawRect(graphics, rect, color, width); return(bitmap); }
/// <summary> /// 人脸识别特征码提取 /// </summary> /// <param name="image"></param> /// <param name="rect"></param> /// <param name="orient"></param> private byte[] RecognizeFace(Bitmap image, MRECT rect, int orient) { IntPtr offInputPtr = ArcFaceDetection.MakeImageInput_ASVLOFFSCREEN(image); AFR_FSDK_FACEINPUT faceInput = new AFR_FSDK_FACEINPUT(); faceInput.lOrient = orient; faceInput.rcFace = rect; //入参 IntPtr faceInputPtr = Marshal.AllocHGlobal(Marshal.SizeOf(faceInput)); Marshal.StructureToPtr(faceInput, faceInputPtr, false); AFR_FSDK_FACEMODEL faceModel = new AFR_FSDK_FACEMODEL(); IntPtr faceModelPtr = Marshal.AllocHGlobal(Marshal.SizeOf(faceModel)); int ret = AFRFunction.AFR_FSDK_ExtractFRFeature(this.faceRecognition.rEngine, offInputPtr, faceInputPtr, faceModelPtr); if (ret == 0) { faceModel = (AFR_FSDK_FACEMODEL)Marshal.PtrToStructure(faceModelPtr, typeof(AFR_FSDK_FACEMODEL)); Marshal.FreeHGlobal(faceModelPtr); byte[] featureContent = new byte[faceModel.lFeatureSize]; Marshal.Copy(faceModel.pbFeature, featureContent, 0, faceModel.lFeatureSize); return(featureContent); } return(null); }
public static FaceInfo[] doFaceDetection(IntPtr hFDEngine, ASVLOFFSCREEN inputImg) { FaceInfo[] faceInfo = new FaceInfo[0]; IntPtr pFaceRes = IntPtr.Zero; IntPtr ret = AFD_FSDKLibrary.AFD_FSDK_StillImageFaceDetection(hFDEngine, ref (inputImg), ref (pFaceRes)); if (ret.ToInt64() != 0) { Console.WriteLine(String.Format("AFD_FSDK_StillImageFaceDetection 0x{0:x}", ret)); return(faceInfo); } AFD_FSDK_FACERES faceRes = (AFD_FSDK_FACERES)Marshal.PtrToStructure(pFaceRes, typeof(AFD_FSDK_FACERES)); if (faceRes.nFace > 0) { faceInfo = new FaceInfo[faceRes.nFace]; for (int i = 0; i < faceRes.nFace; i++) { MRECT rect = (MRECT)Marshal.PtrToStructure(faceRes.rcFace + i * Marshal.SizeOf(typeof(MRECT)), typeof(MRECT)); int orient = Marshal.ReadInt32(faceRes.lfaceOrient + 4 * i); faceInfo[i] = new FaceInfo(); faceInfo[i].left = rect.left; faceInfo[i].top = rect.top; faceInfo[i].right = rect.right; faceInfo[i].bottom = rect.bottom; faceInfo[i].orient = orient; Console.WriteLine(String.Format("{0} ({1} {2} {3} {4}) orient {5}", i, rect.left, rect.top, rect.right, rect.bottom, orient)); } } return(faceInfo); }
/// <summary> /// 从Image图片中提取特征 /// </summary> /// <param name="img"></param> /// <returns></returns> public static IntPtr GetFeatureFromImage(IntPtr pEngine, Image img) { Image image = img; if (image.Width % 4 != 0) { image = ImageUtil.ScaleImage(image, image.Width - (image.Width % 4), image.Height); } ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(pEngine, image); if (multiFaceInfo.faceNum > 0) { //裁剪照片到识别人脸的框的大小 MRECT rect = MemoryUtil.PtrToStructure <MRECT>(multiFaceInfo.faceRects); image = ImageUtil.CutImage(image, rect.left, rect.top, rect.right, rect.bottom); } //提取人脸特征 ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo(); IntPtr feature = FaceUtil.ExtractFeature(pEngine, image, out singleFaceInfo); if (!(singleFaceInfo.faceRect.left == 0 && singleFaceInfo.faceRect.right == 0)) { return(feature);//成功提取到的图像特征值 } return(IntPtr.Zero); }
/// <summary> /// 获取多个人脸检测结果中面积最大的人脸 /// </summary> /// <param name="multiFaceInfo">人脸检测结果</param> /// <returns>面积最大的人脸信息</returns> public static ASF_SingleFaceInfo GetMaxFace(ASF_MultiFaceInfo multiFaceInfo) { ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo(); singleFaceInfo.faceRect = new MRECT(); singleFaceInfo.faceOrient = 1; int maxArea = 0; int index = -1; for (int i = 0; i < multiFaceInfo.faceNum; i++) { MRECT rect = MemoryUtil.PtrToStructure <MRECT>(multiFaceInfo.faceRects + MemoryUtil.SizeOf <MRECT>() * i); int area = (rect.right - rect.left) * (rect.bottom - rect.top); if (maxArea <= area) { maxArea = area; index = i; } } if (index != -1) { singleFaceInfo.faceRect = MemoryUtil.PtrToStructure <MRECT>(multiFaceInfo.faceRects + MemoryUtil.SizeOf <MRECT>() * index); singleFaceInfo.faceOrient = MemoryUtil.PtrToStructure <int>(multiFaceInfo.faceOrients + MemoryUtil.SizeOf <int>() * index); } return(singleFaceInfo); }
/// <summary> /// 构造函数 /// </summary> /// <param name="faceId">人脸Faceid</param> /// <param name="rect">人脸框坐标</param> /// <param name="faceOrient">人脸角度</param> public FaceTrackUnit(int faceId, MRECT rect, int faceOrient, FaceDataInfo faceDataInfo) { FaceId = faceId; Rect = rect; FaceOrient = faceOrient; FaceDataInfo = faceDataInfo; }
/// <summary> /// 获取多个人脸检测结果中面积最大的人脸 /// </summary> /// <param name="multiFaceInfo">人脸检测结果</param> /// <returns>面积最大的人脸信息</returns> public static ASF_SingleFaceInfo GetMaxFace(ASF_MultiFaceInfo multiFaceInfo) { ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo(); singleFaceInfo.faceRect = new MRECT(); singleFaceInfo.faceOrient = 1; int maxArea = 0; int index = -1; for (int i = 0; i < multiFaceInfo.faceNum; i++) { try { MRECT rect = UtilToolMemory.PtrToStructure <MRECT>(multiFaceInfo.faceRects + UtilToolMemory.SizeOf <MRECT>() * i); int area = (rect.right - rect.left) * (rect.bottom - rect.top); if (maxArea <= area) { maxArea = area; index = i; } } catch (Exception ex) { Console.WriteLine(ex.Message); } } if (index != -1) { singleFaceInfo.faceRect = UtilToolMemory.PtrToStructure <MRECT>(multiFaceInfo.faceRects + UtilToolMemory.SizeOf <MRECT>() * index); singleFaceInfo.faceOrient = UtilToolMemory.PtrToStructure <int>(multiFaceInfo.faceOrients + UtilToolMemory.SizeOf <int>() * index); } return(singleFaceInfo); }
static public Image DrawRect(this Image image, MRECT rect, Color color, int width) { Graphics graphics = Graphics.FromImage(image); DrawRect(graphics, rect, color, width); return(image); }
/// <summary> /// 比对函数,将每一帧抓拍的照片和目标人物照片进行比对 /// </summary> /// <param name="bitmap"></param> /// <param name="e"></param> /// <returns></returns> private void CompareImgWithIDImg(Bitmap bitmap, PaintEventArgs e) { if (bitmap != null) { //保证只检测一帧,防止页面卡顿以及出现其他内存被占用情况 if (isLock == false) { isLock = true; Graphics g = e.Graphics; float offsetX = (pic_Video.Width * 1f / bitmap.Width); float offsetY = (pic_Video.Height * 1f / bitmap.Height); //根据Bitmap 获取人脸信息列表 List <FaceInfoModel> list = FaceUtil.GetFaceInfos(pImageEngine, bitmap); foreach (FaceInfoModel sface in list) { //异步处理提取特征值和比对,不然页面会比较卡 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { try { //提取人脸特征 float similarity = CompareTwoFeatures(sface.feature, imageTemp); if (similarity > threshold) { this.pic_cutImg.Image = bitmap; this.Invoke((Action)(() => { this.lbl_simiValue.Text = similarity.ToString(); })); } } catch (Exception ex) { Console.WriteLine(ex.Message); } })); MRECT rect = sface.faceRect; 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(pen, x, y, width, height); trackUnit.message = "年龄:" + sface.age.ToString() + "\r\n" + "性别:" + (sface.gender == 0 ? "男" : "女"); g.DrawString(trackUnit.message, font, brush, x, y + 5); } isLock = false; } } }
/// <summary> /// 剪切人脸范围 /// </summary> /// <param name="bitmap"></param> /// <param name="rect"></param> /// <returns></returns> private Image CutFace(Bitmap bitmap, MRECT rect) { int width = rect.right - rect.left; int height = rect.bottom - rect.top; Image image = new Bitmap(width, height); Graphics g = Graphics.FromImage(image); g.DrawImage(bitmap, 0, 0, new Rectangle(rect.left, rect.top, width, height), GraphicsUnit.Pixel); g.Dispose(); return(image); }
public static MError Register(IntPtr ptrImageEngine, ref MemberWithFeature member) { var retCode = MError.MERR_UNKNOWN.ToInt(); IntPtr feature = IntPtr.Zero; Image image = null; try { image = Image.FromFile(member.FaceImagePath); if (image.Width % 4 != 0) { image = ImageHelper.ScaleImage(image, image.Width - (image.Width % 4), image.Height); } ASF_MultiFaceInfo multiFaceInfo = FaceProcessHelper.DetectFace(ptrImageEngine, image); if (multiFaceInfo.faceNum > 0) { MRECT rect = MemoryHelper.PtrToStructure <MRECT>(multiFaceInfo.faceRects); image = ImageHelper.CutImage(image, rect.left, rect.top, rect.right, rect.bottom); //提取人脸特征 ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo(); feature = FaceProcessHelper.ExtractFeature(ptrImageEngine, Image.FromFile(member.FaceImagePath), out singleFaceInfo); if (singleFaceInfo.faceRect.left == 0 && singleFaceInfo.faceRect.right == 0) { return(MError.MERR_FSDK_FR_INVALID_FACE_INFO); } else { member.AsfFaceFeature = MemoryHelper.PtrToStructure <ASF_FaceFeature>(feature); } } else { return(MError.MERR_FSDK_FR_INVALID_FACE_INFO); } retCode = MError.MOK.ToInt(); } catch (Exception ex) { Afw.Core.Helper.SimplifiedLogHelper.WriteIntoSystemLog(nameof(MemberEnroll), $"Register Exception:{ex.ToString()}"); } finally { MemoryHelper.Free(feature); image.Dispose(); } return(retCode.ToEnum <MError>()); }
/// <summary> /// 获取多个人脸检测结果中面积最大的人脸 /// </summary> /// <param name="multiFaceInfo">人脸检测结果</param> /// <returns>面积最大的人脸信息</returns> public static SingleFaceInfo GetMaxFace(MultiFaceInfo multiFaceInfo) { SingleFaceInfo singleFaceInfo = new SingleFaceInfo(); singleFaceInfo.faceRect = new MRECT(); singleFaceInfo.faceOrient = 1; int maxArea = 0; int index = -1; //遍历查找最大人脸索引 for (int i = 0; i < multiFaceInfo.faceNum; i++) { try { MRECT rect = multiFaceInfo.faceRects[i]; int area = (rect.right - rect.left) * (rect.bottom - rect.top); if (maxArea <= area) { maxArea = area; index = i; } } catch (Exception ex) { LogUtil.LogInfo(typeof(FaceUtil), ex); } } //获取对应的人脸信息 if (index != -1) { singleFaceInfo.faceRect = multiFaceInfo.faceRects[index]; singleFaceInfo.faceOrient = multiFaceInfo.faceOrients[index]; if (multiFaceInfo.faceID != null && multiFaceInfo.faceID.Length > index) { singleFaceInfo.faceID = multiFaceInfo.faceID[index]; } } return(singleFaceInfo); }
/// <summary> /// 人脸库图片选择按钮事件 /// </summary> private void ChooseMultiImg(object sender, EventArgs e) { lock (locker) { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Title = "选择图片"; openFileDialog.Filter = "图片文件|*.bmp;*.jpg;*.jpeg;*.png"; openFileDialog.Multiselect = true; openFileDialog.FileName = string.Empty; if (openFileDialog.ShowDialog() == DialogResult.OK) { List <string> imagePathListTemp = new List <string>(); var numStart = imagePathList.Count; int isGoodImage = 0; //保存图片路径并显示 string[] fileNames = openFileDialog.FileNames; for (int i = 0; i < fileNames.Length; i++) { imagePathListTemp.Add(fileNames[i]); } //人脸检测以及提取人脸特征 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { //禁止点击按钮 Invoke(new Action(delegate { chooseMultiImgBtn.Enabled = false; matchBtn.Enabled = false; btnClearFaceList.Enabled = false; chooseImgBtn.Enabled = false; })); //人脸检测和剪裁 for (int i = 0; i < imagePathListTemp.Count; i++) { Image image = Image.FromFile(imagePathListTemp[i]); ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(pEngine, image); if (multiFaceInfo.faceNum > 0) { imagePathList.Add(imagePathListTemp[i]); MRECT rect = MemoryUtil.PtrToStructure <MRECT>(multiFaceInfo.faceRects); image = ImageUtil.CutImage(image, rect.left, rect.top, rect.right, rect.bottom); } else { continue; } this.Invoke(new Action(delegate { if (image == null) { image = Image.FromFile(imagePathListTemp[i]); } imageLists.Images.Add(imagePathListTemp[i], image); imageList.Items.Add((numStart + isGoodImage) + "号", imagePathListTemp[i]); isGoodImage += 1; image = null; })); } //提取人脸特征 for (int i = numStart; i < imagePathList.Count; i++) { ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo(); IntPtr feature = FaceUtil.ExtractFeature(pEngine, Image.FromFile(imagePathList[i]), out singleFaceInfo); this.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); } })); } //imagePathList.AddRange(imagePathListTemp); //允许点击按钮 Invoke(new Action(delegate { chooseMultiImgBtn.Enabled = true; matchBtn.Enabled = true; btnClearFaceList.Enabled = true; chooseImgBtn.Enabled = true; })); })); } } }
private void InitDB() { string allselect = "selsect * from face"; conn.Open(); MySqlCommand cmd = new MySqlCommand(allselect, conn); MySqlDataReader read = cmd.ExecuteReader(); if (read.FieldCount == 0) { return; } while (read.Read()) { int i = 0; string _name = read.GetString("name"); string path = read.GetString("face"); Image srcImage = Image.FromFile(path); if (srcImage == null) { return; } srcImage = ImageUtil.ScaleImage(srcImage, picImageCompare.Width, picImageCompare.Height); ImageInfo imageInfo = ImageUtil.ReadBMP(srcImage); ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo(); //提取人脸特征 IntPtr ptr = FaceUtil.ExtractFeature(pEngine, srcImage, out singleFaceInfo); if (ptr == IntPtr.Zero) { continue; } imagePathList.Add(path); imagesFeatureList.Add(ptr); KeyValuePair <string, IntPtr> pair = new KeyValuePair <string, IntPtr>(path, ptr); People people = new People(_name, pair); peoples.Add(people); //人脸检测与剪裁 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(pEngine, srcImage); if (multiFaceInfo.faceNum > 0) { imagePathList.Add(path); MRECT rect = MemoryUtil.PtrToStructure <MRECT>(multiFaceInfo.faceRects); srcImage = ImageUtil.CutImage(srcImage, rect.left, rect.top, rect.right, rect.bottom); } this.Invoke(new Action(delegate { if (srcImage == null) { srcImage = Image.FromFile(path); } imageLists.Images.Add(path, srcImage); imageList.Items.Add(i + "号", path); i++; srcImage = null; })); })); } }
/// <summary> /// “选择识别图片”按钮事件 /// </summary> private void ChooseImg(object sender, EventArgs e) { lblCompareInfo.Text = ""; if (pEngine == IntPtr.Zero) { chooseMultiImgBtn.Enabled = false; matchBtn.Enabled = false; btnClearFaceList.Enabled = false; chooseImgBtn.Enabled = false; MessageBox.Show("请先初始化引擎!"); return; } OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Title = "选择图片"; openFileDialog.Filter = "图片文件|*.bmp;*.jpg;*.jpeg;*.png"; openFileDialog.Multiselect = false; openFileDialog.FileName = string.Empty; if (openFileDialog.ShowDialog() == DialogResult.OK) { DateTime detectStartTime = DateTime.Now; AppendText(string.Format("------------------------------开始检测,时间:{0}------------------------------\n", detectStartTime.ToString("yyyy-MM-dd HH:mm:ss:ms"))); image1Path = openFileDialog.FileName; //获取文件,拒绝过大的图片 FileInfo fileInfo = new FileInfo(image1Path); long maxSize = 1024 * 1024 * 2; 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 = Image.FromFile(image1Path); //调整图像宽度,需要宽度为4的倍数 srcImage = ImageUtil.ScaleImage(srcImage, picImageCompare.Width, picImageCompare.Height); //调整图片数据,非常重要 ImageInfo imageInfo = ImageUtil.ReadBMP(srcImage); //人脸检测 ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(pEngine, imageInfo); //年龄检测 int retCode_Age = -1; ASF_AgeInfo ageInfo = FaceUtil.AgeEstimation(pEngine, imageInfo, multiFaceInfo, out retCode_Age); //性别检测 int retCode_Gender = -1; ASF_GenderInfo genderInfo = FaceUtil.GenderEstimation(pEngine, imageInfo, multiFaceInfo, out retCode_Gender); //3DAngle检测 int retCode_3DAngle = -1; ASF_Face3DAngle face3DAngleInfo = FaceUtil.Face3DAngleDetection(pEngine, imageInfo, multiFaceInfo, out retCode_3DAngle); MemoryUtil.Free(imageInfo.imgData); if (multiFaceInfo.faceNum < 1) { image1Feature = IntPtr.Zero; picImageCompare.Image = 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 = MemoryUtil.PtrToStructure <MRECT>(multiFaceInfo.faceRects + MemoryUtil.SizeOf <MRECT>() * i); int orient = MemoryUtil.PtrToStructure <int>(multiFaceInfo.faceOrients + MemoryUtil.SizeOf <int>() * i); int age = 0; if (retCode_Age != 0) { AppendText(string.Format("年龄检测失败,返回{0}!\n\n", retCode_Age)); } else { age = MemoryUtil.PtrToStructure <int>(ageInfo.ageArray + MemoryUtil.SizeOf <int>() * i); } int gender = -1; if (retCode_Gender != 0) { AppendText(string.Format("性别检测失败,返回{0}!\n\n", retCode_Gender)); } else { gender = MemoryUtil.PtrToStructure <int>(genderInfo.genderArray + MemoryUtil.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 = MemoryUtil.PtrToStructure <int>(face3DAngleInfo.status + MemoryUtil.SizeOf <int>() * i); //roll为侧倾角,pitch为俯仰角,yaw为偏航角 roll = MemoryUtil.PtrToStructure <float>(face3DAngleInfo.roll + MemoryUtil.SizeOf <float>() * i); pitch = MemoryUtil.PtrToStructure <float>(face3DAngleInfo.pitch + MemoryUtil.SizeOf <float>() * i); yaw = MemoryUtil.PtrToStructure <float>(face3DAngleInfo.yaw + MemoryUtil.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; } //srcImage = ImageUtil.MarkRectAndString(srcImage, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, age, 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)); } srcImage = ImageUtil.MarkRectAndString(srcImage, temp.left, temp.top, temp.right - temp.left, temp.bottom - temp.top, ageTemp, genderTemp); AppendText(string.Format("{0} - 人脸数量:{1}\n\n", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), multiFaceInfo.faceNum)); //显示标记后的图像 picImageCompare.Image = srcImage; 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(); //提取人脸特征 image1Feature = FaceUtil.ExtractFeature(pEngine, srcImage, out singleFaceInfo); //清空上次的匹配结果 for (int i = 0; i < imagesFeatureList.Count; i++) { imageList.Items[i].Text = string.Format("{0}号", i); } } }
/// <summary> /// 图像显示到窗体上,得到每一帧图像,并进行处理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void videoSource_Paint(object sender, PaintEventArgs e) { if (videoSource.IsRunning) { //得到当前摄像头下的图片 Bitmap bitmap = videoSource.GetCurrentVideoFrame(); if (bitmap == null) { return; } Graphics g = e.Graphics; float offsetX = videoSource.Width * 1f / bitmap.Width; float offsetY = videoSource.Height * 1f / bitmap.Height; //检测人脸,得到Rect框 ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(pVideoEngine, bitmap); //得到最大人脸 ASF_SingleFaceInfo maxFace = FaceUtil.GetMaxFace(multiFaceInfo); //得到Rect MRECT rect = maxFace.faceRect; 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(pen, x, y, width, height); if (trackUnit.message != "" && x > 0 && y > 0) { //将上一帧检测结果显示到页面上 g.DrawString(trackUnit.message, font, brush, x, y + 5); } //保证只检测一帧,防止页面卡顿以及出现其他内存被占用情况 if (isLock == false) { isLock = true; //异步处理提取特征值和比对,不然页面会比较卡 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { if (rect.left != 0 && rect.right != 0 && rect.top != 0 && rect.bottom != 0) { try { //提取人脸特征 IntPtr feature = FaceUtil.ExtractFeature(pVideoImageEngine, bitmap, maxFace); float similarity = 0f; //得到比对结果 int result = compareFeature(feature, out similarity); if (result > -1) { //将比对结果放到显示消息中,用于最新显示 trackUnit.message = string.Format("{0}号 {1}", result, similarity); //执行数据库操作 SignSql(result); } else { //重置显示消息 trackUnit.message = ""; } } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { isLock = false; } } isLock = false; })); } } }
/// <summary> /// 构造函数 /// </summary> /// <param name="faceId">人脸Faceid</param> /// <param name="rect">人脸框坐标</param> /// <param name="faceOrient">人脸角度</param> public FaceTrackUnit(int faceId, MRECT rect, int faceOrient) { FaceId = faceId; Rect = rect; FaceOrient = faceOrient; }
/// <summary> /// RGB摄像头Paint事件,图像显示到窗体上,得到每一帧图像,并进行处理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void videoSource_Paint(object sender, PaintEventArgs e) { if (rgbVideoSource.IsRunning) { //得到当前RGB摄像头下的图片 Bitmap bitmap = rgbVideoSource.GetCurrentVideoFrame(); if (bitmap == null) { return; } //检测人脸,得到Rect框 ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(pVideoEngine, bitmap); //得到最大人脸 ASF_SingleFaceInfo maxFace = FaceUtil.GetMaxFace(multiFaceInfo); //得到Rect MRECT rect = maxFace.faceRect; //检测RGB摄像头下最大人脸 Graphics g = e.Graphics; float offsetX = rgbVideoSource.Width * 1f / bitmap.Width; float offsetY = 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 = ImageUtil.ReadBMP(bitmap); if (imageInfo == null) { return; } int retCode_Liveness = -1; //RGB活体检测 ASF_LivenessInfo liveInfo = FaceUtil.LivenessInfo_RGB(pVideoRGBImageEngine, imageInfo, multiFaceInfo, out retCode_Liveness); //判断检测结果 if (retCode_Liveness == 0 && liveInfo.num > 0) { int isLive = MemoryUtil.PtrToStructure <int>(liveInfo.isLive); isLiveness = (isLive == 1) ? true : false; } if (imageInfo != null) { MemoryUtil.Free(imageInfo.imgData); } if (isLiveness) { //提取人脸特征 IntPtr feature = FaceUtil.ExtractFeature(pVideoRGBImageEngine, bitmap, maxFace); float similarity = 0f; //得到比对结果 int result = compareFeature(feature, out similarity); MemoryUtil.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> /// RGB摄像头Paint事件,同步RGB人脸框,对比人脸框后进行IR活体检测 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void irVideoSource_Paint(object sender, PaintEventArgs e) { if (isDoubleShot && irVideoSource.IsRunning) { //如果双摄,且IR摄像头工作,获取IR摄像头图片 Bitmap irBitmap = irVideoSource.GetCurrentVideoFrame(); if (irBitmap == null) { return; } //得到Rect MRECT rect = new MRECT(); lock (rectLock) { rect = allRect; } float irOffsetX = irVideoSource.Width * 1f / irBitmap.Width; float irOffsetY = irVideoSource.Height * 1f / irBitmap.Height; float offsetX = irVideoSource.Width * 1f / rgbVideoSource.Width; float offsetY = irVideoSource.Height * 1f / 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 = FaceUtil.DetectFace(pVideoIRImageEngine, irBitmap); if (irMultiFaceInfo.faceNum <= 0) { return; } //得到最大人脸 ASF_SingleFaceInfo irMaxFace = FaceUtil.GetMaxFace(irMultiFaceInfo); //得到Rect MRECT irRect = irMaxFace.faceRect; //判断RGB图片检测的人脸框与IR摄像头检测的人脸框偏移量是否在误差允许范围内 if (isInAllowErrorRange(rect.left * offsetX / irOffsetX, irRect.left) && isInAllowErrorRange(rect.right * offsetX / irOffsetX, irRect.right) && isInAllowErrorRange(rect.top * offsetY / irOffsetY, irRect.top) && isInAllowErrorRange(rect.bottom * offsetY / irOffsetY, irRect.bottom)) { int retCode_Liveness = -1; //将图片进行灰度转换,然后获取图片数据 ImageInfo irImageInfo = ImageUtil.ReadBMP_IR(irBitmap); if (irImageInfo == null) { return; } //IR活体检测 ASF_LivenessInfo liveInfo = FaceUtil.LivenessInfo_IR(pVideoIRImageEngine, irImageInfo, irMultiFaceInfo, out retCode_Liveness); //判断检测结果 if (retCode_Liveness == 0 && liveInfo.num > 0) { int isLive = MemoryUtil.PtrToStructure <int>(liveInfo.isLive); isLiveness = (isLive == 1) ? true : false; } if (irImageInfo != null) { MemoryUtil.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; })); } } }
static public Bitmap DrawString(this Bitmap bitmap, MRECT rect, string word) { return(DrawString(bitmap, new Point(rect.left, rect.bottom), word, defaultBrush, new Font("微软雅黑", 14))); }
private void Form_User_Load(object sender, EventArgs e) { //必须保证有可用摄像头 if (filterInfoCollection.Count == 0) { MessageBox.Show("未检测到摄像头,请确保已安装摄像头或驱动!"); Dispose(); Application.Exit(); } if (videoSource.IsRunning) { videoSource.SignalToStop(); videoSource.Hide(); } else { if (isCompare) { //比对结果清除 for (int i = 0; i < imagesFeatureList.Count; i++) { imageList.Items[i].Text = string.Format("{0}号", i); } isCompare = false; } videoSource.Show(); deviceVideo = new VideoCaptureDevice(filterInfoCollection[0].MonikerString); deviceVideo.VideoResolution = deviceVideo.VideoCapabilities[0]; videoSource.VideoSource = deviceVideo; videoSource.Start(); } lock (locker) { List <string> imagePathListTemp = new List <string>(); var numStart = imagePathList.Count; //查询数据库 DataMysql datasql = new DataMysql(); datasql.dataCon(); string cmdStr = "Select faceimg from user"; DataSet ds; ds = datasql.getDataSet(cmdStr); int j = 0; j = ds.Tables[0].Rows.Count; string[] fileNames = new string[j]; j = 0; foreach (DataRow Row in ds.Tables[0].Rows) { fileNames[j] = Convert.ToString(Row["faceimg"]); j++; } for (int i = 0; i < fileNames.Length; i++) { imagePathListTemp.Add(fileNames[i]); } //人脸检测以及提取人脸特征 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { //人脸检测和剪裁 for (int i = 0; i < imagePathListTemp.Count; i++) { WebRequest request = WebRequest.Create(imagePathListTemp[i]); WebResponse response = request.GetResponse(); Stream s = response.GetResponseStream(); byte[] data = new byte[1024]; int length = 0; MemoryStream ms = new MemoryStream(); while ((length = s.Read(data, 0, data.Length)) > 0) { ms.Write(data, 0, length); } ms.Seek(0, SeekOrigin.Begin); // pictureBox1.Image = Image.FromStream(ms); Image image = Image.FromStream(ms); if (image.Width % 4 != 0) { image = ImageUtil.ScaleImage(image, image.Width - (image.Width % 4), image.Height); } ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(pImageEngine, image); if (multiFaceInfo.faceNum > 0) { imagePathList.Add(imagePathListTemp[i]); MRECT rect = MemoryUtil.PtrToStructure <MRECT>(multiFaceInfo.faceRects); image = ImageUtil.CutImage(image, rect.left, rect.top, rect.right, rect.bottom); } else { continue; } } //提取人脸特征 for (int i = numStart; i < imagePathList.Count; i++) { WebRequest request = WebRequest.Create(imagePathListTemp[i]); WebResponse response = request.GetResponse(); Stream s = response.GetResponseStream(); byte[] data = new byte[1024]; int length = 0; MemoryStream ms = new MemoryStream(); while ((length = s.Read(data, 0, data.Length)) > 0) { ms.Write(data, 0, length); } ms.Seek(0, SeekOrigin.Begin); ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo(); IntPtr feature = FaceUtil.ExtractFeature(pImageEngine, Image.FromStream(ms), out singleFaceInfo); this.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); } })); } })); } LoadingHelper.ShowLoading("加载中请稍后。", this, o => { //这里写处理耗时的代码,代码处理完成则自动关闭该窗口 Thread.Sleep(4000); }); }
/// <summary> /// 人脸库图片选择按钮事件 /// </summary> private void ChooseMultiImg(object sender, EventArgs e) { lock (locker) { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Title = "选择图片"; openFileDialog.Filter = "图片文件|*.bmp;*.jpg;*.jpeg;*.png"; openFileDialog.Multiselect = true; openFileDialog.FileName = string.Empty; if (openFileDialog.ShowDialog() == DialogResult.OK)// 用户一点击“确定”按钮,那么对话框就关闭,重新回到主窗体,然后可以在主窗体中进行相应的处理,比如把数据写入数据库等 { List <string> imagePathListTemp = new List <string>(); var numStart = imagePathList.Count; int isGoodImage = 0; //保存图片路径并显示 // TODO 这边将从数据库获取人脸地址 string[] fileNames = openFileDialog.FileNames; Console.WriteLine(fileNames.ToString()); for (int i = 0; i < fileNames.Length; i++) { imagePathListTemp.Add(fileNames[i]);// 将数据库查处的地址列表存入temp } //人脸检测以及提取人脸特征 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { //禁止点击按钮 Invoke(new Action(delegate { chooseMultiImgBtn.Enabled = false; matchBtn.Enabled = false; btnClearFaceList.Enabled = false; chooseImgBtn.Enabled = false; btnStartVideo.Enabled = false; })); //人脸检测和剪裁 for (int i = 0; i < imagePathListTemp.Count; i++) { Image image = Image.FromFile(imagePathListTemp[i]); if (image.Width % 4 != 0) { image = ImageUtil.ScaleImage(image, image.Width - (image.Width % 4), image.Height); } ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(pImageEngine, image); if (multiFaceInfo.faceNum > 0) { imagePathList.Add(imagePathListTemp[i]); MRECT rect = MemoryUtil.PtrToStructure <MRECT>(multiFaceInfo.faceRects); image = ImageUtil.CutImage(image, rect.left, rect.top, rect.right, rect.bottom); } else { continue; } this.Invoke(new Action(delegate { if (image == null) { image = Image.FromFile(imagePathListTemp[i]); } imageLists.Images.Add(imagePathListTemp[i], image); imageList.Items.Add((numStart + isGoodImage) + "号", imagePathListTemp[i]); isGoodImage += 1; image = null; })); } //提取人脸特征 for (int i = numStart; i < imagePathList.Count; i++) { ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo(); // TODO 将feature存入数据库,byte[],这边已经在FaceUtils中处理了 IntPtr feature = FaceUtil.ExtractFeature(pImageEngine, Image.FromFile(imagePathList[i]), out singleFaceInfo);// 人脸特征 this.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); // TODO 数据库中查询出feature /* * IntPtr pFeatureItemFromDB; * MysqlUtils mysqlUtils = new MysqlUtils(); * List<byte[]> featureListFromDB = mysqlUtils.SelectUserFaceByFeature(); * foreach (byte[] featureItemFromDB in featureListFromDB) * { * pFeatureItemFromDB = TabConvert.BytesToIntptr(featureItemFromDB); * imagesFeatureList.Add(pFeatureItemFromDB); * } */ } })); } //允许点击按钮 Invoke(new Action(delegate { chooseMultiImgBtn.Enabled = true; btnClearFaceList.Enabled = true; btnStartVideo.Enabled = true; if (btnStartVideo.Text == "启用摄像头") { chooseImgBtn.Enabled = true; matchBtn.Enabled = true; } else { chooseImgBtn.Enabled = false; matchBtn.Enabled = false; } })); })); } } }
static public Bitmap DrawRect(this Bitmap bitmap, MRECT rect) { return(DrawRect(bitmap, rect, defaultColor, bitmap.Height / 300 + bitmap.Width / 300)); }
static public Image DrawString(this Image image, MRECT rect, string word) { return(DrawString(image, new Point(rect.left, rect.bottom), word, defaultBrush, new Font("微软雅黑", 14))); }
static public Image DrawRect(this Image image, MRECT rect) { return(DrawRect(image, rect, defaultColor, image.Height / 300 + image.Width / 300)); }
/// <summary> /// 图像显示到窗体上,得到每一帧图像,并进行处理(画框) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void videoSource_Paint(object sender, PaintEventArgs e) { if (videoSource.IsRunning)// 摄像头运行中 { //得到当前摄像头下的图片 Bitmap bitmap = videoSource.GetCurrentVideoFrame(); if (bitmap == null) { return; } Graphics g = e.Graphics; float offsetX = videoSource.Width * 1f / bitmap.Width; float offsetY = videoSource.Height * 1f / bitmap.Height; //检测人脸,得到Rect框(方框) ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(pVideoEngine, bitmap); //得到最大人脸 ASF_SingleFaceInfo maxFace = FaceUtil.GetMaxFace(multiFaceInfo); //得到Rect MRECT rect = maxFace.faceRect; 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(pen, x, y, width, height); // 调整摄像头视频框 if (rect.left.ToString() == "0") { this.videoSource.Location = new System.Drawing.Point(this.Width - 1, this.Height - 1); } else { int xVideoSource = (int)(0.5 * (this.Width - this.videoSource.Width)); int yVideoSource = (int)(0.5 * (this.Height - this.videoSource.Height)); this.videoSource.Location = new System.Drawing.Point(xVideoSource, yVideoSource); } // this.logBox.AppendText(rect.left.ToString() + "\n"); // this.videoSource.Show();// 能画框的时候显示摄像头视频框 if (trackUnit.message != "" && x > 0 && y > 0) { //将上一帧检测结果显示到页面上 g.DrawString(trackUnit.message, font, brush, x, y + 5); } //保证只检测一帧,防止页面卡顿以及出现其他内存被占用情况 if (isLock == false) { isLock = true; //异步处理提取特征值和比对,不然页面会比较卡 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { if (rect.left != 0 && rect.right != 0 && rect.top != 0 && rect.bottom != 0) { try { //提取人脸特征 TODO 这是当前摄像头下的人脸的特征值 IntPtr videoFaceFeature = FaceUtil.ExtractFeature(pVideoImageEngine, bitmap, maxFace); float similarity = 0f; //得到比对结果 star TODO 这边compareFeature中 // TODO 数据库中查询出feature MysqlUtils mysqlUtils = new MysqlUtils(); List <byte[]> featureListFromDB = mysqlUtils.SelectUserFaceByFeature();// 数据库查询 var v = 0; for (int i = 0; i < featureListFromDB.Count; i++) { //pFeatureItemFromDB = TabConvert.BytesToIntptr(featureListFromDB[i]); //GCHandle hObject = GCHandle.Alloc(featureListFromDB[i], GCHandleType.Pinned); //pFeatureItemFromDB = hObject.AddrOfPinnedObject(); ASF_FaceFeature localFeature = new ASF_FaceFeature(); localFeature.feature = MemoryUtil.Malloc(featureListFromDB[i].Length); // 申请本地人脸特征指针 MemoryUtil.Copy(featureListFromDB[i], 0, localFeature.feature, featureListFromDB[i].Length); // source, startIndex, destination, length localFeature.featureSize = featureListFromDB[i].Length; // 设置本地特征值长度 IntPtr pLocalFeature = MemoryUtil.Malloc(MemoryUtil.SizeOf <ASF_FaceFeature>()); // 申请本地特征值指针空间 MemoryUtil.StructureToPtr(localFeature, pLocalFeature); // T t,IntPtr ptr /* * IntPtr pFeatureItemFromDB = MemoryUtil.Malloc(MemoryUtil.SizeOf<ASF_FaceFeature>()); * v++; * Marshal.StructureToPtr(featureListFromDB[i], pFeatureItemFromDB, false); * Marshal.FreeHGlobal(pFeatureItemFromDB); */ imagesFeatureList.Add(pLocalFeature); } int result = compareFeatureFromDB(videoFaceFeature, out similarity); if (result > -1) { // TODO //将比对结果放到显示消息中,用于最新显示 trackUnit.message = string.Format("你好,匹配到 {0}号,相似度是 {1}", result, similarity); labelLoginUserName.Text = result.ToString(); Console.WriteLine(result.ToString() + ":" + similarity.ToString() + "\n"); // TODO // 相似度不足0.8,窗口正常显示 if (similarity < 0.8) { this.Visible = true; this.WindowState = FormWindowState.Normal; } else// 相似度超过80,自动缩小至系统托盘 { this.Hide(); this.notifyIcon.Visible = true; } // TODO 隔段时间打开托盘 Thread.Sleep(5000);// TODO 设置多长时间再次验证人脸,这边设置了2秒 this.Visible = true; this.WindowState = FormWindowState.Normal; } else { //重置显示消息 trackUnit.message = ""; } } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { isLock = false; } } isLock = false; })); } } }
/// <summary> /// 为注册会员检测人脸 /// </summary> /// <param name="transImageInfo"></param> /// <returns></returns> public MError DeteceForMemberEnroll( out string errMsg, out IntPtr ptrImgFeature, out ASF_SingleFaceInfo singleFaceInfo, out int face3DStatus, out int faceNum, out string faceDesc, ref Image srcImage, int imageContainerWidth, int imageContainerHeight) { faceNum = 0; face3DStatus = -1; faceDesc = string.Empty; errMsg = string.Empty; ptrImgFeature = IntPtr.Zero; StringBuilder sbErrMsg = new StringBuilder(); var retCode = MError.MERR_UNKNOWN; int retAge = -1; int retGender = -1; int ret3DAngle = -1; singleFaceInfo = new ASF_SingleFaceInfo(); try { if (ptrImageEngine == IntPtr.Zero) { retCode = InitialEngineForImage(); } else { retCode = MError.MOK; } if (retCode == MError.MOK) { //调整图像宽度,需要宽度为4的倍数 if (srcImage.Width % 4 != 0) { //srcImage = ImageHelper.ScaleImage(srcImage, picImageCompare.Width, picImageCompare.Height); srcImage = ImageHelper.ScaleImage(srcImage, srcImage.Width - (srcImage.Width % 4), srcImage.Height); } //调整图片数据,非常重要 ImageInfo transImageInfo = ImageHelper.ReadBMP(srcImage); //人脸检测 ASF_MultiFaceInfo multiFaceInfo = FaceProcessHelper.DetectFace(ptrImageEngine, transImageInfo); faceNum = multiFaceInfo.faceNum; if (multiFaceInfo.faceNum != 1) { retCode = MError.MERR_ASF_EX_INVALID_FACE_INFO; sbErrMsg.Append(multiFaceInfo.faceNum > 1 ? "检测到多张人脸" : "未检测到人脸"); } else { ASF_AgeInfo ageInfo = FaceProcessHelper.AgeEstimation(ptrImageEngine, transImageInfo, multiFaceInfo, out retAge); ASF_GenderInfo genderInfo = FaceProcessHelper.GenderEstimation(ptrImageEngine, transImageInfo, multiFaceInfo, out retGender); ASF_Face3DAngle face3DAngleInfo = FaceProcessHelper.Face3DAngleDetection(ptrImageEngine, transImageInfo, multiFaceInfo, out ret3DAngle); #region 标记出检测到的人脸 MRECT temp = new MRECT(); int ageTemp = 0; int genderTemp = 0; int rectTemp = 0; //标记出检测到的人脸 for (int i = 0; i < multiFaceInfo.faceNum; i++) { MRECT rect = MemoryHelper.PtrToStructure <MRECT>(multiFaceInfo.faceRects + MemoryHelper.SizeOf <MRECT>() * i); int orient = MemoryHelper.PtrToStructure <int>(multiFaceInfo.faceOrients + MemoryHelper.SizeOf <int>() * i); int age = 0; if (retAge != 0) { sbErrMsg.AppendLine($"年龄检测失败,返回{retAge}!"); } else { age = MemoryHelper.PtrToStructure <int>(ageInfo.ageArray + MemoryHelper.SizeOf <int>() * i); } int gender = -1; if (retGender != 0) { sbErrMsg.AppendLine($"性别检测失败,返回{retGender}!"); } else { gender = MemoryHelper.PtrToStructure <int>(genderInfo.genderArray + MemoryHelper.SizeOf <int>() * i); } //int face3DStatus = -1; float roll = 0f; float pitch = 0f; float yaw = 0f; if (ret3DAngle != 0) { sbErrMsg.AppendLine($"3DAngle检测失败,返回{ret3DAngle}!"); } else { //角度状态 非0表示人脸不可信 face3DStatus = MemoryHelper.PtrToStructure <int>(face3DAngleInfo.status + MemoryHelper.SizeOf <int>() * i); //roll为侧倾角,pitch为俯仰角,yaw为偏航角 roll = MemoryHelper.PtrToStructure <float>(face3DAngleInfo.roll + MemoryHelper.SizeOf <float>() * i); pitch = MemoryHelper.PtrToStructure <float>(face3DAngleInfo.pitch + MemoryHelper.SizeOf <float>() * i); yaw = MemoryHelper.PtrToStructure <float>(face3DAngleInfo.yaw + MemoryHelper.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; } //srcImage = ImageHelper.MarkRectAndString(srcImage, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, age, gender); faceDesc = $"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} - 人脸坐标:[left:{rect.left},top:{rect.top},right:{rect.right},bottom:{rect.bottom},orient:{orient},roll:{roll},pitch:{pitch},yaw:{yaw},status:{face3DStatus}] Age:{age} Gender:{(gender >= 0 ? gender.ToString() : "")}\n"; } //提取人脸特征 ptrImgFeature = FaceProcessHelper.ExtractFeature(ptrImageEngine, srcImage, out singleFaceInfo); float scaleRate = ImageHelper.GetWidthAndHeight(srcImage.Width, srcImage.Height, imageContainerWidth, imageContainerHeight); srcImage = ImageHelper.ScaleImage(srcImage, imageContainerWidth, imageContainerHeight); srcImage = ImageHelper.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, imageContainerWidth); #endregion } MemoryHelper.Free(transImageInfo.imgData); } errMsg = sbErrMsg.ToString(); } catch (Exception ex) { Afw.Core.Helper.SimplifiedLogHelper.WriteIntoSystemLog(nameof(Afw.WinForm.EngineContext), $"DeteceForMemberEnroll Exception:{ex.ToString()}"); } return(retCode); }
/// <summary> /// 人脸检测 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnFaceDetect_Click(object sender, EventArgs e) { Bitmap bitmap = (Bitmap)this.pic1.Image; if (bitmap == null) { return; } try { List <string> lstMatchFiles = new List <string>(); //检测图片内的人脸数据 var facers = faceDetection.DetectFace(bitmap); if (facers.nFace > 0) { int sizeRect = Marshal.SizeOf(typeof(MRECT)); //范围size int sizeOrient = Marshal.SizeOf(typeof(int)); //角度size List <MRECT> rects1 = new List <MRECT>(); List <MRECT> rects2 = new List <MRECT>(); for (int i = 0; i < facers.nFace; i++) { MRECT rect = (MRECT)Marshal.PtrToStructure(facers.rcFace + sizeRect * i, typeof(MRECT)); int orient = (int)Marshal.PtrToStructure(facers.lfaceOrient + sizeOrient * i, typeof(int)); //特征码提取 byte[] featureContent = this.RecognizeFace(bitmap, rect, orient); var result = IsMatchFeature(featureContent); //已经被识别过 if (result.Item1) { rects2.Add(rect); lstMatchFiles.Add(result.Item2); } else { rects1.Add(rect); string fileName = Guid.NewGuid().ToString(); //保存脸部区域到文件 Image image = CutFace(bitmap, rect); image.Save(FaceLibraryPath + fileName + ".jpg", ImageFormat.Jpeg); image.Dispose(); //保存特征码到.dat File.WriteAllBytes(FaceLibraryPath + fileName + ".rfa", featureContent); //添加特征码到内存 this.faceFeatures.Add(new FaceFeature() { FileName = fileName, Feature = featureContent, }); } } this.pic2.Image = DrawRectToImage(bitmap, rects1, rects2); } //移除现存的控件 for (int i = this.panel.Controls.Count - 1; i >= 0; i--) { PictureBox pictureBox = this.panel.Controls[i] as PictureBox; pictureBox.Image.Dispose(); pictureBox.Image = null; this.panel.Controls.RemoveAt(i); } //显示特征码存在的图片到panel foreach (var fileName in lstMatchFiles) { PictureBox pictureBox = new PictureBox(); pictureBox.SizeMode = PictureBoxSizeMode.StretchImage; pictureBox.Image = new Bitmap(FaceLibraryPath + fileName + ".jpg"); pictureBox.Size = new Size(this.panel.Height, this.panel.Height); this.panel.Controls.Add(pictureBox); } } catch (Exception ex) { MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } }