如何从视频中提取某一帧的图像

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何从视频中提取某一帧的图像相关的知识,希望对你有一定的参考价值。

参考技术A

1、提取一个视频中的某帧需要使用AdobePremiere,首先打开软件导入视频;

2、击左边或者右边的箭头,移动到要截取的地方,拖动滑块也可以;

3、点击导出帧按钮,如下图所示:

4、接着更改好文件名,如下图所示:

5、然后选择保存的格式,如下图所示:

6、最后点击确定按钮即可。

    官方服务
      官方网站官方网站

获取视频中每一帧的时间戳

【中文标题】获取视频中每一帧的时间戳【英文标题】:Getting timestamp of each frame in a video 【发布时间】:2018-05-24 09:42:42 【问题描述】:

我使用我编写的 Android 5.2 应用程序从平板电脑的前置摄像头录制了几个视频。我已经为每个视频存储了以毫秒(Unix 时间)为单位的开始时间戳。

很遗憾,每个视频都有不同的帧速率(范围从 20 到 30)。使用 OpenCV,我可以获得每个视频的帧率:

import cv2
video = cv2.VideoCapture(videoFile)
fps = video.get(cv2.CAP_PROP_FPS)

这很好用,理论上我可以为视频中的每一帧添加 1000/fps(由于毫秒)。但这假设帧速率在整个录制过程中保持稳定。不知道是不是这样。

在 Python 中是否有可能获得独立于帧速率的视频中每一帧的时间戳(以毫秒为单位)?

【问题讨论】:

您是如何制作视频的?什么编解码器/容器? 【参考方案1】:

这是一个简化版本,它只是读取视频并打印出带有时间戳的帧号。

import cv2

cap = cv2.VideoCapture('path_to_video/video_filename.avi')

frame_no = 0
while(cap.isOpened()):
    frame_exists, curr_frame = cap.read()
    if frame_exists:
        print("for frame : " + str(frame_no) + "   timestamp is: ", str(cap.get(cv2.CAP_PROP_POS_MSEC)))
    else:
        break
    frame_no += 1

cap.release()

这给出了如下所示的输出:

for frame : 0   timestamp is:  0.0
for frame : 1   timestamp is:  40.0
for frame : 2   timestamp is:  80.0
for frame : 3   timestamp is:  120.0
for frame : 4   timestamp is:  160.0
for frame : 5   timestamp is:  200.0
for frame : 6   timestamp is:  240.0
for frame : 7   timestamp is:  280.0
for frame : 8   timestamp is:  320.0
for frame : 9   timestamp is:  360.0
for frame : 10   timestamp is:  400.0
for frame : 11   timestamp is:  440.0
for frame : 12   timestamp is:  480.0
...

【讨论】:

【参考方案2】:

我已经使用moviepy来获取单个帧的秒数

pip install moviepy

import sys
import numpy as np
import cv2
import moviepy.editor as mpy
from matplotlib import pyplot as plt

vid = mpy.VideoFileClip('input_video\\v3.mp4')

for i, (tstamp, frame) in enumerate(vid.iter_frames(with_times=True)):
    print(tstamp%60)
    plt.imshow(frame)
    plt.show()

【讨论】:

【参考方案3】:

通常这些相机都有卷帘快门,这意味着图像是逐行扫描的,所以严格来说,不能在图像上放置一个时间戳。我一直在使用精确定时(ns 级)的 LED 闪光灯同步多个卷帘快门相机(iPhone 6)。我发现帧速率是可变的(高速时标称 240 fps,但在 239 和 241 之间变化。相互同步可以达到 1/500000 秒,但这需要特殊设置。如果你有兴趣我可以发给你一些文档(恐怕我的软件是在Matlab中的,所以没有现成的python代码)

【讨论】:

【参考方案4】:

你想要cv2.CAP_PROP_POS_MSEC。查看所有不同的捕获属性here。

编辑:实际上,正如 Dan Mašek 向我指出的那样,当您获取该属性时,看起来 OpenCV 是 exactly doing that calculation(至少假设您使用的是 FFMPEG):

case CV_FFMPEG_CAP_PROP_POS_MSEC:
    return 1000.0*(double)frame_number/get_fps();

因此,您似乎总是要依赖恒定帧速率假设。但是,即使假设帧速率恒定,重要的是乘以帧数,而不仅仅是不断添加1000/fps。当您反复添加浮点数时,错误会累积起来,在较长的视频中,这会产生很大的不同。例如:

import cv2

cap = cv2.VideoCapture('vancouver2.mp4')
fps = cap.get(cv2.CAP_PROP_FPS)

timestamps = [cap.get(cv2.CAP_PROP_POS_MSEC)]
calc_timestamps = [0.0]

while(cap.isOpened()):
    frame_exists, curr_frame = cap.read()
    if frame_exists:
        timestamps.append(cap.get(cv2.CAP_PROP_POS_MSEC))
        calc_timestamps.append(calc_timestamps[-1] + 1000/fps)
    else:
        break

cap.release()

for i, (ts, cts) in enumerate(zip(timestamps, calc_timestamps)):
    print('Frame %d difference:'%i, abs(ts - cts))

第 0 帧差异:0.0 帧 1 差异:0.0 第 2 帧差异:0.0 第 3 帧差异:1.4210854715202004e-14 第 4 帧差异:0.011111111111091532 第 5 帧差异:0.011111111111091532 第 6 帧差异:0.011111111111091532 第 7 帧差异:0.011111111111119953 第 8 帧差异:0.022222222222183063 第 9 帧差异:0.022222222222183063 ... 第 294 帧差异:0.8111111111411446

这当然是以毫秒为单位的,所以它可能看起来并没有那么大。但在这里我的计算时间差了将近 1 毫秒,而这只是一个 11 秒的视频。无论如何,使用这个属性更容易。

【讨论】:

非常感谢您的回答。 CAP_PROP_POS_MSEC 是否也可以补偿视频录制期间帧率的变化? @machinery no.顶部的帧率计算代码是来自 OpenCV的源代码,所以它就像你做的那样计算它。它假设恒定的 FPS。你确定你真的有可变帧速率吗?这不是很常见。 您是否建议即使是 opencv 也没有在固定帧速率下可靠地提供帧时间戳的解决方案? @PratikKhadloya 除了不自己计算之外,我没有建议任何东西,我在执行该计算的 OpenCV 库中链接了特定代码。它计算帧时间戳——如果视频具有恒定的 FPS,则没有理由不可靠。 感谢您的快速确认!

以上是关于如何从视频中提取某一帧的图像的主要内容,如果未能解决你的问题,请参考以下文章

如何将avi格式的视频文件利用matlab提取成一帧一帧的序列图像?

如何通过matlab把AVI格式的视频提取出随意的一帧,并保存为图像,希望能给出完整的代码!

如何提取视频中一帧图片

怎么从iPhone6s的live photo中提取某一帧的画面

来自视频帧的画布中的drawImage改变色调

如何使用 nodejs 获取 gif 图像帧的 base64?