EmguCV/OpenCV QueryFrame slow/buffers

问题描述:

我们有一个应用程序,我们从外部系统获取消息,然后我们拍摄一张照片,做一些处理并将某些东西还给外部系统。做了一些性能测试,我发现了两个问题(它们有些相关)。我希望有人能够向我解释这一点。EmguCV/OpenCV QueryFrame slow/buffers

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

我们在某种程度上可以通过丢弃一些帧来解决这个问题,例如,调用_capture.QueryFrame() 2-3次并丢弃结果。 2)第二个问题是当我们对应用程序的不同部分进行计时时,我们发现清除缓冲区(调用QueryFrame() 2-3次而不使用结果)大约需要65ms,然后这一行:Image<Bgr, Byte> source = _capture.QueryFrame()需要大约80ms 。这两个部分占用了大部分处理时间,我们的实际处理时间仅需20-30ms左右。

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

如果您有使用OpenCV的经验并知道相关事宜,请告诉我。

这也可能是由于您使用的webcamera的刷新率。我的相机工作在60Hz,所以我有一个计时器,每15毫秒捕获一帧。

我回答了一个类似的问题System.TypeInitializationException using Emgu.CV in C#,并测试了各种可能性来获取最新的框架,我发现beows方法。

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方法。

干杯

克里斯

+0

如何在一个控制台应用程序:有没有Application.Idle事件?捕获如何完成? – Tony 2012-08-04 21:49:04

+2

嗨托尼,你有两个选项要么使用计时器,但这限制了帧速率,或者干脆用while(true){frame = _capture.QueryFrame();来启动一个新线程。 }所以你有一个独立的线程捕捉图像。您可能需要添加访问处理程序或在那里有一个小的延迟,但它应该工作,干杯 – Chris 2012-08-07 08:33:13

+0

谢谢!一个新线程的想法是非常好的。我把它放在控制台appplication上,现在它工作了。 – Tony 2012-08-07 11:53:53