基于OpenCv-Python的视频组合

step0:概述

  • 动机:手头有数个20秒左右的短视频(守望先锋最佳镜头),期望能组合成一个长视频
基于OpenCv-Python的视频组合_第1张图片
英雄不朽,图片来源http://upload-images.jianshu.io/upload_images/7241055-b71baeb2d99c0e77.jpg
  • 技术路线:opencv+python(opencv在Python中的封装库是cv2,依赖于numpy)

step1:打开并显示视频

要组合视频,首先需要打开视频并获取每一帧的图像,在opencv中可以使用VideoCapture这个类来打开视频,打开的视频也存在于这个类中,使用.read()方法也可以获得每一帧的图像,该方法的用法类似于生成器,每调用一次都会返回下一帧的图像。其中.waitKey()方法是延迟并获取键盘输入,传入参数是延迟时间数,单位是1/60s且必须是整数,因为原视频是60帧,所以间隔为1时是常速播放

import cv2

capture = cv2.VideoCapture(
    "../leviathan's highlight_17-08-16_00-52-33.mp4")
if capture.isOpened():
    while True:
        ret, prev = capture.read()
        if ret is True:
            cv2.imshow("", prev)
        else:
            break
        cv2.waitKey(1)

玩过守望先锋的小伙伴应该知道,那个最佳镜头的最后会一段浮现守望先锋logo的部分,我们需要切掉这一部分,方法是只截取前17.5秒的视频,因为不知道是否有24帧的视频,所以要先获得帧率再截取前17.5*fps的视频,现在的代码是

import cv2

capture = cv2.VideoCapture(
    "../leviathan's highlight_17-08-16_00-52-33.mp4")
print(capture.get(cv2.CAP_PROP_FRAME_WIDTH))
print(capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = capture.get(cv2.CAP_PROP_FPS)
if capture.isOpened():
    i = 0
    while i < fps * 17.5:
        i += 1
        ret, prev = capture.read()
        if ret is True:
            cv2.imshow("", prev)
        else:
            break
        cv2.waitKey(1)

顺便还看了下幕布的尺寸为1920*1080
参考python tools:计算视频的 FPS,以及总帧数

step2打开并显示一堆视频

因为视频一共有20个左右,所以可以使用os模块中的listdir()获取所有文件,并筛选带.mp4后缀的视频文件。这样获取的list是完全按顺序排列的,我们还可以使用random.shuffle()方法打乱整个视频列表

mp4list = [x for x in os.listdir("../") if x[-4:] == ".mp4"]
random.shuffle(mp4list)

于是遍历整个列表看所有视频了

import cv2
import os
import random

mp4list = [x for x in os.listdir("../") if x[-4:] == ".mp4"]
random.shuffle(mp4list)
print(mp4list)
for mp4file in mp4list:
    capture = cv2.VideoCapture("../%s" % mp4file)
    fps = capture.get(cv2.CAP_PROP_FPS)
    print(fps)
    if fps != 60:
        jump = 20
    else:
        jump = 1
    if capture.isOpened():
        i = 0
        while i < fps * 1:
            i += 1
            ret, prev = capture.read()
            if ret is True:
                cv2.imshow("", prev)
            else:
                break
            cv2.waitKey(jump)
cv2.destroyAllWindows()

step3:保存为一个大视频

保存视频首先需要创建一个视频容器,可以使用cv2.VideoWriter,输入参数为路径,压缩方式,帧率,幕布大小,随后使用该对象的write()方法即可写入一帧,写入完成后,使用release()方法释放容器并保存,若在次之前程序中断,那视频文件会是损坏状态,于是程序是这样的

import cv2
import os
import random

VideoWriter = cv2.VideoWriter(
    "./overwatch.avi",
    cv2.VideoWriter_fourcc('X', 'V', 'I', 'D'), 60,
    (1920, 1080))

mp4list = [x for x in os.listdir("../") if x[-4:] == ".mp4"]
random.shuffle(mp4list)
print(mp4list)
for mp4file in mp4list:
    print(mp4file)
    capture = cv2.VideoCapture("../%s" % mp4file)
    fps = capture.get(cv2.CAP_PROP_FPS)
    if capture.isOpened():
        i = 0
        while i < fps * 17.5:
            i += 1
            ret, prev = capture.read()
            if ret is True:
                if fps == 60:
                    VideoWriter.write(prev)
                else:
                    VideoWriter.write(prev)
                    VideoWriter.write(prev)
            else:
                break
VideoWriter.release()
cv2.destroyAllWindows()

其中为了补偿30帧左右的视频,非60帧图片一帧写入两次

你可能感兴趣的:(基于OpenCv-Python的视频组合)