是否有可能在OpenCV中向后播放视频? 无论是通过API调用或者通过缓冲视频帧和反向排序到一个新的视频文件。
谢谢
是否有可能在OpenCV中向后播放视频? 无论是通过API调用或者通过缓冲视频帧和反向排序到一个新的视频文件。
谢谢
做到这一点唯一可行的方法是手动提取帧,其中缓冲液(上存储器或文件)然后以相反的顺序重新装载它们。
问题是,视频压缩是一切剥削时间冗余 - 事实上,两个连续帧的大部分时间非常相似。 所以,它们编码全帧不时(通常每隔几百帧),那么只发送先前和当前的差异。
现在,解码工作,必须以相同的顺序做 - 解码关键帧(完整的),然后为每个新帧,增加差异来获得当前图像。
这种策略使得它很难在视频退播放。 有几种技术,但都涉及缓冲。
现在,你可能已经看到了CV_CAP_PROP_POS_FRAMES参数,由阿斯特描述。 这似乎不错,但由于上述问题,OpenCV的是不能正确地跳转到指定的帧(有多个错误在这些问题上打开)。 他们(OpenCV的开发者)正在对一些解决方案,但即使是那些会很慢(它们涉及追溯到前一个关键帧,然后解码回选择一个)。 如果你使用这个技术,每个帧必须被解码数以百计的平均时间,使得它非常慢。 然而,这是行不通的。
编辑如果你追求的缓冲办法扭转它,记住,一个解码的视频很快就会吃掉一个普通计算机的内存资源。 一种内存通常720p视频一分钟的长度需要4.7GB当解压! 在磁盘上存储帧作为单独的文件是这个问题的切实办法。
另一种解决方案,类似于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;
}
}
是的,这是可能的。 请参阅使用注释代码:
//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;
}
}
另请阅读此文章。