在OpenCV的反向视频播放(Reverse video playback in OpenCV)

2019-06-25 21:27发布

是否有可能在OpenCV中向后播放视频? 无论是通过API调用或者通过缓冲视频帧和反向排序到一个新的视频文件。

谢谢

Answer 1:

做到这一点唯一可行的方法是手动提取帧,其中缓冲液(上存储器或文件)然后以相反的顺序重新装载它们。

问题是,视频压缩是一切剥削时间冗余 - 事实上,两个连续帧的大部分时间非常相似。 所以,它们编码全帧不时(通常每隔几百帧),那么只发送先前和当前的差异。

现在,解码工作,必须以相同的顺序做 - 解码关键帧(完整的),然后为每个新帧,增加差异来获得当前图像。

这种策略使得它很难在视频退播放。 有几种技术,但都涉及缓冲。

现在,你可能已经看到了CV_CAP_PROP_POS_FRAMES参数,由阿斯特描述。 这似乎不错,但由于上述问题,OpenCV的是不能正确地跳转到指定的帧(有多个错误在这些问题上打开)。 他们(OpenCV的开发者)正在对一些解决方案,但即使是那些会很慢(它们涉及追溯到前一个关键帧,然后解码回选择一个)。 如果你使用这个技术,每个帧必须被解码数以百计的平均时间,使得它非常慢。 然而,这是行不通的。

编辑如果你追求的缓冲办法扭转它,记住,一个解码的视频很快就会吃掉一个普通计算机的内存资源。 一种内存通常720p视频一分钟的长度需要4.7GB当解压! 在磁盘上存储帧作为单独的文件是这个问题的切实办法。



Answer 2:

另一种解决方案,类似于ArtemStorozhuk的回答是使用FPS从帧域移动到时域,然后寻求向后使用CV_CAP_PROP_POS_MSEC (其不锤像CPU CV_CAP_PROP_POS_FRAMES即可)。 下面是我的示例代码,它完美的作品上.MPG,只用大约50%的CPU。

#include <opencv2/opencv.hpp>

int main (int argc, char* argv[])
{
  cv::VideoCapture cap(argv[1]);

  double frame_rate = cap.get(CV_CAP_PROP_FPS);

  // Calculate number of msec per frame.
  // (msec/sec / frames/sec = msec/frame)
  double frame_msec = 1000 / frame_rate;

  // Seek to the end of the video.
  cap.set(CV_CAP_PROP_POS_AVI_RATIO, 1);

  // Get video length (because we're at the end).
  double video_time = cap.get(CV_CAP_PROP_POS_MSEC);

  cv::Mat frame;
  cv::namedWindow("window");

  while (video_time > 0)
  {
    // Decrease video time by number of msec in one frame
    // and seek to the new time.
    video_time -= frame_msec;
    cap.set(CV_CAP_PROP_POS_MSEC, video_time);

    // Grab the frame and display it.
    cap >> frame;
    cv::imshow("window", frame);

    // Necessary for opencv's event loop to work.
    // Wait for the length of one frame before
    // continuing the loop. Exit if the user presses
    // any key. If you want the video to play faster
    // or slower, adjust the parameter accordingly.    
    if (cv::waitKey(frame_msec) >= 0)
      break;
  }
}


Answer 3:

是的,这是可能的。 请参阅使用注释代码:

//create videocapture
VideoCapture cap("video.avi");

//seek to the end of file
cap.set(CV_CAP_PROP_POS_AVI_RATIO, 1);

//count frames
int number_of_frames = cap.get(CV_CAP_PROP_POS_FRAMES);

//create Mat frame and window to display
Mat frame;
namedWindow("window");

//main loop
while (number_of_frames > 0)
{
    //decrease frames and move to needed frame in file
    number_of_frames--;
    cap.set(CV_CAP_PROP_POS_FRAMES, number_of_frames);

    //grab frame and display it
    cap >> frame;
    imshow("window", frame);

    //wait for displaying
    if (waitKey(30) >= 0)
    {
        break;
    }
}

另请阅读此文章。



文章来源: Reverse video playback in OpenCV