/// <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> /// 从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); }
public int ScanFaceFeature(Bitmap bitmap, FaceInfo singleFaceInfo) { singleFaceInfo.faceFeature = FaceUtil.ExtractFeature(pVideoRGBImageEngine, bitmap, singleFaceInfo.singleFaceInfo); if (singleFaceInfo.faceFeature.featureSize > 0) { return(0); } return(-1); }
/// <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; })); })); } } }
/// <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> /// 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> /// 图像显示到窗体上,得到每一帧图像,并进行处理(画框) /// </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> 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; } })); })); } } }
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> /// <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; })); } } }
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 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"); } }
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(); } })); } }
/// <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); }