View Full Version : Something like RGBAdjust but in YUV
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)
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.