【发布时间】:2021-10-30 01:45:29
【问题描述】:
我试图在 C# 中使用“EigenFaceRecognizer”进行人脸识别。但问题是识别器将未知人脸识别为已知人脸。一旦识别器被训练来识别那张未知的脸,它就会正确地识别出那张脸。但它从不显示下面代码中所写的“未知”。
这是识别、捕捉、保存和训练人脸的完整代码:-
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using System.Drawing;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Face;
using Emgu.CV.Structure;
namespace FaceRecognition
{
class FaceRecognition:Form
{
private double distance = 50;
private CascadeClassifier CascadeClassifier = new CascadeClassifier(Environment.CurrentDirectory + "/Resources/Haarcascade/haarcascade_frontalface_alt2.xml");
private Image<Bgr, byte> Frame = (Image<Bgr, byte>)null;
private Capture camera;
private Mat mat = new Mat();
private List<Image<Gray, byte>> trainedFaces = new List<Image<Gray, byte>>();
private List<int> PersonLabs = new List<int>();
private bool isEnable_SaveImage = false;
private string ImageName;
private PictureBox PictureBox_Frame;
private PictureBox PictureBox_smallFrame;
private string setPersonName;
public bool isTrained = false;
private List<string> Names = new List<string>();
private EigenFaceRecognizer eigenFaceRecognizer;
private IContainer components = (IContainer)null;
private List<String> retNames = new List<string>();
public FaceRecgnition()
{
this.InitializeComponent();
if (Directory.Exists(Environment.CurrentDirectory + "\\Training_Data\\Faces\\Image"))
return;
Directory.CreateDirectory(Environment.CurrentDirectory + "\\Training_Data\\Faces\\Image");
}
public void getPersonName(Control control)
{
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
timer.Tick += new EventHandler(timer_getPersonName_Tick);
timer.Interval = 100;
timer.Start();
void timer_getPersonName_Tick(object sender, EventArgs e) => control.Text = this.setPersonName;
}
public void openCamera(PictureBox pictureBox_Camera, PictureBox pictureBox_Trained)
{
this.PictureBox_Frame = pictureBox_Camera;
this.PictureBox_smallFrame = pictureBox_Trained;
this.camera = new Capture();
this.camera.ImageGrabbed += new EventHandler(this.Camera_ImageGrabbed);
this.camera.Start();
}
public void Save_IMAGE(string imageName)
{
this.ImageName = imageName;
this.isEnable_SaveImage = true;
}
private void Camera_ImageGrabbed(object sender, EventArgs e)
{
this.camera.Retrieve((IOutputArray)this.mat, 0);
this.Frame = this.mat.ToImage<Bgr, byte>(false).Resize(this.PictureBox_Frame.Width, this.PictureBox_Frame.Height, (Inter)2);
this.detectFace();
this.PictureBox_Frame.Image = (Image)this.Frame.Bitmap;
}
private void detectFace()
{
Image<Bgr, byte> resultImage = this.Frame.Convert<Bgr, byte>();
Mat mat = new Mat();
CvInvoke.CvtColor((IInputArray)this.Frame, (IOutputArray)mat, (ColorConversion)6, 0);
CvInvoke.EqualizeHist((IInputArray)mat, (IOutputArray)mat);
Rectangle[] rectangleArray = this.CascadeClassifier.DetectMultiScale((IInputArray)mat, 1.1, 4, new Size(), new Size());
if ((uint)rectangleArray.Length > 0U)
{
foreach (Rectangle face in rectangleArray)
{
Image<Bgr, byte> frame = this.Frame;
Rectangle rectangle = face;
Bgr bgr = new Bgr(Color.SpringGreen);
MCvScalar mcvScalar = ((Bgr)bgr).MCvScalar;
CvInvoke.Rectangle((IInputOutputArray)frame, rectangle, mcvScalar, 2, (LineType)8, 0);
this.SaveImage(face);
resultImage.ROI = face;
this.trainedIamge();
String name = this.CheckName(resultImage, face);
if (!retNames.Contains(name))
{
retNames.Add(name);
}
}
}
else
{
this.setPersonName = "";
retNames.Clear();
}
}
private void SaveImage(Rectangle face)
{
if (!this.isEnable_SaveImage)
return;
Image<Bgr, byte> image = this.Frame.Convert<Bgr, byte>();
image.ROI = face;
Task.Factory.StartNew(() =>
{
for(int i = 0; i < 40; i++)
{
((CvArray<byte>)image.Resize(100, 100, (Inter)2)).Save(Environment.CurrentDirectory + "\\Training_Data\\Faces\\Image\\" + this.ImageName + "_" + DateTime.Now.ToString("dd-mm-yyyy-hh-mm-ss") + ".jpg");
Thread.Sleep(1000);
}
});
this.isEnable_SaveImage = false;
this.trainedIamge();
}
private void trainedIamge()
{
try
{
int num = 0;
this.trainedFaces.Clear();
this.PersonLabs.Clear();
this.Names.Clear();
foreach (string file in Directory.GetFiles(Directory.GetCurrentDirectory() + "\\Training_Data\\Faces\\Image", "*.jpg", SearchOption.AllDirectories))
{
this.trainedFaces.Add(new Image<Gray, byte>(file));
this.PersonLabs.Add(num);
String name = file.Split('\\').Last().Split('_')[0];
this.Names.Add(name);
++num;
}
this.eigenFaceRecognizer = new EigenFaceRecognizer(num, this.distance);
((FaceRecognizer)this.eigenFaceRecognizer).Train<Gray, byte>(this.trainedFaces.ToArray(), this.PersonLabs.ToArray());
}
catch
{
}
}
private string CheckName(Image<Bgr, byte> resultImage, Rectangle face)
{
retNames.Clear();
try
{
if (!this.isTrained)
return null;
Image<Gray, byte> image = resultImage.Convert<Gray, byte>().Resize(100, 100, (Inter)2);
//);
CvInvoke.EqualizeHist((IInputArray)image, (IOutputArray)image);
//.Predict((IInputArray)image)
FaceRecognizer.PredictionResult predictionResult = ((FaceRecognizer)this.eigenFaceRecognizer).Predict(image);
if (predictionResult.Label != -1 && predictionResult.Distance < 5000)
{
this.PictureBox_smallFrame.Image = (Image)this.trainedFaces[(int)predictionResult.Label].Bitmap;
this.setPersonName = this.Names[(int)predictionResult.Label].Replace(Environment.CurrentDirectory + "\\Training_Data\\Faces\\Image\\", "").Replace(".jpg", "");
Image<Bgr, byte> frame = this.Frame;
string setPersonName = this.setPersonName;
Point point = new Point(face.X - 2, face.Y - 2);
Bgr bgr = new Bgr(Color.Gold);
MCvScalar mcvScalar = ((Bgr)bgr).MCvScalar;
CvInvoke.PutText((IInputOutputArray)frame, setPersonName, point, (FontFace)1, 1.0, mcvScalar, 1, (LineType)8, false);
return setPersonName;
}
else
{
Image<Bgr, byte> frame = this.Frame;
Point point = new Point(face.X - 2, face.Y - 2);
Bgr bgr = new Bgr(Color.OrangeRed);
MCvScalar mcvScalar = ((Bgr)bgr).MCvScalar;
CvInvoke.PutText((IInputOutputArray)frame, "Unknown", point, (FontFace)1, 1.0, mcvScalar, 1, (LineType)8, false);
return "Unknown";
}
}
catch
{
return null;
}
}
protected override void Dispose(bool disposing)
{
if (disposing && this.components != null)
this.components.Dispose();
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.SuspendLayout();
this.AutoScaleDimensions = new SizeF(8f, 16f);
this.AutoScaleMode = AutoScaleMode.Font;
this.ClientSize = new Size(800, 450);
this.Name = nameof(FaceRecognition);
this.Text = nameof(FaceRecognition);
this.ResumeLayout(false);
}
public List<String> getRetNames { get => retNames; }
private String setRetNames { set => retNames.Add(value); }
}
}
这是识别人脸的主要代码(如果你赶时间的话):-
private string CheckName(Image<Bgr, byte> resultImage, Rectangle face)
{
retNames.Clear();
try
{
if (!this.isTrained)
return null;
Image<Gray, byte> image = resultImage.Convert<Gray, byte>().Resize(100, 100, (Inter)2);
CvInvoke.EqualizeHist((IInputArray)image, (IOutputArray)image);
FaceRecognizer.PredictionResult predictionResult = ((FaceRecognizer)this.eigenFaceRecognizer).Predict((IInputArray)image);
if (predictionResult.Label != -1 && predictionResult.Distance < 5000)
{
this.PictureBox_smallFrame.Image = (Image)this.trainedFaces[(int)predictionResult.Label].Bitmap;
this.setPersonName = this.Names[(int)predictionResult.Label].Replace(Environment.CurrentDirectory + "\\Training_Data\\Faces\\Image\\", "").Replace(".jpg", "");
Image<Bgr, byte> frame = this.Frame;
string setPersonName = this.setPersonName;
Point point = new Point(face.X - 2, face.Y - 2);
Bgr bgr = new Bgr(Color.Gold);
MCvScalar mcvScalar = ((Bgr)bgr).MCvScalar;
CvInvoke.PutText((IInputOutputArray)frame, setPersonName, point, (FontFace)1, 1.0, mcvScalar, 1, (LineType)8, false);
return setPersonName;
}
else
{
Image<Bgr, byte> frame = this.Frame;
Point point = new Point(face.X - 2, face.Y - 2);
Bgr bgr = new Bgr(Color.OrangeRed);
MCvScalar mcvScalar = ((Bgr)bgr).MCvScalar;
CvInvoke.PutText((IInputOutputArray)frame, "Unknown", point, (FontFace)1, 1.0, mcvScalar, 1, (LineType)8, false);
return "Unknown";
}
}
catch
{
return null;
}
}
现在无论是哪张脸,--FaceRecognizer.PredictionResult predictionResult = ((FaceRecognizer)this.eigenFaceRecognizer).Predict((IInputArray)image); 总是返回predictionResult.Label = 0 和predictionResult.Distance = 0。
我尝试了什么:-
- 更改
private double distance = 50;。最初是 1E+19,然后我将其设为 5000、2000,并使用许多不同的值对其进行了调整。 - 使用所有 CascadeClassifier xml 文件。
但在我采取措施解决问题的所有情况下,predictionResult.Label 和 predictionResult.Distance 的值始终为“0”。
P.S :- 这个问题可以是 1 或 2 个问题的重复,但在这些问题中,提问者既没有提供足够的信息,也没有答案。
【问题讨论】:
-
还没有答案吗?奇怪....
-
它是一个特定的库,它给您带来麻烦,因此没有答案,jet 并不少见。您是否尝试在开发者 github 上打开问题?
-
@lsparia 所以我的代码有什么问题吗?而且这个问题在库的开发人员支持之前无法解决?
-
我第一眼看不到一个,但这并不意味着没有,因为我不熟悉这个库。由于这个问题的性质,我建议直接询问开发人员,因为他们更适合帮助您。
标签: c# .net face-recognition