我正在尝试使用 EmguCV 3.1.0.1 库通过视频捕获实现人脸检测,该库由VS15的NuGet软件包在WinForms桌面应用程序中的PC Windows 10 64位OS上安装。
我的目标是从摄像机中检测和跟踪人脸并检测笑容,但是在下面的示例中,我将仅使用人脸HaarCascade
.xml和CascadeClassifier
。
因此,我在DirectShowLib
videoDevice
中为comboBox1_SelectedIndexChanged
使用SelectedItem
库:
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.CV.UI;
using DirectShowLib;
HaarCascade xml-s的路径:
string facePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "dir\\haarcascade_frontalface_default.xml");
计时器:
private void timer1_Tick(object sender, EventArgs e)
{
detectFace();
}
尝试1:
private void detectFace()
{
CascadeClassifier face = new CascadeClassifier(facePath);
Image<Bgr, Byte> currentframe = null;
Image<Gray, byte> grayFrame = null;
Capture grabber;
grabber = new Capture(videoDevice);
currentframe = grabber.QueryFrame().Resize(500, 320, Emgu.CV.CvEnum.INTER.CV_INTER_CUBIC);
if (currentframe != null)
{
grayFrame = currentframe.Convert<Gray, Byte>();
Rectangle[] faceDetected = face.DetectMultiScale(grayFrame, 1.1, 10, Size.Empty, Size.Empty);
foreach (Rectangle faceFound in faceDetected)
{
currentframe.Draw(faceFound, new Bgr(Color.Red), 2);
}
pictureBox1.Image = currentframe.ToBitmap();
}
}
第currentframe = grabber.QueryFrame().Resize(500, 320, Emgu.CV.CvEnum.INTER.CV_INTER_CUBIC);
行说:
错误CS0234类型或名称空间名称'INTER'在 命名空间“ Emgu.CV.CvEnum”(您是否缺少程序集引用?)
相反,我尝试将currentframe = grabber.QueryFrame().Resize(500, 320, Emgu.CV.CvEnum.TemplateMatchingType.CcoeffNormed);
或grabber.QueryFrame().MatchTemplate
或grabber.QueryFrame().Retrieve
与 private Capture _capture;
private CascadeClassifier _cascadeClassifier;
private void detectFace()
{
_capture = new Capture(videoDevice);
_cascadeClassifier = new CascadeClassifier(facePath);
using (var imageFrame = _capture.QueryFrame().ToImage())
{
if (imageFrame != null)
{
var grayframe = imageFrame.Convert();
var faces = _cascadeClassifier.DetectMultiScale(grayframe, 1.1, 10, Size.Empty);
foreach (var face in faces)
{
imageFrame.Draw(face, new Bgr(Color.Red), 3);
}
}
pictureBox1.Image = imageFrame.ToBitmap();
}
}
一起使用,但另一个错误仍然与以下内容相同:
错误CS1061“垫子”不包含以下内容的定义: 'Resize'并且没有扩展方法'Resize'接受第一个参数 可以找到类型为'Mat'的(您是否缺少using指令或 程序集参考?)
我不确定我必须在哪里下载所需的dll-s(如果是丢失的原因?),以及我应该另外添加哪些dll-s。
尝试2:
using (var imageFrame = _capture.QueryFrame().ToImage())
第var grayframe = imageFrame.Convert();
行:
错误CS0411无法从用法中推断出方法'Mat.ToImage(bool)'的类型参数。尝试指定 明确键入参数。
第imageFrame.Draw(face, new Bgr(Color.Red), 3);
行:
错误CS0411无法从中推断方法'Image.Convert()'的类型参数 用法。尝试显式指定类型参数。
第private void detectFace()
{
CascadeClassifier face = new CascadeClassifier(facePath);
Image<Bgr, Byte> currentframe = null;
Image<Gray, byte> grayFrame = null;
Capture grabber;
grabber = new Capture(videoDevice);
var dstMat = new Mat();
var frame = grabber.QueryFrame();
CvInvoke.Resize(frame, dstMat, new Size(500, 320), interpolation: Emgu.CV.CvEnum.Inter.Cubic);
currentframe = dstMat.ToImage<Bgr, byte>();
if (currentframe != null)
{
grayFrame = currentframe.Convert<Gray, Byte>();
Rectangle[] faceDetected = face.DetectMultiScale(grayFrame, 1.1, 10, Size.Empty, Size.Empty);
foreach (Rectangle faceFound in faceDetected)
{
currentframe.Draw(faceFound, new Bgr(Color.Red), 2);
}
pictureBox1.Image = currentframe.ToBitmap();
}
}
行:
错误CS1503参数2:无法从“ Emgu.CV.Structure.Bgr”转换 到“ TColor”
任何指南,建议或示例都会有所帮助
由 Michal Nawrocik 编辑,答案如下:
方法1:
private Capture _capture;
private CascadeClassifier _cascadeClassifier;
private void detectFace()
{
_capture = new Capture(videoDevice);
_cascadeClassifier = new CascadeClassifier(facePath);
using (var imageFrame = _capture.QueryFrame().ToImage<Bgr, byte>())
{
if (imageFrame != null)
{
var grayframe = imageFrame.Convert<Gray, byte>();
var faces = _cascadeClassifier.DetectMultiScale(grayframe, 1.1, 10, Size.Empty);
foreach (var face in faces)
{
imageFrame.Draw(face, new Bgr(Color.Red), 3);
}
}
pictureBox1.Image = imageFrame.ToBitmap();
}
}
}
未处理的异常:
System.AccessViolationException'发生在Emgu.CV.World.dll中 附加信息:尝试读取或写入受保护的内存。 这通常表明其他内存已损坏
方法2:
DbContext
例外:
Emgu.CV.Util.CvException”发生在Emgu.CV.World.dll中 信息:OpenCV:无法识别或不受支持的数组类型
答案 0 :(得分:0)
正如您的错误消息所述,Mat
类没有Resize()
实例方法,一些快速的搜索显示您需要调用CvInvoke
类的静态方法。 EmguCV的开发人员有时也会更改三次插值的枚举值。
以下是与您的尝试1对应的工作代码:
var dstMat = new Mat();
var frame = grabber.QueryFrame();
CvInvoke.Resize(frame, dstMat, new Size(500, 320), interpolation: Emgu.CV.CvEnum.Inter.Cubic);
currentframe = dstMat.ToImage<Bgr, byte>();
请注意,我保存了对Mat
对象的引用,以便以后处理它们。也可以使用using
语句。
您的其他问题相似。没有像Mat.ToImage()
或Image.Convert()
这样的无参数非泛型方法。它们甚至没有多大意义,因为您需要指定要转换为哪种格式。
您可以使用:
var imageFrame =_capture.QueryFrame().ToImage<Bgr, byte>();
var grayFrame = imageFrame.Convert<Gray, byte>();
Image.Draw()
调用中的最后一个错误将消失。
您的问题表明,仔细研究可用的类元数据可能会有所帮助。通过Visual Studio中内置的对象浏览器。
编辑:
在第一种方法中,您忘记为某些对象调用Dispose()
,这导致了异常。这是经过验证且可以正常工作的更正代码:
private void detectFace()
{
CascadeClassifier face = new CascadeClassifier(facePath);
Image<Bgr, Byte> currentframe = null;
Image<Gray, byte> grayFrame = null;
Capture grabber;
grabber = new Capture(videoDevice);
var dstMat = new Mat();
var frame = grabber.QueryFrame();
CvInvoke.Resize(frame, dstMat, new Size(500, 320), interpolation: Emgu.CV.CvEnum.Inter.Cubic);
currentframe = dstMat.ToImage<Bgr, byte>();
if (currentframe != null)
{
grayFrame = currentframe.Convert<Gray, Byte>();
Rectangle[] faceDetected = face.DetectMultiScale(grayFrame, 1.1, 10, Size.Empty, Size.Empty);
foreach (Rectangle faceFound in faceDetected)
{
currentframe.Draw(faceFound, new Bgr(Color.Red), 2);
}
var oldImage = panAndZoomPictureBox1.Image;
panAndZoomPictureBox1.Image = currentframe.ToBitmap();
if (oldImage != null)
{
oldImage.Dispose();
}
currentframe.Dispose();
grayFrame.Dispose();
}
face.Dispose();
grabber.Dispose();
dstMat.Dispose();
frame.Dispose();
}
我进行了尽可能少的修复,以使其正常运行。有相当大的改进空间。您只需创建一次Capture
和CascadeClassifier
即可(而不是每个计时器滴答),这将大大提高性能。
我还注意到您使用的Emgu软件包的版本相当旧,即使NuGet对此软件包没有显示较新的版本。原因是它已重命名为EMGU.CV。