Log in

View Full Version : Color vibrance


Motenai Yoda
27th October 2011, 13:28
Hi! I'm looking for a simple way to do a color vibrance effect with avisynth, but after searching a little on google I have not found anything.

there is a way to make a saturation mask to merge a saturated clip or apply saturation only where saturation is low?

thanks

SSH4
27th October 2011, 14:00
mask:

mt_lut("x 128 - abs 4 *",u=3,v=3).Spline36Resize(width*2,height*2)
mt_lutxy(UtoY(),VtoY(),"x y > x y ?",chroma="128")

play with 4 in first line

Motenai Yoda
27th October 2011, 14:20
@SSH4 thanks I'll try
but I'm thinking something like

mask=mt_lutxy(Vtoy(),Utoy(),"x 128 - abs y 128 - abs +").levels(0,1.0,40,0,255,false)
mt_merge(tweak(sat=2.0),last,YToUV(mask,mask),y=4,u=3,v=3)

Dogway
27th October 2011, 17:05
Wow very good, I tried to make this a few weeks ago, didn't know it was called Vibrance. In my case I found to make a good range if I multiplied everything by 3.
msk=mt_lutxy(Vtoy(),Utoy(),"x 128 - abs y 128 - abs + 3 *")
Thanks for this!

I'll add it to my mask pack functions if you don't mind.

SSH4
27th October 2011, 17:31
first scale x2 than UtoY or VtoY or on mod2 you can catch error.
or *toY(last.scale(x2))

I'm always forgot about this :)

Gavino
27th October 2011, 17:43
Rather than using abs(u-128)+abs(v-128) as a measure of saturation, you could try sqrt((u-128)^2+(v-128)^2) which corresponds more to the 'color circle' viewpoint.

Didée
27th October 2011, 18:46
First, though I agree that doing this step-by-step (with masks and filters and chroma-to-luma-and-back and merging and stuff and all and whatnotelse) might be easier to understand while setting-up. But really, you can do it all with 2 mt_lutxy and 1 swapUV().

Second: expsat (http://forum.doom9.org/showthread.php?t=97052)

And, as a matter of course, LaTo's splendid SmoothAdjust (http://forum.doom9.org/showthread.php?t=154971).

Motenai Yoda
27th October 2011, 20:56
@Dogway nvidia, ati, and ps call it so
http://www.photo-mark.com/notes/2009/jan/19/analyzing-photoshop-vibrance-and-saturation/

@Gavino while I was eating dinner, I saw the bowl and had reached the point. but at the corner isn't 128 is ≈181 i notice that in CIELUV the formula is the same, but 255/255 shouldn't be 128 too?

@Didée I've found a link to a page about brabbudu, but it was broken. For SmoothAdjust that don't know very well, it's work on saturation or on channels? 'Cause with ps in Lab using a S curve on a and b does something similar saturation...
also understand how these things work is my gripe for some time.

now assuming that
U=x and increased_sat_U = x*k
difference between should be (x*k) -x = x*(k-1)
mask is (128 - sqrt((u-128)^2+(v-128)^2))/128, 1 at 0, 0 at 128

so vibrance_U = x+[x*(k-1)*mask] = x * {1 + [(k-1)*mask]}

this
mask=mt_lutxy(UtoY(),VtoY(),"x 128. - 2. ^ y 128. - 2. ^ + 1. 2. / ^ 128 > 0 "+
\+"128. x 128. - 2. ^ y 128. - 2. ^ + 1. 2. / ^ - 128. / "+string(float(g))+" ^ 255. * ? ",u=1,v=1)
mt_lutxy(last,YToUV(mask,mask),"x 128. - y 255. / "+string(float(k-1))+" * 1.0 + * 128. +",y=2,u=3,v=3)

should be right, it isn't?
(g is the gamma of mask)

http://img7.imagebanana.com/img/29uszcbf/thumb/original.png (http://www.imagebanana.com/view/29uszcbf/original.png) http://img6.imagebanana.com/img/vy8pvq6w/thumb/saturated_1.5.png (http://www.imagebanana.com/view/vy8pvq6w/saturated_1.5.png) http://img6.imagebanana.com/img/hjpywayl/thumb/script_k1.5_g1.0.png (http://www.imagebanana.com/view/hjpywayl/script_k1.5_g1.0.png) http://img7.imagebanana.com/img/6ylsp9j3/thumb/script_k1.5_g2.0.png (http://www.imagebanana.com/view/6ylsp9j3/script_k1.5_g2.0.png)
sorry for the screenshoots but I'haven't nothing free to use
for g=0., k=1.5 it looks very like as tweak(sat=1.5)
edit also is the same as Smoothtweak(saturation=1.5,smooth=200), changing smooth from 0 to 200 don't affect the saturation.

edited as suggested Gavino
mask=mt_lutxy(UtoY(),VtoY(),"x 128 - 2 ^ y 128 - 2 ^ + .5 ^ 128 > 0 "+
\+"128 x 128 - 2 ^ y 128 - 2 ^ + .5 ^ - 128 / "+string(g)+" ^ 255 * ? ",u=1,v=1)
mt_lutxy(last,YToUV(mask,mask),"x 128 - y 255 / "+string(k-1)+" * 1 + * 128 +",y=2,u=3,v=3)

Gavino
27th October 2011, 23:37
"1. 2. /" can of course be replaced by "0.5". ;)
Also, you don't need to use float literals (eg "128."), since internally masktools treats everything as float (just use "128", it's easier to read).

