Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#QueryFrame中的EmguCV 2.3.0返回先前查询的帧_C#_Opencv_Emgucv - Fatal编程技术网

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

C#QueryFrame中的EmguCV 2.3.0返回先前查询的帧,c#,opencv,emgucv,C#,Opencv,Emgucv,我使用的是EmguCV 2.3.0,并以随机间隔查询要保存到硬盘上的捕获帧。问题是,当我调用Capture.QueryFrame()或Capture.querySallFrame()时,它会延迟一个帧。 为了更清楚地说明这一点:我启动程序并查询指向我脸的帧。我的脸显示在.jpeg中。然后,我将相机从我的脸上移开,查询另一帧,我的脸再次出现在.jpeg中。然后我再次将它指向我的脸,查询一帧,.jpeg包含指向我脸的图像。 查询中似乎有1帧延迟。是否存在一些底层缓冲区?这是什么原因造成的?最重要的是

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

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

注:此解决方案不足以快速获取帧,问题继续存在:

你的问题是,你没有处理旧的捕获,因此当你发送另一个捕获时,它总是返回旧的捕获,然后再获取另一个捕获。下面的代码根据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();
\u capture=new capture();
图像帧=_capture.QueryFrame();
Image grayFrame=frame.Convert();
Image smallGrayFrame=grayFrame.PyrDown();
Image SmoothdGrayFrame=smallGrayFrame.PyrUp();
图像cannyFrame=SmoothdGrayFrame.Canny(新灰度(100)、新灰度(60));
captureImageBox.Image=frame;
grayscaleImageBox.Image=grayFrame;
SmoothdRayScaleImageBox.Image=SmoothdRayFrame;
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;
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;
            }
        }
    }
}
图像帧;
使用(Capture=new Capture())
{
frame=capture1.QueryFrame().Copy();//必须复制,否则该帧将被丢弃
}
Image grayFrame=frame.Convert();
Image smallGrayFrame=grayFrame.PyrDown();
Image SmoothdGrayFrame=smallGrayFrame.PyrUp();
图像cannyFrame=SmoothdGrayFrame.Canny(新灰度(100)、新灰度(60));
grayscaleImageBox.Image=grayFrame;
SmoothdRayScaleImageBox.Image=SmoothdRayFrame;
cannyImageBox.Image=cannyFrame;
其次,您可以使用.resize(缩放、插值方法)调整捕获图像的大小。大图像通常使用专用的帧抓取器从相机传递,因此可以避免系统依赖性。显然,高清USB网络摄像头不再是这种情况

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

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;
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;
            }
        }
    }
}
图像帧;
使用(Capture capture1=new Capture())
{
frame=capture1.QueryFrame().Resize(0.5,Emgu.CV.CvEnum.INTER.CV_INTER_区域)。Copy();
captureImageBox.Image=frame;
}
使用(Image grayFrame=frame.Convert())
{
grayscaleImageBox.Image=grayFrame;
使用(Image smallGrayFrame=grayFrame.PyrDown())
{
使用(Image SmoothdGrayFrame=smallGrayFrame.PyrUp())
{
SmoothdRayScaleImageBox.Image=SmoothdRayFrame;
使用(图像cannyFrame=SmoothdGrayFrame.Canny(新灰度(100)、新灰度(60)))
{
cannyImageBox.Image=cannyFrame;
}
}
}
}
干杯
克里斯

我的意思是,尽管听起来很愚蠢,只要查询两次画面就行了。我知道这不是解决问题的“最先进”方法,但我也有同样的问题,我可以用这种方法解决

这是我的捕获方法

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);
        }
    }

非常感谢您的回复!我将尝试尽快实施。非常感谢。我的程序现在崩溃了,在“using”语句中的不同点抛出System.TypeInitializationException。是什么导致了这种情况/它是如何预防的?这很奇怪,上面的代码在我的工作和家用机器上工作。我希望您在某个地方尝试使用一个变量而不实际创建它,例如使用(Image smallGrayFrame=grayFrame.PyrDown())将无法工作,如果grayFrame在使用之前没有被赋值。请您通过查看底部操作:区域中的“查看详细信息”来发布内部异常详细信息,我将尝试解决它。Cheeset可能值得打开另一个问题并发布您的代码,这样我就可以应用它并找出错误的来源,Cheeser下面链接到这里: