View Full Version : Something like RGBAdjust but in YUV


Stormborec
28th December 2014, 11:45
RGBAdjust:


rb, gb, bb

"OFFSETS rb, gb, bb - add a value to the red, green, blue" (the same could be done in coloryuv - in YUV)


r, g, b

"red (/green/blue) is scaled. For example, a scale of 3.0 MULTIPLIES the red channel of each pixel by 3"

- I doubt it would go something like this done in YUV, but I mean something else ...


The third, which isn't yet possible in RGB nor in YUV is:

OFFSET of chroma, but with values multiplied by level of LUMA of each pixel

http://www.imghosting.cz/images/901.png (http://www.imghosting.cz/view-901.png)

black - no shift
white - max shift

Exists the WhiteBalance plugin, but it is relatively inaccurate - changing some value only by 1 step do big color change ...

colours
28th December 2014, 13:41
Even if there's no currently existing filter to do exactly what you want, it's not hard to throw something together using Masktools.

source
y = converttoy8()
u = utoy8()
v = vtoy8()
y_adjusted = mt_lut(y,expr="x")
u_adjusted = mt_lutxy(u,y,expr="x y 16 - 0.1 * +")
v_adjusted = mt_lutxy(v,y,expr="x y 16 - 0.1 * +")
ytouv(u_adjusted,v_adjusted,y_adjusted) # note that the order here is U, V, Y


Tweak the expr parameters to taste; if you want higher precision, look into using CLExpr with lsb=true.

StainlessS
28th December 2014, 15:33
r, g, b

"red (/green/blue) is scaled. For example, a scale of 3.0 MULTIPLIES the red channel of each pixel by 3"

- I doubt it would go something like this done in YUV, but I mean something else ...

ColorYUV uses weird int gain arg, where eg
int gain_y = 0 is same as usual float gain=1.0 (no change)
int gain_y = 256 is same as usual float gain=2.0
int gain_y = 512 is same as usual float gain=3.0
int gain_y = -256 is same as usual float gain=0.5

See ColorYUV docs.

EDIT:
Cont_u=256 : Cont_v=256 : Same as Saturation * 2.0
ColorYUV2(), also has SPow (S shaped power curve) as well as RPow (As gamma).

ColorYUV2 here: http://forum.doom9.org/showthread.php?t=156774&highlight=coloryuv2

Stormborec
28th December 2014, 19:29
colours:

many thanks :thanks:
I had in mind masktools, but the strange writing
of its functions will be forever a secret for me :confused:

Could you describe, what the script actually do?
I'm going to test it ...


StainlessS:

I am surprised that until now I have not come across your Coloryuv2 ... :)

The gain in ColorYUV is analogy of contrast in Tweak. For chroma it is useless, because of the strange chroma waveform.

Every parameter in this basic internal functions is independent of the others.

Reel.Deel
28th December 2014, 19:38
Even if there's no currently existing filter to do exactly what you want, it's not hard to throw something together using Masktools.

source
y = converttoy8()
u = utoy8()
v = vtoy8()
y_adjusted = mt_lut(y,expr="x")
u_adjusted = mt_lutxy(u,y,expr="x y 16 - 0.1 * +")
v_adjusted = mt_lutxy(v,y,expr="x y 16 - 0.1 * +")
ytouv(u_adjusted,v_adjusted,y_adjusted) # note that the order here is U, V, Y



This only produces correct results with YV24, for YV12 I guess one needs to use a scaled luma for U/V adjustment (not sure if if chroma placement matters here)?

Stormborec
28th December 2014, 19:39
y = converttoy8() # ... creating "y clip" without chroma from "last"
u = utoy8() # ... creating "u clip" without chroma with values from chroma u in "last"
v = vtoy8() # ... creating "v clip" without chroma with values from chroma v in "last"
y_adjusted = mt_lut(y,expr="x") # ... crating some mask from luma of "last" ???
u_adjusted = mt_lutxy(u,y,expr="x y 16 - 0.1 * +") # ... some aplication of the mask on "chroma u" ???
v_adjusted = mt_lutxy(v,y,expr="x y 16 - 0.1 * +") # ... some aplication of the mask on "chroma v" ???
ytouv(u_adjusted,v_adjusted,y_adjusted) # ... gluing back together ???

Stormborec
28th December 2014, 19:41
Reel.Deel: you mean - the fact, that chroma is quarter of luma in YV12?

Stormborec
28th December 2014, 19:49
http://imgur.com/rya4YFO

It's great !! I will further test it ...

Reel.Deel
28th December 2014, 19:51
@Stormborec

This is what I mean:

y = converttoy8()
u = utoy8()
v = vtoy8()
y_scaled = y.bicubicresize(width(u), height(u))
y_adjusted = mt_lut(y,expr="x")
u_adjusted = mt_lutxy(u,y_scaled,expr="x y 16 - 0.1 * +")
v_adjusted = mt_lutxy(v,y_scaled,expr="x y 16 - 0.1 * +")
ytouv(u_adjusted,v_adjusted,y_adjusted) # note that the order here is U, V, Y

Stormborec
28th December 2014, 20:01
Good news - on grayscale it works perfect, from black to white !!!

Stormborec
28th December 2014, 20:04
And the resize will affect the result, or it is just for computing values for masktools? I mean if using bilinear or lanczos does matter ...

Reel.Deel
28th December 2014, 20:12
The scaled luma is only use for the chroma adjustment in MaskTools. You can try a different resizer but I'm not sure how it will affect the output. As always, you're welcome to try and report back :)

Stormborec
28th December 2014, 20:39
Many thanks !!!

BlankClip(length=1,width=640,height=360,fps=25,pixel_type="yv12",color=$ffffff)
levels(0,1,255,0,235)

y = converttoy8()
u = utoy8()
v = vtoy8()
y_scaled = y.bicubicresize(width(u), height(u))
y_adjusted = mt_lut(y,expr="x")
u_adjusted = mt_lutxy(u,y_scaled,expr="x y 16 - 0.05 * +")
v_adjusted = mt_lutxy(v,y_scaled,expr="x y 16 - 0.0 * +")
a = ytouv(u_adjusted,v_adjusted,y_adjusted)


interleave(a,last)
converttorgb.rgbadjust(analyze=true)
#coloryuv(analyze=true)

I've tested different colors and it works exactly as I wanted
:thanks:

Stormborec
28th December 2014, 21:43
I made from your code a function:

function Colorsbyy( clip last, float "ou", float "ov" )

{


ou = default(ou/219, 0.0)
ov = default(ov/219, 0.0)


y = converttoy8()
u = utoy8()
v = vtoy8()
y_scaled = y.bilinearresize(width(u), height(u))
y_adjusted = mt_lut(y,expr="x")
u_adjusted = mt_lutxy(u,y_scaled,expr="x y 16 - "+string(ou)+" * +")
v_adjusted = mt_lutxy(v,y_scaled,expr="x y 16 - "+string(ov)+" * +")
ytouv(u_adjusted,v_adjusted,y_adjusted)

return last

}




I added: /219, in order to the output looked - when input is a monochromatic image with luma = 235 - same like by using coloryuv(off_u, off_v).

I'll still test different resizers ...

So I tested spline36resize vs. bilinearresize - by using coloryuv(analyze=true) - there is a "one or two number" change, but it isn't a chance to see the change, although I sharpened, brightened and enlarged the image 3× ...

spline36resize vs. bilinearresize - the speed is about 3 % higher for bilinear ...

Wilbert
28th December 2014, 23:57
Do you guys never use the cont_u and cont_v arguments of ColorYUV? It stretches the chroma channels from the center:

it stretches the signal out from the center. That means that if the contrast is set to 0, it preserves the values as they are. When the contrast is 256 all values are multiplied by 2 (twice as bright). If the contrast is 512 all values are multiplied by 3. Thus if cont = k*256 for some integer k (and zero gain) then Y becomes Y + k*(Y-128) (idem for the chroma). Although it is possible, it doesn't make sense to apply this setting to the luma of the signal.

So setting cont_u = 512 (=2*256) means that U becomes: U_new = U_old + 2*(U_old-128).

You need to set opt=coring to clamp the values to tv-levels. Or isn't this what you want?


@Reel.Deel,

What are you trying to do in your script above? My polish ;) is very bad, but i guess i need to read it as follows:

// u_adjusted = mt_lutxy(u,y_scaled,expr="x y 16 - 0.1 * +")
u_adjusted = 0.1 * (16 - y_scaled) + u

Doesn't make much sense to me, but perhaps i completely misread it ... Why do you need a 2d lut table at all?

Overdrive80
29th December 2014, 00:02
SmoothAdjust works fine (16 bitdepth), you can try it.

http://forum.doom9.org/showthread.php?t=154971

Reel.Deel
29th December 2014, 01:11
@Reel.Deel,

What are you trying to do in your script above?

colours (post #2) came up with this, I just added a small change.

My polish is very bad, but i guess i need to read it as follows:

// u_adjusted = mt_lutxy(u,y_scaled,expr="x y 16 - 0.1 * +")
u_adjusted = 0.1 * (16 - y_scaled) + u

To me RPN and LUTs are like black magick :D. Fortunately MaskTools has mt_infix/mt_polish.

mt_infix("x y 16 - 0.1 * +") returns this: x+((y-16)*0.1)

StainlessS
29th December 2014, 04:29
Do you guys never use the cont_u and cont_v arguments of ColorYUV?

You talkin' to me? You talkin' to me? You talkin' to me? Then who the hell else are you talking... you talking to me? Well I'm the only one here. Who the f*** do you think you're talking to? Oh yeah? OK.

:)

Stormborec
29th December 2014, 04:59
SmoothAdjust is just other very very slow overkill for me :)

I know cont_u, cont_v very well. It's equivalent for saturation if it is used both ones.



OT.:
BlankClip(length=125,width=640,height=360,fps=25,pixel_type="yv12",color=$0000e2)
coloryuv(analyze=true)

=> y=38 ; u=227 ; v=112 ; r=0 ; g=0 ; b=225

BlankClip(length=125,width=640,height=360,fps=25,pixel_type="yv12",color=$0000ff)
coloryuv(off_y=-25)
coloryuv(analyze=true)

=> y=16 ; u=240 ; v=110 ; r=0 ; g=0 ; b=226

The color is nearly the same. So what does the big different in yuv mean? Am I dreaming or awake ???

feisty2
29th December 2014, 05:14
why do you just have to adjust colors under yuv colorspace?
if ur clip is ycbcr
you can see y as green (obviously not actual green tho)
u as blue (not actual blue also)
v as red

let's say you wanna enhance blue a little bit
mt_lut ("x 128 > x 128 - 1.24 * 128 + x 128 - 0.72 * 128 + ?", y=2, u=3, v=2) might help
# ((x > 128) ? (x - 128) * 1.24 + 128 : (x - 128) * 0.72 + 128)

Stormborec
29th December 2014, 05:18
Now I'm confused perfectly :confused:

feisty2
29th December 2014, 05:26
Now I'm confused perfectly :confused:

you can assume u as the difference of green and blue approximately
when u =128, means blue and green share the same value
when u > 128 means blue value is greater than green
u < 128, blue value is less than green
what that rpn does is extend the difference if blue is greater than green and neutralize some difference if blue is less than green, there, blue got enhanced

StainlessS
29th December 2014, 05:26
Stormborec
Not sure what what you were doing there but if wanting YUV in BlankClip might want to use color_yuv rather than color.
eg color_yuv=$808080 or whatever.

feisty2
29th December 2014, 05:43
Stormborec
Not sure what what you were doing there but if wanting YUV in BlankClip might want to use color_yuv rather than color.
eg color_yuv=$808080 or whatever.

just out of curiosity, does British really use "color", shouldn't it be "colour" in UK? I thought we yankees and maybe some Canadians are the only native English speakers on this planet that use the "color" spelling
:)
(I saw "favorite", not "favourite" on your screenshot last time and it has been haunting me ever since, so I couldn't help to ask this time)

EDIT: well, thx for answering my long time question, that was such a pain in my "head"

EDIT: cmon, no need to be mad, I suffer the same every time I use mvtools when part of my mind is in the middle of noplace, till a huge "There is no function named "MAnalyze" error wakes me up and I realize it's called "MAnalyse"
as for auto correct or spelling check, I guess there're many English versions for English users all around the world, at least on my iPhone, there're English (aka, American English), English (Canada), English (United Kingdom), English (Australia) and a lot more could be selected, I think I even saw English (India), some not so friendly softwares have 2 versions of English, English (North America) and English (International), maybe you can use a UK version of spelling checker and all the problems will be gone and my mvtools problem still remains :)

Stormborec
29th December 2014, 05:46
you are competing, who of you writes more bizzare mt expression :)

StainlessS
29th December 2014, 05:50
Well correct is colour, but everybody else seems to want to use that strange pidgin English from the colonies (as it happens,
the spell checker is showing 'colour' as misspelling, what can you do when everybody wants to speak pidgin).

EDIT: And don't take my spelling as any indication of correctness, I tend to spell-em however the fancy takes me at that moment.

EDIT: favorite, not favourite
Guess what shows up as wrong spelling in forum spell checker.

EDIT: One day, we shall take back that which is rightfully ours and we will do it on the 4th of July - just for the hell of it.

Stormborec
29th December 2014, 06:00
http://www.picturetopeople.org/p2p/picture_to_people_colors.p2p/color_converter?color_space=RGB&color_channel1=0&color_channel2=0&color_channel3=225

RGB (0, 0, 225) =

CMY = (255, 255, 30);
HSB = (240, 1.000, 0.882);
HSV = (240, 1.000, 0.882);
HSI = (240, 1.000, 0.294);
HSL = (240, 1.000, 0.441);
YIQ = (0.101, -0.284, 0.274);
YUV = (0.101, 0.386, -0.088);
YCbCr = (38, 227, 112);
CIE = (0.159, 0.064, 0.838);

Stormborec
29th December 2014, 06:02
It is perhaps bad idea to do: blankclip ... 0000FF >>> coloryuv(off_y=-25) >>> 0000E2

feisty2
29th December 2014, 06:05
yeah, yeah
I said u is not the real blue
but you can see it as the approximate blue

Stormborec
29th December 2014, 06:44
It was to the "BlankClip(length=125,width=640,height=360,fps=25,pixel_type="yv12",color=$0000ff)
coloryuv(off_y=-25)"
strange behavior

