EmguCV/OpenCV QueryFrame 慢/缓冲区

发布于 2024-08-27 01:56:47 字数 566 浏览 6 评论 0原文

我们有一个应用程序,我们从外部系统获取消息,然后拍照,进行一些处理并将某些内容返回到外部系统。做了一些性能测试,我发现了两个问题(它们有些相关)。我希望有人能够向我解释这一点。

1) _capture.QueryFrame() 是否缓冲帧? 我们看到的是,如果对来自网络摄像头的两帧的查询之间存在间隙,则第二帧通常是较旧的图片,而不是调用 queryFrame 时的图片。

我们能够通过丢弃一些帧来在一定程度上缓解这个问题,即调用 _capture.QueryFrame() 2-3 次并丢弃结果。

2) 第二个问题是当我们对应用程序的不同部分进行计时时,我们发现清除缓冲区(调用 QueryFrame() 2-3 次并且不使用结果)大约需要 65ms,然后这一行: 图像source = _capture.QueryFrame() 大约需要 80 毫秒。这两个部分占用了最大的处理时间,我们的实际处理只多花费了大约 20-30 毫秒。

是否有更快的方法(a)清除缓冲区(b)以捕获帧?

如果您有 OpenCV 经验并了解相关知识,请告诉我。

We have an application, where we get a message from an external system and then we take a picture, do some processing and return something back to the external system. Doing some performance testing, I found two problems (they are somewhat related). I was hoping someone will be able to explain this to me.

1) Does _capture.QueryFrame() buffer frames?
What we see is, if there is a gap between the query for two frames from a web camera, the second frame is often an older picture and not the one when the queryFrame was called.

We were able to mitigate this problem to some extent by discarding some frames, i.e. calling _capture.QueryFrame() 2-3 times and discarding the results.

2) The second issue is when we timed different parts of the application, we found that clearing the buffer (calling QueryFrame() 2-3 times and not using the results) takes about 65ms and then this line: Image<Bgr, Byte> source = _capture.QueryFrame() takes about 80ms. These two parts take the biggest chunk of processing time, our actual processing takes just about 20-30ms more.

Is there a faster way (a) to clear the buffer (b) to capture the frame?

If you have experience with OpenCV and know of something related, please do let me know.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

尸血腥色 2024-09-03 01:56:48

这也可能是由于您所使用的网络摄像头的刷新率造成的。我的相机工作频率为 60Hz,因此我有一个计时器,每 15 毫秒捕获一帧。

This could also be due to the refresh rate of the webcamera you are using. My camera works at 60Hz so I have a timer that takes captures a frame every 15 milliseconds.

流殇 2024-09-03 01:56:48

你可以调用 _capture.Grab();在怠速期间。或者在计时器的代码中。保持计时器间隔与相机帧捕获率相匹配。

然后当你需要调用 _capture.QueryFrame();

Grab() 所做的就是在调用 _capture.QueryFrame() 时刷新缓冲区并获取最新的帧;

You could call _capture.Grab(); during the idling time. Or inside the code of a timer. Keep the timer interval matching your camera frames capture rate.

Then when you need call the _capture.QueryFrame();

What Grab() will do is flush out the buffer and get you the latest frame when calling _capture.QueryFrame();

执着的年纪 2024-09-03 01:56:47

我回答了类似的问题 System.TypeInitializationException using Emgu.CV in C#并测试了获取最新框架的各种可能性后,我找到了以下最佳方法。

1) 是的,当您从网络摄像头设置捕获时,会创建一个环形缓冲区来存储图像,这样可以有效分配内存。

2)是的,有一种更快的方法,全局设置您的捕获设备,并将其设置为记录和调用 ProcessFrame 以尽可能从缓冲区获取图像。现在只需更改您的 QueryFrame 即可复制刚刚获取的任何帧。这有望解决您获取前一帧的问题,并且您现在将从缓冲区中获得最新的帧。

private Capture cap;
Image<Bgr, Byte> frame;

public CameraCapture()
{
    InitializeComponent();
    cap= new Capture();
    cap.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_HEIGHT, height);
    cap.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_WIDTH, width);

    Application.Idle += ProcessFrame;
}

private void ProcessFrame(object sender, EventArgs arg)
{
    frame = _capture.QueryFrame();
    grayFrame = frame.Convert<Gray, Byte>();
}

public Image<Bgr,byte> QueryFrame()
{
    return frame.Copy();
}

我希望这会有所帮助,如果不让我知道的话,我会尝试根据您的要求定制解决方案。不要忘记您始终可以让采集在不同的线程上运行并调用新的 QueryFrame 方法。

干杯

克里斯

I answered a similar question System.TypeInitializationException using Emgu.CV in C# and having tested the various possibilities to acquire an up to date frame I found the bellow the bes method.

1) yes when you set up a Capture from a webcam a ring buffer is created to store the images in this allows effcient allocation of memory.

2) yes there is a faster way, Set your Capture device up globally and set it of recording and calling ProcessFrame to get an image from the buffer whenever it can. Now change your QueryFrame simply to copy whatever frames its just acquired. This will hopefully stop your problem of getting the previous frame and you will now have the most recent frame out of the buffer.

private Capture cap;
Image<Bgr, Byte> frame;

public CameraCapture()
{
    InitializeComponent();
    cap= new Capture();
    cap.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_HEIGHT, height);
    cap.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_WIDTH, width);

    Application.Idle += ProcessFrame;
}

private void ProcessFrame(object sender, EventArgs arg)
{
    frame = _capture.QueryFrame();
    grayFrame = frame.Convert<Gray, Byte>();
}

public Image<Bgr,byte> QueryFrame()
{
    return frame.Copy();
}

I hope this helps if not let me know and I'll try and tailor a solution to your requirements. Don't forget you can always have your acquisition running on a different thread and invoke the new QueryFrame method.

Cheers

Chris

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文