2010-03-28 102 views
2

我們有一個應用程序,我們從外部系統獲取消息,然後我們拍攝一張照片,做一些處理並將某些東西還給外部系統。做了一些性能測試,我發現了兩個問題(它們有些相關)。我希望有人能夠向我解釋這一點。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的經驗並知道相關事宜,請告訴我。

回答

0

這也可能是由於您使用的webcamera的刷新率。我的相機工作在60Hz,所以我有一個計時器,每15毫秒捕獲一幀。

2

我回答了一個類似的問題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