Video combination based on OpenCv-Python

Video combination based on OpenCv-Python

step0: Overview

  • Motivation: I have several short videos of about 20 seconds (the best shot of Overwatch), I hope they can be combined into a long video

The hero is immortal, image source http://upload-images.jianshu.io/upload_images/7241055-b71baeb2d99c0e77.jpg

  • Technical route: opencv+python (the package library of opencv in Python is cv2, which depends on numpy)

step1: Open and display the video

To combine videos, you first need to open the video and get the image of each frame. You can use VideoCapturethis class to open the video in opencv . The opened video also exists in this class. The .read()method can also get the image of each frame. The usage is similar to the generator, each call will return the image of the next frame. The .waitKey()method is to delay and get keyboard input. The incoming parameter is the delay time, the unit is 1/60s and must be an integer, because the original video is 60 frames, so when the interval is 1, it is played at a constant speed.

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)

Friends who have played Overwatch should know that the last part of the best shot will show the Overwatch logo. We need to cut this part. The method is to only capture the first 17.5 seconds of the video, because I don’t know if there are 24 frames. Video, so you need to get the frame rate first and then capture the video of the first 17.5*fps, the current code is

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)

By the way, I also saw that the size of the screen is 1920*1080. Reference python tools: Calculate the FPS of the video and the total number of frames

step2 open and display a bunch of videos

Because there are about 20 videos, you can use the osmodule to listdir()get all the files and filter the .mp4suffixed video files. The list obtained in this way is completely arranged in order, and we can also use random.shuffle()methods to disrupt the entire video list

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

So traverse the entire list to see all the videos

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: save as a big video

To save a video, you first need to create a video container, which can be used cv2.VideoWriter. The input parameters are path, compression method, frame rate, screen size, and then use the write()method of the object to write a frame. After the writing is completed, use the release()method to release the container and save , If the program is interrupted before this time, the video file will be damaged, so the program is like this

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()

In order to compensate for about 30 frames of video, non-60 frames of pictures are written twice a frame

Reference: https://cloud.tencent.com/developer/article/1110615 Video combination based on OpenCv-Python-Cloud + Community-Tencent Cloud