如何实现摄像头人脸自动识别并将标签设为对应人脸文件名?
人脸识别系统:自动匹配人脸标签问题求助
我正在开发一套人脸识别系统,已实现将人脸保存为对象并存储到指定文件夹的功能。目前遇到的问题是:开启摄像头后如何自动识别人脸,并将识别标签设置为对应人脸文件的名称?我觉得自己的代码比网上示例更简洁,但调整后反而更困惑,想请教是否需要重写整个代码?
当前代码
private async Task StreamVideo2() { var faceCasade = new CascadeClassifier("./detection/haarcascade_frontalface_default.xml"); var vc = new VideoCapture(0, Emgu.CV.VideoCapture.API.DShow); // Get the list of saved face images string folder = Path.Combine(Application.StartupPath, "TrainedFaces"); string[] savedImages = Directory.GetFiles(folder, "*.bmp"); while (streamVideo) { var frame = new Mat(); var frameGray = new Mat(); vc.Read(frame); CvInvoke.CvtColor(frame, frameGray, Emgu.CV.CvEnum.ColorConversion.Bgr2Gray); var faces = faceCasade.DetectMultiScale(frameGray, 1.3, 5); if (faces != null && faces.Length > 0) { CvInvoke.Rectangle(frame, faces[0], new MCvScalar(0, 255, 0), 2); // --> MCvScalar EMGU STRUCTURE [ RETACLE GREEN ON FACE ] // Crop var faceRect = faces[0]; var croppedFace = new Mat(frame, faceRect); // LABEL string labelText = "Detected Face"; var font = new Emgu.CV.CvEnum.FontFace(); var fontScale = 0.8; var fontThickness = 1; var fontColor = new MCvScalar(0, 255, 0); var textOrg = new System.Drawing.Point(faceRect.X, faceRect.Y - 10); CvInvoke.PutText(frame, labelText, textOrg, font, fontScale, fontColor, fontThickness); // ResizedCroppedFace var resizedCroppedFace = new Mat(); var resizedSize = new System.Drawing.Size(184, 192); // Size to keep the croppedFace. CvInvoke.Resize(croppedFace, resizedCroppedFace, resizedSize); // Convert cropped face to black and white (grayscale) var grayCroppedFace = new Mat(); CvInvoke.CvtColor(resizedCroppedFace, grayCroppedFace, Emgu.CV.CvEnum.ColorConversion.Bgr2Gray); // Display the grayscale cropped face in pictureBox2 pictureBox2.Image = grayCroppedFace.ToBitmap(); } else { pictureBox2.Image = null; } // TURN CAMERA TO IMG PICTURE BOX var img = frame.ToBitmap(); pictureBox1.Image = img; label1.Text = "Mat Size: " + frame.Width.ToString() + " X " + frame.Height.ToString(); if (CvInvoke.WaitKey(1) == 27) { break; } await Task.Delay(16); } } private void button1_Click(object sender, System.EventArgs e) { if (pictureBox2.Image != null) { string folder = Path.Combine(Application.StartupPath, "TrainedFaces"); string filename = textBox1.Text.Trim(); string savePath = Path.Combine(folder, $"{filename}.bmp"); // Saved As An Object using var bitmapImage = new Bitmap(pictureBox2.Image); bitmapImage.Save(savePath, System.Drawing.Imaging.ImageFormat.Bmp); MessageBox.Show("Succed"); textBox1.Clear(); if (!Directory.Exists(folder)) { MessageBox.Show("Not Found"); } } else { MessageBox.Show("Turn On The Camera"); } }
解决方案建议:无需重写,扩展特征匹配逻辑
当前代码仅完成了人脸检测,缺少特征提取与匹配环节,只需在现有代码基础上添加以下步骤:
预加载并训练人脸特征
在StreamVideo2方法的开头(循环外),加载已保存的人脸图片,提取特征并训练识别器,同时建立标签与文件名的映射:// 初始化特征识别器(推荐LBPH,对姿态/光照变化适应性更强) var recognizer = new LBPHFaceRecognizer(); List<Mat> faceSamples = new List<Mat>(); List<int> labelIds = new List<int>(); Dictionary<int, string> idToName = new Dictionary<int, string>(); int currentId = 0; foreach (var imgPath in savedImages) { // 读取灰度图(与后续检测的人脸格式一致) var faceMat = CvInvoke.Imread(imgPath, Emgu.CV.CvEnum.ImreadModes.Grayscale); faceSamples.Add(faceMat); labelIds.Add(currentId); // 提取文件名作为标签 idToName[currentId] = Path.GetFileNameWithoutExtension(imgPath); currentId++; } // 训练识别器 recognizer.Train(faceSamples.ToArray(), labelIds.ToArray());实时匹配并替换标签
在检测到人脸并生成grayCroppedFace后,用识别器预测结果,替换原有的固定标签:// 替换原有的labelText赋值逻辑 string labelText = "Unknown"; var prediction = recognizer.Predict(grayCroppedFace); // 距离阈值根据实际样本调整,越小匹配越严格 if (prediction.Label != -1 && prediction.Distance < 50) { labelText = idToName[prediction.Label]; }关键优化点
- 特征训练只执行一次,不要放在循环内,避免重复计算浪费资源。
- 测试并调整匹配阈值(
prediction.Distance),根据你的样本质量找到合适的数值。 - 确保已保存的人脸图片尺寸与实时检测后裁剪的尺寸一致(当前是184x192),否则匹配会失效。
内容的提问来源于stack exchange,提问作者Alexander
相关产品推荐
相关产品推荐

