Python

您所在的位置:网站首页 图片转场特效软件 Python

Python

2024-07-08 18:07| 来源: 网络整理| 查看: 265

文章目录 前言一、卡帧二、竖向开幕/横向开幕三、渐隐/渐显四、推近/拉远五、方形开幕六、灰度渐变

前言

最近学了一点简单的图像几何变换,想找点什么东西练练手,于是想起了手机上的美图秀秀,找点特效来仿制仿制😜

当然,这里并没有生成gif图片,只是通过imshow和waitKey来展示效果,不过基本原理能实现,找个库再生成gif想必也不难吧

为了避免篇幅过长,本篇只讨论单张图片的特效实现(下一篇讨论两张图片的转场实现)

以下是练习时用到的两张图片素材

001.jpg 002.jpg 一、卡帧

效果对比

美图秀秀【卡帧】 OpenCV实现【卡帧】

实现思路

简单的定时贴图

实现代码

import cv2 import numpy as np '''读入图像''' img = cv2.imread("001.jpg") rows, cols = img.shape[:2] '''缩放原图80%''' img = cv2.resize(img, (int(rows * 0.8), int(cols * 0.8))) rows_new, cols_new = img.shape[:2] '''准备更大的画布''' cav_np = np.zeros((rows, cols), np.uint8) cav = cv2.cvtColor(cav_np, cv2.COLOR_GRAY2BGR) '''偏移量准备''' dic = { 0: (int(cols * 0.08), int(rows * 0.12)), 1: (int(cols * 0.12), int(rows * 0.08)), 2: (int(cols * 0.12), int(rows * 0.06)), 3: (int(cols * 0.16), int(rows * 0.07)), 4: (int(cols * 0.14), int(rows * 0.10)), 5: (int(cols * 0.13), int(rows * 0.05)), 6: (int(cols * 0.14), int(rows * 0.08)), 7: (int(cols * 0.15), int(rows * 0.10)) } '''特效展示''' for i in range(8): xs, ys = dic[i] xe, ye = (xs + rows_new, ys + cols_new) cav[xs: xe, ys: ye] = img cv2.imshow("show", cav) cv2.waitKey(500) '''关闭窗口''' cv2.waitKey(1000) cv2.destroyAllWindows() 二、竖向开幕/横向开幕

效果对比

美图秀秀【竖向开幕】 OpenCV实现【竖向开幕】 美图秀秀【横向开幕】 OpenCV实现【横向开幕】

实现思路

