Log in

View Full Version : Transparent overlay on VapourSynth?


SilSinn9801
3rd May 2019, 03:29
I am using vsutils.py to try to overlay a sequence of transparent-background PNG visual effects on top of an opaque PNG logo screen:
from vapoursynth import core
import vsutils as vsu
import functools
import sys
vsufuncs = vsu.vsutils()

# Background logo
# 24-bit RGB (RGB888); using most recent version of FFMS2 to open PNG image
rawlogo = core.ffms2.Source(r'logo.png')
rawlogoframe = rawlogo.std.AssumeFPS(fpsnum=60000,fpsden=1001)
blackframe = rawlogoframe.std.BlankClip()
blackframeseq1 = blackframe*150
rawlogoseq = rawlogoframe*339
blackframeseq2 = blackframe*20
fadeinlogo = vsufuncs.FadeIn(rawlogoseq,1.685)
fadeoutlogo = vsufuncs.FadeOut(fadeinlogo,0.25)
logo = blackframeseq1+fadeoutlogo+blackframeseq2

# Overlaid VFX; 32-bit RGB+alpha (ARGB8888)
vfx00 = core.ffms2.Source(r'VFX__000.PNG')*118
vfx01 = core.ffms2.Source(r'VFX__118.PNG')*8
vfx02 = core.ffms2.Source(r'VFX__126.PNG')*18
vfx03 = core.ffms2.Source(r'VFX__144.PNG')*2
vfx04 = core.ffms2.Source(r'VFX__146.PNG')*2
vfx05 = core.ffms2.Source(r'VFX__148.PNG')*2
vfx06 = core.ffms2.Source(r'VFX__150.PNG')*2
vfx07 = core.ffms2.Source(r'VFX__152.PNG')*2
vfx08 = core.ffms2.Source(r'VFX__154.PNG')*2
vfx09 = core.ffms2.Source(r'VFX__156.PNG')*2
vfx10 = core.ffms2.Source(r'VFX__158.PNG')*2
vfx11 = core.ffms2.Source(r'VFX__160.PNG')*4
vfx12 = core.ffms2.Source(r'VFX__164.PNG')*2
vfx13 = core.ffms2.Source(r'VFX__166.PNG')*2
vfx14 = core.ffms2.Source(r'VFX__168.PNG')*2
vfx15 = core.ffms2.Source(r'VFX__170.PNG')*2
vfx16 = core.ffms2.Source(r'VFX__172.PNG')*2
vfx17 = core.ffms2.Source(r'VFX__174.PNG')*2
vfx18 = core.ffms2.Source(r'VFX__176.PNG')*2
vfx19 = core.ffms2.Source(r'VFX__178.PNG')*2
vfx20 = core.ffms2.Source(r'VFX__180.PNG')*2
vfx21 = core.ffms2.Source(r'VFX__182.PNG')*2
vfx22 = core.ffms2.Source(r'VFX__184.PNG')*2
vfx23 = core.ffms2.Source(r'VFX__186.PNG')*2
vfx24 = core.ffms2.Source(r'VFX__188.PNG')*2
vfx25 = core.ffms2.Source(r'VFX__190.PNG')*2
vfx26 = core.ffms2.Source(r'VFX__192.PNG')*4
vfx27 = core.ffms2.Source(r'VFX__196.PNG')*2
vfx28 = core.ffms2.Source(r'VFX__198.PNG')*2
vfx29 = core.ffms2.Source(r'VFX__200.PNG')*2
vfx30 = core.ffms2.Source(r'VFX__202.PNG')*2
vfx31 = core.ffms2.Source(r'VFX__204.PNG')*2
vfx32 = core.ffms2.Source(r'VFX__206.PNG')*3
vfx33 = core.ffms2.Source(r'VFX__210.PNG')*2
vfx34 = core.ffms2.Source(r'VFX__211.PNG')*2
vfx35 = core.ffms2.Source(r'VFX__213.PNG')*2
vfx36 = core.ffms2.Source(r'VFX__215.PNG')*4
vfx37 = core.ffms2.Source(r'VFX__219.PNG')*2
vfx38 = core.ffms2.Source(r'VFX__221.PNG')*4
vfx39 = core.ffms2.Source(r'VFX__225.PNG')*2
vfx40 = core.ffms2.Source(r'VFX__227.PNG')*2
vfx41 = core.ffms2.Source(r'VFX__229.PNG')*2
vfx42 = core.ffms2.Source(r'VFX__231.PNG')*2
vfx43 = core.ffms2.Source(r'VFX__233.PNG')*4
vfx44 = core.ffms2.Source(r'VFX__237.PNG')*2
vfx45 = core.ffms2.Source(r'VFX__239.PNG')*2
vfx46 = core.ffms2.Source(r'VFX__242.PNG')*2
vfx47 = core.ffms2.Source(r'VFX__243.PNG')*2
vfx48 = core.ffms2.Source(r'VFX__245.PNG')*2
vfx49 = core.ffms2.Source(r'VFX__247.PNG')*4
vfx50 = core.ffms2.Source(r'VFX__251.PNG')*2
vfx51 = core.ffms2.Source(r'VFX__253.PNG')*2
vfx52 = core.ffms2.Source(r'VFX__255.PNG')*2
vfx53 = core.ffms2.Source(r'VFX__257.PNG')*2
vfx54 = core.ffms2.Source(r'VFX__259.PNG')*2
vfx55 = core.ffms2.Source(r'VFX__261.PNG')*2
vfx56 = core.ffms2.Source(r'VFX__263.PNG')*4
vfx57 = core.ffms2.Source(r'VFX__267.PNG')*2
vfx58 = core.ffms2.Source(r'VFX__269.PNG')*2
vfx59 = core.ffms2.Source(r'VFX__271.PNG')*2
vfx60 = core.ffms2.Source(r'VFX__273.PNG')*2
vfx61 = core.ffms2.Source(r'VFX__275.PNG')*2
vfx62 = core.ffms2.Source(r'VFX__277.PNG')*2
vfx63 = core.ffms2.Source(r'VFX__279.PNG')*4
vfx64 = core.ffms2.Source(r'VFX__283.PNG')*4
vfx65 = core.ffms2.Source(r'VFX__287.PNG')*2
vfx66 = core.ffms2.Source(r'VFX__289.PNG')*2
vfx67 = core.ffms2.Source(r'VFX__291.PNG')*2
vfx68 = core.ffms2.Source(r'VFX__293.PNG')*2
vfx69 = core.ffms2.Source(r'VFX__295.PNG')*2
vfx70 = core.ffms2.Source(r'VFX__297.PNG')*2
vfx71 = core.ffms2.Source(r'VFX__299.PNG')*3
vfx72 = core.ffms2.Source(r'VFX__302.PNG')*3
vfx73 = core.ffms2.Source(r'VFX__305.PNG')*2
vfx74 = core.ffms2.Source(r'VFX__307.PNG')*3
vfx75 = core.ffms2.Source(r'VFX__310.PNG')*2
vfx76 = core.ffms2.Source(r'VFX__312.PNG')*2
vfx77 = core.ffms2.Source(r'VFX__314.PNG')*2
vfx78 = core.ffms2.Source(r'VFX__316.PNG')*2
vfx79 = core.ffms2.Source(r'VFX__318.PNG')*4
vfx80 = core.ffms2.Source(r'VFX__322.PNG')*2
vfx81 = core.ffms2.Source(r'VFX__324.PNG')*2
vfx82 = core.ffms2.Source(r'VFX__326.PNG')*4
vfx83 = core.ffms2.Source(r'VFX__330.PNG')*2
vfx84 = core.ffms2.Source(r'VFX__332.PNG')*2
vfx85 = core.ffms2.Source(r'VFX__334.PNG')*4
vfx86 = core.ffms2.Source(r'VFX__338.PNG')*2
vfx87 = core.ffms2.Source(r'VFX__000.PNG')*169
vfxseq = vfx00+vfx01+vfx02+vfx03+vfx04+vfx05+vfx06+vfx07+vfx08+vfx09+ \
vfx10+vfx11+vfx12+vfx13+vfx14+vfx15+vfx16+vfx17+vfx18+vfx19+ \
vfx20+vfx21+vfx22+vfx23+vfx24+vfx25+vfx26+vfx27+vfx28+vfx29+ \
vfx30+vfx31+vfx32+vfx33+vfx34+vfx35+vfx36+vfx37+vfx38+vfx39+ \
vfx40+vfx41+vfx42+vfx43+vfx44+vfx45+vfx46+vfx47+vfx48+vfx49+ \
vfx50+vfx51+vfx52+vfx53+vfx54+vfx55+vfx56+vfx57+vfx58+vfx59+ \
vfx60+vfx61+vfx62+vfx63+vfx64+vfx65+vfx66+vfx67+vfx68+vfx69+ \
vfx70+vfx71+vfx72+vfx73+vfx74+vfx75+vfx76+vfx77+vfx78+vfx79+ \
vfx80+vfx81+vfx82+vfx83+vfx84+vfx85+vfx86+vfx87
vfx = vfxseq.std.AssumeFPS(fpsnum=60000,fpsden=1001)