joka
28th October 2011, 12:55
I'am still learning. Sorry for the question. Shouldn't be g=1. In my opinion g=0 (as mentioned for the screen shots) will disable the mask.

Motenai Yoda
28th October 2011, 13:18
I'am still learning. Sorry for the question. Shouldn't be g=1. In my opinion g=0 (as mentioned for the screen shots) will disable the mask.

g=0 don't disable mask at all, 'cause codition
sqrt((u-128)^2+(v-128)^2) < 128 to apply some value of g (ie g=2.) it returns 0 if sqrt((u-128)^2+(v-128)^2) >= 128 instead of negative value, so for high saturated area the mask is always 0 (or 255 depending on your point).

the g & k values should be tuned for different content, anime & cartoon are more saturated than real life content, so g=2. is ok for animation, but for live action higher values works better (about 10 - 20).

also as Didée said (even if with only one mt_lutxy...)
mt_lutxy(last,SwapUV(),"x 128 - 2 ^ y 128 - 2 ^ + .5 ^ 128 > x "+
\+" x 128 - 128 x 128 - 2 ^ y 128 - 2 ^ + .5 ^ - 128 / "+string(g)+" ^ "+string(k-1)+
\+" * 1 + * 128 + ?",y=2,u=3,v=3)

SSH4
31st October 2011, 02:03
rough code....

a=last
Overlay(Grayscale(),mode="difference")
mt_lutxy(UtoY(Spline64Resize(width*2,height*2)),VtoY(Spline64Resize(width*2,height*2)),"x y > x y ?",chroma="128").ColorYUV(autogain=true,levels="TV->PC").RemoveGrain(12,-1)
mt_merge(a,a.Tweak(sat=3),last,luma=true)
StackHorizontal(a.Tweak(sat=3).Subtitle("Saturaion"),last.Subtitle("Vibrance"))


Source: http://www.digitalphoton.net/color-vibrance-in-photoshop/

IanB
1st November 2011, 00:20
Try Tweak(Sat=1.5, MaxSat=59.5, interp=20)

Increase saturation by 50% when below 59.5, linearly reducing from 50% to 0% over 59.5 up to 79.5. (Peak saturation is 150 tweak units, [R=255,G=B=0] has a saturation of 119 tweak units)

Motenai Yoda
6th November 2011, 13:26
@SSH4 It's wrong
- "x y > x y ?", this take only max, but u & v are 128 centered, if u=128 and y=200 it's different from u=199 and y=200...
also u=128 and y=56 instead is the same.
- ColorYUV(autogain=true,levels="TV->PC") , autolevels can be done there for photo content, but is no good for video content.

edit typing error change y with v

Nevilne
6th November 2011, 13:32
Color vibrance in photoshop radically changes luma as well by the way.

SSH4
7th November 2011, 13:55
Motenai Yoda yep, you right. "x y > x y ? 128 - abs 2 *" is little bit better...
but IanB give better and more native Avisynth way for vibrance.

IanB
7th November 2011, 23:08
You probably meant :-

"x 128 - abs y 128 - abs > x y ? 128 - abs"

or better still try

"x 128 - x 128 - * y 128 - y 128 - * + sqrt" # sqrt( (x-128)**2 + (y-128)**2 )

SSH4
7th November 2011, 23:21
oops you right.

