2015-04-28 76 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