# Overlay VFX on top of background logo
finallogo = vsufuncs.Overlay(logo,vfx,0,0)

finallogo.set_output()
But rather than seeing the logo behind the VFX, I only see the VFX alone, as if the VFX’s transparent background were converted to black.

Any insights on this? Maybe shall I use raw code rather than Overlay() and extract different mask data for the VFX overlay?

poisondeathray
3rd May 2019, 03:50
I don't know about vsutils' Overlay , but havsfunc's Overlay works like this (basically the same as avisynth's Overlay):

Overlay using transparency requires you to specify the alpha channel mask

But in vapoursynth for RGBA , the [0] is for the RGB channels , [1] is for the alpha (different than avisynth)

Overlay order is the base layer first , then the overlay on top ie. overlay(base, top) .


.
.
.
import havsfunc as haf
.
.
.

final = haf.Overlay( logo, vfx[0], mask=vfx[1])

final.set_output()

SilSinn9801
3rd May 2019, 04:00
I don't know about vsutils' Overlay , but havsfunc's Overlay works like this (basically the same as avisynth's Overlay):

Overlay using transparency requires you to specify the alpha channel mask

But in vapoursynth for RGBA , the [0] is for the RGB channels , [1] is for the alpha (different than avisynth)

Overlay order is the base layer first , then the overlay on top ie. overlay(base, top) .

