Python图像合成与视频倒放

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、视频抓帧
  • 二、图像转换
    • 1,图像翻转
    • 2,图像文件倒序
  • 三、倒序视频合成
  • 四、图像截取拓展任务——动态图合成与倒放
    • 1,gif动态图生成
    • 2,gif动态图倒放
  • 总结


前言

  视频倒放涉及到视频抓帧、图像转换、视频合成等技术,这三种方法不仅可以让我们熟练运用python语法和库,还有助于我们对图像处理有进一步的认知。


一、视频抓帧

  作为MJ的忠实粉丝,小编情不自禁地选取了他的一段舞蹈视频。

永远的MJ

  视频抓帧主要是调用opencv库的方法,获取视频文件内容再按一帧为单位截取视频中每一帧的图片,最终将这些图片保存起来,保存的图片文件名按照先后顺序用数字标号。
  帧:frame,帧率:fps(frame per second)表示一个视频每秒的帧数。

  代码如下:

import cv2 #pip install opencv-python

# 定义保存图片函数
# image:要保存的图片
# pic_address:图片保存地址
# num: 图片后缀名,用于区分图片,int 类型
def save_image(image, address, num):
    pic_address = address + str(num) + '.jpg'
    cv2.imwrite(pic_address, image)

def video_to_pic(video_path, save_path, frame_rate):
    # 读取视频文件
    videoCapture = cv2.VideoCapture(video_path)
    j = 0
    i = 0
    # 读帧
    success, frame = videoCapture.read()
    while success:
        i = i + 1
        # 每隔固定帧保存一张图片
        if i % frame_rate == 0:
            j = j + 1
            save_image(frame, save_path, j)
            print('图片保存地址:', save_path + str(j) + '.jpg')
        success, frame = videoCapture.read()

if __name__ == '__main__':
    # 视频文件和图片保存地址
    SAMPLE_VIDEO = './video/test.mp4'
    SAVE_PATH = './img/'

    # 设置固定帧率
    FRAME_RATE = 1
    video_to_pic(SAMPLE_VIDEO, SAVE_PATH, FRAME_RATE)

  如下图所示,按帧读取的部分图片
Python图像合成与视频倒放_第1张图片

二、图像转换

1,图像翻转

  在部分视频抓帧的过程中,按帧截取的图片可能是倒置的,我们可以调用pillow库中的方法,将文件夹中的每一张图片摆正。小编选择的视频在按帧截取的时候并未出现图片倒置的情况,因此,这里我不做演示。

  代码如下:

import PIL.Image as img
import os
path_old = "./img/"
path_new = "./img/"
filelist = os.listdir(path_old)
total_num = len(filelist)
print(total_num)
for i in range(1,total_num + 1):
    im = img.open(path_old + str(i) + ".jpg")
    ng = im.transpose(img.ROTATE_180) #旋转 180 度角。
    #ng = im.transpose(img.FLIP_LEFT_RIGHT) #左右对换。
    # ng = im.transpose(img.FLIP_TOP_BOTTOM) # 上下对换。
    ng.save(path_new + str(i) +'.jpg')
    if i%20 == 0:
        print(i)
    print(i)

2,图像文件倒序

  图像文件倒序其实并不难,就是利用python读取文件夹里的每一个图片文件,然后根据文件名的数字序列进行倒序存储。由于os库中open方法无法打开过多文件,所以我们选取视频当中一部分进行倒放。
选取第2001到第8190张图片,然后拼接成无声的视频part_test.mp4。
  part_test代码如下:

import cv2
import os
# 保存的视频路径及视频size(1920, 1080)
writer = cv2.VideoWriter('./video/part_test.mp4', cv2.VideoWriter_fourcc('m', 'p', '4', 'v'), 60, (1920, 1080), True)

# **********设置帧的数量**********
# total_frame = len(os.listdir('./img_rev/'))
# print(total_frame)
for frame_num in range(2001,3319 + 1):

    img_path = './img/%d.jpg' % frame_num  #图片路径

    read_img = cv2.imread(img_path)
    writer.write(read_img)

writer.release()

  截取的图片生成视频如下。