So this is mt_infix/mt_polish OR mt_chinese? ((x > 128) ? (x - 128) * 1.24 + 128 : (x - 128) * 0.72 + 128)


Is anywhere an explanation, or so you speak from birth? :D


I find:

Y = 0.299R + 0.587G + 0.114B
U =-0.147R - 0.289G + 0.436B
V = 0.615R - 0.515G - 0.100B

R = Y + 1.14V
G = Y - 0.39U - 0.58V
B = Y + 2.03U

Maybe it is possible in masktools to do calculations from YUV to RGB, but maybe it would be the same in terms of speed and quality like converttoRGB - RGBAdjust(1,2,3) - converttoyv12 ?

feisty2
29th December 2014, 07:02
The explanation is at #22, I used rpn for a while then got used to it

Wilbert
29th December 2014, 15:07
It was to the "BlankClip(length=125,width=640,height=360,fps=25,pixel_type="yv12",color=$0000ff)
coloryuv(off_y=-25)"
strange behavior

What's so strange about this? RGB = [0,0,255] equals YUV = [41,240,110]. off_y = -25 results in YUV = [16,240,110]. Converting back to RGB it will be a little less blue than the original. Did you expect/want something else?

After some thought about the cont_u and cont_v parameters, and looking at the code. The documentation is correct, but it is not written in a clear way. Example: cont_u = 512 corresponds with:

U_new = 128 + 3*(U_old-128)

or

U_new = U_old + 2*(U_old-128) // docs

When cont_u = -256, it becomes grey (thus U_new = 128). When cont_u = 0, nothing happens to the image.
For higher values it will get more blue (when U_old > 128), or more green (when U_old < 128). I will clarify the documentation.

Stormborec
29th December 2014, 19:37
ColorYUV:
"cont (contrast) stretches the signal out from the center"
It's clear to me - gray stay gray, max. saturated are max. shifted
=> just like saturation in Tweak, just only separated in U and V

What's so strange?

BlankClip(length=125,width=640,height=360,fps=25,pixel_type="yv12",color=$0000E2)
c=coloryuv(analyze=true).converttorgb Y38 U227 V112
r=converttorgb.rgbadjust(analyze=true) R0 G0 B225
stackvertical(c,r)


BlankClip(length=125,width=640,height=360,fps=25,pixel_type="yv12",color=$0000FF)
coloryuv(off_y=-25)
c=coloryuv(analyze=true).converttorgb Y16 U240 V110
r=converttorgb.rgbadjust(analyze=true) R0 G0 B226 (nearly the same blue)

Nearly same values in RGB, give very different values in YUV.
Both colors look the same.

Stormborec
29th December 2014, 20:01
It does what it wants ....

http://www.imagehosting.cz/thumbs/000000upu.png (http://www.imagehosting.cz/?v=000000upu.png)

http://www.imagehosting.cz/thumbs/000000cyc.png (http://www.imagehosting.cz/?v=000000cyc.png)

Does it mean, that for each ones RGB values could be plenty of different combinations of YUV values?

Stormborec
29th December 2014, 20:30
I found that the problem is in the coloryuv(off_y=...)

Stormborec
29th December 2014, 22:37
Is possible to do with Masktools something like RGBAdjust(0.9,0.8,1.1,1,0,0,0,0,1,1,1,1), all in YUV? What I perhaps could understand - it could be done using mt_lutxyz, but it would be very slow ...
Take values from Y, U, V - do the expresion - something like newY= calculation newY(calculation R, calculation G, calculation B) ... very difficult - I wonder how it would look in comparison with converttoRGB.RGBAdjust.converttoYV12 ...
But maybe there is some abbreviation / "trick" ...

I don't know the koeficients ...
But it will be always something like R= k1*(Y-16) + k2*(V-128) ...
http://forum.blackmagicdesign.com/viewtopic.php?f=12&t=29413

e.g.: RGBAdjust(3,3,3) multiplies each color channel with the given value =3. E.g. if some pixel is R=10, G=20, B=50 - then the output is R=30, G=60, B=150

Stormborec
29th December 2014, 23:31
Theoretically, it could only be 220 + 225 + 225 calculations (YUV range) ...
While using RGBAdjust: conversion from YV12 to RGB + RGBAdjust calculations + the conversion back from RGB to YV12. Thus, even though I don't know what are the calculations in convertto - maybe there is a trick ...

Wilbert
29th December 2014, 23:46
I found that the problem is in the coloryuv(off_y=...)
There is nothing wrong with coloryuv(off_y=...). It does what it is supposed to do. Perhaps that's not what you want but that's a different story.

Does it mean, that for each ones RGB values could be plenty of different combinations of YUV values?
It's the other way around. Many YUV values don't correspond with a valid RGB value, meaning at least one of the RGB components gets negative and is rounded to zero. That's why different YUV values can result in the same RGB value. See also http://forum.doom9.org/showthread.php?t=154731 .