I tried this other Overlay with your suggestion and still I get the same result: the VFX’s transparent background turning into black and completely hiding the logo behind it. Is there something I am missing (like changing the assumed colorspace)?

poisondeathray
3rd May 2019, 04:02
This works on standard RGBA and RGB images or video (8bit)

It might be an alpha interpretation issue for you

Can you see the alpha channel when you return [1] ? It should be black/white

This should show the alpha
vfx[1].set_output()

This should show the RGB as what you see normally, but without transparency (black where transparent should be)
vfx[0].set_output()



Upload 1 image of each, logo.png, and VFX__118.PNG (or choose one that you can see something)

SilSinn9801
3rd May 2019, 04:06
This works on standard RGBA and RGB images or video (8bit)

It might be an alpha interpretation issue for you

Upload 1 image of each, logo.png, and VFX__118.PNG (or choose one that you can see something)

Done. As a side note, after you edited your reply and reversed the order, I got instead the logo but no VFX showing up

poisondeathray
3rd May 2019, 04:08
Done. As a side note, after you edited your reply and reversed the order, I got instead the logo but no VFX showing up

Upload it somewhere else , such as zippyshare.com, mediafire.com . Attachments can take long time to get approved

(Yes , I got the wrong order first, because usually "logo" is on top,like you know...a logo...:) but you're actually using it as the background)

Check my edit above with viewing the alpha channel directly

SilSinn9801
3rd May 2019, 04:11
Upload it somewhere else , such as zippyshare.com, mediafire.com . Attachments can take long time to get approved

(Yes , I got the wrong order first, because usually "logo" is on top,like you know...a logo...:) but you're actually using it as the background)

Check my edit above with viewing the alpha channel directly

Is Google Drive acceptable?

Also, trying vfx[1].set_output() got me a single solid-black frame (rather than a sequence of frames). Trying vfx[0].set_output() also got me a single solid-black frame.

