View Full Version : Photo Collage - memory hog
tin3tin
27th November 2010, 05:41
This photo collage script works well, but unfortunately it is such a memory hog, that it is pretty useless for my purpose.
The masking is needed to remove black frames from source images in the 0-16 level.
Any idears on how to make this script avoid eating up 1.6 GB of RAM?
imgout=colorbars(1920,1080).trim(0,20).converttoyv12()
imgout
mostotal=last.framecount()
Loadplugin("GScript.dll")
thumbnails= imgout.Lanczos4Resize(int(imgout.width()/4), int(imgout.height()/4))
mos=last.trim(1,-1).levels(0,1,255,0,0)
mosmax=200
GScript("""
for (moscnt=1, int(mosmax/thumbnails.framecount()))
{
for ( moscnt2=1,thumbnails.framecount() )
{
mosselected=Rand(thumbnails.framecount())
mosmask=ColorKeyMask(thumbnails.Trim(mosselected,mosselected).greyscale().converttorgb32(), $00000000, 3)
mosx=Rand(mos.width()+int(thumbnails.width()/2))-int(thumbnails.width()/2)
mosy=Rand(mos.height()+int(thumbnails.height()/2))-int(thumbnails.height()/2)
mos=Overlay(mos,thumbnails.Trim(mosselected,mosselected),mosx,mosy, mask=showalpha(mosmask),greymask=true,mode="blend")
mosmask=nop()
}
}
""")
thumbnails=nop()
mos.loop(mostotal)
Here's an example of the photo collage in function:
http://www.youtube.com/watch?v=5Cz7DLJa8vE
http://download.videohelp.com/tin2tin/collage.jpg
tin3tin
27th November 2010, 23:17
It seem to be the combination of loops and overlay.
As if Overlay claims space for a new image in the RAM each time a new image is overlayed on top of the others. So 200 overlays - equals 200 images in the RAM?
So if you use a single Overlay over your entire clip, will that double the RAM usage? And two Overlays will triple the RAM usage? And so forth?
tin3tin
27th November 2010, 23:34
Apparently 'Layer' is more RAM friendly that 'Overlay' - can this be true?
http://download.videohelp.com/tin2tin/Layer_vs_Overlay.jpg
imgout=colorbars(1920,1080).trim(0,20).converttoyv12()
imgout
mostotal=last.framecount()
Loadplugin("GScript.dll")
thumbnails= imgout.Lanczos4Resize(int(imgout.width()/4), int(imgout.height()/4))
mos=last.trim(1,-1).levels(0,1,255,0,0)
mosmax=200
GScript("""
for (moscnt=1, int(mosmax/thumbnails.framecount()))
{
for ( moscnt2=1,thumbnails.framecount() )
{
mosselected=Rand(thumbnails.framecount())
mosmask=ColorKeyMask(thumbnails.Trim(mosselected,mosselected).greyscale().converttorgb32(), $00000000, 3)
mosx=Rand(mos.width()+int(thumbnails.width()/2))-int(thumbnails.width()/2)
mosy=Rand(mos.height()+int(thumbnails.height()/2))-int(thumbnails.height()/2)
mos=layer(mos.converttorgb32(),thumbnails.Trim(mosselected,mosselected).converttorgb32().mask(showalpha(mosmask)),"add", 257, x=mosx,y=mosy)
mosmask=nop()
}
}
""")
thumbnails=nop()
mos.loop(mostotal)
Gavino
27th November 2010, 23:48
Although there's only one place in the script where Overlay is called, each iteration of the (GScript) loop gives rise to a separate Overlay instance at runtime. Thus you have a filter chain with 200 instances of Overlay, each with an input clip of 1920x1080. Overlay is a notorious memory hog - Layer is better in that respect.
A minor improvement would be to take the calls to greyscale and converttorgb32 (used in the ColorKeyMask call) outside the loop:
xxx = thumbnails.greyscale().converttorgb32()
Then inside the loop use
mosmask=ColorKeyMask(xxx.Trim(mosselected,mosselected), $00000000, 3)
tin3tin
28th November 2010, 10:54
Thank you for a clever reply as always. :)
One could hope the Overlay could use the memory handling code from Layer at some point, untill then I'll have to use/change(got loads) to Layer instead of Overlay.
Gavino
28th November 2010, 13:11
One could hope the Overlay could use the memory handling code from Layer at some point
The problem is they work internally in different ways. Overlay converts everything (source clip, overlay clip and mask clip) into an internal YUV 4:4:4 format, whereas Layer works directly with the input clips. This makes Overlay more flexible, being able to accept mixed colorspace inputs, but comes at a price of additional memory overhead.
There are some further optimisations that can be made in your script by moving repeated code outside the looped part:
imgout=colorbars(1920,1080).trim(0,20).converttoyv12()
imgout
mostotal=last.framecount()
Loadplugin("GScript.dll")
thumbnails= imgout.Lanczos4Resize(int(imgout.width()/4), int(imgout.height()/4))
mosmask=ColorKeyMask(thumbnails.greyscale().converttorgb32(), $00000000, 3).ShowAlpha()
thumbnails = thumbnails.converttorgb32().mask(mosmask)
mos=last.trim(1,-1).levels(0,1,255,0,0).ConvertToRGB32()
mosmax=200
GScript("""
for (moscnt=1, int(mosmax/thumbnails.framecount()))
{
for ( moscnt2=1,thumbnails.framecount() )
{
mosselected=Rand(thumbnails.framecount())
mosx=Rand(mos.width()+int(thumbnails.width()/2))-int(thumbnails.width()/2)
mosy=Rand(mos.height()+int(thumbnails.height()/2))-int(thumbnails.height()/2)
mos=layer(mos,thumbnails.Trim(mosselected,-1),"add", 257, x=mosx,y=mosy)
}
}
""")
mos.ConvertToYV12().loop(mostotal)
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.