Dogway
17th November 2011, 13:37
function SatMask(clip c, "Sat", float "bias", string "mode", clip "Rc", bool "lsb", bool "show"){

bias = string(default(bias, 5))
mode = string(default(mode, "Vibrance"))
lsb = default(lsb, false)
show = default(show, false)


lsb ? c.ditherpost(mode=6) : c

w=width()
h=height()

Assert(isclip(Sat) || isint(Sat) || isfloat(Sat), "'Sat' only accepts float, integers or clip inputs")
Assert(w%4 == 0, "width and height must be mod 4 resolution")
Assert(h%4 == 0, "width and height must be mod 4 resolution")

fmode = isclip(Sat) ? false : (Sat>0.0 ? true : false)
a= mode=="Recover" ? mt_lutxy(Vtoy(Rc),Utoy(Rc),"x 128 - 2 ^ y 128 - 2 ^ + .5 ^ 128 > 255 x 128 - 2 ^ y 128 - 2 ^ + .5 ^ "+bias+" * ?",u=1,v=1) : nop
b= !fmode || show || mode=="Recover" ? mt_lutxy(Vtoy(),Utoy(), "x 128 - 2 ^ y 128 - 2 ^ + .5 ^ 128 > 255 x 128 - 2 ^ y 128 - 2 ^ + .5 ^ "+bias+" * ?",u=1,v=1) : nop



msk = !fmode || show ? ((mode=="Vibrance") ? mt_lutxy(Vtoy(),Utoy(),"x 128 - 2 ^ y 128 - 2 ^ + .5 ^ 128 > 0 128 x 128 - 2 ^ y 128 - 2 ^ + .5 ^ - 128 / "+bias+" ^ 255 * ? ",u=1,v=1) : \
(mode=="Dullness") ? b : \
(mode=="Recover") ? mt_lutxy(a,b,"x y - abs 2 *",u=-128,v=-128) : \
Assert(false, "Wrong Saturation Mode")) : nop

show ? (lsb ? msk.Spline36Resize(w,h).Dither_convert_8_to_16() :\
msk.Spline36Resize(w,h)) :\
(Defined(Sat) || fmode ? \
((mode=="Vibrance") ? \
(lsb ? (fmode ? mergeluma(Dither_lutxy8(SwapUV(),"x 128 - 2 ^ y 128 - 2 ^ + .5 ^ 256 * 32768 > x 256 * "+
\+" x 128 - 128 x 128 - 2 ^ y 128 - 2 ^ + .5 ^ - 128 / "+bias+" ^ "+string(sat-1)+
\+" * 1 + * 128 + 256 * ?",y=2,u=3,v=3),c) :\
Dither_merge16(c,Sat,YToUV(msk,msk).Dither_convert_8_to_16,y=4)) :\
(fmode ? mt_lutxy(SwapUV(),"x 128 - 2 ^ y 128 - 2 ^ + .5 ^ 128 > x "+
\+" x 128 - 128 x 128 - 2 ^ y 128 - 2 ^ + .5 ^ - 128 / "+bias+" ^ "+string(sat-1)+
\+" * 1 + * 128 + ?",y=2,u=3,v=3) :\
mt_merge(Sat,YToUV(msk,msk),y=4,u=3,v=3))) :\
(mode=="Dullness") ? \
(lsb ? (fmode ? mergeluma(Dither_lutxy8(SwapUV(),"x 128 - 2 ^ y 128 - 2 ^ + .5 ^ 256 * 32768 > x 256 * "+
\+" x 128 - x 128 - 2 ^ y 128 - 2 ^ + .5 ^ "+string(sat-1)+
\+" * "+bias+" / 1 + / 128 + 256 * ?",y=2,u=3,v=3),c) :\
Dither_merge16(c,Sat,YToUV(msk,msk).Dither_convert_8_to_16,y=4)) :\
(fmode ? mt_lutxy(SwapUV(),"x 128 - 2 ^ y 128 - 2 ^ + .5 ^ 128 > x "+
\+" x 128 - x 128 - 2 ^ y 128 - 2 ^ + .5 ^ "+string(sat-1)+
\+" * "+bias+" / 1 + / 128 + ?",y=2,u=3,v=3) :\
mt_merge(Sat,YToUV(msk,msk),y=4,u=3,v=3))) :\
(mode=="Recover") ? \
(lsb ? (fmode ? mergeluma(Dither_lutxy8(SwapUV(),"x 128 - 2 ^ y 128 - 2 ^ + .5 ^ 256 * 32768 > x 256 * "+
\+" x 128 - 128 x 128 - 2 ^ y 128 - 2 ^ + .5 ^ - 128 / "+bias+" ^ "+string(sat-1)+
\+" * 1 + * 128 + 256 * ?",y=2,u=3,v=3),c) :\
Dither_merge16(c,Sat,YToUV(msk,msk).Dither_convert_8_to_16,y=4)) :\
(fmode ? mt_lutxy(SwapUV(),"x 128 - 2 ^ y 128 - 2 ^ + .5 ^ 128 > x "+
\+" x 128 - 128 x 128 - 2 ^ y 128 - 2 ^ + .5 ^ - 128 / "+bias+" ^ "+string(sat-1)+
\+" * 1 + * 128 + ?",y=2,u=3,v=3) :\
mt_merge(Sat,YToUV(msk,msk),y=4,u=3,v=3))): nop ) : c)}

bcn_246
4th January 2013, 03:47
VERY nice script DogWay, just a couple of suggestions...

1. Any way to modify it to use SVP for motion detection?
2. Did some testing on various videos, I would think a default bias of say, 10 would be better than 5

StainlessS
4th January 2013, 12:03
bcn_246,

Think you will find Dogway on Doom10, seldom visiits D9 now.