poisondeathray
3rd May 2019, 04:13
Is Google Drive acceptable?

Also, trying vfx[1].set_output() got me a single solid-black frame (rather than a sequence of frames). Trying vfx[0].set_output() also got me a single solid-black frame.

Yes google drive is ok

This means you don't have a valid alpha channel. Perhaps that version of ffms2 isn't reading it correctly

poisondeathray
3rd May 2019, 04:15
For example, newer ffms2 versions do not read the alpha correctly in PNG or MOV
eg. ffms2-20190326 from WolfBerry does not work here on my local test with different images

But really old versions work, such as ffms2-2.23-clang , or ImageMagick for PNG RGBA sequences

SilSinn9801
3rd May 2019, 04:16
Yes google drive is ok

This means you don't have a valid alpha channel. Perhaps that version of ffms2 isn't reading it correctly

Here you go:
https://drive.google.com/open?id=1m__FLM7kgGGRdQ8IVV0Kdx1a6MAjOXCI

SilSinn9801
3rd May 2019, 04:19
For example, newer ffms2 versions do not read the alpha correctly in PNG or MOV
eg. ffms2-20190326 from WolfBerry does not work here on my local test with different images

But really old versions work, such as ffms2-2.23-clang , or ImageMagick for PNG RGBA sequences

Older versions of FFMS2 don't work with me because they cannot open PNG files (as per an older thread of mine: https://forum.doom9.org/showthread.php?t=176223 ). And ImageMagick does not work with international filepaths.

poisondeathray
3rd May 2019, 04:24
Works ok with old ffms2 (ffms2-2.23-clang)


vfx = core.ffms2.Source(r'VFX__172.PNG')
logo = core.ffms2.Source(r'Logo.png')

o = haf.Overlay(logo[0], vfx[0], mask=vfx[1])
o.set_output()




(This is why I keep like 20 ffms2 versions around)

SilSinn9801
3rd May 2019, 04:31
Works ok with old ffms2 (ffms2-2.23-clang)


vfx = core.ffms2.Source(r'VFX__172.PNG')
logo = core.ffms2.Source(r'Logo.png')

o = haf.Overlay(logo[0], vfx[0], mask=vfx[1])
o.set_output()



Do you have a link to that old ffms2? The latest ffms2 version just posted by Wolfberry crashes my VirtualDub2 x64.

poisondeathray
3rd May 2019, 04:43
Each version has various quirks. About 19 other ffms2 versions don't work correctly with PNG or MOV RGBA

I can't find the original github release from way back . Looks like it was taken down and replaced with ffms2-2.23.1-msvc (which doesn't work here either) . But it might mean there are other issues with that build
https://github.com/FFMS/ffms2/releases

Lucky for you I have them saved on a HDD somewhere for exactly these scenarios
https://www.mediafire.com/file/ug0mqp553jsgc9j/ffms2-2.23-clang.7z/file

SilSinn9801
3rd May 2019, 04:51
I am trying that old ffms2 and now I get some errors:
Avisynth open failure:
Python exception: 'list' object has no attribute 'std'

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 1927, in vapoursynth.vpy_evaluateScript
File "src\cython\vapoursynth.pyx", line 1928, in vapoursynth.vpy_evaluateScript
File "C:\(fakepath)\Script.vpy", line 11, in <module>
rawlogoframe = rawlogo.std.AssumeFPS(fpsnum=60000,fpsden=1001)
AttributeError: 'list' object has no attribute 'std'
What do I do?

poisondeathray
3rd May 2019, 04:54
I am trying that old ffms2 and now I get some errors:

Avisynth open failure:
Python exception: 'list' object has no attribute 'std'

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 1927, in vapoursynth.vpy_evaluateScript
File "src\cython\vapoursynth.pyx", line 1928, in vapoursynth.vpy_evaluateScript
File "C:\(fakepath)\Script.vpy", line 11, in <module>
rawlogoframe = rawlogo.std.AssumeFPS(fpsnum=60000,fpsden=1001)
AttributeError: 'list' object has no attribute 'std'

What do I do?


try core.std.AssumeFPS

