Python opencv realizes Meitu XiuXiu video editing effect [special effects]

preface Recently, I learned some simple image geometric transformation and wanted to find something to practice. So I th...

preface

Recently, I learned some simple image geometric transformation and wanted to find something to practice. So I thought of Meitu XiuXiu on my mobile phone and found some special effects to imitate 😜

Of course, there is no gif image generated here, but the effect is displayed through imshow and waitKey, but the basic principle can be realized. It must not be difficult to find a library to generate gif again

In order to avoid too long, this article only discusses the special effect implementation of a single picture (the next article discusses the transition implementation of two pictures)

Here are two pictures used in the exercise


001.jpg
002.jpg 1, Card frame

Effect comparison


Meitu XiuXiu [card frame]
OpenCV implementation [card frame]

Realization idea

Simple timing map

Implementation code

import cv2 import numpy as np '''Read in image''' img = cv2.imread("001.jpg") rows, cols = img.shape[:2] '''Zoom original 80%''' img = cv2.resize(img, (int(rows * 0.8), int(cols * 0.8))) rows_new, cols_new = img.shape[:2] '''Prepare a larger canvas''' cav_np = np.zeros((rows, cols), np.uint8) cav = cv2.cvtColor(cav_np, cv2.COLOR_GRAY2BGR) '''Offset preparation''' 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)) } '''Special effects display''' 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) '''close window''' cv2.waitKey(1000) cv2.destroyAllWindows()
2, Vertical opening / horizontal opening

Effect comparison


Meitu XiuXiu [vertical opening]
OpenCV implementation [vertical opening]
Meitu XiuXiu [horizontal opening]
OpenCV realizes [horizontal opening]

Realization idea

Prepare the black canvas, control the time to map on the canvas, and control the speed to be slower and slower, that is, the loading amount is less and less
The requirements are as follows: stay 3 second within , 50 % β†’ 0 % , wrong Line nature reduce less ( More come More slow ) In 3 seconds, 50 \% → 0 \%, nonlinear reduction (slower and slower) Within 3 seconds, 50% → 0%, non-linearity decreases (more and more slowly)
Simple polynomial functions can be set y = 50 % 3 n ( 3 βˆ’ t ) n ( n β‰₯ 2 ) his in , { t Time between ( single position : second ) y from in between position Set towards upper , not plus load Department branch of high degree hundred branch than \Begin & y = \ frac (3-T) ^ n \ Quad (n \ GEQ 2) \ \ \ \ & where, \ begin T & time (in seconds) \ \ Y & height percentage of unloaded part from the middle position \ end \end y=3n50% (3 − t)n(n ≥ 2), where & \ text = (0.5 - y) \ cdot \ text \ \ \ & where \ text represents the height that needs to be loaded from the middle up at time t \ end pt=(0.5 − y) ⋅ height, where pt represents the height that needs to be loaded from the middle up at time t

Take the quintic function here( n = 5 n = 5 n=5), per 30 30 Load once every 30 milliseconds

Tips: tested, n β€Ύ \bm{\underline} The larger the value of n, the faster the animation display (the earlier the full picture is loaded)

Implementation code

  • Vertical opening
    import cv2 import numpy as np '''Read in image''' img = cv2.imread("001.jpg") rows, cols = img.shape[:2] '''Canvas preparation''' cav_np = np.zeros((rows, cols), np.uint8) cav = cv2.cvtColor(cav_np, cv2.COLOR_GRAY2BGR) '''Special effects display''' 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) '''close window''' cv2.waitKey(1000) cv2.destroyAllWindows()
  • Horizontal opening
    import cv2 import numpy as np '''Read in image''' img = cv2.imread("001.jpg") rows, cols = img.shape[:2] '''Canvas preparation''' cav_np = np.zeros((rows, cols), np.uint8) cav = cv2.cvtColor(cav_np, cv2.COLOR_GRAY2BGR) '''Special effects display''' 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) '''close window''' cv2.waitKey(1000) cv2.destroyAllWindows()
3, Fade / fade

Effect comparison


