我一直在使用 EmguCV (C#) 开发人脸识别应用程序。如果我将面部图像(训练集)存储在简单的 Windows 文件夹中,我可以让整个工作正常。但是,在我尝试迁移要存储在 Microsoft Access 数据库中的面部图像后,当应用程序尝试时,经常会出现“未设置对象实例的对象引用”异常消息(并非总是如此,但大多数情况下)从视频源中识别人脸。
有趣的是,如果碰巧没有发生异常,识别实际上仍然可以正常工作。
这是我的程序的代码片段,使用 windows 文件夹和数据库:
从 Windows 文件夹中读取存储的图像
private void FaceRecognition_Load(object sender, EventArgs e)
{
//if capture is not created, create it now
if (capture == null)
{
try
{
capture = new Capture();
}
catch (NullReferenceException excpt)
{
MessageBox.Show(excpt.Message);
}
}
if (capture != null)
{
if (captureInProgress)
{
Application.Idle -= ProcessFrame;
}
else
{
Application.Idle += ProcessFrame;
}
captureInProgress = !captureInProgress;
}
#endregion
{
// adjust path to find your xml at loading
haar = new HaarCascade("haarcascade_frontalface_default.xml");
try
{
//Load of previus trainned faces and labels for each image
string Labelsinfo = File.ReadAllText(Application.StartupPath + "\\TrainedFaces\\TrainedLabels.txt");
string[] Labels = Labelsinfo.Split('%');
NumLabels = Convert.ToInt16(Labels[0]);
ContTrain = NumLabels;
string LoadFaces;
for (int tf = 1; tf < NumLabels + 1; tf++)
{
LoadFaces = "face" + tf + ".bmp";
trainingImages.Add(new Image<Gray, byte>(Application.StartupPath + "\\TrainedFaces\\" + LoadFaces));
labels.Add(Labels[tf]);
}
}
catch (Exception error)
{
//MessageBox.Show(e.ToString());
MessageBox.Show("Nothing in binary database, please add at least a face(Simply train the prototype with the Add Face Button).", "Triained faces load", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
}
从 Microsoft Access 数据库中读取存储的图像
private void connectToDatabase()
{
DBConnection.ConnectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=FacesDatabase.mdb";
DBConnection.Open();
dataAdapter = new OleDbDataAdapter("Select * from TrainingSet1", DBConnection);
dataAdapter.Fill(localDataTable);
if (localDataTable.Rows.Count != 0)
{
numOfRows = localDataTable.Rows.Count;
}
}
private void FaceRecognition_Load(object sender, EventArgs e)
{
//if capture is not created, create it now
if (capture == null)
{
try
{
capture = new Capture();
}
catch (NullReferenceException excpt)
{
MessageBox.Show(excpt.Message);
}
}
if (capture != null)
{
if (captureInProgress)
{
Application.Idle -= ProcessFrame;
}
else
{
Application.Idle += ProcessFrame;
}
captureInProgress = !captureInProgress;
}
#endregion
{
// adjust path to find your xml at loading
haar = new HaarCascade("haarcascade_frontalface_default.xml");
connectToDatabase();
Bitmap bmpImage;
for (int i = 0; i < numOfRows; i++)
{
byte[] fetchedBytes = (byte[])localDataTable.Rows[i]["FaceImage"];
MemoryStream stream = new MemoryStream(fetchedBytes);
bmpImage = new Bitmap(stream);
trainingImages.Add(new Emgu.CV.Image<Gray, Byte>(bmpImage));
String faceName = (String)localDataTable.Rows[i]["Name"];
labels.Add(faceName);
}
}
}
导致异常的人脸识别功能(使用windows文件夹和Access数据库时完全相同):
private void ProcessFrame(object sender, EventArgs arg)
{
Image<Bgr, Byte> ImageFrame = capture.QueryFrame();
Image<Gray, byte> grayframe = ImageFrame.Convert<Gray, byte>();
MinNeighbors = int.Parse(comboBoxMinNeighbors.Text);
WindowsSize = int.Parse(textBoxWinSiz.Text);
ScaleIncreaseRate = Double.Parse(comboBoxMinNeighbors.Text);
var faces = grayframe.DetectHaarCascade(haar, ScaleIncreaseRate, MinNeighbors,
HAAR_DETECTION_TYPE.DO_CANNY_PRUNING,
new Size(WindowsSize, WindowsSize))[0];
if (faces.Length > 0)
{
Bitmap BmpInput = grayframe.ToBitmap();
Graphics FaceCanvas;
foreach (var face in faces)
{
t = t + 1;
result = ImageFrame.Copy(face.rect).Convert<Gray, byte>().Resize(100, 100, Emgu.CV.CvEnum.INTER.CV_INTER_CUBIC);
ImageFrame.Draw(face.rect, new Bgr(Color.Red), 2);
ExtractedFace = new Bitmap(face.rect.Width, face.rect.Height);
FaceCanvas = Graphics.FromImage(ExtractedFace);
FaceCanvas.DrawImage(BmpInput, 0, 0, face.rect, GraphicsUnit.Pixel);
ImageFrame.Draw(face.rect, new Bgr(Color.Red), 2);
if (trainingImages.ToArray().Length != 0)
{
MCvTermCriteria termCrit = new MCvTermCriteria(ContTrain, 0.001);
EigenObjectRecognizer recognizer = new EigenObjectRecognizer(
trainingImages.ToArray(),
labels.ToArray(),
3000,
ref termCrit);
try
{
name = recognizer.Recognize(result).Label;
}
catch (Exception error)
{
MessageBox.Show(error.ToString());
}
ImageFrame.Draw(name, ref font, new Point(face.rect.X - 2, face.rect.Y - 2), new Bgr(Color.LightGreen));
}
}
}
CamImageBox.Image = ImageFrame;
}
这是异常消息的屏幕截图:http: //i.imgur.com/DvAhABK.jpg
发生异常的第 146 行是 ProcessFrame 函数的这一行:
name = recognizer.Recognize(result).Label;
我尝试在互联网上搜索类似的问题,并找到了这些: 尝试将图像上传到数据库时出现“对象引用未设置为对象实例”错误 对象引用未设置为对象实例#5 C#错误“对象引用”未设置为对象的实例' C#,“对象引用未设置为对象的实例。” 错误
他们中的大多数人建议检查任何涉及的变量是否为空。我检查了所涉及的变量,当recognizer.Recognize(result)
语句返回 null 时确实发生了异常。
所以我的问题是,为什么当我使用数据库中的训练图像时该语句经常返回 null,而当我使用 windows 文件夹中的训练图像时它从不返回 null?