eg.
rawlogoframe = core.std.AssumeFPS(rawlogo, fpsnum=60000,fpsden=1001)


Did you try the 2 test image simple script above first ? Does it look like what you expect ?

SilSinn9801
3rd May 2019, 05:04
try core.std.AssumeFPS

eg.
rawlogoframe = core.std.AssumeFPS(rawlogo, fpsnum=60000,fpsden=1001)
I now get this new error:
Avisynth open failure:
Python exception: AssumeFPS: argument clip is not of array type but more than one value was supplied

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 1927, in vapoursynth.vpy_evaluateScript
File "src\cython\vapoursynth.pyx", line 1928, in vapoursynth.vpy_evaluateScript
File "C:\(fakepath)\Script.vpy", line 11, in <module>
rawlogoframe = core.std.AssumeFPS(rawlogo,fpsnum=60000,fpsden=1001)
File "src\cython\vapoursynth.pyx", line 1833, in vapoursynth.Function.__call__
vapoursynth.Error: AssumeFPS: argument clip is not of array type but more than one value was supplied

I also get this error with the Wolfberry version with the alpha=TRUE edit by HolyWu.

Did you try the 2 test image simple script above first ? Does it look like what you expect ?

The two-test script worked fine, with vfx[0] giving me the normal image and vfx[1] giving me the alpha represented as black.

poisondeathray
3rd May 2019, 05:06
Also works ok with the latest ffms2 here, albeit you need to specify the alpha argument.

logo = core.ffms2.Source(r'Logo.png')
vfx = core.ffms2.Source(r'VFX__172.PNG', alpha=True)
clip = haf.Overlay(logo, vfx[0], mask=vfx[1])


Nice.

