Opencv VideoCapture设置CV_CAP_PROP_POS_FRAMES不起作用

use*_*426 9 opencv

我正在使用opencv从使用mpeg压缩的Vivotek相机的视频输出中读取帧.我正在尝试使用该函数从特定位置启动视频.如下所示,其中start是我想跳过的帧数.

inputVideo.set(CV_CAP_PROP_POS_FRAMES, start); 
Run Code Online (Sandbox Code Playgroud)

但是我遇到了这个问题,因为正在捕获不正确的帧,这在帧开始之前发生.

我使用的是opencv 2.4.2版

有人可以帮忙解决这个问题吗?

Blo*_*lou 14

有点太晚了,但搜索相同的主题(不是特定于Vivotek相机,而是更多关于opencV的mpeg问题):

  • 视频已编码
  • OpenCV使用FFMPEG
  • 编码使用关键帧
  • 跳过某些帧编码时无法为您提供所需的帧

看到类似的问题:

  • 在cvSetCaptureProperty中使用CV_CAP_PROP_POS_FRAMES获取单个帧

  • 如何从视频文件中获取一个帧?

  • CV_CAP_PROP_POS_FRAMES设置下一帧编号的问题

    desired position        key frame (this is where the cursor will stop)
     |   |                       |                    |
     |   >                       |                    |
     |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
    
    Run Code Online (Sandbox Code Playgroud)

    使用带轨迹板的openCV 2.4.8/VS2013的示例代码:

  • 用AVI格式测试[MPEG4视频(H264)]:设置帧位置工作正常
  • 用MPG格式测试[MPEG1/MPEG2]:设置帧位置工作正常

    double currentPos = capture.get(CV_CAP_PROP_POS_FRAMES);
    std::cout << "CV_CAP_PROP_POS_FRAMES = " << currentPos << std::endl;
    
    // position_slider 0 - 100
    double noFrame = position_slider*nbFrames / 100;
    
    // solution 1
    bool success = capture.set(CV_CAP_PROP_POS_FRAMES, noFrame);
    // solution 2
    double frameRate = capture.get(CV_CAP_PROP_FPS);
    double frameTime = 1000.0 * noFrame / frameRate;
    bool success = capture.set(CV_CAP_PROP_POS_MSEC, frameTime);
    
    if (!success) {
        std::cout << "Cannot set frame position from video file at " << noFrame << std::endl;       
        return;
    }
    
    currentPos = capture.get(CV_CAP_PROP_POS_FRAMES);
    if (currentPos != noFrame) {
        std::cout << "Requesting frame " << noFrame << " but current position == " << currentPos << std::endl;
    }
    
    success = capture.read(frame_aux);
    if (!success) {
        std::cout << "Cannot get frame from video file " << std::endl;
        return;
    }
    imshow("test", frame_aux);
    
    Run Code Online (Sandbox Code Playgroud)


ver*_*hit 7

正如 BlouBlou 所说,当你用 FFMPEG 读取一些高压缩视频格式时,它使用了“关键帧”技术来解码视频。所以设置CV_CAP_PROP_POS_FRAMES属性不会像你想要的那样工作。

我测试了 5 个 mpeg 视频以从中读取所有帧。使用获取总帧数long totalFrameNumber = capture.get(CV_CAP_PROP_FRAME_COUNT);

然后我将每个视频读了两次,第一次没有设置CV_CAP_PROP_POS_FRAMES为 0,第二次设置它。

当您设置CV_CAP_PROP_POS_FRAMES为 0 时,它确实掉了一些帧,每个视频大约 10 帧。我猜是因为关键帧不在视频的第一帧,所以FFMPEG会跳过一些帧到第一个关键帧。但有些视频格式如.avi 不会出现这样的问题。我希望我的真实经历可以为其他人节省很多时间(我花了很长时间才找到这个页面,但已经足够了)。

无论如何,强烈建议CV_CAP_PROP_POS_FRAMES您在面对 mpeg 格式的视频时不要使用获取特定帧。设置它是一个明智的选择CV_CAP_PROP_POS_MSEC:)