如何从 Python 中的视频创建某些选定帧的幻灯片?

问题描述

我有一个视频。在那个视频中,有一些我称之为关键帧的帧。我想选择这些帧并从中制作一个单独的视频,也许使用 FPS 10,我想尽可能高效地执行此操作

这就是我现在正在做的事情。

我保留了一个我想提取的帧数列表。然后我使用以下代码将帧保存为图像,使用 OpenCV

myFrameNumber = frame_no
cap = cv2.VideoCapture(VIDEO_FILE)
totalFrames = cap.get(cv2.CAP_PROP_FRAME_COUNT)
if myFrameNumber >= 0 & myFrameNumber <= totalFrames:
    cap.set(1,myFrameNumber)
ret,frame = cap.read()
plt.imshow(frame)
plt.savefig(f'{RESULT_FOLDER}/{frame_no}.png')
plt.close()

此后,我在结果文件夹中有大约 200-300 张图片,现在我使用 skvideo 使用以下代码将这些图像组合成视频。

frame = cv2.imread(os.path.join(image_folder,images[0]))
height,width,layers = frame.shape
out_video =  np.empty([len(images),height,3],dtype = np.uint8)
out_video =  out_video.astype(np.uint8)
for i in range(0,len(images)):
    img = cv2.imread(image_folder+'/'+images[i])
    out_video[i] = img
skvideo.io.vwrite(video_name,out_video,inputdict={'-r':str(BASE_FPS)})

但这整个过程相当缓慢,我觉得还可以做得更好。有什么建议吗?目标是快速高效地做这件事

解决方法

这取决于您要保存多少帧以及它们在原始视频中的位置。但也许它可以工作:

import cv2

frame_idx_list = [1,2,3,4,5,6,7,8,9,10]
video_name = 'video_name.mp4'
out_filename = 'out.mp4'
fps = 10

cap = cv2.VideoCapture(video_name)

h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
writer = cv2.VideoWriter(out_filename,fourcc=fourcc,fps=fps,frameSize=(w,h))

i = 0
while frame_idx_list:
    ret,frame = cap.read()
    if not ret:
        break
    if i in frame_idx_list:
        writer.write(frame)
        frame_idx_list.remove(i)
    i += 1

writer.release()

如果帧数不大,原始视频很大,而且要保存的帧数比较在视频的末尾,则应使用cap.set()方法。