11-12-2018, 07:58 AM | #1 |
Human being with feelings
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
|
Is blur, bokeh, gaussian blur in Video processor possible?
I asked myself,
if Reapers video processor is capable of any kind of blur or noise. Now that we have masks it would be awesome if even the simplest "out of focus", blur, noise etc. could be done. This would allow to take the same video once untouched and once blurred to interchange it via masks with different shapes. Just an idea. And I'm curious by nature. |
11-12-2018, 09:13 AM | #2 |
Human being with feelings
Join Date: May 2009
Posts: 29,269
|
"Lens blur" as they call it in Photoshop, Davinci Resolve etc? I think that's a fairly complex thing to do based on my use of it in PS and Resolve since actual lens components are usually emulated (blade number, blade shape and so on).
I'd imagine something generic is possible but that's about all I know but making it pleasing vs just making it will matter. With at least some background in photography, bokeh is a big deal to me in general. I have a couple of lenses that I consider best of the best for the quality of their bokeh - and a few other lenses who's strengths are anything but good bokeh, aka the bokeh is ugly and sickly looking. That's also why I mostly use DSLRs for my video work, because I get to use my bokeh-friendly lenses for subject isolation and the finer visual qualities it offers, I really hate (sometimes) cameras with fixed high apertures and endless DOF. That said, I can get by with Gaussian if I have to but bokeh is almost always better.
__________________
Music is what feelings sound like. |
11-12-2018, 03:32 PM | #3 |
Human being with feelings
Join Date: Jul 2009
Posts: 7,595
|
I too would really like to have this even if it's very basic. the only thing roughly similar right now is the pixelate preset.
In one of my Q&A videos that I edited using Resolve. I tracked an oval mask around my face, feathered it and added a bit of blur to everything outside the mask. IIRC it was extremely cpu intense and took ages to track and render. A nice effect but not worth the effort IMO.
__________________
REAPER Video Tutorials, Tips & Tricks and more at The REAPER Blog
|
11-12-2018, 03:41 PM | #4 | |
Human being with feelings
Join Date: May 2009
Posts: 29,269
|
Quote:
Did you use the stock free blur or the paid blur in Resolve? Just curious. I just upgraded to Resolve Studio over the weekend because I found that they restrict GPU usage in the free version - which also gave me the lens blur and a few other niceties as well.
__________________
Music is what feelings sound like. |
|
11-13-2018, 07:51 AM | #5 | |
Human being with feelings
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
|
Quote:
Noise or grain is also possible and would be a big deal for video projects as its a good method for matching different video sources. Question was and is if Reapers Video processor eel is capable for doing something like this. |
|
11-13-2018, 06:44 PM | #6 |
Human being with feelings
Join Date: Oct 2009
Posts: 99
|
Atm it's really not a matter of is it pretty. To the best of my knowledge gfx_evalrect() can only convolve in x-direction so useful filters aren't possible.
Unless you resort to slight hacks like convolve in x, rotate the image 90°, convolve again and rotate back but that's a bit silly. Which of course I did anyways lol. This really ugly and really costly 1st order lowpass is only supposed to be a proof of concept, maybe somebody else knows better: Code:
// simple 1st order lowpass //@param1:weight 'weight' 0.1 0 1 0.5 0.001 in=0; oldCS=colorspace; gfx_dest = xWs = gfx_img_resize(xWs,project_w,project_h); gfx_blit(in); w=project_w; h=project_h; colorspace='RGBA'; #code=" (_1 -= 1) < 0 ? ( _1=w-1; _2=0; _3=0; _4=0; _5=0; ); r=_2+weight*(r-_2); _2=r; // weight*r + (1-weight)*lr g=_3+weight*(g-_3); _3=g; b=_4+weight*(b-_4); _4=b; a=_5+weight*(a-_5); _5=a; "; // convolve in x gfx_evalrect(0,0,w,h, #code); // rotate 90° gfx_dest = rotWs1 = gfx_img_resize(rotWs1,w,w,-1); gfx_rotoblit(xWs,$pi/2); // convolve in y (now x) gfx_evalrect(0,0,w,w, #code); // rotate back gfx_dest = rotWs2 = gfx_img_resize(rotWs2,w,w,-1); gfx_rotoblit(rotWs1,-$pi/2); //gfx_img_resize(-1,w,h); gfx_dest=-1; gfx_blit(rotWs2); colorspace=oldCS; Last edited by wwwmaze; 11-15-2018 at 11:48 AM. Reason: maybe in the end it's not so silly? |
11-13-2018, 07:21 PM | #7 |
Human being with feelings
Join Date: May 2009
Posts: 29,269
|
For Gaussian blur, pretty is irrelevant, and just trying to figure things out, pretty is also irrelevant but... if creating "lens blur/bokeh", it's completely useless if the bokeh is ugly - because that is what bokeh is about... "the aesthetic quality of out of focus elements from a lens". I can create examples from a real camera to demonstrate the difference if that helps in the future.
However, I misread the original post where they were just wanting to be able to do blur period, which has plenty of value on it's own. Not trying to be overly pedantic, it's just the difference between the two matters a bit.
__________________
Music is what feelings sound like. Last edited by karbomusic; 11-13-2018 at 07:31 PM. |
11-14-2018, 01:04 AM | #8 |
Human being with feelings
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
|
wwwmaze,
you are just crazy! What the heck? Its like: "Can we fly to the moon?" Wwwmaze, waving from the moon: "Yes, we can!" That is just amazing. And you think its ugly? Take a look at this: This gif shows your preset thru a mask I made in Photoshop. Simple but cool! This gif shows the exact same setting expect I used a pre rendered video from Adobe Premiere. It uses the standard blur preset. Isn't it amazing how nice your preset is? Many, many thanks! |
11-14-2018, 01:39 AM | #9 |
Human being with feelings
Join Date: Jul 2009
Posts: 7,595
|
yep real costly but concept is proven. Blur transitions have been on my wishlist for a while and this is now possible, even if it does take 25% of my i7's power. thanks
My quick test here, with weight automated https://youtu.be/BrkuqUf97Sk
__________________
REAPER Video Tutorials, Tips & Tricks and more at The REAPER Blog
|
11-14-2018, 03:01 AM | #10 |
Human being with feelings
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
|
Yes, it needs a lot of power. But blur is essential. And I had to wait with Adobe Premiere too.
Here are two examples of animating "weight" vs. blend over from video a to blurred video a. You clearly see how the low pass comes in in the second case. Looks a bit like a 70s softsex movie. I'm still impressed. Really nice one. |
11-14-2018, 03:25 PM | #11 |
Human being with feelings
Join Date: Oct 2009
Posts: 99
|
Hehe awesome demos guys, yes it's the definition of a CPU-Hog, isn't it?
A huge factor is that I'm using RGBA colorspace. If I use "YV12", which I'm absolutely not familiar with, CPU goes down by roughly a quarter here. The flip side is that I'm currently getting strange black stripy things using that. I must be doing something wrong... |
11-15-2018, 07:13 AM | #12 |
Administrator
Join Date: Jan 2005
Location: NYC
Posts: 15,746
|
Awesome!
Here's a simplified version that operates in YV12, and adjusts the blur/weight knob to give a nice feeling curve: Code:
// simple blur, YV12 //@param1:weight_parm 'blur amount' .5 0 .99 0.5 0.001 in=0; colorspace='YV12'; input_info(in,w,h); gfx_img_resize(-1,w,h); weight = weight_parm^.25; uvweight= sqr(weight); code=" (_1 -= 1) < 0 ? ( _1=eval_w*.5-1; _2=y1; _3=y3; _4=u; _5=v; ); y1+=weight*(_2-y1); _2=(y2+=weight*(y1-y2)); y3+=weight*(_3-y3); _3=(y4+=weight*(y3-y4)); _4=(u+=uvweight*(_4-u)); _5=(v+=uvweight*(_5-v)); "; weight>.00001 ? ( extrasz=min((log(0.5)/log(weight) + 2),w/4)&0xfffc; // phase adjustment size // copy to expanded work buffer (to fix phase) gfx_dest = rotWs2 = gfx_img_resize(rotWs2,w+extrasz,h); gfx_blit(in,0,0,0,w,h,0,0,w,h); gfx_fillrect(w,0,extrasz,h); // convolve in x eval_w = w+extrasz; gfx_evalrect(0,0,w+extrasz,h, code); // rotate to expanded vertical work buffer gfx_dest = rotWs1 = gfx_img_resize(rotWs1,h+extrasz,w); gfx_deltablit(rotWs2,0,0,h,w, extrasz*.5,0, 0,1,1,0,0,0); gfx_fillrect(h,0,extrasz,w); // convolve in y (now x) eval_w = h+extrasz; gfx_evalrect(0,0,h+extrasz,w, code); // rotate back to output framebuffer gfx_dest = -1; gfx_deltablit(rotWs1,0,0,w,h,extrasz*.5,0, 0,1,1,0,0,0); ) : gfx_blit(in); (edit: bugfixed and simplified a little -- there are some artifacts on the left edge, though, hm). Last edited by Justin; 11-15-2018 at 08:06 AM. |
11-15-2018, 07:46 AM | #13 |
Human being with feelings
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
|
Works great. Preview mostly in real time. Rendering HD in 0.7 real time h624, quality 95%.
Very nice. And thanks to all who made this happen. |
11-15-2018, 08:07 AM | #14 |
Administrator
Join Date: Jan 2005
Location: NYC
Posts: 15,746
|
Edited the above post again -- it now preserves phase (position) and has a slightly better knob curve
|
11-15-2018, 09:00 AM | #15 |
Human being with feelings
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
|
Hi,
I guess you moved the shifting to the right side. I have no idea if this can be fixed. But it only shows with extreme settings. So ... But this is now possible. Blur blending. Its one of the things that I really missed. Thanks again. |
11-15-2018, 09:16 AM | #16 |
Administrator
Join Date: Jan 2005
Location: NYC
Posts: 15,746
|
That's awesome! Yeah, the shifting to the right side is not avoidable due to the algorithm used, to fix it would require a lot more CPU (given the way evalrect() is implemented, boo).
Last edited by Justin; 11-15-2018 at 09:25 AM. |
11-15-2018, 09:37 AM | #17 |
Administrator
Join Date: Jan 2005
Location: NYC
Posts: 15,746
|
Here's a version that shifts down/right and up/left simultaneously, though at the cost of twice the CPU use:
Code:
// blur, YV12 //@param1:weight_parm 'blur amount' .5 0 .99 0.5 0.001 //@param2:bidir 'bidirectional' 1 0 1 0 1 in=0; colorspace='YV12'; input_info(in,w,h); gfx_img_resize(-1,w,h); weight = weight_parm ^.25; uvweight= sqr(weight); code=" (_1 -= 1) < 0 ? ( _1=eval_w*.5-1; _2=y1; _3=y3; _4=u; _5=v; ); y1+=weight*(_2-y1); _2=(y2+=weight*(y1-y2)); y3+=weight*(_3-y3); _3=(y4+=weight*(y3-y4)); _4=(u+=uvweight*(_4-u)); _5=(v+=uvweight*(_5-v)); "; pass=0; weight>.00001 ? loop(bidir?2:1, gfx_dest = rotWs2 = gfx_img_resize(rotWs2,w,h); pass==0 ? gfx_blit(in,0,0,0,w,h,0,0,w,h) : gfx_deltablit(in,0,0,w,h,w-1,h-1,-1,0,0,-1); // convolve in x eval_w = w; gfx_evalrect(0,0,w,h, code); // rotate to expanded vertical work buffer gfx_dest = rotWs1 = gfx_img_resize(rotWs1,h,w); gfx_deltablit(rotWs2,0,0,h,w, 0,0, 0,1,1,0,0,0); // convolve in y (now x) eval_w = h; gfx_evalrect(0,0,h,w, code); // rotate back to output framebuffer gfx_dest = -1; gfx_a=pass?0.5:1; pass==0? gfx_deltablit(rotWs1,0,0,w,h,0,0, 0,1,1,0,0,0): gfx_deltablit(rotWs1,0,0,w,h,h-1,w-1, 0,-1,-1,0,0,0); gfx_a=1; pass+=1; ) : gfx_blit(in); Last edited by Justin; 11-15-2018 at 01:26 PM. |
11-15-2018, 10:24 AM | #18 |
Human being with feelings
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
|
Yes, that fixed it.
It looks now even more amazing as it reminds a bit of defocusing a lens objective. (At least a bit.) Pretty cool. And the CPU usage isn't as high as expected. I could even preview it in real time with only some lags. Thank you. |
11-15-2018, 11:38 AM | #19 |
Human being with feelings
Join Date: Oct 2009
Posts: 99
|
Cool thank you for making it linear phase Justin! And for making it much lighter
Going to look at the code now. Had some problems rotating the workspace and probably overdone it a bit so I'm interested to see what you've done. |
11-15-2018, 01:43 PM | #20 | |
Administrator
Join Date: Jan 2005
Location: NYC
Posts: 15,746
|
Quote:
Here's a slightly improved version (it avoids creating second extra buffer on single-pass mode): Code:
// Blur //@param1:weight_parm 'blur amount' .5 0 .99 0.5 0.001 //@param2:bidir 'bidirectional' 1 0 1 0 1 in=0; colorspace='YV12'; input_info(in,w,h); gfx_img_resize(-1,w,h); weight = weight_parm ^.25; uvweight= sqr(weight); code=" (_1 -= 1) < 0 ? ( _1=eval_w*.5-1; _2=y1; _3=y3; _4=u; _5=v; ); y1+=weight*(_2-y1); _2=(y2+=weight*(y1-y2)); y3+=weight*(_3-y3); _3=(y4+=weight*(y3-y4)); _4=(u+=uvweight*(_4-u)); _5=(v+=uvweight*(_5-v)); "; pass=0; weight>.00001 ? loop(bidir?2:1, pass ? ( // second pass, use a copy rotated 180 gfx_dest = rotWs2 = gfx_img_resize(rotWs2,w,h); gfx_deltablit(in,0,0,w,h,w-1,h-1,-1,0,0,-1); ) : ( gfx_blit(in,0,0,0,w,h,0,0,w,h); ); // convolve in x eval_w = w; gfx_evalrect(0,0,w,h, code); // rotate to vertical work buffer gfx_dest = rotWs1 = gfx_img_resize(rotWs1,h,w); gfx_deltablit(pass?rotWs2:-1,0,0,h,w, 0,0, 0,1,1,0,0,0); // convolve in y (now x) eval_w = h; gfx_evalrect(0,0,h,w, code); // rotate back to output framebuffer gfx_dest = -1; gfx_a=pass?0.5:1; pass?gfx_deltablit(rotWs1,0,0,w,h,h-1,w-1, 0,-1,-1,0,0,0): gfx_deltablit(rotWs1,0,0,w,h,0,0, 0,1,1,0,0,0); gfx_a=1; pass+=1; ) : gfx_blit(in); |
|
11-15-2018, 04:05 PM | #21 |
Human being with feelings
Join Date: Oct 2009
Posts: 99
|
It's now more than half as CPU intensive (on single pass) than my try and doesn't have that huge shift. Awesome work!
gfx_deltablit() was one of the last 2 mysteries of video processor for me, thanks for pushing me into that direction. So s and t are really only the x- and y-coordinates of the source? I.e. dsdx set to 2 means 2 steps of s results in 1 step of x in the destination buffer/image. Cool! |
11-15-2018, 04:56 PM | #22 |
Human being with feelings
Join Date: Jul 2009
Posts: 7,595
|
so if we can blur then unsharp mask shouldn't be too far off right?
__________________
REAPER Video Tutorials, Tips & Tricks and more at The REAPER Blog
|
11-15-2018, 08:49 PM | #23 |
Administrator
Join Date: Jan 2005
Location: NYC
Posts: 15,746
|
OK one more -- this one looks extra good, allows you to control the ratio between vertical and horizontal, allows you to turn off diff l/r/u/d blurs, but is also pretty slow.
Code:
// Blur //@param1:weight_parm 'blur amount' .5 0 .99 0.5 0.001 //@param2:weight_mod 'Y modifier' 1 .8 1.2 1.0 0.001 //@param4:want_l 'leftward' 1 0 1 0 1 //@param5:want_r 'rightward' 1 0 1 0 1 //@param6:want_u 'upward' 1 0 1 0 1 //@param7:want_d 'downward' 1 0 1 0 1 in=0; colorspace='YV12'; input_info(in,w,h); gfx_img_resize(-1,w,h); function rot(new_ang, dest, blur) local(lw,lh,ang) ( gfx_dest=dest; ang = (new_ang+4-c_ang)&3; c_ang = new_ang&3; lw=(c_ang&1) ? h:w; lh=(c_ang&1) ? w:h; ang==0 ? gfx_blit(c_last,0, 0,0,lw,lh,0,0,lw,lh) : ang==1 ? gfx_deltablit(c_last, 0,0, lw,lh, 0, lw-1, 0, -1, 1, 0) : ang==2 ? gfx_deltablit(c_last, 0,0, lw,lh, lw-1,lh-1, -1, 0, 0, -1): ang==3 ? gfx_deltablit(c_last, 0,0, lw,lh, lh-1,0, 0, 1, -1, 0); blur ? ( weight= min(weight_parm*((c_ang&1) ? weight_mod : 1/weight_mod),1) ^.25; uvweight=max(min(weight*5.2-3.7,.94),0); // experimentally derived eval_w = lw; gfx_evalrect(0,0,lw,lh, sprintf(#," (_1 -= 1) < 0 ? ( _1=eval_w*.5-1; _2=y1; _3=y3; _4=u; _5=v; ); y1+=weight*(_2-y1); _2=(y2+=weight*(y1-y2)); y3+=weight*(_3-y3); _3=(y4+=weight*(y3-y4)); %s", uvweight > 0.000001 ? " _4=(u+=uvweight*(_4-u)); _5=(v+=uvweight*(_5-v)); " : "") ); ); c_last=dest; ); c_ang=0; c_last=in; weight_parm>.00001? ( want_l ? rot(2, -1, 1); want_d ? rot(3, img3 = gfx_img_resize(img3,h,w),1); want_u ? rot(1, img2 = gfx_img_resize(img2,h,w),1); want_r || c_last==-1 ? rot(0, c_last==-1 ? (img1 = gfx_img_resize(img1,w,h)) : -1,want_r); ); c_last != -1 ? rot(0, -1, 0); Last edited by Justin; 11-15-2018 at 09:18 PM. Reason: tweaked the UV filtering coefficient some to look better (for one bit of test material anyway) |
11-16-2018, 12:18 AM | #24 |
Human being with feelings
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
|
This is actually bonus and very handy for a special challenge: Motion blur of a camera movement. If you have a video and want to pan it, this would be the perfect solution to let it look more natural as you can follow the direction.
But this one really sucks the energy out of my Laptop. Anyway. Very nice. Thanks. |
11-16-2018, 12:51 AM | #25 |
Human being with feelings
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
|
Here are the examples:
Without motion blur its hard to follow the movement. It looks unnatural. With (fake) motion blur it looks like a real movement. Its a bit over done to show the effect more clearly. Of course you have to take care at the speed of the movement. As you can see I peaked the blur at the steepest movement curve. And I chose the leftward parameter at max. level. And one last thing: This last preset with the separate 4 directions is nearly impossible to preview but for some reason it renders more quickly than expected. |
11-18-2018, 05:24 PM | #26 |
Human being with feelings
Join Date: Oct 2009
Posts: 99
|
Hey all,
I went and implemented this Gaussian filter (3rd-order recursive) approximation: https://www.researchgate.net/publica...aussian_filter Alas it's again working in 'RGBA' colorspace as I still have no clue about 'YV12' and can't fathom what Justin is doing with these YV12 vars in gfx_evalrect(). So it's again a bit CPU intensive. The good thing is, since it's recursive, it should be equal bad (or good after some optimization) for every value of sigma, unlike some other Gaussian implementations. I'm interested to hear how it looks compared to other Gaussian blurs. @Justin: I noticed that you blend the 2 passes together in your filters. I just work on the main framebuffer after the 1st pass which (I think) has the same effect of correcting the phase. Code:
Edit: updated version, see post 37 below Last edited by wwwmaze; 11-23-2018 at 10:20 AM. |
11-18-2018, 07:32 PM | #27 |
Administrator
Join Date: Jan 2005
Location: NYC
Posts: 15,746
|
heh nice, though maybe you should look at the newer YV12 ones I did (where there's not really two passes, instead it just blurs the output of the previous passes)
You could also probably speed the RGBA version up a bit by not bothering with alpha |
11-18-2018, 07:47 PM | #28 |
Administrator
Join Date: Jan 2005
Location: NYC
Posts: 15,746
|
YV12 version:
Code:
// Recursive Gaussian Blur //@param1:sigma 'Sigma' 10 0.5 50 25 0.1 //@param2:bidir 'bidirectional' 1 0 1 0 1 in=0; initDone==0 ? (lsigma=-1; initDone=1;); // coeffs lsigma!=sigma ? ( q = (0.5<=sigma && sigma <=2.5) ? 3.97156-4.14554*sqrt(1-0.26891*sigma) : 0.98711*sigma-0.96330; b0 = 1.57825 + 2.44413*q + 1.4281*q^2 + 0.422205*q^3; b1 = 2.44413*q + 2.85619*q^2 + 1.26661*q^3; b2 = -1.4281*q^2 - 1.26661*q^3; b3 = 0.422205*q^3; BB = 1-(b1+b2+b3)/b0; b1b0=b1/b0; b2b0=b2/b0; b3b0=b3/b0; lsigma=sigma; ); colorspace='YV12'; input_info(in,w,h); gfx_img_resize(-1,w,h); code=" (_1 -= 1) < 0 ? ( _1=eval_w-1; _31=_21=_11=0; _32=_22=_12=0; _33=_23=_13=128; _34=_24=_14=128; ); y1=BB*y1 + b1b0*_11 + b2b0*_21 +b3b0*_31; _31=_21; _21=_11; y2=BB*y2 + b1b0*y1 + b2b0*_21 +b3b0*_31; _31=_21; _21=y1; _11=y2; y3=BB*y3 + b1b0*_12 + b2b0*_22 +b3b0*_32; _32=_22; _22=_12; y4=BB*y4 + b1b0*y3 + b2b0*_22 +b3b0*_32; _32=_22; _22=y3; _12=y4; u=BB*u + b1b0*_13 + b2b0*_23 +b3b0*_33; _33=_23; _23=_13; _13=u; v=BB*v + b1b0*_14 + b2b0*_24 +b3b0*_34; _34=_24; _24=_14; _14=v; "; gfx_dest=-1; pass=0; loop(bidir?2:1, pass ? ( // second pass, use main buffer rotated 180 gfx_dest = rotWs2 = gfx_img_resize(rotWs2,w,h); gfx_deltablit(-1,0,0,w,h,w-1,h-1,-1,0,0,-1); ) : ( gfx_blit(in,0,0,0,w,h,0,0,w,h); ); // convolve in x eval_w = w/2; gfx_evalrect(0,0,w,h, code); // rotate to vertical work buffer gfx_dest = rotWs1 = gfx_img_resize(rotWs1,h,w); gfx_deltablit(pass?rotWs2:-1,0,0,h,w, 0,0, 0,1,1,0,0,0); // convolve in y (now x) eval_w = h/2; gfx_evalrect(0,0,h,w, code); // rotate back to output framebuffer gfx_dest = -1; pass?gfx_deltablit(rotWs1,0,0,w,h,h-1,w-1, 0,-1,-1,0,0,0): gfx_deltablit(rotWs1,0,0,w,h,0,0, 0,1,1,0,0,0); pass+=1; ); In YV12 mode, the image is processed with 4 pixels at a time (apologies for inaccuracies in terminology):
So this filter runs the two Y rows as separate filters (avoiding some extra shuffling), and U/V filters separate (The U/V filters probably should have different coefficients since they are running at half the rate). Both this filter and the simpler one-pole filter have some weird effects on the color/saturation. It might actually make more sense to convert the U/V values to polar coordinates and filter that, but that would be excruciatingly slow. Last edited by Justin; 11-18-2018 at 07:57 PM. |
11-19-2018, 01:28 AM | #29 |
Human being with feelings
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
|
First of all: I worship you wizards of code really hard.
But now lets get to the Gaussian blur challenge. As you can see, the directional feature does not really work. It just changes the direction from NW to SE. Adobe somehow managed to let the pixels stay in place as in Justins blur preset with four directions. Here is a comparison of three variations of one clip: First is the rgba version from wwwmaze which was hardly playable in arrange preview. Rendering speed 0.2 real time Second version is Justins YV12 version. Also hardly watchable in preview. But 0.4 real time rendering. As Justin mentioned. For some reason the colors are bleeding out the more you increase the blur. And finally the Premiere pro rendering. The final blur amount is just a guess. Preview was also not possible. Rendering seemed as fast or a little bit faster then Reapers. Many thanks for your work. Its just amazing to see what is possible. Gaussian blur is a beautiful effect with lots of possibilities. Reaper video becomes more and more professional. I really love it. (If there wouldn't be so much guessing for cropping, panning etc.) Greetings from Cologne Eli |
11-19-2018, 01:43 AM | #30 |
Human being with feelings
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
|
In a side by side comparison its clearly visible that the rgba version nearly nails it. Though the Premiere pro version seems to get a bit brighter. But this could be a an optical illusion because of the dark frame becoming thicker in the other versions. The YV12 version is at the moment not comparable because of the fading colors but it would be a really step forward in rendering time.
As much as I love Photoshop I really don't like Adobe. Its probably the most arrogant company in the world. So its even more welcome to have a rising alternative in one of their scopes. |
11-19-2018, 09:59 AM | #31 |
Human being with feelings
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
|
One thing I have to ask. If I use a picture on one track, use its transparency to let the video beneath shining thru and then want to blur it to give the effect of a defocused leave above a video background it just blurs everything. Is it even possible to blur only the track input or does it always blur everything coming thru?
Its a bit confusing to me as Reapers video tracks sometimes don't act like tracks. I will post an example later because my English isn't good enough to describe it properly. |
11-19-2018, 02:20 PM | #32 | ||
Human being with feelings
Join Date: Oct 2009
Posts: 99
|
Quote:
Quote:
Since u and v are set to 128 (=zero saturation) at the border and the effect increases at higher sigmas I have a strong feeling that this may be caused by the problem above. I'll investigate further. Last edited by wwwmaze; 11-19-2018 at 02:41 PM. |
||
11-19-2018, 02:39 PM | #33 | |
Human being with feelings
Join Date: Oct 2009
Posts: 99
|
Quote:
Concerning the shift, if you focus a single feature in the image it should stay in place (unlike the 1-directional blur) but I agree that black margin at SE is confusing so I should think about a way to remove it. Yes, the conversion of the preset to YV12 colorspace is probably not yet complete (see also my answer to Justin). |
|
11-22-2018, 02:06 AM | #34 |
Human being with feelings
Join Date: Nov 2011
Posts: 143
|
Awesome, incredible, thank you for the blurs!
This should make a high pass / unsharp mask (mix inverted blurred signal back to source, restore contrast) possible as well, like EpicSounds mentioned. https://en.wikipedia.org/wiki/Unsharp_masking |
11-22-2018, 08:50 AM | #35 |
Human being with feelings
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
|
This is already possible per Selective Blender from wwmaze. Works in a limited way. Maybe it could be set up in one preset.
Keep it in mind. The setup would be a folder with Selective Blender blend mode 4 and 100% video b. Inside a "track a" with the clean video and a "track b" with the same video but also a video processors with blur. "Track b" needs also a black and white filter, a contrast adjustment after the blur and finally a color invert. Here an example with an increasing amount of blur. (But 0.1 real time render.) Greetings Eli |
11-22-2018, 09:24 AM | #36 |
Human being with feelings
Join Date: Jul 2009
Posts: 7,595
|
I must have missed that one. That looks pretty good
__________________
REAPER Video Tutorials, Tips & Tricks and more at The REAPER Blog
|
11-22-2018, 05:51 PM | #37 |
Human being with feelings
Join Date: Oct 2009
Posts: 99
|
For the Gaussian blurs I think I managed to let the YV12 version work almost (not exactly, there are still minor color differences) like the RGBA version. I had to introduce some additional multi-add pairs though because I couldn't figure out how to modify the coefficients. So there's still room for optimization.
I also fixed the image borders for the bidirectional case. RGBA version: Code:
// Gaussian Blur RGBA // v0.2 //@param1:sigma 'Sigma' 10 0.5 50 25 0.1 //@param2:bidir 'bidirectional' 1 0 1 0 1 //@param8:restore_cs 'preserve colorspace' 1 0 1 0 1 in=0; initDone==0 ? (lsigma=-1; initDone=1;); // coeffs lsigma!=sigma ? ( q = (0.5<=sigma && sigma <=2.5) ? 3.97156-4.14554*sqrt(1-0.26891*sigma) : 0.98711*sigma-0.96330; b0 = 1.57825 + 2.44413*q + 1.4281*q^2 + 0.422205*q^3; b1 = 2.44413*q + 2.85619*q^2 + 1.26661*q^3; b2 = -1.4281*q^2 - 1.26661*q^3; b3 = 0.422205*q^3; BB = 1-(b1+b2+b3)/b0; b1b0=b1/b0; b2b0=b2/b0; b3b0=b3/b0; lsigma=sigma; ); oldcs=colorspace; colorspace='RGBA'; input_info(in,w,h); gfx_img_resize(-1,w,h); code=" (_1 -= 1) < 0 ? ( _1=eval_w-1; _31=_21=_11=r; _32=_22=_12=g; _33=_23=_13=b; ); r=BB*r + b1b0*_11 + b2b0*_21 +b3b0*_31; _31=_21; _21=_11; _11=r; // r=BB*r + b1b0*lr + b2b0*llr +b3b0*lllr; lllr=llr; llr=lr; lr=r; g=BB*g + b1b0*_12 + b2b0*_22 +b3b0*_32; _32=_22; _22=_12; _12=g; b=BB*b + b1b0*_13 + b2b0*_23 +b3b0*_33; _33=_23; _23=_13; _13=b; "; pass=0; loop(bidir?2:1, pass ? ( // second pass, use main buffer rotated 180 gfx_dest = rotWs2 = gfx_img_resize(rotWs2,w,h); gfx_deltablit(-1,0,0,w,h,w-1,h-1,-1,0,0,-1); ) : ( gfx_blit(in,0,0,0,w,h,0,0,w,h); ); // convolve in x eval_w = w; gfx_evalrect(0,0,w,h, code); // rotate to vertical work buffer gfx_dest = rotWs1 = gfx_img_resize(rotWs1,h,w); gfx_deltablit(pass?rotWs2:-1,0,0,h,w, 0,0, 0,1,1,0,0,0); // convolve in y (now x) eval_w = h; gfx_evalrect(0,0,h,w, code); // rotate back to output framebuffer gfx_dest = -1; pass?gfx_deltablit(rotWs1,0,0,w,h,h-1,w-1, 0,-1,-1,0,0,0): gfx_deltablit(rotWs1,0,0,w,h,0,0, 0,1,1,0,0,0); pass+=1; ); restore_cs && oldcs != colorspace ? colorspace=oldcs; Code:
// Gaussian Blur YV12 // v0.2 //@param1:sigma 'Sigma' 10 0.5 50 25 0.1 //@param2:bidir 'bidirectional' 1 0 1 0 1 in=0; initDone==0 ? (lsigma=-1; initDone=1;); // coeffs lsigma!=sigma ? ( q = (0.5<=sigma && sigma <=2.5) ? 3.97156-4.14554*sqrt(1-0.26891*sigma) : 0.98711*sigma-0.96330; b0 = 1.57825 + 2.44413*q + 1.4281*q^2 + 0.422205*q^3; b1 = 2.44413*q + 2.85619*q^2 + 1.26661*q^3; b2 = -1.4281*q^2 - 1.26661*q^3; b3 = 0.422205*q^3; BB = 1-(b1+b2+b3)/b0; b1b0=b1/b0; b2b0=b2/b0; b3b0=b3/b0; lsigma=sigma; ); colorspace='YV12'; input_info(in,w,h); gfx_img_resize(-1,w,h); code=" (_1 -= 1) < 0 ? ( _1=eval_w-1; _31=_21=_11=y1; _32=_22=_12=y3; _33=_23=_13=u; _34=_24=_14=v; ); y1=BB*y1 + b1b0*_11 + b2b0*_21 +b3b0*_31; y2=BB*y2 + b1b0*y1 + b2b0*_11 +b3b0*_21; _31=_11; _21=y1; _11=y2; y3=BB*y3 + b1b0*_12 + b2b0*_22 +b3b0*_32; y4=BB*y4 + b1b0*y3 + b2b0*_12 +b3b0*_22; _32=_12; _22=y3; _12=y4; _90=BB*u + b1b0*_13 + b2b0*_23 +b3b0*_33; u=BB*u + b1b0*_90 + b2b0*_13 +b3b0*_23; _33=_13; _23=_90; _13=u; _91=BB*v + b1b0*_14 + b2b0*_24 +b3b0*_34; v=BB*v + b1b0*_91 + b2b0*_14 +b3b0*_24; _34=_14; _24=_91; _14=v; "; gfx_dest=-1; pass=0; loop(bidir?2:1, pass ? ( // second pass, use main buffer rotated 180 gfx_dest = rotWs2 = gfx_img_resize(rotWs2,w,h); gfx_deltablit(-1,0,0,w,h,w-1,h-1,-1,0,0,-1); ) : ( gfx_blit(in,0,0,0,w,h,0,0,w,h); ); // convolve in x eval_w = w/2; gfx_evalrect(0,0,w,h, code); // rotate to vertical work buffer gfx_dest = rotWs1 = gfx_img_resize(rotWs1,h,w); gfx_deltablit(pass?rotWs2:-1,0,0,h,w, 0,0, 0,1,1,0,0,0); // convolve in y (now x) eval_w = h/2; gfx_evalrect(0,0,h,w, code); // rotate back to output framebuffer gfx_dest = -1; pass?gfx_deltablit(rotWs1,0,0,w,h,h-1,w-1, 0,-1,-1,0,0,0): gfx_deltablit(rotWs1,0,0,w,h,0,0, 0,1,1,0,0,0); pass+=1; ); EDIT: updated versions with a bugfix see Justins posts below Last edited by wwwmaze; 11-27-2018 at 08:30 AM. |
11-23-2018, 01:32 AM | #38 |
Human being with feelings
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
|
INCREDIBLE!
This looks so awesome now. Here is the obligatory test to show how great this works. It seems the YV12 version tends a bit more to saturation or green in lighter areas. But I would say that's a normal behavior as its a color conversion. Take a look how beautiful this is: (despite the fact that i had to convert it into a gif ) Many thanks again. |
11-23-2018, 10:30 AM | #39 | |
Human being with feelings
Join Date: Oct 2009
Posts: 99
|
Cool I like lizards too
Quote:
Many thanks also for starting the preset collection thread Eli. Very useful initiative! Imo this could easily be a sticky thread. |
|
11-25-2018, 07:15 PM | #40 |
Administrator
Join Date: Jan 2005
Location: NYC
Posts: 15,746
|
Here's a version that uses the native colorspace (YV12 or RGBA), rather than forcing a colorspace (colorspace conversion is quite slow by itself!)
Code:
// Gaussian Blur // v0.2 //@param1:sigma 'Sigma' 10 0.5 50 25 0.1 //@param2:bidir 'bidirectional' 1 0 1 0 1 in=0; initDone==0 ? (lsigma=-1; initDone=1;); // coeffs lsigma!=sigma ? ( q = (0.5<=sigma && sigma <=2.5) ? 3.97156-4.14554*sqrt(1-0.26891*sigma) : 0.98711*sigma-0.96330; b0 = 1.57825 + 2.44413*q + 1.4281*q^2 + 0.422205*q^3; b1 = 2.44413*q + 2.85619*q^2 + 1.26661*q^3; b2 = -1.4281*q^2 - 1.26661*q^3; b3 = 0.422205*q^3; BB = 1-(b1+b2+b3)/b0; b1b0=b1/b0; b2b0=b2/b0; b3b0=b3/b0; lsigma=sigma; ); colorspace!='RGBA' ? colorspace='YV12'; input_info(in,project_w,project_h); w=project_w; h=project_h; code=colorspace=='RGBA' ? " (_1 -= 1) < 0 ? ( _1=eval_w-1; _31=_21=_11=r; _32=_22=_12=g; _33=_23=_13=b; ); r=BB*r + b1b0*_11 + b2b0*_21 +b3b0*_31; _31=_21; _21=_11; _11=r; g=BB*g + b1b0*_12 + b2b0*_22 +b3b0*_32; _32=_22; _22=_12; _12=g; b=BB*b + b1b0*_13 + b2b0*_23 +b3b0*_33; _33=_23; _23=_13; _13=b; " : " (_1 -= 1) < 0 ? ( _1=eval_w*.5-1; _31=_21=_11=y1; _32=_22=_12=y3; _33=_23=_13=u; _34=_24=_14=v; ); y1=BB*y1 + b1b0*_11 + b2b0*_21 +b3b0*_31; y2=BB*y2 + b1b0*y1 + b2b0*_11 +b3b0*_21; _31=_11; _21=y1; _11=y2; y3=BB*y3 + b1b0*_12 + b2b0*_22 +b3b0*_32; y4=BB*y4 + b1b0*y3 + b2b0*_12 +b3b0*_22; _32=_12; _22=y3; _12=y4; _90=BB*u + b1b0*_13 + b2b0*_23 +b3b0*_33; u=BB*u + b1b0*_90 + b2b0*_13 +b3b0*_23; _33=_13; _23=_90; _13=u; _91=BB*v + b1b0*_14 + b2b0*_24 +b3b0*_34; v=BB*v + b1b0*_91 + b2b0*_14 +b3b0*_24; _34=_14; _24=_91; _14=v; " ; pass=0; loop(bidir?2:1, pass ? ( // second pass, use main buffer rotated 180 gfx_dest = rotWs2 = gfx_img_resize(rotWs2,w,h); gfx_deltablit(-1,0,0,w,h,w-1,h-1,-1,0,0,-1); ) : ( gfx_blit(in,0,0,0,w,h,0,0,w,h); ); // convolve in x eval_w = w; gfx_evalrect(0,0,w,h, code); // rotate to vertical work buffer gfx_dest = rotWs1 = gfx_img_resize(rotWs1,h,w); gfx_deltablit(pass?rotWs2:-1,0,0,h,w, 0,0, 0,1,1,0,0,0); // convolve in y (now x) eval_w = h; gfx_evalrect(0,0,h,w, code); // rotate back to output framebuffer gfx_dest = -1; pass?gfx_deltablit(rotWs1,0,0,w,h,h-1,w-1, 0,-1,-1,0,0,0): gfx_deltablit(rotWs1,0,0,w,h,0,0, 0,1,1,0,0,0); pass+=1; ); Code:
// Blur (low quality) //@param1:weight_parm 'blur amount' .5 0 .99 0.5 0.001 //@param2:weight_mod 'Y modifier' 1 .8 1.2 1.0 0.001 //@param4:want_l 'leftward' 1 0 1 0 1 //@param5:want_r 'rightward' 1 0 1 0 1 //@param6:want_u 'upward' 1 0 1 0 1 //@param7:want_d 'downward' 1 0 1 0 1 in=0; colorspace!='RGBA' ? colorspace='YV12'; input_info(in,project_w,project_h); w=project_w; h=project_h; function rot(new_ang, dest, blur) local(lw,lh,ang) ( gfx_dest=dest; ang = (new_ang+4-c_ang)&3; c_ang = new_ang&3; lw=(c_ang&1) ? h:w; lh=(c_ang&1) ? w:h; ang==0 ? gfx_blit(c_last,0, 0,0,lw,lh,0,0,lw,lh) : ang==1 ? gfx_deltablit(c_last, 0,0, lw,lh, 0, lw-1, 0, -1, 1, 0) : ang==2 ? gfx_deltablit(c_last, 0,0, lw,lh, lw-1,lh-1, -1, 0, 0, -1): ang==3 ? gfx_deltablit(c_last, 0,0, lw,lh, lh-1,0, 0, 1, -1, 0); blur ? ( weight= min(weight_parm*((c_ang&1) ? weight_mod : 1/weight_mod),1) ^.25; weight2 = sqr(weight); eval_w = lw; gfx_evalrect(0,0,lw,lh, colorspace=='RGBA' ? " (_1 -= 1) < 0 ? ( _1=eval_w-1; _2=r; _3=g; _4=b; ); r+=weight*(_2-r); _2=r; g+=weight*(_3-g); _3=g; b+=weight*(_4-b); _4=b; " : " (_1 -= 1) < 0 ? ( _1=eval_w*.5-1; _2=y1; _3=y3; _4=u; _5=v; ); y1+=weight*(_2-y1); _2=(y2+=weight*(y1-y2)); y3+=weight*(_3-y3); _3=(y4+=weight*(y3-y4)); _4=(u+=weight2*(_4-u)); _5=(v+=weight2*(_5-v)); " ); ); c_last=dest; ); c_ang=0; c_last=in; weight_parm>.00001? ( want_l ? rot(2, -1, 1); want_d ? rot(3, img3 = gfx_img_resize(img3,h,w),1); want_u ? rot(1, img2 = gfx_img_resize(img2,h,w),1); want_r || c_last==-1 ? rot(0, c_last==-1 ? (img1 = gfx_img_resize(img1,w,h)) : -1,want_r); ); c_last != -1 ? rot(0, -1, 0); Last edited by Justin; 11-25-2018 at 07:47 PM. |
Thread Tools | |
Display Modes | |
|
|