part_test


  需要注意的是,cv2.VideoWriter()方法中的第二个参数强调了视频合成后的文件格式,第三个参数(此处是60)指的是合成视频的帧率,第四个参数(此处是(1920,1080))指的是合成视频的分辨率。在这串代码中,每张图片的尺寸都是严格要求的,都是1920*1080的。
  如果原视频帧率是60fps,我们将60改成30,那么合成的视频将会有些卡,类似于0.5倍速播放原视频。如果原视频帧率是120fps,而参数仍是60,那么合成的视频就类似于0.5倍速播放原视频。

  接着将这些图片倒序
  代码如下:

import PIL.Image as img
import os

path_old = "./img/"
path_new = "./img_rev/"
filelist = os.listdir(path_old)
# total_num = len(filelist)
# print(total_num)

new_imgs = [] #初始化一个新的列表,用来存放图像名称
for i in range(2001,3425 + 1):
    im = img.open(path_old + str(i) + ".jpg")
    new_imgs.append(im)

new_imgs.reverse() #列表倒序

for i,j in enumerate(new_imgs):
    j.save(path_new + str(i+1) + '.jpg')
    if i%20 == 0:
        print(i)
    print(i)

三、倒序视频合成

  使用opencv库中的VideoWriter方法,将倒序完毕的图片按照固定的帧数拼接成想要倒放的视频。
  代码如下:

import cv2
import os
# 保存的视频路径及视频size(1920, 1080)
writer = cv2.VideoWriter('./video/reversed_test.mp4', cv2.VideoWriter_fourcc('m', 'p', '4', 'v'), 60, (1920, 1080), True)

# **********设置帧的数量**********
total_frame = len(os.listdir('./img_rev/'))
print(total_frame)
for frame_num in range(1,total_frame + 1):

    img_path = './img_rev/%d.jpg' % frame_num  #图片路径

    read_img = cv2.imread(img_path)
    writer.write(read_img)

writer.release()

  倒序的图片生成视频如下。

reversed_test

四、图像截取拓展任务——动态图合成与倒放

  动态图倒放和视频倒放原理基本上是一样的,接下来我们先试着将几张不同的图片拼接起来合成一个动态图。
  小编选择了一些《狂飙》的海报,一共十张图片,图片尺寸也不完全相同。

Python图像合成与视频倒放_第2张图片

1,gif动态图生成

  代码如下:

from PIL import Image

im = Image.open("../../data/img/1.jpg")
images = []
images.append(Image.open('../../data/img/2.jpg'))
images.append(Image.open('../../data/img/3.jpg'))
images.append(Image.open('../../data/img/4.jpg'))
images.append(Image.open('../../data/img/5.jpg'))
images.append(Image.open('../../data/img/6.jpg'))
images.append(Image.open('../../data/img/7.jpg'))
images.append(Image.open('../../data/img/8.jpg'))
images.append(Image.open('../../data/img/9.jpg'))
images.append(Image.open('../../data/img/10.jpg'))

im.save('gif.gif', save_all=True, append_images=images, loop=1, duration=1, comment=b"aaabb")

  合成的gif动态图如下图所示:

gif

  我们会发现,合成的gif图片,是从第一张图片依次往后覆盖的。也就是说,动态图的合成不会因为图片尺寸不同而失败,这是与视频合成最明显的区别。

2,gif动态图倒放


  代码如下:

from PIL import Image, ImageSequence
# 读取 GIF
im = Image.open("../../data/gif/ergouzi.gif")
# GIF 图片流的迭代器
iter = ImageSequence.Iterator(im)
i = 1 #索引/位置
# 遍历图片流的每一帧
for frame in iter:
    print("image %d: mode %s, size %s" % (i, frame.mode, frame.size))
    frame.save("../../data/gif/%d.png" % i)
    i += 1
# 把 GIF 拆分为图片流
imgs = [frame.copy() for frame in ImageSequence.Iterator(im)]
# 图片流反序
imgs.reverse()  #reverse()函数/方法,是用来将列表/数组/元组/集合/字典等进行倒序的
# 将反序后的所有帧图像保存下来
imgs[0].save("../../data/gif/reverse.gif", save_all=True, append_images=imgs[1:])

  图片流部分展示:

  倒放后的动态图如下:

总结

  关于视频倒放任务到目前为止只涉及到图像处理的部分,关于视频中音频提取与音频倒放的部分将在下一期呈现给大家。以上内容仅供参考,如果大家有其他突发奇想的方法,敬请在评论区一同探讨!

你可能感兴趣的:(python编程,图像处理,opencv,python,计算机视觉)