准备黑色画布,控制好时间向画布上贴图,要控制好速度越来越慢即加载量越来越少 要求如下: 在 3 秒 内 , 50 % → 0 % , 非 线 性 减 少 ( 越 来 越 慢 ) 在3秒内,50\% → 0\%,非线性减少(越来越慢) 在3秒内,50%→0%,非线性减少(越来越慢) 可以设置简单的多项式函数 y = 50 % 3 n ( 3 − t ) n ( n ≥ 2 ) 其 中 , { t 时 间 ( 单 位 : 秒 ) y 从 中 间 位 置 向 上 , 未 加 载 部 分 的 高 度 百 分 比 \begin{aligned} & y = \frac{50\%}{3^n}(3-t)^n \quad (n \geq 2)\\ \\ & 其中, \begin{cases} t & 时间(单位:秒)\\ y & 从中间位置向上,未加载部分的高度百分比 \end{cases} \end{aligned} ​y=3n50%​(3−t)n(n≥2)其中,{ty​时间(单位:秒)从中间位置向上,未加载部分的高度百分比​​ 那么就可以知道 pt = ( 0.5 − y ) ⋅ height 其 中 , pt 表 示 在 t 时 刻 , 需 要 从 中 间 向 上 方 加 载 的 高 度 \begin{aligned} & \text{pt} = (0.5 - y) \cdot \text{height} \\ \\ & 其中,\text{pt}表示在t时刻,需要从中间向上方加载的高度 \end{aligned} ​pt=(0.5−y)⋅height其中,pt表示在t时刻,需要从中间向上方加载的高度​

这边取五次函数( n = 5 n = 5 n=5)、每 30 30 30 毫秒加载一次

Tips:经过测试, n ‾ \bm{\underline{n}} n​ 取值越大,动画展示越快(越早加载完整张图片)

实现代码

竖向开幕import cv2 import numpy as np '''读入图像''' img = cv2.imread("001.jpg") rows, cols = img.shape[:2] '''画布准备''' cav_np = np.zeros((rows, cols), np.uint8) cav = cv2.cvtColor(cav_np, cv2.COLOR_GRAY2BGR) '''特效展示''' load_f = 30 n = 5 half = int(rows / 2) xs1, xs2 = half, half xe1, xe2 = half, half for t in range(3000 // load_f): load_percent = 0.5 / (3 ** n) * ((3 - t * load_f / 1000) ** n) load_height = int((0.5 - load_percent) * rows) xe1, xe2 = half - load_height, half + load_height cav[xe1:xs1, :] = img[xe1:xs1, :] cav[xs2:xe2, :] = img[xs2:xe2, :] xs1, xs2 = xe1, xe2 cv2.imshow("show", cav) cv2.waitKey(load_f) '''关闭窗口''' cv2.waitKey(1000) cv2.destroyAllWindows() 横向开幕import cv2 import numpy as np '''读入图像''' img = cv2.imread("001.jpg") rows, cols = img.shape[:2] '''画布准备''' cav_np = np.zeros((rows, cols), np.uint8) cav = cv2.cvtColor(cav_np, cv2.COLOR_GRAY2BGR) '''特效展示''' load_f = 30 n = 5 half = int(rows / 2) ys1, ys2 = half, half ye1, ye2 = half, half for t in range(3000 // load_f): load_percent = 0.5 / (3 ** n) * ((3 - t * load_f / 1000) ** n) load_height = int((0.5 - load_percent) * rows) ye1, ye2 = half - load_height, half + load_height cav[:, ye1:ys1] = img[:, ye1:ys1] cav[:, ys2:ye2] = img[:, ys2:ye2] ys1, ys2 = ye1, ye2 cv2.imshow("show", cav) cv2.waitKey(load_f) '''关闭窗口''' cv2.waitKey(1000) cv2.destroyAllWindows() 三、渐隐/渐显

效果对比

美图秀秀【渐隐】 OpenCV实现【渐隐】 美图秀秀【渐显】 OpenCV实现【渐显】

实现思路

准备图像,控制好时间改变图像强度(亮度),要控制好速度越来越快 要求如下: 渐 隐 : 100 % → 0 % , 减 少 渐 显 : 0 % → 100 % , 增 长 \begin{aligned} & 渐隐:100\% → 0\%,减少 \\ & 渐显:0\% → 100\%,增长 \end{aligned} ​渐隐:100%→0%,减少渐显:0%→100%,增长​ 可以设置简单的多项式函数 渐 隐 : y = 100 % − 100 % 3 n t n ( n ≥ 1 ) 渐 显 : y = 100 % − 100 % 3 n ( 3 − t ) n ( n ≥ 1 ) 其 中 , { t 时 间 ( 单 位 : 秒 ) y 亮 度 百 分 比 \begin{aligned} & 渐隐:y = 100\%-\frac{100\%}{3^n}t^n \quad (n \geq 1)\\ \\ & 渐显:y = 100\%-\frac{100\%}{3^n}(3-t)^n \quad (n \geq 1)\\ \\ & 其中, \begin{cases} t & 时间(单位:秒)\\ y & 亮度百分比 \end{cases} \end{aligned} ​渐隐:y=100%−3n100%​tn(n≥1)渐显:y=100%−3n100%​(3−t)n(n≥1)其中,{ty​时间(单位:秒)亮度百分比​​ 这边渐隐取 n = 1 n = 1 n=1、渐显取 n = 1.5 n = 1.5 n=1.5、总时间 2 2 2 秒、每 40 40 40 毫秒加载一次

Tips:经过测试, n ‾ \bm{\underline{n}} n​ 取值越大,动画展示越快(因此,可以将动画的起点时间设置在40%的时间左右,跳过高次多项式的慢速增长阶段)

实现代码

渐隐import cv2 import numpy as np '''读入图像''' img = cv2.imread("001.jpg") rows, cols = img.shape[:2] '''特效展示''' load_f = 40 n = 1 time = 2 for t in range(time * 1000 // load_f): sc = 1 - 1 / (time ** n) * (t * load_f / 1000) ** n img_show = cv2.multiply(img, (1, 1, 1, 1), scale=sc) cv2.imshow("show", img_show) cv2.waitKey(load_f) '''关闭窗口''' cv2.waitKey(500) cv2.destroyAllWindows() 渐显import cv2 import numpy as np '''读入图像''' img = cv2.imread("001.jpg") rows, cols = img.shape[:2] '''特效展示''' load_f = 40 n = 1.5 time = 2 for t in range(time * 1000 // load_f): sc = 1 - 1 / (time ** n) * (time - t * load_f / 1000) ** n img_show = cv2.multiply(img, (1, 1, 1, 1), scale=sc) cv2.imshow("show", img_show) cv2.waitKey(load_f) '''关闭窗口''' cv2.waitKey(500) cv2.destroyAllWindows() 四、推近/拉远

效果对比

美图秀秀【推近】 OpenCV实现【推近】 美图秀秀【拉远】 OpenCV实现【拉远】

实现思路

准备图像,控制好时间展示resize后的图像局部,速度越来越慢 要求如下: 左 侧 推 近 长 度 : 0 % → 20 % , 非 线 性 增 长 ( 越 来 越 慢 ) 左 侧 拉 远 长 度 : 20 % → 0 % , 非 线 性 减 少 ( 越 来 越 慢 ) \begin{aligned} & 左侧推近长度:0\% → 20\%,非线性增长(越来越慢) \\ & 左侧拉远长度:20\% → 0\%,非线性减少(越来越慢) \\ \end{aligned} ​左侧推近长度:0%→20%,非线性增长(越来越慢)左侧拉远长度:20%→0%,非线性减少(越来越慢)​ 可以设置简单的多项式函数 推 近 : y = 33 % − 33 % 3 n ( 3 − t ) n ( n ≥ 2 ) 拉 远 : y = 33 % 3 n ( 3 − t ) n ( n ≥ 2 ) 其 中 , { t 时 间 ( 单 位 : 秒 ) y 左 侧 推 近 / 拉 远 百 分 比 \begin{aligned} & 推近:y = 33\%-\frac{33\%}{3^n}(3-t)^n \quad (n \geq 2)\\ \\ & 拉远:y = \frac{33\%}{3^n}(3 - t)^n \quad (n \geq 2)\\ \\ & 其中, \begin{cases} t & 时间(单位:秒)\\ y & 左侧推近/拉远百分比 \end{cases} \end{aligned} ​推近:y=33%−3n33%​(3−t)n(n≥2)拉远:y=3n33%​(3−t)n(n≥2)其中,{ty​时间(单位:秒)左侧推近/拉远百分比​​ 如此繁琐地自己去寻找这样的函数关系有点麻烦,因此我们需要定义一个函数,给定 a % → b % mode = { faster 越来越快 slower 越来越慢 \color{#AA66FF} \begin{aligned} & \bm{a\% → b\%} \\ \\ & \textbf{mode} = \begin{cases} \textbf{faster} & \textbf{越来越快} \\ \\ \textbf{slower} & \textbf{越来越慢} \\ \end{cases} \end{aligned} ​a%→b%mode=⎩⎪⎨⎪⎧​fasterslower​越来越快越来越慢​​ 可以生成一个根据当前时间 t \bm{t} t 计算当前到达百分比 c % \bm{c\%} c% 的函数

草稿纸上简单归纳计算,得到公式如下: y = sgn ( a % − b % ) ⋅ δ % ( time ) n ⋅ ( time − t ) n + b % mode = slower y = sgn ( b % − a % ) ⋅ δ % ( time ) n ⋅ t n + a % mode = faster 其中, δ % = ∣    a % − b %    ∣ \color{#AA66FF} \begin{aligned} & \bm{y =} \textbf{sgn}\bm{(a \% - b \%) \cdot \frac{\delta \%}{(\textbf{time})^n} \cdot (\textbf{time} - t)^n + b \%} & \textbf{mode} = \textbf{slower} \\ \\ & \bm{y =} \textbf{sgn}\bm{(b \% - a \%) \cdot \frac{\delta \%}{(\textbf{time})^n} \cdot t^n + a \%} & \textbf{mode} = \textbf{faster} \\ \\ & \textbf{其中,} \bm{\delta\% = | \; a\% - b\% \; |} \end{aligned} ​y=sgn(a%−b%)⋅(time)nδ%​⋅(time−t)n+b%y=sgn(b%−a%)⋅(time)nδ%​⋅tn+a%其中,δ%=∣a%−b%∣​mode=slowermode=faster​

再以 faster \textbf{faster} faster为基准,高度概括一下,即为 如果mode为slower,交换 a 和 b ,令      t   =   time   -   t y = sgn ( b % − a % ) ⋅ δ % ( time ) n ⋅ t n + a % \color{#AA66FF} \begin{aligned} & \textbf{如果\text{mode}为\text{slower},交换}\bm{a}\textbf{和}\bm{b}\textbf{,令 \; t = \text{time} - t} \\ \\ & \bm{y =} \textbf{sgn}\bm{(b \% - a \%) \cdot \frac{\delta \%}{(\textbf{time})^n} \cdot t^n + a \%} \\ \end{aligned} ​如果mode为slower,交换a和b,令 t = time - ty=sgn(b%−a%)⋅(time)nδ%​⋅tn+a%​

以下为百分比多项式计算函数生成器的代码:

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, a delta = abs(a - b) sgn = 1 if b - a > 0 else (-1 if b - a 0 else (-1 if b - a 0 else (-1 if b - a 0 else (-1 if b - a 0 else (-1 if b - a


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3