/// <summary> /// 比对函数,将每一帧抓拍的照片和身份证照片进行比对 /// </summary> /// <param name="bitmap"></param> /// <param name="e"></param> /// <returns></returns> private bool CompareImgWithIDImg(Bitmap bitmap, PaintEventArgs e) { recTimes--; if (bitmap == null) { return(false); } 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); //将上一帧检测结果显示到页面上 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 = CompareTwoFeatures(feature, idCardHelper.idInfo.imageFeature); this.similarity.Text = ("相似度为: " + similarity.ToString("P"));; //显示在界面上 this.similarity.ForeColor = similarity > threshold ? Color.Green : Color.Red; //得到比对结果 int result = (CompareTwoFeatures(feature, idCardHelper.idInfo.imageFeature) >= threshold) ? 1 : -1; if (result > -1) { bool isLiveness = false; ImageInfo imageInfo = ImageUtil.ReadBMP(bitmap); //调整图片数据 if (imageInfo == null) { return; } int retCode_Liveness = -1; //RGB活体检测 ASF_LivenessInfo liveInfo = FaceUtil.LivenessInfo_RGB(pVideoImageEngine, 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 (isLiveness)//活体检测成功 { //存放当前人脸识别的相似度 idCardHelper.idInfo.similarity = similarity; //记录下当前的摄像头的人脸抓拍照 idCardHelper.idInfo.capImage = bitmap; //验证通过则不再是当前身份证,等待下一次身份证 idCardHelper.idInfo.isRight = false; //在子线程中输出信息到messageBox AppendText p = new AppendText(AddTextToMessBox); lbl_msg.Invoke(p, "人脸验证成功,请取卡...\n"); pass = 1; idCardHelper.idInfo.isPass = 1; //将比对结果放到显示消息中,用于最新显示 trackUnit.message = string.Format("通过验证,相似度为{0}", similarity); FileHelper.DeleteFile(m_strPath); //删除验证过的本地文件 Thread.Sleep(1000); //延时1秒 this.IDPbox.Image = defaultImage; //照片恢复默认照片 trackUnit.message = ""; //人脸识别框文字置空 setFormResultValue(true); } else { pass = 0;//标志未通过 trackUnit.message = "未通过,系统识别为照片"; AppendText p = new AppendText(AddTextToMessBox); lbl_msg.Invoke(p, "抱歉,您未通过人脸验证...\n"); FileHelper.DeleteFile(m_strPath);//删除验证过的本地文件 } } else { pass = 0;//标志未通过 trackUnit.message = "未通过人脸验证"; AppendText p = new AppendText(AddTextToMessBox); lbl_msg.Invoke(p, "抱歉,您未通过人脸验证...\n"); FileHelper.DeleteFile(m_strPath);//删除验证过的本地文件 } } catch (Exception ex) { Console.WriteLine(ex.Message); FileHelper.DeleteFile(m_strPath);//删除验证过的本地文件 } finally { isLock = false; } } isLock = false; })); } return(false); }
//比对函数 //将每一帧抓拍的照片和身份证照片进行比对 private bool CompareImgWithIDImg(Bitmap bitmap, PaintEventArgs e) { recTimes--; if (bitmap == null) { return(false); } 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 = CompareTwoFeatures(feature, idInfo.imageFeature); messageBox.AppendText("相似度为: " + similarity); this.similarityText.Text = similarity.ToString(); //显示在界面上 //得到比对结果 int result = (CompareTwoFeatures(feature, idInfo.imageFeature) >= threshold) ? 1 : -1; if (result > -1) { //存放当前人脸识别的相似度 idInfo.similarity = similarity; //记录下当前的摄像头的人脸抓拍照 idInfo.capImage = bitmap; //标志人脸比对验证通过 faceState = true; //验证通过则不再是当前身份证,等待下一次身份证 idInfo.isRight = false; //在子线程中输出信息到messageBox AppendText p = new AppendText(AddTextToMessBox); messageBox.Invoke(p, "人脸验证成功,请通过闸机...\n"); //关闭读卡线程 //workThread.Suspend(); //最终通过闸机 pass = 1; //以人脸识别的方式通过闸机 idInfo.isPass = 1; /* *通信部分,将内存中的数据存放到数据库中 */ //将身份证数据传入到服务器上 sendMessageToServer(); //将比对结果放到显示消息中,用于最新显示 trackUnit.message = string.Format("通过验证,相似度为{0}", similarity); DeleteFile(); //删除验证过的本地文件 //延时3秒 Thread.Sleep(1000); //照片恢复默认照片 this.IDPbox.Image = defaultImage; } else { pass = 0; //重置显示消息 trackUnit.message = "未通过人脸验证"; AppendText p = new AppendText(AddTextToMessBox); messageBox.Invoke(p, "抱歉,您未通过人脸验证...\n"); DeleteFile(); //删除验证过的本地文件 } } catch (Exception ex) { Console.WriteLine(ex.Message); DeleteFile(); //删除验证过的本地文件 } finally { isLock = false; } } isLock = false; })); } return(false); }
/// <summary> /// 提取人脸特征 /// </summary> /// <param name="pEngine">引擎Handle</param> /// <param name="imageInfo">图像数据</param> /// <param name="multiFaceInfo">人脸检测结果</param> /// <returns>保存人脸特征结构体指针</returns> public static IntPtr ExtractFeature(IntPtr pEngine, ImageInfo imageInfo, ASF_MultiFaceInfo multiFaceInfo, out ASF_SingleFaceInfo singleFaceInfo) { singleFaceInfo = new ASF_SingleFaceInfo(); if (multiFaceInfo.faceRects == null) { ASF_FaceFeature emptyFeature = new ASF_FaceFeature(); IntPtr pEmptyFeature = MemoryUtil.Malloc(MemoryUtil.SizeOf <ASF_FaceFeature>()); MemoryUtil.StructureToPtr(emptyFeature, pEmptyFeature); return(pEmptyFeature); } singleFaceInfo.faceRect = MemoryUtil.PtrToStructure <MRECT>(multiFaceInfo.faceRects); singleFaceInfo.faceOrient = MemoryUtil.PtrToStructure <int>(multiFaceInfo.faceOrients); IntPtr pSingleFaceInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf <ASF_SingleFaceInfo>()); MemoryUtil.StructureToPtr(singleFaceInfo, pSingleFaceInfo); IntPtr pFaceFeature = MemoryUtil.Malloc(MemoryUtil.SizeOf <ASF_FaceFeature>()); int retCode = ASFFunctions.ASFFaceFeatureExtract(pEngine, imageInfo.width, imageInfo.height, imageInfo.format, imageInfo.imgData, pSingleFaceInfo, pFaceFeature); Console.WriteLine("FR Extract Feature result:" + retCode); if (retCode != 0) { //释放指针 MemoryUtil.Free(pSingleFaceInfo); MemoryUtil.Free(pFaceFeature); ASF_FaceFeature emptyFeature = new ASF_FaceFeature(); IntPtr pEmptyFeature = MemoryUtil.Malloc(MemoryUtil.SizeOf <ASF_FaceFeature>()); MemoryUtil.StructureToPtr(emptyFeature, pEmptyFeature); return(pEmptyFeature); } //人脸特征feature过滤 ASF_FaceFeature faceFeature = MemoryUtil.PtrToStructure <ASF_FaceFeature>(pFaceFeature); byte[] feature = new byte[faceFeature.featureSize]; MemoryUtil.Copy(faceFeature.feature, feature, 0, faceFeature.featureSize); ASF_FaceFeature localFeature = new ASF_FaceFeature(); localFeature.feature = MemoryUtil.Malloc(feature.Length); MemoryUtil.Copy(feature, 0, localFeature.feature, feature.Length); localFeature.featureSize = feature.Length; IntPtr pLocalFeature = MemoryUtil.Malloc(MemoryUtil.SizeOf <ASF_FaceFeature>()); MemoryUtil.StructureToPtr(localFeature, pLocalFeature); //释放指针 MemoryUtil.Free(pSingleFaceInfo); MemoryUtil.Free(pFaceFeature); return(pLocalFeature); }
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; })); })); } }
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; imageList.Refresh(); 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++) { //图片格式判断 if (checkImage(fileNames[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; btnStartVideo.Enabled = false; })); //人脸检测和剪裁 for (int i = 0; i < imagePathListTemp.Count; i++) { Image image = ImageUtil.readFromFile(imagePathListTemp[i]); if (image == null) { continue; } if (image.Width > 1536 || image.Height > 1536) { image = ImageUtil.ScaleImage(image, 1536, 1536); } if (image == null) { continue; } 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 { if (image != null) { image.Dispose(); } continue; } //显示人脸 this.Invoke(new Action(delegate { if (image == null) { image = ImageUtil.readFromFile(imagePathListTemp[i]); if (image.Width > 1536 || image.Height > 1536) { image = ImageUtil.ScaleImage(image, 1536, 1536); } } imageLists.Images.Add(imagePathListTemp[i], image); imageList.Items.Add((numStart + isGoodImage) + "号", imagePathListTemp[i]); imageList.Refresh(); isGoodImage += 1; if (image != null) { image.Dispose(); } })); } //提取人脸特征 for (int i = numStart; i < imagePathList.Count; i++) { ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo(); Image image = ImageUtil.readFromFile(imagePathList[i]); if (image == null) { continue; } IntPtr feature = FaceUtil.ExtractFeature(pImageEngine, image, 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); } })); if (image != null) { image.Dispose(); } } //允许点击按钮 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; } })); })); } } }
/// <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; })); } } }
/// <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(); }
private bool getFaceFeature(ref t_face t_Face) { Image image = ImageUtil.readFromFile(t_Face.image_path); bool result = false; //压缩图片的长宽为临界大小1536 if (image.Width > 1536 || image.Height > 1536) { image = ImageUtil.ScaleImage(image, 1536, 1536); } //裁剪,因为虹软要求图片宽度要是4的整数倍,所以要检测一下,如果不是就把宽缩小为4的倍数 if (image.Width % 4 != 0) { image = ImageUtil.ScaleImage(image, image.Width - (image.Width % 4), image.Height); } //把image对象转化为位图的对象 Bitmap bitmap = new Bitmap(image); //使用人脸检测引擎去检测人脸,返回的lis列表里存了人脸的位置 List <FaceInfo> faceInfos = faceImageRecognizer.ScanFaces(bitmap); //判断一张照片是否就一个人脸 if (faceInfos.Count == 1) { //把第一个人脸的信息传入人脸识别引擎中,提取出特征的结构体指引到faceinfo中,返回是否成功 int num = faceImageRecognizer.ScanFaceFeature(bitmap, faceInfos[0]); if (num == 0) { ASF_SingleFaceInfo singleFaceInfo = faceInfos[0].singleFaceInfo; //t_face就是实体类映射对象 t_Face.face_feature_length = faceInfos[0].faceFeature.featureSize; t_Face.face_feature = new byte[(int)t_Face.face_feature_length]; //把结构体里的特征纯copy到t_face中 MemoryUtil.Copy(faceInfos[0].faceFeature.feature, t_Face.face_feature, 0, faceInfos[0].faceFeature.featureSize); result = true; LoggerService.logger.Info(string.Format("已提取人脸特征值,[left:{0},right:{1},top:{2},bottom:{3},orient:{4}]", singleFaceInfo.faceRect.left, singleFaceInfo.faceRect.right, singleFaceInfo.faceRect.top, singleFaceInfo.faceRect.bottom, singleFaceInfo.faceOrient)); string tempImagePath = t_Face.image_path; string id = t_Face.studnet_id; //裁剪出头像,依次展示在界面,多线程操作,解决可能异常越界问题 Invoke(new Action(() => { image = ImageUtil.CutImage(image, singleFaceInfo.faceRect.left, singleFaceInfo.faceRect.top, singleFaceInfo.faceRect.right, singleFaceInfo.faceRect.bottom); imageLists.Images.Add(tempImagePath, image); ImageListView.Items.Add(id, tempImagePath); listViewFaceDetal.Items.Add(new ListViewItem(new string[] { "等待", id, "" })); listViewFaceDetal.Refresh(); ImageListView.Refresh(); })); } else { LoggerService.logger.Error("提取人脸特征失败!"); } faceInfos[0].Dispose(); faceInfos[0] = null; faceInfos.Clear(); } image.Dispose(); bitmap.Dispose(); return(result); }
/// <summary> /// 提取人脸特征 /// </summary> /// <param name="pEngine">引擎Handle</param> /// <param name="imageInfo">图像数据</param> /// <param name="multiFaceInfo">人脸检测结果</param> /// <returns>保存人脸特征结构体指针</returns> public static IntPtr ExtractFeature(IntPtr pEngine, ImageInfo imageInfo, ASF_MultiFaceInfo multiFaceInfo, out ASF_SingleFaceInfo singleFaceInfo) { singleFaceInfo = new ASF_SingleFaceInfo(); singleFaceInfo.faceRect = MemoryUtil.PtrToStructure <MRECT>(multiFaceInfo.faceRects); singleFaceInfo.faceOrient = MemoryUtil.PtrToStructure <int>(multiFaceInfo.faceOrients); IntPtr pSingleFaceInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf <ASF_SingleFaceInfo>()); // 申请内存,单人脸检测结构体 MemoryUtil.StructureToPtr(singleFaceInfo, pSingleFaceInfo); // 结构体进入内存 IntPtr pFaceFeature = MemoryUtil.Malloc(MemoryUtil.SizeOf <ASF_FaceFeature>()); // 申请内存,人脸特征结构体 int retCode = ASFFunctions.ASFFaceFeatureExtract(pEngine, imageInfo.width, imageInfo.height, imageInfo.format, imageInfo.imgData, pSingleFaceInfo, pFaceFeature); // 单人脸特征提取 Console.WriteLine("FR Extract Feature result:" + retCode); // 直接打印结果 if (retCode != 0) // 返回结果非0,即匹配到人脸,释放指针 { // 释放指针 MemoryUtil.Free(pSingleFaceInfo); // 释放单人脸检测结构体指针 MemoryUtil.Free(pFaceFeature); // 释放人脸特征结构体指针 ASF_FaceFeature emptyFeature = new ASF_FaceFeature(); // 声明空人脸特征结构体 IntPtr pEmptyFeature = MemoryUtil.Malloc(MemoryUtil.SizeOf <ASF_FaceFeature>()); // 声明空人脸特征结构体指针 MemoryUtil.StructureToPtr(emptyFeature, pEmptyFeature); // 将数据从托管对象封送到非托管内存块 return(pEmptyFeature); // 匹配成功,返回空的人脸特征结构体指针 } // 人脸特征feature过滤 ASF_FaceFeature faceFeature = MemoryUtil.PtrToStructure <ASF_FaceFeature>(pFaceFeature);// 将ptr托管的内存转化为结构体对象 int cc = faceFeature.featureSize; var ff = faceFeature.feature; byte[] feature = new byte[faceFeature.featureSize]; MemoryUtil.Copy(faceFeature.feature, feature, 0, faceFeature.featureSize);// source, destination, startIndex, length ASF_FaceFeature localFeature = new ASF_FaceFeature(); localFeature.feature = MemoryUtil.Malloc(feature.Length); // 申请本地人脸特征指针 MemoryUtil.Copy(feature, 0, localFeature.feature, feature.Length); // source, startIndex, destination, length localFeature.featureSize = feature.Length; // 设置本地特征值长度 IntPtr pLocalFeature = MemoryUtil.Malloc(MemoryUtil.SizeOf <ASF_FaceFeature>()); // 申请本地特征值指针空间 MemoryUtil.StructureToPtr(localFeature, pLocalFeature); // T t,IntPtr ptr // 释放指针 MemoryUtil.Free(pSingleFaceInfo); MemoryUtil.Free(pFaceFeature); /******** 特征值feature存入数据库 start **********/ Users users = new Users(); users.Id = SidUtils.sid(); users.Feature = feature; MysqlUtils mysqlUtils = new MysqlUtils(); mysqlUtils.InsertUserFaceFeature(users); /******** 特征值feature存入数据库 end **********/ return(pLocalFeature);// 返回人脸特征 }
public static extern MResult ASFFaceFeatureExtractEx(IntPtr hEngine, ASVLOFFSCREEN imgData, ASF_SingleFaceInfo faceInfo, out ASF_FaceFeature feature, int threadNum = 1);
public static extern MResult ASFFaceFeatureExtract(IntPtr hEngine, int width, int height, int format, IntPtr imgData, ASF_SingleFaceInfo faceInfo, out ASF_FaceFeature feature, int threadNum = 1);
/// <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; ASF_MultiFaceInfo multiFaceInfoIr = default(ASF_MultiFaceInfo); //检测人脸,得到Rect框 ASF_MultiFaceInfo multiFaceInfo = engineContext.DetectFace(bitmap); if (multiFaceInfo.Equals(default(ASF_MultiFaceInfo))) { return; } //得到最大人脸 ASF_SingleFaceInfo maxFace = FaceProcessHelper.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) { //g.DrawRectangle(pen, x, y, width, height); //if (trackUnit.message != "" && x > 0 && y > 0) //{ // //将上一帧检测结果显示到页面上 // g.DrawString(trackUnit.message, font, brush, x, y + 5); //} isLock = true; //异步处理提取特征值和比对,不然页面会比较卡 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { if (rect.left != 0 && rect.right != 0 && rect.top != 0 && rect.bottom != 0) { try { var liveness = 1; var livenessIR = -1; if (this.chbLiveness.Checked) { liveness = -1; var livenessInfo = engineContext.GetLivenessScore(bitmap, maxFace); try { liveness = MemoryHelper.PtrToStructure <int>(livenessInfo.isLive); } catch (Exception ex) { liveness = -1; this.Invoke(new Action(delegate { //WinMessageHelper.SendMessage(this.Handle, UserMessage.WM_MESSAGE, IntPtr.Zero, $"liveness => {ex.Message}"); Afw.Core.Helper.SimplifiedLogHelper.WriteIntoSystemLog(nameof(FaceForm), $"videoSource_Paint livenessInfo exception=> {ex.ToString()}"); })); } } if (currentIrImage != null) { //检测人脸,得到Rect框 multiFaceInfoIr = engineContext.DetectFaceIR(currentIrImage); if (multiFaceInfoIr.faceNum > 0) { //得到最大人脸 ASF_SingleFaceInfo maxFaceIR = FaceProcessHelper.GetMaxFace(multiFaceInfoIr); var livenessInfoIR = engineContext.GetLivenessScoreIR(currentIrImage, maxFace); try { livenessIR = MemoryHelper.PtrToStructure <int>(livenessInfoIR.isLive); } catch (Exception ex) { livenessIR = -1; this.Invoke(new Action(delegate { //WinMessageHelper.SendMessage(this.Handle, UserMessage.WM_MESSAGE, IntPtr.Zero, $"liveness IR => {ex.Message}"); Afw.Core.Helper.SimplifiedLogHelper.WriteIntoSystemLog(nameof(FaceForm), $"videoSource_Paint livenessIRInfo exception=> {ex.ToString()}"); })); } } else { livenessIR = -1; } } else { livenessIR = engineContext.IrCameraIdx >= 0 ? -1 : 1; } if (liveness == 1 && livenessIR == 1) { //提取人脸特征 IntPtr feature = engineContext.ExtractFeature(bitmap, maxFace); float similarity = 0f; if (feature == IntPtr.Zero) { return; } //得到比对结果 int result = CompareFeature(feature, out similarity); if (result > -1) { //将比对结果放到显示消息中,用于最新显示 trackUnit.message = $" 员工Id{result} 相似度{similarity}"; this.Invoke(new Action(delegate { var member = iFaceDataRepository.GetById(result); WinMessageHelper.SendMessage(this.Handle, UserMessage.WM_MESSAGE, IntPtr.Zero, $"人脸比对成功,【姓名:{member.Name},雇员号:{member.EmployeeNo}】"); if (this.chbAutoCloseVideo.Checked) { ButtonEnableForImage(); btnStartVideo.Text = "开启摄像头"; engineContext.StopVideoCapture(); this.rdbThresholdHigh.Enabled = true; this.rdbThresholdLow.Enabled = true; this.rdbThresholdMid.Enabled = true; this.dgvFace.Enabled = true; MessageBox.Show($"人脸比对成功,【姓名:{member.Name},雇员号:{member.EmployeeNo}】"); } })); } else { //重置显示消息 trackUnit.message = ""; } MemoryHelper.Free(feature); } else { trackUnit.message = ""; } } catch (Exception ex) { this.Invoke(new Action(delegate { WinMessageHelper.SendMessage(this.Handle, UserMessage.WM_MESSAGE, IntPtr.Zero, ex.Message); })); } finally { isLock = false; } } isLock = false; if (currentIrImage != null) { currentIrImage = null; } })); } } GC.Collect(); }
private void btnSelectImageToRegister_Click(object sender, EventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Title = "Select"; openFileDialog.Filter = "Image File|*.bmp;*.jpg;*.jpeg;*.png"; //openFileDialog.Multiselect = true; openFileDialog.FileName = string.Empty; if (openFileDialog.ShowDialog() == DialogResult.OK) { var numStart = imagePathList.Count; string fileName = openFileDialog.FileName; if (!checkImage(fileName)) { return; } pictureBoxSelected.ImageLocation = fileName; currentLeftFeature = IntPtr.Zero; //人脸检测以及提取人脸特征 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { Image image = ImageUtil.readFromFile(fileName); if (image == null) { return; } if (image.Width > 1536 || image.Height > 1536) { image = ImageUtil.ScaleImage(image, 1536, 1536); } if (image == null) { return; } 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); } else { if (image != null) { image.Dispose(); } return; } //提取人脸特征 ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo(); Image image1 = ImageUtil.readFromFile(fileName); if (image1 == null) { return; } currentLeftFeature = FaceUtil.ExtractFeature(pImageEngine, image1, out singleFaceInfo); this.Invoke(new Action(delegate { if (singleFaceInfo.faceRect.left == 0 && singleFaceInfo.faceRect.right == 0) { AppendText(string.Format("No face detected\r\r\n")); } else { AppendText(string.Format("Face landmark detected,[left:{0},right:{1},top:{2},bottom:{3},orient:{4}]\r\r\n", singleFaceInfo.faceRect.left, singleFaceInfo.faceRect.right, singleFaceInfo.faceRect.top, singleFaceInfo.faceRect.bottom, singleFaceInfo.faceOrient)); imagesFeatureList.Add(currentLeftFeature); } })); if (image1 != null) { image1.Dispose(); } })); } }
public static extern MResult ASFImageQualityDetect(IntPtr hEngine, int width, int height, int format, IntPtr imgData, ASF_SingleFaceInfo faceInfo, int isMask, out float confidenceLevel, ASF_DetectModel detectModel = ASF_DetectModel.ASF_DETECT_MODEL_RGB);
private void btnSelectImageToRecognize_Click(object sender, EventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Title = "Select"; openFileDialog.Filter = "Image File|*.bmp;*.jpg;*.jpeg;*.png"; //openFileDialog.Multiselect = true; openFileDialog.FileName = string.Empty; if (openFileDialog.ShowDialog() == DialogResult.OK) { var numStart = imagePathList.Count; string fileName = openFileDialog.FileName; if (!checkImage(fileName)) { return; } image1Feature = IntPtr.Zero; pictureBoxToRecognize.ImageLocation = fileName; Image srcImage = ImageUtil.readFromFile(fileName); ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo(); //提取人脸特征 image1Feature = FaceUtil.ExtractFeature(pImageEngine, srcImage, out singleFaceInfo); if (imagesFeatureList.Count == 0) { MessageBox.Show("请注册人脸!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (image1Feature == IntPtr.Zero) { if (pictureBoxToRecognize.Image == null) { MessageBox.Show("请选择识别图!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { MessageBox.Show("比对失败,识别图未提取到特征值!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } return; } for (int i = 0; i < imagesFeatureDictionary.Count; i++) { IntPtr feature = imagesFeatureDictionary.ElementAt(i).Key; float similarity = 0f; int ret = ASFFunctions.ASFFaceFeatureCompare(pImageEngine, image1Feature, feature, ref similarity); //增加异常值处理 if (similarity.ToString().IndexOf("E") > -1) { similarity = 0f; } if (similarity > threshold) { string name = imagesFeatureDictionary.ElementAt(i).Value; AppendText("对比结果:" + name + " 可信度:" + similarity + "\r\n"); return; } } AppendText("无结果\r\n"); } }
public static extern MResult ASFImageQualityDetectEx(IntPtr hEngine, ASVLOFFSCREEN imgData, ASF_SingleFaceInfo faceInfo, int isMask, out float confidenceLevel, ASF_DetectModel detectModel = ASF_DetectModel.ASF_DETECT_MODEL_RGB);
/// <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; })); } } }
public static extern MResult ASFFaceFeatureExtract(IntPtr hEngine, int width, int height, int format, IntPtr imgData, ASF_SingleFaceInfo faceInfo, ASF_RegisterOrNot registerOrNot, int mask, out ASF_FaceFeature feature);
/// <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 srcImage = Image.FromFile(imagePathListTemp[i]); ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(pEngine, srcImage); if (multiFaceInfo.faceNum > 0) { imagePathList.Add(imagePathListTemp[i]); MRECT rect = MemoryUtil.PtrToStructure <MRECT>(multiFaceInfo.faceRects); srcImage = ImageUtil.CutImage(srcImage, rect.left, rect.top, rect.right, rect.bottom); } else { continue; } this.Invoke(new Action(delegate { if (srcImage == null) { srcImage = Image.FromFile(imagePathListTemp[i]); } imageLists.Images.Add(imagePathListTemp[i], srcImage); imageList.Items.Add((numStart + isGoodImage) + "号", imagePathListTemp[i]); isGoodImage += 1; srcImage = 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); KeyValuePair <string, IntPtr> pair = new KeyValuePair <string, IntPtr>(imagePathList[i], feature); string _name = string.Format("{0}号", i); if (textBox1.Text != null) { _name = textBox1.Text; textBox1.Text = null; } People people = new People(_name, pair); peoples.Add(people); string sqlstr = string.Format("insert into face(name,face) values('{0}','{1}')", _name, imagePathList[i]); MySqlCommand cmd = new MySqlCommand(sqlstr, conn); int resule = cmd.ExecuteNonQuery(); } })); } //imagePathList.AddRange(imagePathListTemp); //允许点击按钮 Invoke(new Action(delegate { chooseMultiImgBtn.Enabled = true; matchBtn.Enabled = true; btnClearFaceList.Enabled = true; chooseImgBtn.Enabled = true; })); })); } } }
public static extern MResult ASFFaceFeatureExtractEx(IntPtr hEngine, ASVLOFFSCREEN imgData, ASF_SingleFaceInfo faceInfo, ASF_RegisterOrNot registerOrNot, int mask, out ASF_FaceFeature feature);
/// <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="pEngine">人脸识别引擎</param> /// <param name="image">图片</param> /// <param name="singleFaceInfo">单人脸信息</param> /// <returns>单人脸特征</returns> public static IntPtr ExtractFeature(IntPtr pEngine, Image image, ASF_SingleFaceInfo singleFaceInfo) { ImageInfo imageInfo = ImageUtil.ReadBMP(image); if (imageInfo == null) { ASF_FaceFeature emptyFeature = new ASF_FaceFeature(); IntPtr pEmptyFeature = MemoryUtil.Malloc(MemoryUtil.SizeOf <ASF_FaceFeature>()); MemoryUtil.StructureToPtr(emptyFeature, pEmptyFeature); return(pEmptyFeature); } IntPtr pSingleFaceInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf <ASF_SingleFaceInfo>()); MemoryUtil.StructureToPtr(singleFaceInfo, pSingleFaceInfo); IntPtr pFaceFeature = MemoryUtil.Malloc(MemoryUtil.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) { //释放指针 MemoryUtil.Free(pSingleFaceInfo); MemoryUtil.Free(pFaceFeature); MemoryUtil.Free(imageInfo.imgData); ASF_FaceFeature emptyFeature = new ASF_FaceFeature(); IntPtr pEmptyFeature = MemoryUtil.Malloc(MemoryUtil.SizeOf <ASF_FaceFeature>()); MemoryUtil.StructureToPtr(emptyFeature, pEmptyFeature); return(pEmptyFeature); } //人脸特征feature过滤 ASF_FaceFeature faceFeature = MemoryUtil.PtrToStructure <ASF_FaceFeature>(pFaceFeature); byte[] feature = new byte[faceFeature.featureSize]; MemoryUtil.Copy(faceFeature.feature, feature, 0, faceFeature.featureSize); ASF_FaceFeature localFeature = new ASF_FaceFeature(); localFeature.feature = MemoryUtil.Malloc(feature.Length); MemoryUtil.Copy(feature, 0, localFeature.feature, feature.Length); localFeature.featureSize = feature.Length; IntPtr pLocalFeature = MemoryUtil.Malloc(MemoryUtil.SizeOf <ASF_FaceFeature>()); MemoryUtil.StructureToPtr(localFeature, pLocalFeature); //释放指针 MemoryUtil.Free(pSingleFaceInfo); MemoryUtil.Free(pFaceFeature); MemoryUtil.Free(imageInfo.imgData); return(pLocalFeature); }
/// <summary> /// “选择识别图片”按钮事件 /// </summary> private void ChooseImg(object sender, EventArgs e) { lblCompareInfo.Text = ""; if (pImageEngine == 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的倍数 if (srcImage.Width % 4 != 0) { //srcImage = ImageUtil.ScaleImage(srcImage, picImageCompare.Width, picImageCompare.Height); srcImage = ImageUtil.ScaleImage(srcImage, srcImage.Width - (srcImage.Width % 4), srcImage.Height); } //调整图片数据,非常重要 ImageInfo imageInfo = ImageUtil.ReadBMP(srcImage); //人脸检测 ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(pImageEngine, imageInfo); //年龄检测 int retCode_Age = -1; ASF_AgeInfo ageInfo = FaceUtil.AgeEstimation(pImageEngine, imageInfo, multiFaceInfo, out retCode_Age); //性别检测 int retCode_Gender = -1; ASF_GenderInfo genderInfo = FaceUtil.GenderEstimation(pImageEngine, imageInfo, multiFaceInfo, out retCode_Gender); //3DAngle检测 int retCode_3DAngle = -1; ASF_Face3DAngle face3DAngleInfo = FaceUtil.Face3DAngleDetection(pImageEngine, imageInfo, multiFaceInfo, out retCode_3DAngle); MemoryUtil.Free(imageInfo.imgData); if (multiFaceInfo.faceNum < 1) { srcImage = ImageUtil.ScaleImage(srcImage, picImageCompare.Width, picImageCompare.Height); 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)); } 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();// 单人脸检测 //提取人脸特征 image1Feature = FaceUtil.ExtractFeature(pImageEngine, srcImage, out singleFaceInfo); //清空上次的匹配结果 for (int i = 0; i < imagesFeatureList.Count; i++) { imageList.Items[i].Text = string.Format("{0}号", i); } float scaleRate = ImageUtil.getWidthAndHeight(srcImage.Width, srcImage.Height, picImageCompare.Width, picImageCompare.Height); srcImage = ImageUtil.ScaleImage(srcImage, picImageCompare.Width, picImageCompare.Height); srcImage = ImageUtil.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, picImageCompare.Width); //显示标记后的图像 picImageCompare.Image = srcImage; } }
/// <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; } })); })); } } }