Confirmed for ffms2-20190326 from WolfBerry (not sure if it's the "newest")

SilSinn9801
3rd May 2019, 05:06
Also works ok with the latest ffms2 here, albeit you need to specify the alpha argument.

logo = core.ffms2.Source(r'Logo.png')
vfx = core.ffms2.Source(r'VFX__172.PNG', alpha=True)
clip = haf.Overlay(logo, vfx[0], mask=vfx[1])


Which of the Wolfberry versions, the one released on March 23 or 26, or the one released now on April 27? Because the April release is crashing my VirtualBox2 setup; the March release ran fine for me.

poisondeathray
3rd May 2019, 05:11
The two-test script worked fine, with vfx[0] giving me the normal image and vfx[1] giving me the alpha represented as black.

vfx[1] should be black and white


I now get this new error:

If you're loading as an array of RGB + alpha, you need to specify if it's using [0] or [1] . Those newer versions require alpha = True to load the alpha. So just omit that for the RGB background

If you're loading both (it will be a "dummy" alpha) . Since you want the RGB background, it should be [0]

rawlogoframe = core.std.AssumeFPS(rawlogo[0],fpsnum=60000,fpsden=1001)

SilSinn9801
3rd May 2019, 05:28
vfx[1] should be black and white
Yes, it was binary black and white (monochrome).

If you're loading as an array of RGB + alpha, you need to specify if it's using [0] or [1] . Those newer versions require alpha = True to load the alpha. So just omit that for the RGB background

If you're loading both (it will be a "dummy" alpha) . Since you want the RGB background, it should be [0]

rawlogoframe = core.std.AssumeFPS(rawlogo[0],fpsnum=60000,fpsden=1001)

I now get a new, different error when applying HolyWu’s Overlay:
Avisynth open failure:
Python exception: List index out of bounds

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 1927, in vapoursynth.vpy_evaluateScript
File "src\cython\vapoursynth.pyx", line 1928, in vapoursynth.vpy_evaluateScript
File "C:\(fakepath)\Script.vpy", line 134, in <module>
finallogo = haf.Overlay(logo,vfx[0],mask=vfx[1])
File "src\cython\vapoursynth.pyx", line 1402, in vapoursynth.VideoNode.__getitem__
IndexError: List index out of bounds

poisondeathray
3rd May 2019, 05:32
I now get a new, different error when applying HolyWu’s Overlay:

Avisynth open failure:
Python exception: List index out of bounds

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 1927, in vapoursynth.vpy_evaluateScript
File "src\cython\vapoursynth.pyx", line 1928, in vapoursynth.vpy_evaluateScript
File "C:\(fakepath)\Script.vpy", line 134, in <module>
finallogo = haf.Overlay(logo,vfx[0],mask=vfx[1])
File "src\cython\vapoursynth.pyx", line 1402, in vapoursynth.VideoNode.__getitem__
IndexError: List index out of bounds



If you're loading the alpha for "logo" you need to specify [0] or [1] . You want [0] for RGB

finallogo = haf.Overlay(logo[0],vfx[0],mask=vfx[1])

SilSinn9801
3rd May 2019, 05:35
If you're loading the alpha for "logo" you need to specify [0] or [1] . You want [0] for RGB

finallogo = haf.Overlay(logo[0],vfx[0],mask=vfx[1])

I am not using alpha for logo.

poisondeathray
3rd May 2019, 05:36
I am not using alpha for logo.

Then don't load it. Use alpha=False or omit it for ffms2 for the logo

Use alpha=True for vfx ffms2 loading

SilSinn9801
3rd May 2019, 05:49
Then don't load it. Use alpha=False or omit it for ffms2 for the logo

Use alpha=True for vfx ffms2 loading

Even with alpha=False for logo and alpha=True for each vfx image, I get the same error, and I am suspecting why:

Did you see above on my original script that I was repeating each VFX frame by either 2, 3, or 4 (using the * operator) and then concatenating all repeated frames together (with the + operator)? When trying separately vfx00[0].set_output(), vfx01[0].set_output(), vfx02[0].set_output(), … and vfx00[1].set_output(), vfx01[1].set_output(), vfx02[1].set_output(), …, I am not getting repeated frames, but rather single frames at the output. Is there some other way to repeat a frame without using the * operator?

poisondeathray
3rd May 2019, 05:59
Is there some other way to repeat a frame without using the * operator?

Loop
http://www.vapoursynth.com/doc/functions/loop.html

SilSinn9801
3rd May 2019, 06:08
Loop
http://www.vapoursynth.com/doc/functions/loop.html

Using Loop:
vfx00 = core.std.Loop(vfx00, times=118)
I get error:
Python exception: Loop: argument clip is not of array type but more than one value was supplied

SilSinn9801
3rd May 2019, 06:15
Apparently, for Loop not to crash, I have to issue the Loop command individually for both [0] and [1]:
vfx00[0] = core.std.Loop(vfx00[0], times=118)
vfx00[1] = core.std.Loop(vfx00[1], times=118)

So my code will get more tedious since I have to deal with 88 different VFX frames.

poisondeathray
3rd May 2019, 06:16
You have to divide up the RGB, and alpha

eg.


clip = core.ffms2.Source(r'VFX__172.PNG', alpha=True)
clip2rgb = clip[0] * 30
clip2alpha = clip[1] * 30

clip2rgb.set_output()
#clip2alpha.set_output()

poisondeathray
3rd May 2019, 06:18
So my code will get more tedious since I have to deal with 88 different VFX frames.

I must say that avisynth handles it much better from a user standpoint...

There might be some 'python magic' that can simplify this

SilSinn9801
3rd May 2019, 06:23
I must say that avisynth handles it much better from a user standpoint...

There might be some 'python magic' that can simplify this

Yes, I was originally an avisynth user, but got tired of it being non-Unicode-aware (and tired of having to either rename my sources to ASCII only or move them to ASCII-only filepaths).

SilSinn9801
3rd May 2019, 07:01
Since we are in python scripting, you can simply define a helper function for convenience.


def loop_vfx(c, times):
c[0] = c[0] * times
c[1] = c[1] * times
return c

vfx00 = loop_vfx(core.ffms2.Source('VFX__000.png', alpha=True), 118)
vfx01 = loop_vfx(core.ffms2.Source('VFX__118.png', alpha=True), 8)
vfx02 = loop_vfx(core.ffms2.Source('VFX__126.png', alpha=True), 18)


Thanks. And I imagine I would have to do something similar for concatenating the various vfx## clips together with the + operator.

Finally got the result I desired. Thankee for all your support.