Meitu XiuXiu [fading]
OpenCV implementation [fade]
Meitu XiuXiu [gradually showing]
OpenCV implementation [ fade ]

Realization idea

Prepare the image, control the time, change the image intensity (brightness), and control the speed faster and faster
The requirements are as follows: gradually latent : 100 % β†’ 0 % , reduce less gradually display : 0 % β†’ 100 % , increase long \Begin & fade: 100 \% → 0 \%, decrease \ \ & fade: 0 \% → 100 \%, increase \ end Fade: 100% → 0%, decrease: 0% → 100%, increase
Simple polynomial functions can be set gradually latent : y = 100 % βˆ’ 100 % 3 n t n ( n β‰₯ 1 ) gradually display : y = 100 % βˆ’ 100 % 3 n ( 3 βˆ’ t ) n ( n β‰₯ 1 ) his in , { t Time between ( single position : second ) y bright degree hundred branch than \Begin & fade: y = 100 \% - \ frac T ^ n \ Quad (n \ GEQ 1) \ \ \ \ & fade: y = 100 \% - \ frac (3-T) ^ n \ Quad (n \ GEQ 1) \ \ \ \ & where, \ begin T & time (in seconds) \ \ Y & brightness percentage \ end \end Fade out: y=100% − 3n100% tn(n ≥ 1) fade out: y=100% − 3n100% (3 − t)n(n ≥ 1) where, } The larger the value of n, the faster the animation will be displayed (therefore, the starting time of the animation can be set at about 40% of the time, skipping the slow growth stage of higher-order polynomials)

Implementation code

  • Fade
    import cv2 import numpy as np '''Read in image''' img = cv2.imread("001.jpg") rows, cols = img.shape[:2] '''Special effects display''' 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) '''close window''' cv2.waitKey(500) cv2.destroyAllWindows()
  • Gradually show
    import cv2 import numpy as np '''Read in image''' img = cv2.imread("001.jpg") rows, cols = img.shape[:2] '''Special effects display''' 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) '''close window''' cv2.waitKey(500) cv2.destroyAllWindows()
4, Push close / pull far

Effect comparison


Meitu XiuXiu [push closer]
OpenCV implementation [push closer]
Meitu XiuXiu [pull away]
OpenCV implementation [pull away]

Realization idea

