【发布时间】:2015-09-23 08:18:43
【问题描述】:
我正在尝试使用 OpenCV 2.4.11 从视频文件中获取特定帧。 我已尝试遵循有关如何正确执行此操作的文档和在线教程,现在已经测试了两种方法:
1) 第一种方法是使用 video.grab() 蛮力读取每一帧,直到达到我想要的特定帧(时间戳)。如果特定帧在视频序列中较晚,则此方法很慢!
string videoFile(videoFilename);
VideoCapture video(videoFile);
double videoTimestamp = video.get(CV_CAP_PROP_POS_MSEC);
int videoFrameNumber = static_cast<int>(video.get(CV_CAP_PROP_POS_FRAMES));
while (videoTimestamp < targetTimestamp)
{
videoTimestamp = video.get(CV_CAP_PROP_POS_MSEC);
videoFrameNumber = static_cast<int>(video.get(CV_CAP_PROP_POS_FRAMES));
// Grabe frame (but don't decode the frame as we are only "Fast forwarding")
video.grab();
}
// Get and save frame
if (video.retrieve(frame))
{
char txtBuffer[100];
sprintf(txtBuffer, "Video1Frame_Target_%f_TS_%f_FN_%d.png", targetTimestamp, videoTimestamp, videoFrameNumber);
string imgName = txtBuffer;
imwrite(imgName, frame);
}
2) 第二种方法我使用 video.set(...)。如果特定帧在视频序列中较晚,则此方法更快,并且似乎不会更慢。
string videoFile(videoFilename);
VideoCapture video2(videoFile);
videoTimestamp = video2.get(CV_CAP_PROP_POS_MSEC);
videoFrameNumber = static_cast<int>(video2.get(CV_CAP_PROP_POS_FRAMES));
video2.set(CV_CAP_PROP_POS_MSEC, targetTimestamp);
while (videoTimestamp < targetTimestamp)
{
videoTimestamp = video2.get(CV_CAP_PROP_POS_MSEC);
videoFrameNumber = (int)video2.get(CV_CAP_PROP_POS_FRAMES);
// Grabe frame (but don't decode the frame as we are only "Fast forwarding")
video2.grab();
}
// Get and save frame
if (video2.retrieve(frame))
{
char txtBuffer[100];
sprintf(txtBuffer, "Video2Frame_Target_%f_TS_%f_FN_%d.png", targetTimestamp, videoTimestamp, videoFrameNumber);
string imgName = txtBuffer;
imwrite(imgName, frame);
}
问题)现在的问题是,使用这两种方法最终得到相同帧数的目标图像帧的内容不相等?!?
我很想得出结论,方法 1 是正确的,而 OpenCV video.set(...) 方法有问题。但是如果我使用 VLC 播放器找到近似的目标帧位置,实际上是方法 2 最接近“正确”结果?
作为一些额外信息:我已经测试了相同的视频序列,但在两个不同的视频文件中分别使用“avc1”MPG4 和“wmv3”WMV 编解码器进行编码。
使用 WMV 文件,找到的两个帧是否相距甚远?
使用 MPG4 文件,找到的两个帧只是略有偏差?
有没有人有这方面的经验,可以解释我的发现并告诉我从视频文件中获取特定帧的正确方法?
【问题讨论】:
-
我不是这方面的专家,但我怀疑这个问题根本不是错误。检查您的视频文件是否包含索引。如果不是,那么直接倒回到任何位置(不处理之前的所有帧)只是比特率的平均估计。因此,该例程估计从文件开始帧的距离,然后围绕该位置扫描关键帧块。这可能会很多......
标签: c++ opencv video video-capture