2015-04-28 105 views
2

我想用OpenCV在C++中讀取視頻,但是當顯示視頻時,幀率非常慢,就像原始幀率的10%。opencv video reading slow framerate

整個代碼是在這裏:

// g++ `pkg-config --cflags --libs opencv` play-video.cpp -o play-video 
// ./play-video [video filename] 

#include <iostream> 
#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 

using namespace std; 
using namespace cv; 

int main(int argc, char** argv) 
{ 
    // video filename should be given as an argument 
    if (argc == 1) { 
     cerr << "Please give the video filename as an argument" << endl; 
     exit(1); 
    } 

    const string videofilename = argv[1]; 

    // we open the video file 
    VideoCapture capture(videofilename); 

    if (!capture.isOpened()) { 
     cerr << "Error when reading video file" << endl; 
     exit(1); 
    } 

    // we compute the frame duration 
    int FPS = capture.get(CV_CAP_PROP_FPS); 
    cout << "FPS: " << FPS << endl; 

    int frameDuration = 1000/FPS; // frame duration in milliseconds 
    cout << "frame duration: " << frameDuration << " ms" << endl; 

    // we read and display the video file, image after image 
    Mat frame; 
    namedWindow(videofilename, 1); 
    while(true) 
    { 
     // we grab a new image 
     capture >> frame; 
     if(frame.empty()) 
      break; 

     // we display it 
     imshow(videofilename, frame); 

     // press 'q' to quit 
     char key = waitKey(frameDuration); // waits to display frame 
     if (key == 'q') 
      break; 
    } 

    // releases and window destroy are automatic in C++ interface 
} 

我試圖從GoPro的英雄3+的視頻,並與我的MacBook上的攝像頭的視頻,同樣的問題,這兩個視頻。這兩個視頻都可以通過VLC播放。

在此先感謝。

+0

does .get(CV_CAP_PROP_FPS)給你正確的fps?你的waitKey太大了! imshow也需要相當多的cimputation(例如,不能通過imshow獲得100fps顯示)。並記住waitKey是不準確的,特別是如果你選擇了小的等待時間。更好地切換到一些「更好」的渲染,例如像使用openGL或directShow的qt。 openCV gui比最終用戶gui更適合測試! – Micka

+0

是的,'.get(CV_CAP_PROP_FPS)'給了我正確的FPS。我的錯誤是,我沒有想到抓住框架並顯示它將需要這麼多的計算。感謝您指出了這一點! – vmarquet

+0

我用下面的答案來計算獲取幀的時間(不包括顯示時間),大概是20ms。要以正常速度播放視頻,應該是8ms。有什麼解決方案來縮短這個時間嗎? – vmarquet

回答

2

嘗試減少waitKey幀等待時間。您正在等待幀速率時間(即33 ms),以及抓取幀並顯示幀的所有時間。這意味着如果捕獲幀並顯示它需要超過0ms(它的確如此),那麼你肯定會等待太久。或者如果你真的想要準確的話,你可以計算該部分需要多長時間,然後等待剩下的部分,例如沿着線的東西:

while(true) 
{ 
    auto start_time = std::chrono::high_resolution_clock::now(); 

    capture >> frame; 
    if(frame.empty()) 
     break; 
    imshow(videofilename, frame); 

    auto end_time = std::chrono::high_resolution_clock::now(); 
    int elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count(); 

    //make sure we call waitKey with some value > 0 
    int wait_time = std::max(1, elapsed_time); 

    char key = waitKey(wait_time); // waits to display frame 
    if (key == 'q') 
     break; 
} 

整個int wait_time = std::max(1, elapsed_time);行只是爲了確保我們等待至少1毫秒,如OpenCV的需要不得不在那裏waitKey調用來獲取和處理事件,並呼籲waitKey與值< = 0告訴它等待無限的用戶輸入,我們不希望任何(在這種情況下)

+0

感謝您的回答,的確,正如上面評論中所說的那樣,我並不認爲有時間抓住一個很大的框架,因爲視頻可以順暢地播放VLC等球員。有沒有一種解決方案來減少抓幀的時間? – vmarquet

+0

有很多原因可能導致一段軟件運行速度比預期慢。也許嘗試直接使用ffmpeg和/或使用一些硬件加速解碼?閱讀720p視頻應該比你所看到的要快得多 – alrikai