Nearly same values in RGB, give very different values in YUV.
Both colors look the same.
They look the same because you are looking at their RGB representations (which are nearly the same). You don't see the YUV colors directly.
If you do a RGB [0,255] -> YUV [16,235] conversion (without rounding at the end), your colors will correspond with:

Y38 U227 V112 => R0.08 G-0.16 B225.32
Y16 U240 V110 => R-28.73 G-29.24 B225.93

Thus, even though I don't know what are the calculations in convertto - ...
Have a look at http://avisynth.nl/index.php/Color_conversions .

Oh, and could you stop responding to yourself a dozen of times.

Stormborec
30th December 2014, 04:43
Thanks fo the link, I don't understand, that I didn't find it myself :thanks:
It already is complicated by Rec.s, and then still YCbCr ....
It is still more confusing for me.

There was some mistake in my last post - the LUT would be NOT 220+225+225, but 220*225*225, of course ... But if the luma would stays untouched ... Then I could use maybe only lutxy. Much to learn ....

PS. "without rounding at the end ..." - but coloryuv has in default coring OFF ...

feisty2
30th December 2014, 04:57
I just failed to understand
why is it so important to adjust colors under yuv?

feisty2
30th December 2014, 16:15
If ur clip is chroma subsampled (422 or 420/411)
Precise rgb like color adjustments could never be done without converting to 444 or rgb, just don't put ur faith on lutxyz or whatever stuff, the answer is still no, cuz the resolutions of y and uv are different and it makes them unable to be calculated at the same time all together in an expression
If ur clip is 444, then just convert it to rgb and do whatever color stuff u want under rgb, it's harmless, use dither package if u worry about rounding errors during the color adjustments and colorspace conversions

Stormborec
30th December 2014, 17:48
I think, my videos are always 4:2:0 (MediaInfo) - maybe you mean something else ...
I did some tests - >converttoRGB > converttoYV12 - and there was always relatively visible color distortions in comparison wiht the input.
I could use something like 16bit depth - Dither ... but it would be to much for my slow computer ...
So my idea is not to do conversions (- btw. the output of converttoxx are intiger values?)
Masktools seems to me like the "second best solution", after internal functions ...
Btw. I read something more about masktools - infix is for me good news :), so now I already understand your:

mt_lut ("x 128 > x 128 - 1.24 * 128 + x 128 - 0.72 * 128 + ?", y=2, u=3, v=2)

It is something like Coloryuv(cont_u) but divided to half <128<
Yes - something like this may be good compromise for "real time"

feisty2
31st December 2014, 06:48
do you know you can choose chroma resample algorithm other than "bicubic" which is default in converttoxxx functions
yeah, bicubic could soften the chroma a little bit, maybe the "color distortions" ur talking about
"spline64" should be enough to soothe the loss to invisible level

Stormborec
2nd January 2015, 22:20
I just finished a script " RGBAdjust in YV12 " :)
I used your script that you created for me . By modifying equations of http://avisynth.nl/index.php/Color_conversions
I put together a script which I can modify R and B channel , without converting to RGB . Although it's a bit awkward , but 2 times FASTER than the way :
converttorgb.RGBAdjust.converttuyv12 .
Maybe speed is only a last- advantage ... I do not know yet

Green somehow disappeared :D but the white balance can be done just with two colors ...

I'm not a programmer , so I do not know if it would run faster script type :
255 * 16/219 + 255 * 128/112 * 0,886
than 347,556

I rounded to three decimal places - again - I do not know how many decimals it counts in masktools ...

y = converttoy8()
u = utoy8()
v = vtoy8()
y_scaled = y.bicubicresize(width(u), height(u))
u1 = mt_lutxy(u,y_scaled,mt_polish(" ((1.164 * y + 2.017 * x + 347.556) * 1.01 - 1.164 * y - 347.556) / 2.017 "))
v1 = mt_lutxy(v,y_scaled,mt_polish(" ((1.164 * y + 1.596 * x + 434.363) * 1.02 - 1.164 * y - 434.363) / 1.596 "))
ytouv(u1,v1,y)

if it was incomprehensible:

http://avisynth.nl/index.php/Color_conversions

b = (255/219)*y + (255/112)*u*(1-Kb) - (255*16/219 + 255*128/112*(1-Kb))
b*x = a1 *y + a2 * u1 - a3
(a1*y + a2*u + a3)*x = a1 *y + a2 * u1 - a3
u1 = ((a1*y + a2*u + a3)*x - a1 *y - a3)/a2

I already deleted it , maybe here's some plus and minus vice versa ...

Yes, the error will be about the missing y1 ... or I don't know ...

Wilbert
2nd January 2015, 23:52
It seems to me that your final clip is 1/4 of the size of your source clip. Since you are resizing the luma, and not resizing it back. That would explain why it is faster ;)

