Python 视频转场特效处理笔记

本文参考Python-OpenCV 实现美图秀秀视频剪辑效果【特效】_opencv 多张图片 视频 特效-CSDN博客

最近研究了点python处理视频相关的东西,本文展示特效包括,竖向开幕/横向开幕,渐隐/渐显,推近/拉远,方形开幕,灰度渐变。不多说,直接上代码。

import cv2
import numpy as np
import randomdef addCardFrame(video_writer,img,backimg=None,fps=18,sec=1,eachtime=0.5):"""视频特效:卡帧"""rows, cols = img.shape[:2]'''缩放原图80%'''img = cv2.resize(img, (int(cols * 0.8),int(rows * 0.8)))rows_new, cols_new = img.shape[:2]'''准备更大的画布'''cav = Noneif backimg is None:cav_np = np.zeros((rows, cols), np.uint8)cav = cv2.cvtColor(cav_np, cv2.COLOR_GRAY2BGR)else:cav = backimg'''偏移量准备'''dic = {0: (int(cols * 0.08), int(rows * 0.12)),1: (int(cols * 0.10), int(rows * 0.10)),2: (int(cols * 0.12), int(rows * 0.08)),3: (int(cols * 0.12), int(rows * 0.07)),4: (int(cols * 0.12), int(rows * 0.06)),5: (int(cols * 0.14), int(rows * 0.07)),6: (int(cols * 0.16), int(rows * 0.07)),7: (int(cols * 0.15), int(rows * 0.09)),8: (int(cols * 0.14), int(rows * 0.10)),9: (int(cols * 0.14), int(rows * 0.07)),10: (int(cols * 0.13), int(rows * 0.05)),11: (int(cols * 0.14), int(rows * 0.06)),12: (int(cols * 0.14), int(rows * 0.08)),13: (int(cols * 0.15), int(rows * 0.10)),14: (int(cols * 0.14), int(rows * 0.09)),15: (int(cols * 0.12), int(rows * 0.12)),16: (int(cols * 0.10), int(rows * 0.10)),17: (int(cols * 0.08), int(rows * 0.12))}'''添加特效展示'''for _ in range(int(sec)):xs, ys = dic[random.randrange(0,18,1)]xe, ye = (xs + rows_new, ys + cols_new)cav[xs: xe, ys: ye] = imgfor _ in range(int(eachtime*fps)):video_writer.write(cav)def addVerticalOpening(video_writer,img,backimg=None,fps=18,sec=1,mode='H'):"""视频特效:竖向开幕H 横向开幕V"""rows, cols = img.shape[:2]'''画布准备'''cav = Noneif backimg is None:cav_np = np.zeros((rows, cols), np.uint8)cav = cv2.cvtColor(cav_np, cv2.COLOR_GRAY2BGR)else:cav = backimg'''特效展示'''load_f = 1000/fpsn = 5height_half,weight_half = int(rows / 2),int(cols / 2)xs1, xs2 = height_half, height_halfxe1, xe2 = height_half, height_halfys1, ys2 = weight_half, weight_halfye1, ye2 = weight_half, weight_halffor t in range(int(sec*1000 // load_f)):load_percent = 0.5 / (sec ** n) * ((sec - t * load_f / 1000) ** n)if mode=='H':load_height = int((0.5 - load_percent) * rows)xe1, xe2 = height_half - load_height, height_half + load_heightcav[xe1:xs1, :] = img[xe1:xs1, :]cav[xs2:xe2, :] = img[xs2:xe2, :]xs1, xs2 = xe1, xe2else:load_weight = int((0.5 - load_percent) * cols)ye1, ye2 = weight_half - load_weight,weight_half + load_weightcav[:, ye1:ys1] = img[:, ye1:ys1]cav[:, ys2:ye2] = img[:, ys2:ye2]ys1, ys2 = ye1, ye2video_writer.write(cav)def addFadeOut(video_writer,img,backimg=None,fps=18,sec=2):"""视频特效:渐隐"""'''特效展示'''load_f = 1000/fpsn = 1for t in range(int(sec * 1000 // load_f)):sc = 1 - 1 / (sec ** n) * (t * load_f / 1000) ** nimg_show = cv2.multiply(img, (1, 1, 1, 1), scale=sc)video_writer.write(img_show)def addFadeIn(video_writer,img,fps=18,sec=2):"""视频特效:渐隐"""'''特效展示'''load_f = 1000/fpsn = 1.5for t in range(int(sec * 1000 // load_f)):sc = 1 - 1 / (sec ** n) * (t * load_f / 1000) ** nsc = 1 - 1 / (sec ** n) * (sec - t * load_f / 1000) ** nimg_show = cv2.multiply(img, (1, 1, 1, 1), scale=sc)video_writer.write(img_show)def percent_func_gen(a, b, time, n, mode):"""高次多项式计算函数生成器:param a: 起始百分比(如:0.25):param b: 结束百分比:param time: 动画持续时间:param n: 多项式次数:param mode: faster(越来越快)、slower(越来越慢):return: 每个时刻到达百分比的计算函数"""if mode == "slower":a, b = b, adelta = abs(a - b)sgn = 1 if b - a > 0 else (-1 if b - a < 0 else 0)def percent_calc(ti):if mode == "slower":ti = time - tireturn sgn * delta / (time ** n) * (ti ** n) + areturn percent_calcdef addAdvance(video_writer,img,fps=18,sec=2):"""视频特效:推近"""rows, cols = img.shape[:2]'''特效展示'''load_f = 1000/fpspercent_func = percent_func_gen(a=0, b=0.2, time=sec, n=4, mode="slower")for t in range(int(sec * 1000 // load_f + 1)):percent = percent_func(t * load_f / 1000)xs, xe = int(percent * rows), int((1 - percent) * rows)ys, ye = int(percent * cols), int((1 - percent) * cols)img_show = img[xs:xe, ys:ye]img_show = cv2.resize(img_show, (cols,rows))video_writer.write(img_show)def addZoomOut(video_writer,img,fps=18,sec=2):"""视频特效:拉远"""rows, cols = img.shape[:2]'''特效展示'''load_f = 1000/fpspercent_func = percent_func_gen(a=0.2, b=0, time=sec, n=3, mode="slower")for t in range(int(sec * 1000 // load_f + 1)):percent = percent_func(t * load_f / 1000)xs, xe = int(percent * rows), int((1 - percent) * rows)ys, ye = int(percent * cols), int((1 - percent) * cols)img_show = img[xs:xe, ys:ye]img_show = cv2.resize(img_show, (cols,rows))video_writer.write(img_show)def addSquareOpening(video_writer,img,backimg=None,fps=18,sec=2):"""视频特效:方形开幕"""rows, cols = img.shape[:2]'''画布准备'''cav = Noneif backimg is None:cav_np = np.zeros((rows, cols), np.uint8)cav = cv2.cvtColor(cav_np, cv2.COLOR_GRAY2BGR)else:cav = backimg'''特效展示'''load_f = 1000/fpspercent_func = percent_func_gen(a=0, b=0.5, time=sec, n=5, mode="faster")rows_half = rows // 2cols_half = cols // 2for t in range(int(sec * 1000 // load_f + 1)):percent = percent_func(t * load_f / 1000)width, height = int(percent * rows), int(percent * cols)xs, xe = rows_half-width, rows_half+widthys, ye = cols_half-height, cols_half+heightcav[xs:xe, ys:ye] = img[xs:xe, ys:ye]video_writer.write(cav)def addGradientWipe(video_writer,img,backimg=None,fps=18,sec=2,mode='L'):   """视频特效:灰度渐变 L左 R右 U上 D下"""rows, cols = img.shape[:2]'''灰度准备'''img_gray_bgr = Noneif backimg is None:img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)img_gray_bgr = cv2.cvtColor(img_gray, cv2.COLOR_GRAY2BGR)else:img_gray_bgr = backimg'''特效展示'''load_f = 1000/fpspercent_func = percent_func_gen(a=0, b=1, time=sec, n=1, mode="slower")if mode=='L':ys, ye = 0, 0for t in range(int(sec * 1000 // load_f + 1)):percent = percent_func(t * load_f / 1000)width = int(percent * cols)ye = widthimg_gray_bgr[:, ys:ye] = img[:, ys:ye] ys = yevideo_writer.write(img_gray_bgr)if mode=='R':ys, ye = cols, colsfor t in range(int(sec * 1000 // load_f + 1)):percent = percent_func(t * load_f / 1000)width = int(percent * cols)ys = cols-widthimg_gray_bgr[:, ys:ye] = img[:, ys:ye] ye = ysvideo_writer.write(img_gray_bgr)if mode=='U':xs, xe = 0, 0for t in range(int(sec * 1000 // load_f + 1)):percent = percent_func(t * load_f / 1000)height = int(percent * rows)xe = heightimg_gray_bgr[xs:xe, :] = img[xs:xe, :] xs = xevideo_writer.write(img_gray_bgr)if mode=='D':xs, xe = rows, rowsfor t in range(int(sec * 1000 // load_f + 1)):percent = percent_func(t * load_f / 1000)height = int(percent * rows)xs = cols-heightimg_gray_bgr[xs:xe, :] = img[xs:xe, :] xe = xsvideo_writer.write(img_gray_bgr)

调用方法进行视频合成

fps = 25 #视频帧数
sec = 3 # 特效时间
eachtime = 0.5 # 每帧所占时间
video_temp_path= "test.mp4"
img1 = cv2.imread("0.jpg")
img2 = cv2.imread("1.jpg")
img3 = cv2.imread("2.jpg")
video_height,video_weight =img.shape[:2]
video_writer = cv2.VideoWriter(video_temp_path, cv2.VideoWriter_fourcc(*'mp4v'), fps, (video_weight,video_height))
addCardFrame(video_writer,img1,fps,sec,eachtime)
addVerticalOpening(video_writer,img2,img1,fps,sec,mode='V')
addFadeOut(video_writer,img3,fps,sec)
addFadeIn(video_writer,img1,fps,sec)
addAdvance(video_writer,img2,fps,sec)
addZoomOut(video_writer,img3,fps,sec)
addSquareOpening(video_writer,img2,img3,fps,sec)
addGradientWipe(video_writer,img1,img2,fps,sec,mode='D')
video_writer.release()

视频效果如下:

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

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

相关文章

Excel——有效性、二级菜单联动

一、录入规范数据 1.手动输入序列录入有效性信息 选择需要录入有效性的所有单元格 选择【数据】——【有效性】——【有效性】 在【允许】输入的值之间选择【序列】 在【序列】输入框中输入想要选择的值&#xff0c;中间用逗号&#xff08;必须是英文逗号&#xff09;隔开 。…

Spring Authorization Server Spring Security密码加密

文章目录 一、修改密码编码器二、效果三、注意点1. RegisteredClient2. UserDetailsService 一、修改密码编码器 以BCryptPasswordEncoder举例。 直接将其注册成PasswordEncoder 的Bean即可。 Beanpublic PasswordEncoder passwordEncoder() {// 密码为明文方式 // ret…

【Qt学习笔记】Qt Creator环境下 信号与槽 详解(自定义信号槽、断连、lambda表达式等)

文章目录 1. 信号槽概念1.1 信号的本质1.2 槽的本质1.3 标准信号槽1.4 信号槽 实例 2. 自定义信号槽2.1 自定义槽函数2.2 自定义信号2.3 带参 信号槽 3. 信号槽的意义 与 作用4. 信号槽断连 &#xff08;了解&#xff09;5. lamda表达式的使用5.1 基本用法5.2 捕获局部变量5.3 …

JavaScript相关(一)——作用域

本篇将从JS的执行上下文开始&#xff0c;去理解&#xff1a;变量提升、 栈式调用、作用域和闭包。 参考&#xff1a; 浏览器工作原理与实践 JS执行上下文 执行上下文是 JavaScript 执行一段代码时的运行环境&#xff0c;比如调用一个函数&#xff0c;就会生成这个函数的执行…

『运维备忘录』之 Ansible 自动化运维工具

一、简介 Ansible是基于Python开发&#xff0c;集合了众多运维工具&#xff08;puppet、cfengine、chef、func、fabric&#xff09;的优点&#xff0c;实现了批量系统配置、批量程序部署、批量运行命令等功能的自动化运维工具&#xff0c;广泛用于配置管理、应用部署以及任务协…

ES节点故障的容错方案

ES节点故障的容错方案 1. es启动加载逻辑1.1 segment和translg组成和分析1.2 es节点启动流程1.3 es集群的初始化和启动过程 2. master高可用2.1 选主逻辑2.1.1 过滤选主的节点列表2.1.2 Bully算法2.1.2 类Raft协议2.1.3 元数据合并 2.2 HA切换 3. 分片高可用3.1 集群分片汇报3.…

DoWhy:Python 中的因果推断库

DoWhy&#xff1a;Python 中的因果推断库 DoWhy 是一个强大的 Python 库&#xff0c;用于因果推断和因果推断分析。本文将介绍 DoWhy 的基本概念、主要功能和使用方法&#xff0c;帮助读者了解如何利用该库进行因果推断&#xff0c;并解决因果关系的相关问题。 什么是DoWhy&…

备战蓝桥杯---动态规划(理论基础)

目录 动态规划的概念&#xff1a; 解决多阶段决策过程最优化的一种方法 阶段&#xff1a; 状态&#xff1a; 决策&#xff1a; 策略&#xff1a; 状态转移方程&#xff1a; 适用的基本条件 1.具有相同的子问题 2.满足最优子结构 3.满足无后效性 动态规划的实现方式…

2024年【R2移动式压力容器充装】考试内容及R2移动式压力容器充装免费试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 R2移动式压力容器充装考试内容参考答案及R2移动式压力容器充装考试试题解析是安全生产模拟考试一点通题库老师及R2移动式压力容器充装操作证已考过的学员汇总&#xff0c;相对有效帮助R2移动式压力容器充装免费试题学…

【Java八股面试系列】JVM-内存区域

目录 Java内存区域 运行时数据区域 线程独享区域 程序计数器 Java 虚拟机栈 StackFlowError&OOM 本地方法栈 线程共享区域 堆 GCR-分代回收算法 字符串常量池 方法区 运行时常量池 HotSpot 虚拟机对象探秘 对象的创建 对象的内存布局 句柄 Java内存区域 运…

网络套件字(理论知识)

一、源IP地址和目的IP地址 上次说到IP地址是为了是为了让信息正确的从原主机传送到目的主机&#xff0c;而原IP地址和目的IP地址就是用于标识两个主机的&#xff0c;既然叫做地址必然有着路径规划的作用&#xff0c;而路径规划最重要的就是&#xff0c;从哪来到哪去&#xff0…

机器人学、机器视觉与控制 上机笔记(第一版译文版 2.1章节)

机器人学、机器视觉与控制 上机笔记&#xff08;第一版译文版 2.1章节&#xff09; 1、前言2、本篇内容3、代码记录3.1、新建se23.2、生成坐标系3.3、将T1表示的变换绘制3.4、完整绘制代码3.5、获取点*在坐标系1下的表示3.6、相对坐标获取完整代码 4、结语 1、前言 工作需要&a…

简单说网络:TCP+UDP

TCP和UPD: (1)都工作在传输层 (2)目的都是在程序之中传输数据 (3)数据可以是文本、视频或者图片(对TCP和UDP来说都是一堆二进制数没有太大区别) 一、区别:一个基于连接一个基于非连接 将人与人之间的通信比喻为进程和进程之前的通信:基本上有两种方式(1)写信;(2)打电话;这…

Docker容器化K8s集群部署教程(一键部署sheel脚本)

本文通过脚本&#xff0c;可以快速地部署和配置Kubernetes环境&#xff0c;省去了各插件手动部署、配置的繁琐过程。 先看最终结果&#xff1a; [rootlocalhost home]# kubectl get node NAME STATUS ROLES AGE VERSION k8smaster Ready control-p…

LlamaIndex 入门实战

文章目录 LlamaIndex 入门实战1. 基本概念2. 优劣势分析3. 简单代码示例4. Index持久化5. 使用场景6. 总结 LlamaIndex 入门实战 LlamaIndex是一个连接大型语言模型&#xff08;LLMs&#xff09;与外部数据的工具&#xff0c;它通过构建索引和提供查询接口&#xff0c;使得大模…

Java学习17-- super类

重点&#xff1a;super类 & 方法重写 super类 super指的是本级的上一级&#xff0c;即father class父类 很好理解&#xff0c;比如Person class>Student class 当前在Student class执行&#xff0c;那么就写this.xxx 需要在Student程序里面调用Person&#xff0c;那就…

HarmonyOS应用/服务发布:打造多设备生态的关键一步

目前 前言HarmonyOS 应用/服务发布的重要性使用HarmonyOS 构建跨设备的应用生态前期准备工作简述发布流程生成签名文件配置签名信息编译构建.app文件上架.app文件到AGC结束语 前言 随着智能设备的快速普及和多样化&#xff0c;以及编程语言的迅猛发展&#xff0c;构建一个无缝…

大数据 - Spark系列《四》- Spark分布式运行原理

Spark系列文章&#xff1a; 大数据 - Spark系列《一》- 从Hadoop到Spark&#xff1a;大数据计算引擎的演进-CSDN博客 大数据 - Spark系列《二》- 关于Spark在Idea中的一些常用配置-CSDN博客 大数据 - Spark系列《三》- 加载各种数据源创建RDD-CSDN博客 目录 &#x1f360;…

sqli-labs-master靶场训练笔记(38-53|boss战)

2024.2.4 level-38 &#xff08;堆叠注入&#xff09; 这题乍一看感觉又是来卖萌的&#xff0c;这不是和level-1一模一样吗 然后仔细看了一下源代码&#xff0c;根据 mysqli_multi_query 猜测这题的本意应该是堆叠注入 mysqli_multi_query() 是 PHP 中用于执行多个 SQL 查…

品牌如何营造生活感氛围?媒介盒子分享

「生活感」简而言之是指人们对生活的感受和意义&#xff0c;它往往没有充斥在各种重要的场合和事件中&#xff0c;而是更隐藏在细碎平凡的生活场景中。在营销越来越同质化的当下&#xff0c;品牌应该如何打破常规模式&#xff0c;洞察消费情绪&#xff0c;找到更能打动消费者心…