C#QueryFrame中的EmguCV 2.3.0返回先前查询的帧

时间:2011-09-20 22:55:40

标签: c# opencv emgucv

我正在使用EmguCV 2.3.0并且从Capture中以随机间隔查询帧以保存到硬盘驱动器。问题是,当我调用Capture.QueryFrame()或Capture.QuerySmallFrame()时,它会延迟一帧。 为了更清楚:我启动程序并查询指向我脸部的框架。我的脸出现在.jpeg中。然后我将相机指向远离我的脸并查询另一帧,我的脸再次出现在.jpeg中。然后我再次将它指向我的脸,查询一个框架,.jpeg包含指向我脸部的图像。 查询中似乎有1帧延迟。是否有一些底层缓冲区?是什么造成的?最重要的是:如何在不查询单个捕获图像的多个帧的情况下解决此问题?

我的另一个问题是,当我将网络摄像头分辨率设置为1600x1200时,程序和计算机开始滞后 - 即使不使用图像或查询帧。这是因为我创建了一个Capture并将其保存在内存中吗?有没有办法减轻这种影响?

注意:此解决方案不足以快速获取帧,问题仍在此处继续: System.TypeInitializationException using Emgu.CV in C#

2 个答案:

答案 0 :(得分:3)

你遇到的问题是你没有丢弃你的旧捕获物,所以当你发送给另一个捕获物时,它总会返回旧的捕获物,然后再得到另一个捕获物。从Web摄像头示例调整的以下代码应该可以解决问题。

_capture = new Capture();
Image<Bgr, Byte> frame = _capture.QueryFrame();

Image<Gray, Byte> grayFrame = frame.Convert<Gray, Byte>();
Image<Gray, Byte> smallGrayFrame = grayFrame.PyrDown();
Image<Gray, Byte> smoothedGrayFrame = smallGrayFrame.PyrUp();
Image<Gray, Byte> cannyFrame = smoothedGrayFrame.Canny(new Gray(100), new Gray(60));

captureImageBox.Image = frame;
grayscaleImageBox.Image = grayFrame;
smoothedGrayscaleImageBox.Image = smoothedGrayFrame;
cannyImageBox.Image = cannyFrame;
_capture.Dispose();

是_capture.Dispose();这是重要的一点。

至于你的1600x1200是的,你的权利是因为你在内存中有大量的数据。首先,通过有效地“使用”内存流并在完成它时处理它。这是通过'using'语句完成的,该语句在开始时自动创建对象,并在结束时调用其.Dispose函数,这样您就不必这样做了。请注意复制过程,否则传递指针,当您退出使用代码时,您也将处理帧。使用图像时,您还应该练习“使用”语句。但上面的代码现在看起来像这样:

Image<Bgr, Byte> frame;
using (Capture capture = new Capture())
{
    frame = capture1.QueryFrame().Copy(); //You must copy else frame will be disposed off
}
Image<Gray, Byte> grayFrame = frame.Convert<Gray, Byte>();
Image<Gray, Byte> smallGrayFrame = grayFrame.PyrDown();
Image<Gray, Byte> smoothedGrayFrame = smallGrayFrame.PyrUp();
Image<Gray, Byte> cannyFrame = smoothedGrayFrame.Canny(new Gray(100), new Gray(60));

grayscaleImageBox.Image = grayFrame;
smoothedGrayscaleImageBox.Image = smoothedGrayFrame;
cannyImageBox.Image = cannyFrame;

其次,您可以使用.Resize(缩放,插值方法)调整捕获的图像大小。通常使用专用的帧抓取器从摄像机传递大图像,因此显然避免了系统依赖性,高清USB网络摄像头不再是这种情况。

您可以像这样调整输入图像的大小,并有效地使用“使用”语句,最终代码将如下所示:

Image<Bgr, Byte> frame;
using (Capture capture1 = new Capture())
{
    frame = capture1.QueryFrame().Resize(0.5, Emgu.CV.CvEnum.INTER.CV_INTER_AREA).Copy();
    captureImageBox.Image = frame;
}

using (Image<Gray, Byte> grayFrame = frame.Convert<Gray, Byte>())
{
    grayscaleImageBox.Image = grayFrame;
    using (Image<Gray, Byte> smallGrayFrame = grayFrame.PyrDown())
    {
        using (Image<Gray, Byte> smoothedGrayFrame = smallGrayFrame.PyrUp())
        {
            smoothedGrayscaleImageBox.Image = smoothedGrayFrame;
            using (Image<Gray, Byte> cannyFrame = smoothedGrayFrame.Canny(new Gray(100), new Gray(60)))
            {
                cannyImageBox.Image = cannyFrame;
            }
        }
    }
}

干杯 克里斯

答案 1 :(得分:0)

我的意思是听起来很愚蠢,只需查询一下框架两次即可。我知道这不是解决问题的“最先进”方法,但是我遇到了同样的问题,我可以那样解决。

这是我的捕获方法

public void Capture_Image()
    {
        try
        {
            capture.Start();
            capture.Pause();

            tempImg = capture.QueryFrame().Bitmap;//Capture twice here
            tempImg = capture.QueryFrame().Bitmap;
            tempImg.Save("C:/FHT59N3/Bildanalyse_Projekt/image.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
        }
        catch (NullReferenceException)
        {
            string message = "No Camera found";
            string title = "Please connect Camera";
            MessageBoxButtons buttons = MessageBoxButtons.OK;
            MessageBox.Show(message, title, buttons, MessageBoxIcon.Warning);
        }
    }