c# - C# QueryFrame 中的 EmguCV 2.3.0 返回上一个查询的帧

标签 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#

最佳答案

好吧,你遇到的问题是你没有处理你的旧捕获,所以当你发送另一个捕获时,它总是会返回旧的,然后再得到另一个。从网络摄像头示例调整而来的以下代码应该可以解决问题。

_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(scale, Interpolation Method) 调整捕获图像的大小。大图像通常使用专用图像采集卡从相机传递,因此显然避免了系统依赖性,高清 USB 网络摄像头不再是这种情况。

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

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

干杯 克里斯

关于c# - C# QueryFrame 中的 EmguCV 2.3.0 返回上一个查询的帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7492764/

相关文章:

c# - 如何创建 word 文档对象的克隆?

c# - 拖放重新排序

c# - 如何从 C# 中的 List<T> 中删除对象并返回删除的对象?

c++ - 如何看懂opencv中warpAffine的源码

opencv - 人脸检测错误物体

c# - 使用 OpenCV(C#、emgu cv)检测屏幕上的输入文本字段

c# - Blazor 中的 Razor View 引擎(在运行时将 blazor 组件转换为 html 字符串)

python - 如何从python大图像中提取图片

python - 如何使用Python和OpenCV实现BRISK检测特征?

c# - 将位图转换为 OpenCvSharp IplImage