Python图像合成与视频倒放

news2025/1/11 7:03:06

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

文章目录

  • 前言
  • 一、视频抓帧
  • 二、图像转换
    • 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)

  如下图所示,按帧读取的部分图片
在这里插入图片描述

二、图像转换

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

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

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

海报图

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:])

  图片流部分展示:
在这里插入图片描述

  倒放后的动态图如下:
在这里插入图片描述

总结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/194022.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

面了个阿里拿28k跳槽出来的,真正见识到了跳槽天花板

2022年已经结束了,迎来的是2023崭新的一年,最近内卷严重,各种跳槽裁员,相信很多小伙伴也在准备金三银四的面试计划。 作为一个入职5年的老人家,目前工资比较乐观,但是我还是会选择跳槽,因为感觉…

MySQL表中的联合查询

上一篇有关聚合查询的博客:MySQL表中的聚合查询_徐憨憨!的博客-CSDN博客主要是针对单个表进行查询操作,但是实际的开发环境中,数据往往来自己于不同的数据表,此时就需要使用联合查询进行操作!联合查询多表查询的基本执行过程:进行笛卡尔积然后设置条件删除无效数据进…

Echarts环形图线性渐变,hover后显示阴影

第004个点击查看专栏目录Echarts的渐变在上一篇文章中已经讲过 ECharts线性渐变色示例演示(2种渐变方式),这里做了环形图,饼图的一个渐变示例演示,hover到元素后,会呈现出一个阴影。注意,颜色属…

年度总结 | 积跬步以至千里,2023一起筑梦新征程

2022年,是值得载入史册的一年。疫情开放,健康码隐入历史尘埃。国际形势紧张,信创化进入快车道。企业加速转型,跨界技术融合的运维新生态已初露苗头。回顾2022,我们聚沙成塔逆寒流而勇进,精造创新以实践诠释…

【Linux】基础网络编程

计算机网络基本概念 在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。 计算机网络的分类与一般的事物分类方法一样,可以按事物所具有的不同性质特点分类。计算机网络通俗地讲就是由多台计算…

VMware双网卡配置(ubuntu)

桥接的时候不能上网,上网的时候又不能桥接和开发板通信,这是一个非常难受的事情,下面我来配置一下双网卡,一个用来桥接和单片机通信,一个用来上网。 ⚫ NAT 网卡:Ubuntu 通过它上网,只要 Windo…

【快速开始】vuejs环境搭建第一个项目

本篇包含vuejs环境安装以及通过vue客户端快速创建运行第一个项目。(注:以下内容均已windows平台为基准) 目录: 一、安装nodejs 二、配置国内源加速 三、安装vue客户端 四、创建第一个应用 1、安装nodejs: 1.1、下载 官网下载地址&…

【Java】java | smart-doc + tonar | API文档统一管理

一、说明 1、准备舍弃swagger了,拥抱smart-doc 2、win10 3、jdk8 4、idea 二、搭建torna 1)下载zip https://foruda.gitee.com/attach_file/1672544760054905357/torna-1.19.4.zip?token25e02a8e2817a757a0aa47172349cc20&ts1675345098&am…

06 Sentinel规则持久化(3)

Sentinel 持久化模式 Sentinel规则的推送有下面三种模式: 1、原始模式 如果不做任何修改,Dashboard 的推送规则方式是通过 API 将规则推送至客户端并直接更新到内存中: 这种做法的好处是简单,无依赖;坏处是应用重启规则就会消失…

智能网联汽车信息安全敲响「警钟」,如何筑牢防线?

2009年起,谷歌、百度等互联网科技公司就入局自动驾驶,旨在赋予汽车更智慧的大脑。 如今,物流、港口等场景下自动驾驶的商业化落地,众多的网联化接口不仅加强了智能网联汽车与操作环境之间的紧密关联,也促使智能网联汽…

Linux 学习笔记 文件、目录操作与用户群组权限

一、命令行提示符 1.1 命令行基础 bearpi:当前用户名,在前是用户名 ubuntu:用户所在的域名,在后面,这是我自定义的,默认应该是主机名 ~ 波浪线为目前所在目录,~代表家目录(home d…

【LMI传感器】LMI Gocator线激光传感器环境变量配置

文章目录1 打开系统环境配置界面2 环境变量配置1 打开系统环境配置界面 控制面板>系统和安全>系统>高级系统设置 系统属性>高级>环境变量 2 环境变量配置 环境变量配置 GENICAM_GENTL32_PATH E:\Program Files(x86)\GoCator\Release_5.3.22.22(SR1)\Integ…

ios pod更换三方库source

无法访问github,pod无法添加三方库,此时gitlab上有这个三方库并且可以访问。以FMDB为例子本地路径:/Users/用户名/.cocoapods/repos/trunk/Specs/f/4/e/FMDB/2.7.5修改podspec.json内sourcegithubgitlab"source": { "git"…

Pipenv:作为 Python 开发人员为什么应该使用它

Pipenv 是一个旨在将所有打包世界中最好的东西带到 Python 世界的工具。它将 Pipfile、pip 和 virtualenv 整合到一个命令中。它会自动为您的项目创建和管理虚拟环境,并在您安装/卸载包时从您的 Pipfile 添加/删除包。在深入研究之前,让我们先看看 Pipen…

抓包对抗原理与案例

服务端校验客户端 案例:爱奇艺 平时我们碰到的HTTP和HTTPS都在应用层,SOCKS在会话层,TCP和UDP在传输层,IP在网络层。 HTTP未加密主要有这些不足 通信使用明文(不加密),内容可能会被窃听 不验证通信方的身份,因此有可能遭遇伪装…

2月2日 读书笔记

段的起始地址用32位来表示,被称为段的基址,在本书中被分成了3段,分别为2字节、1字节、1字节。之所以这么做,主要是为了与80286时代的程序兼容。有了这样的规格,80286用的操作系统,也可以不用修改就在386以后…

不忘初心,勇攀高峰!低代码公司流辰信息紧抓机遇,努力超前冲!

在数字化发展趋势越来越激烈的当下,市场变得风云变幻,作为一家致力于提升企业办公自动化效率的低代码公司平台服务商,流辰信息矢志不渝,不忘初心,紧跟时代发展潮流,坚持围绕客户需求研发创新,提…

马哥架构第4周课程作业

docker应用一. docker常用命令博客1.1 Docker安装及基础命令介绍1.1.1 Docker 安装准备1.1.2 安装和删除方法1.1.2.1 Ubuntu 安装和删除Docker1.1.2.2 CentOS 安装和删除Docker1.1.2.3 Linux 二进制安装1.1.2.4 安装 podman1.1.2.5 在不同系统上实现一键安装 docker 脚本1.1.2.…

HBase入门概念

文章目录HBase存储结构数据模型table 逻辑结构切分存储table 物理结构架构 todo使用DDLDMLphoenixHBase nosql (k,v) 以HDFS为基础存储数据 存储结构 数据模型 nameSpace: 命名空间table: 表(需要声明…

浅谈C/S和B/S架构的工作原理及优缺点

C/S架构 一、C/S架构及其背景 C/S架构是一种比较早的软件架构,主要应用于局域网内。在这之前经历了集中计算模式,随着计算机网络的进步与发展,尤其是可视化工具的应用,出现过两层C/S和三层C/S架构,不过一直很流行也比…