Reel.Deel
3rd January 2015, 01:21
It seems to me that your final clip is 1/4 of the size of your source clip. Since you are resizing the luma, and not resizing it back. That would explain why it is faster ;)

The luma is simply copied from the source clip, the resized luma channel (y_scaled) is only used in mt_lutxy.

Stormborec
3rd January 2015, 15:03
Yes.
I know why it does not work.
Adjusting of B leads to change the value of luma. But I just copy the luma from source.
To adjust luma - I would have to compute it from all three RGB, and it would not make sense ...

Btw. Could somebody tell me, where I can find manual for masktools? I found only:

http://avisynth.nl/index.php/MaskTools2
or for older version: http://manao4.free.fr/MaskTools.htm

I have many questions like what is the difference between V=3 and vexpr - it is just a different notation, or how many decimal places is works, etc. ...

Stormborec
4th January 2015, 22:19
I've written: "Adjusting of B leads to change the value of luma ..."

No, that's not true - the script changes only u and v, so the luma remaines untouched ...


I guess I'm wrong solved the equation. Now I've tried to model it again in Excel and it seems that it could work ...

u1 = 112*(1,2*(Y + 0,886*(u-128)/112)-Y)/0,886 +128
v1 = 112*(1,2*(Y + 0,701*(v-128)/112)-Y)/0,701 +128

0.0 <= Y <= 1.0
Y= (y-16)/219

I'll try it later in masktools ...

Wilbert
4th January 2015, 22:40
Adjusting B leads to a change in the luma too since y - 16 = (Kr*219/255)*r + (Kg*219/255)*g + (Kb*219/255)*b .
Suppose R and G remain constant, and only B changes. In that case you will get

delta y = (Kb*219/255) * delta b

Stormborec
4th January 2015, 23:22
Yes, but I don't adjust the B directly ... It's "hidden" in the equation - the change of B is made by changing U - and it leads automaticaly to change of G in opposite way. So the luma stays constant.

u1 = 112*(1,2*(Y + 0,886*(u-128)/112)-Y)/0,886 +128

the "1,2" is the adjustment of B, that is the same as RGBAdjust(1,0.??,1.2)

The G is changed this way:

Y = Kr*R + Kg*G + Kb*B
Kg*G + Kb*B = Kg*G1 + Kb*B1
G1=Kg*G+Kb*(B-B1)

Stormborec
5th January 2015, 22:12
I finally realized that my idea is wrong.
The point is that RGBAdjust (r, g, b, ...) is changing Luma, when I did not expect. The change depends on the values of each pixel that is being adjusted. So if perhaps someone in the future want to do something similar here ... forget it : D
But the script that you wrote at the beginning of this thread, on real content does essentially the same as RGBAdjust. The difference is only in extreme values, which reflected the fact that in RGBAdjust the rate of change of the values is directly proportional to the value of each RGB channel, while in your script the rate of change is directly proportional to the value luma
Once again, thanks for the script ! :thanks:

colours
10th January 2015, 08:00
Btw. Could somebody tell me, where I can find manual for masktools? I found only:

http://avisynth.nl/index.php/MaskTools2
or for older version: http://manao4.free.fr/MaskTools.htm

I have many questions like what is the difference between V=3 and vexpr - it is just a different notation, or how many decimal places is works, etc. ...

This might be slightly irrelevant now, but for posterity…