Prepare the image and control the time to display the part of the image after resizing. The speed is getting slower and slower
The requirements are as follows: Left side PUSH near long degree : 0 % β†’ 20 % , wrong Line nature increase long ( More come More slow ) Left side PULL far long degree : 20 % β†’ 0 % , wrong Line nature reduce less ( More come More slow ) \Begin & left push length: 0 \% → 20 \%, nonlinear growth (slower and slower) \ \ & left pull length: 20 \% → 0 \%, nonlinear decrease (slower and slower) \ \ \ end Left push length: 0% → 20%, non-linear growth (slower and slower) left pull length: 20% → 0%, non-linear reduction (slower and slower)
Simple polynomial functions can be set PUSH near : y = 33 % βˆ’ 33 % 3 n ( 3 βˆ’ t ) n ( n β‰₯ 2 ) PULL far : y = 33 % 3 n ( 3 βˆ’ t ) n ( n β‰₯ 2 ) his in , { t Time between ( single position : second ) y Left side PUSH near / PULL far hundred branch than \Begin & push close: y = 33 \% - \ frac (3-T) ^ n \ Quad (n \ GEQ 2) \ \ \ \ & pull away: y = \ frac (3 - t) ^ n \ Quad (n \ GEQ 2) \ \ \ \ & where, \ begin T & time (unit: seconds) \ \ Y & left push / pull away percentage \ end \end Push in: y=33% − 3n33% (3 − t)n(n ≥ 2) pull away: y=3n33% (3 − t)n(n ≥ 2) where, \ begin & \ BM \ \ \ & \ textbf = \ begin \ textbf & \ textbf \ \ \ \ textbf & \ textbf \ \ \ \ end \end a% → b%mode = ⎩βŽͺ⎨βŽͺ⎧ fasterslower faster and slower
You can generate one based on the current time t \bm Tcalculate the current arrival percentage c % \bm Function of c%

After simple induction and calculation on the draft paper, the formula is as follows:
y = sgn ( a % βˆ’ b % ) β‹… Ξ΄ % ( time ) n β‹… ( time βˆ’ t ) n + b % mode = slower y = sgn ( b % βˆ’ a % ) β‹… Ξ΄ % ( time ) n β‹… t n + a % mode = faster Among them, Ξ΄ % = ∣ a % βˆ’ b % ∣ \color{#AA66FF} \begin & \bm \textbf\bm{(a \% - b \%) \cdot \frac{\delta \%}{(\textbf)^n} \cdot (\textbf - t)^n + b \%} & \textbf = \textbf \ \ & \bm \textbf\bm{(b \% - a \%) \cdot \frac{\delta \%}{(\textbf)^n} \cdot t^n + a \%} & \textbf = \textbf \ \ & \textbf \ BM {\ Delta \% = |; a \% - B \% \; |} \ end ​y=sgn(a%−b%)⋅(time)n δ% ​⋅(time−t)n+b%y=sgn(b%−a%)⋅(time)n δ% ⋅ tn+a%, where, δ%= ∣a%−b%βˆ£β€‹mode=slowermode=faster​

Again faster \textbf Fast is the benchmark. To sum up, it is
If the mode is slow, swap a and b , order t = time - t y = sgn ( b % βˆ’ a % ) β‹… Ξ΄ % ( time ) n β‹… t n + a % \Color {#aa66ff} \ begin & \ textbf is \ text , swap} \ bm\textbf \ bm\textbf - t} \ \ \ & \ BM \ textbf \ BM {(B \% - a \%) \ cdot \ frac {\ Delta \%} {(\ textbf ) ^ n} \ cdot T ^ n + a \%} \ \ \ end If the mode is slow, exchange a and B to make   t  =  time  -  ty=sgn(b%−a%)⋅(time)n δ% ​⋅tn+a%​

The following is the code of the percentage polynomial calculation function generator:

def percent_func_gen(a, b, time, n, mode): """ Higher order polynomial calculation function generator :param a: Starting percentage (e.g. 0).25) :param b: End percentage :param time: Animation duration :param n: Polynomial degree :param mode: faster(Faster and faster) slower((slower and slower) :return: Calculation function of arrival percentage at each time """ if mode == "slower": a, b = b, a delta = 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 - ti return sgn * delta / (time ** n) * (ti ** n) + a return percent_calc

Push close here n = 4 n = 4 n=4. Pull in n = 3 n = 3 n=3. Total time 2 2 2 seconds per 40 40 Load once every 40 milliseconds

Implementation code

  • Push close
    import cv2 import numpy as np def percent_func_gen(a, b, time, n, mode): """ Higher order polynomial calculation function generator :param a: Starting percentage (e.g. 0).25) :param b: End percentage :param time: Animation duration :param n: Polynomial degree :param mode: faster(Faster and faster) slower((slower and slower) :return: Calculation function of arrival percentage at each time """ if mode == "slower": a, b = b, a delta = 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 - ti return sgn * delta / (time ** n) * (ti ** n) + a return percent_calc '''Read in image''' img = cv2.imread("001.jpg") rows, cols = img.shape[:2] '''Special effects display''' load_f = 40 tim = 2 percent_func = percent_func_gen(a=0, b=0.2, time=tim, n=4, mode="slower") for t in range(tim * 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, (rows, cols)) cv2.imshow("show", img_show) cv2.waitKey(load_f) '''close window''' cv2.waitKey(500) cv2.destroyAllWindows()
  • Pull away
    import cv2 import numpy as np def percent_func_gen(a, b, time, n, mode): """ Higher order polynomial calculation function generator :param a: Starting percentage (e.g. 0).25) :param b: End percentage :param time: Animation duration :param n: Polynomial degree :param mode: faster(Faster and faster) slower((slower and slower) :return: Calculation function of arrival percentage at each time """ if mode == "slower": a, b = b, a delta = 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 - ti return sgn * delta / (time ** n) * (ti ** n) + a return percent_calc '''Read in image''' img = cv2.imread("001.jpg") rows, cols = img.shape[:2] '''Special effects display''' load_f = 40 tim = 2 percent_func = percent_func_gen(a=0.2, b=0, time=tim, n=3, mode="slower") for t in range(tim * 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, (rows, cols)) cv2.imshow("show", img_show) cv2.waitKey(load_f) '''close window''' cv2.waitKey(500) cv2.destroyAllWindows()
5, Square opening

Effect comparison


Meitu XiuXiu [square opening]
OpenCV implementation [square opening]

Realization idea

Prepare the canvas and control the time to display the parts of the image of the corresponding size. The speed is getting faster and faster
The requirements are as follows: game Department just square shape of half wide degree : 0 % β†’ 50 % , wrong Line nature increase long ( More come More fast ) \Begin & half width of local square: 0 \% → 50 \%, nonlinear growth (faster and faster) \ \ \ end Half width of local square: 0% → 50%, nonlinear growth (faster and faster)

This way n = 5 n = 5 n=5, total time 1 1 1 second per 10 10 Load once every 10 milliseconds

Implementation code

import cv2 import numpy as np def percent_func_gen(a, b, time, n, mode): """ Higher order polynomial calculation function generator :param a: Starting percentage (e.g. 0).25) :param b: End percentage :param time: Animation duration :param n: Polynomial degree :param mode: faster(Faster and faster) slower((slower and slower) :return: Calculation function of arrival percentage at each time """ if mode == "slower": a, b = b, a delta = 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 - ti return sgn * delta / (time ** n) * (ti ** n) + a return percent_calc '''Read in image''' img = cv2.imread("001.jpg") rows, cols = img.shape[:2] '''Canvas preparation''' cav_np = np.zeros((rows, cols), np.uint8) cav = cv2.cvtColor(cav_np, cv2.COLOR_GRAY2BGR) '''Special effects display''' load_f = 30 tim = 3 percent_func = percent_func_gen(a=0, b=0.5, time=tim, n=6, mode="faster") rows_half = rows // 2 cols_half = cols // 2 for t in range(tim * 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+width ys, ye = cols_half-height, cols_half+height cav[xs:xe, ys:ye] = img[xs:xe, ys:ye] cv2.imshow("show", cav) cv2.waitKey(load_f) '''close window''' cv2.waitKey(500) cv2.destroyAllWindows()
6, Grayscale gradient

Effect comparison


Meitu XiuXiu [grayscale gradient]
OpenCV implementation [grayscale gradient]

Realization idea

Prepare the gray canvas, control the time and display the local color image of corresponding size at a uniform speed

Implementation code

import cv2 import numpy as np def percent_func_gen(a, b, time, n, mode): """ Higher order polynomial calculation function generator :param a: Starting percentage (e.g. 0).25) :param b: End percentage :param time: Animation duration :param n: Polynomial degree :param mode: faster(Faster and faster) slower((slower and slower) :return: Calculation function of arrival percentage at each time """ if mode == "slower": a, b = b, a delta = 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 - ti return sgn * delta / (time ** n) * (ti ** n) + a return percent_calc '''Read in image''' img = cv2.imread("001.jpg") rows, cols = img.shape[:2] '''Grayscale preparation''' img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) img_gray_bgr = cv2.cvtColor(img_gray, cv2.COLOR_GRAY2BGR) '''Special effects display''' load_f = 20 tim = 1 percent_func = percent_func_gen(a=0, b=1, time=tim, n=1, mode="slower") ys, ye = 0, 0 for t in range(tim * 1000 // load_f + 1): percent = percent_func(t * load_f / 1000) width = int(percent * cols) ye = width img_gray_bgr[:, ys:ye] = img[:, ys:ye] ys = ye cv2.imshow("show", img_gray_bgr) cv2.waitKey(load_f) '''close window''' cv2.waitKey(500) cv2.destroyAllWindows()

29 September 2021, 18:04 | Views: 7247

Add new comment

For adding a comment, please log in
or create account

0 comments