The documentation is on GitHub (https://github.com/tp7/masktools/tree/master/masktools/documentation). It's not packaged nicely in the release zip like Manao's releases, but I'm sure people can deal with a slight one-time hassle.

u/v=3 specifies that the U/V plane should be processed. u/vexpr specifies what expression to apply to the U/V plane if it is processed. u/vexpr does not, by itself, automatically flag the U/V plane for processing.

IIRC, MaskTools uses single precision for floats, so while you can specify as many decimal places as you want, the digits beyond the seventh significant figure are pretty much useless. (I'm a bit too lazy to fact-check this statement at the moment, but if it uses double precision instead, the cutoff would be at 16 significant figures.) The usual caveats about floating-point arithmetic apply, which I won't describe here.

Stormborec
10th January 2015, 12:05
I use this version: MaskTools2 b1
http://avisynth.nl/index.php/MaskTools2

If I understand, foundations are:

expresion is string value
there can be yexpr, uexpr, vexpr - or expr common for all planes
which plane is processed depends on value Y U V behihd the "string", ...
mt_lut returns clip with the same colorspace like the last
mt_lutxy as well, x and y - input clips have to be the same colorspace, corresponding planes are proccessed and they have to be the same resolutions ...

single precision for floats means: http://en.wikipedia.org/wiki/Decimal32_floating-point_format
so e.g. 255.1234 makes sense - I understand well?

colours
10th January 2015, 16:14
If I understand, foundations are:

expresion is string value
there can be yexpr, uexpr, vexpr - or expr common for all planes
which plane is processed depends on value Y U V behihd the "string", ...
mt_lut returns clip with the same colorspace like the last
mt_lutxy as well, x and y - input clips have to be the same colorspace, corresponding planes are proccessed and they have to be the same resolutions ...

Pretty much.

single precision for floats means: http://en.wikipedia.org/wiki/Decimal32_floating-point_format
so e.g. 255.1234 makes sense - I understand well?

Always assume binary floating-point unless otherwise specified. Decimal floats are almost never used in software. 7 (or 16) significant figures is just a rough approximation of how much precision 32-bit (or 64-bit) floats have.

Anyway, you don't have to fret over exactly how floats are handled; you can pretend MaskTools uses infinite-precision real numbers and the result much should be about the same anyway.

Stormborec
12th January 2015, 19:45
MaskTools uses single precision for floats, so while you can specify as many decimal places as you want, the digits beyond the seventh significant figure are pretty much useless.

I found, that mt_polish gives 7 figures float results:

eg.

mt_polish("x+(((((abs((x-y))/4)^(1/4))*4)*1.51)*((x-y)/(abs((x-y))+1.001)))")

=

x x y - abs 4 / 1 4 / ^ 4 * 1.510000 * x y - x y - abs 1.001000 + / * +

just for fun ...

Stormborec
19th January 2015, 21:58
Back to top ...

I found that if I add saturation, then the result is almost identical.
At least visually ...

coloryuv(cont_u=50,cont_v=20)
#(I know, that it could be done: x 128 - ? * 128 +)

y = converttoy8()
u = utoy8()
v = vtoy8()
y_scaled = y.bicubicresize(width(u), height(u))
y_adjusted = mt_lut(y,expr="x 16 - 1.086 * 16 +") # rather blowout than e.g. gamma change for me ...
u_adjusted = mt_lutxy(u,y_scaled,expr="x y 16 - 0.076 * +")
v_adjusted = mt_lutxy(v,y_scaled,expr="x y 16 - 0.024 * -")
ytouv(u_adjusted,v_adjusted,y_adjusted)
coloryuv(analyze=true)

http://www.imagehosting.cz/thumbs/yuv0000.png (http://www.imagehosting.cz/?v=yuv0000.png)

vs.

converttorgb24().rgbadjust(1.05,1.08,1.22).converttoyv12.coloryuv(analyze=true)


http://www.imagehosting.cz/thumbs/rgb0000.png (http://www.imagehosting.cz/?v=rgb0000.png)

320 vs. 130 FPS

I measured: cca 62 FPS - with no filters, 52 with "Masktools" and 42 with RGBAdjust

So: 1/(1/52-1/62) = 320 ...

Source:
http://www.imagehosting.cz/thumbs/source0000.png (http://www.imagehosting.cz/?v=source0000.png)


so this approximately:

y = converttoy8()
u = utoy8()
v = vtoy8()
y_scaled = y.bicubicresize(width(u), height(u))
y_adjusted = mt_lutxy(y,y.blur (0.5),"x 16 - 1.084 * 16 + x y - abs 4 / 1 4 / ^ 4 * 1.5 * x y - x y - abs 1 + / * + ")
u_adjusted = mt_lutxy(u,y_scaled,expr="x 128 - 1.20 * 128 + y 16 - 0.076 * +")
v_adjusted = mt_lutxy(v,y_scaled,expr="x 128 - 1.07 * 128 + y 16 - 0.024 * -")
ytouv(u_adjusted,v_adjusted,y_adjusted)


fix: there should be: y_adjusted = mt_lutxy(y,y.blur (0.5),"x x y - abs 4 / 1 4 / ^ 4 * 1.51 * x y - x y - abs 1.001 + / * + 16 - 1.036 * 16 +")
instead of y_adjusted = mt_lutxy(y,y.blur (0.5),"x 16 - 1.084 * 16 + x y - abs 4 / 1 4 / ^ 4 * 1.5 * x y - x y - abs 1 + / * + ")

Stormborec
11th February 2015, 14:27
So, now I finished the script which I replaced RGBAdjust (for my purposes - written above).
Masktools version doesn't make banding - like the RGBAdjust and the 640×360 video is rendered in Virtualdub:
RGBAdjust: 95 FPS, MaskTools: 160 FPS.

RGBAdjust:
directshowsource("1.flv",audio=false)
spline36resize(640,360)

coloryuv(cont_u=32,cont_v=32)

converttorgb24.rgbadjust(0.971,1,1.126)

Masktools:
directshowsource("1.flv",audio=false)

spline36resize(640,360)

y = converttoy8()
u = utoy8()
v = vtoy8()

y_scaled = y.bilinearresize(width(u),height(u))
u_scaled = u.pointresize(width(y),height(y))
v_scaled = v.pointresize(width(y),height(y))


uv = mt_lutxy(u_scaled,v_scaled,mt_polish("((-1.125*0.011885386*(y-128) + 1.125*0.0248848605*(x-128))+10)*10"))
uv_scaled = uv.pointresize(width(y),height(y))
y_adjusted = mt_lutxy(uv_scaled,y,mt_polish("x/10-10 + 1.005693*(y-16)+16"))

vy = mt_lutxy(v,y_scaled,mt_polish("((1.125*0.006860464*(x-128) + 0.069443417*(y-16))+5)*10"))
u_adjusted = mt_lutxy(u,vy,mt_polish("1.125*1.111636*(x-128)+128 + y/10-5"))

uy = mt_lutxy(u,y_scaled,mt_polish("((-1.125*0.018154785*(x-128) - 0.025310327*(y-16))+15)*10"))
v_adjusted = mt_lutxy(v,uy,mt_polish("1.125*0.979671*(x-128)+128 + y/10-15"))

ytouv(u_adjusted,v_adjusted,y_adjusted)

Now it's applicable

Lenchik
11th February 2015, 16:23
Can you please create a function like rgbadjust4yuv() that can be put into *.avsi and the called like
rgbadjust4yuv(0.971,1,1.126)?

Stormborec
11th February 2015, 18:20
It's possible, but there are some hitches ...

It's all based on this equations (for TV ranges):

Y = (y-16)/219 V = (v-128)/112 U = (u-128)/112

Y = Kr*R + Kg*G + Kb*B
V = R - G * Kg/(1-Kr) - B * Kb/(1-Kr)
U = - R * Kr/(1-Kb) - G * Kg/(1-Kb) + B

R = Y + V*(1-Kr)
G = Y - U*(1-Kb)*Kb/Kg - V*(1-Kr)*Kr/Kg
B = Y + U*(1-Kb)

Kr, Kg, Kb are coefficients for e.g. Rec.601 (TV)
see http://avisynth.nl/index.php/Color_conversions


procedure is as follows:

E.g.:
rgbadjus4yuv(rx,gx,bx)

R = Y + V*(1-Kr) ... R_adjusted = rx* (Y + V*(1-Kr))

Y = Kr*R + Kg*G + Kb*B ... Y_adjusted = Kr*(rx* (Y + V*(1-Kr))) + Kg*G + Kb*B

I must express all the R,G,B in Y,U,V. The big R,G,B,Y,U,V are in ranges 0 to 1 resp. -0.5 to 0.5.
After the exprssion I must express YUV to yuv - for TV ranges: y: 16 to 235, u and v: 16 to 240. I use the equations:

Y = (y-16)/219 V = (v-128)/112 U = (u-128)/112

Then I obtain very long equations - in the above script they are already multiplied.

Then I make the masktools sript.

The equations are in shape:

y1 = coef * y + coef * u + coef * v
u1 = coef * y + coef * u + coef * v
v1 = coef * y + coef * u + coef * v

You can use mt_lutxyz, but the speed up wouldn't be to big in coparrison with RGBAdjust, if ever.
It was my original script:

directshowsource("1.flv",audio=false)


spline36resize(640,360)


y = converttoy8()
u = utoy8()
v = vtoy8()

y_scaled = y.bilinearresize(width(u),height(u))
u_scaled = u.pointresize(width(y),height(y))
v_scaled = v.pointresize(width(y),height(y))

y_adjusted = mt_lutxyz(y,u_scaled,v_scaled,mt_polish("-1.125*0.011885386*(z-128) + 1.125*0.0248848605*(y-128) + 1.005693*(x-16)+16"))
u_adjusted = mt_lutxyz(u,y_scaled,v,mt_polish("1.125*0.006860464*(z-128) + 1.125*1.111636*(x-128)+128 + 0.069443417*(y-16)"))
v_adjusted = mt_lutxyz(v,y_scaled,u,mt_polish("-1.125*0.018154785*(z-128) + 1.125*0.979671*(x-128)+128 - 0.025310327*(y-16)"))

ytouv(u_adjusted,v_adjusted,y_adjusted)

The output is the same like for the script in the post above, but it's slower.

So ... I create instead of 3*3D luts ... 6*2D luts.

E.g.:

uv = mt_lutxy(u_scaled,v_scaled,mt_polish("((-1.125*0.011885386*(y-128) + 1.125*0.0248848605*(x-128))+10)*10"))

here I created clip "uv" like sum of coef * u and coef * v, because the values in the equation for luma of coef * u and coef * v are tipically smaller than the value of coef * y.

In masktools are the values calculated in float accuracy. But if I make the clip "uv", the values are rounded to intiger.
So I multiply the values by 10, to obtain more accuracy. I also added plus 5, 10 or 15, because the clip can't have negative values.

I have relatively small changes. And here is the hitch. If you want to do big changes in colors, then you can't too much multiply, and there will be rounding errors.

Btw. the 1.125 is saturation change equal to coloryuv(cont_u=32,cont_v=32) .... (32/256+1)