Log in

View Full Version : RGBAdapt v0.5 plugin 06 Dec 2018


Pages : [1] 2 3 4

StainlessS
21st May 2014, 04:10
RGBAdapt, By StainlessS

For Avisynth v2.58, v2.60, Avs+ x86 & x64. Requires VS 2008 CPP runtimes.

RGB24/RGB32.
Audio as original.

RGBAdapt(clip c, \
\ Float "R_Bias"=0.0,Float "R_Gain"=1.0,Float "R_Cont"=1.0,Float "R_RPow"=1.0,Float "R_Spow"=1.0,Float "R_SPMid"=0.5,Bool "R_Pord"=false,
\ Float "G_Bias"=0.0,Float "G_Gain"=1.0,Float "G_Cont"=1.0,Float "G_RPow"=1.0,Float "G_Spow"=1.0,Float "G_SPMid"=0.5,Bool "G_Pord"=false,
\ Float "B_Bias"=0.0,Float "B_Gain"=1.0,Float "B_Cont"=1.0,Float "B_RPow"=1.0,Float "B_Spow"=1.0,Float "B_SPMid"=0.5,Bool "B_Pord"=false,
\ Int "R_IMin"=0,Int "R_OMin"=0,Int "R_IMax"=255,Int "R_OMax"=255,
\ Int "G_IMin"=0,Int "G_OMin"=0,Int "G_IMax"=255,Int "G_OMax"=255,
\ Int "B_IMin"=0,Int "B_OMin"=0,Int "B_IMax"=255,Int "B_OMax"=255
\ )

Bias -512.0 -> 512.0. Bias = Brightness.
Gain -8.0 -> 8.0 Gain = Zero relative contrast.
Cont -8.0 -> 8.0 Cont = Centre relative Contrast.
RPow 0.1 -> 4.0 RPow = Gamma, r shaped power curve.
SPow 0.1 -> 4.0 SPow = S shaped power curve.
SPMid 0.01 -> 0.99 SPMid = Controls Inflection point for S shaped power curve, 0.5 = mid point ie 0.5*255.0
Pord True/False Pord=Rpow processed first (False) or SPow first (True). The power functions are non commutative.

Assuming all settings apart from RPow, SPow and SPMid at defaults:-
Pord Default (false) RPow1st, when modifying RPow or SPow, the SPow power curve inflection point will
remain fixed at Y = SPMid * 255.0, Rpow will slide it left or right.
Pord SPow1st, when modifying RPow or SPow, the SPow power curve inflection point will remain fixed
at X = SPMid * 255.0, RPow will slide it up or down.

New args v0.3
IMin 0 -> 255 : IMin <= (IMax+1)
OMin 0 -> 255
IMax 0 -> 255 : (IMin-1) <= IMax
OMax 0 -> 255

Any INPUT value less than IMin will be mapped to OMin (both default to 0), and values greater than IMax will be mapped to
OMax (both default to 255). With default settings the Min/Max options have no effect.
These options allow for weird shaped LUT's to eg create masks. Example, Leaving all other settings at default and
for some channel set IMax to eg 127 and OMax to 64 would map all input above 127 to 64 while leaving everything else untouched.
If you additionally set eg IMin=128 and OMin=180, then 0-127 would map to 180 and 128->255 map to 64.
The IMin <= (IMax+1) requirement allows you to map the entire 0->255 range to any two output values.



RgbAdapt_Graffer.exe demos the plugin and all arguments. (Will require VB6 runtimes, most will already have these.)


v0.4, Added RGBAdapt16() arguments identical to RGBAdapt().
Takes 8 bit interleaved RGB and produces Stack16 interleaved RGB, MSB on top.
Can use something like:-

Avisource("D:\avs\test.avi").convertToRGB32
RGBAdapt16(R_SPow=1.2,G_SPow=1.2,B_SPow=1.2)
Dither_convert_rgb_to_yuv(showred("yv12"), showgreen("yv12"), showblue("yv12"),lsb=false)
return Last

###########################################################

EDIT:
Graffer_Update,
The button "Get Fn Call From ClipBoard" reads in RgbAdapt settings from the clipboard, in format as created via RT_String().
Can write to Clipboard using ClipBoard plugin.

Ie, all 33 args In Default Order, with exception of the first clip argument which should be omitted.

# EDIT: Below added comman at end of every line, else cause error
Format = "RgbAdapt(" +
\ "%f,%f,%f,%f,%f,%f,%s," +
\ "%f,%f,%f,%f,%f,%f,%s," +
\ "%f,%f,%f,%f,%f,%f,%s," +
\ "%d,%d,%d,%d," +
\ "%d,%d,%d,%d," +
\ "%d,%d,%d,%d" +
\ ")"

CBStr=RT_String(Format,
\ red_bias, red_gain, red_cont, red_rpow, red_spow, r_spmid, r_pord,
\ grn_bias, grn_gain, grn_cont, grn_rpow, grn_spow, g_spmid, g_pord,
\ blu_bias, blu_gain, blu_cont, blu_rpow, blu_spow, b_spmid, b_pord,
\ red_imin, red_omin, red_imax, red_omax,
\ grn_imin, grn_omin, grn_imax, grn_omax,
\ blu_imin, blu_omin, blu_imax, blu_omax
\ )

err = ClipBoard_PutText(CBStr)
Assert(Err==0, "Error writing to ClipBoard")

##################
Reading Data written to clipboard via RgbAdapt_Graffer button "Copy Fn Call to Clipboard",
Use ClipBoard_GetText() to return as formatted below. (Add "c." before result to use c clip or without defaults to Last clip).
Or just use CTRL/V to insert from ClipBoard.

"""RgbAdapt(
\ R_Bias=0.1,R_Gain=1.001,R_Cont=1.001,R_Rpow=1.001,R_Spow=1.001,R_SPMid=0.501,R_Pord=True,
\ G_Bias=0.1,G_Gain=1.001,G_Cont=1.001,G_Rpow=1.001,G_Spow=1.001,G_SPMid=0.501,G_Pord=True,
\ B_Bias=0.1,B_Gain=1.001,B_Cont=1.001,B_Rpow=1.001,B_Spow=1.001,B_SPMid=0.501,B_Pord=True,
\ R_IMin=1,R_OMin=1,R_IMax=254,R_OMax=254,
\ G_IMin=1,G_OMin=1,G_IMax=254,G_OMax=254,
\ B_IMin=1,B_OMin=1,B_IMax=254,B_OMax=254
\ )
"""


And here a pic of the Graffer:-
https://s20.postimg.cc/wxyq8spkt/Fishv3_zpsfjmoyerr.jpg (https://postimg.cc/image/yd0axiqnt/)

The Ring on the Fish's cheek shows the pixel that is being tracked and the Before and After colors shown in status bar.
Monitor changes for single pixel as you modify the sliders.
The tick box on left show that SPow is locked so R + G + B settings are affected simultaneously.

From doc
Assuming all settings apart from RPow, SPow and SPMid at defaults:-
Pord Default (false) RPow1st, when modifying RPow or SPow, the SPow power curve inflection point will
remain fixed at Y = SPMid * 255.0, Rpow will slide it left or right.

As Pord RPow1st and SPMid @ 0.5 so SPow inflection point is fixed at Y = 0.5 * 255.0 for all three channels, and
as all three channels have SPow @ 1.18, the differing channels values of RPow shift it left or right as in graph.


dll's, + source + full VS2008 Project files for easy rebuild.
Click on MediaFire below.

EDIT: Clipboard plugin might be useful with RgbAdapt_Graffer:- https://forum.doom9.org/showthread.php?t=176145

Bernardd
23rd May 2014, 19:19
Hello StainlessS

Your plugin is great.

Thus i have tried to use it for auto white balance.

AVISource("C:\....\video.avi")

LoadPlugin("C:\..................\RGBAdapt_dll_v0.1-20140522\RGBAdapt.dll")

threshold = [<"threshold", 0, 255, 127>]
divisor_bias = [<"divisor_bias", 1, 10, 2>]
divisor_rpow = [<"divisor_rpow", 50, 150, 100>]
divisor_spow = [<"divisor_spow", 50, 150, 150>]


ConvertToRGB32(matrix="Rec601")

a=last

neutre = BlankClip(a, pixel_type="RGB32", color=$000000)

red=a.ShowRed("RGB32")
green = a.ShowGreen("RGB32")
blue = a.ShowBlue("RGB32")

b=a.ScriptClip("""
r = RGBDifference(red,neutre)
g = RGBDifference(green,neutre)
b = RGBDifference(blue,neutre)
dr = threshold - r
dg = threshold - g
db = threshold - b
dr1 = (threshold - r)*1/divisor_bias
dg1 = (threshold - g)*1/divisor_bias
db1 = (threshold - b)*1/divisor_bias
RGBAdapt( \
R_Bias = dr1, R_Gain = 1.0, R_Cont = 1.0, R_RPow = 1.0, R_Spow = 1.0, R_SPMid = 0.5, R_Pord = false, \
G_Bias = dg1, G_Gain = 1.0, G_Cont = 1.0, G_RPow = 1.0, G_Spow = 1.0, G_SPMid = 0.5, G_Pord = false,\
B_Bias = db1, B_Gain = 1.0, B_Cont = 1.0, B_RPow = 1.0, B_Spow = 1.0, B_SPMid = 0.5, B_Pord = false)
""")

red2=b.ShowRed("RGB32")
green2 = b.ShowGreen("RGB32")
blue2 = b.ShowBlue("RGB32")

c=b.ScriptClip("""
r = RGBDifference(red2,neutre)
g = RGBDifference(green2,neutre)
b = RGBDifference(blue2,neutre)
dr = threshold - r
dg = threshold - g
db = threshold - b
yr = 1+(threshold - r)*1/divisor_rpow
yg = 1+(threshold - g)*1/divisor_rpow
yb = 1+(threshold - b)*1/divisor_rpow
RGBAdapt( \
R_Bias = 0.0, R_Gain = 1.0, R_Cont = 1.0, R_RPow = yr, R_Spow = 1.0, R_SPMid = 0.5, R_Pord = false, \
G_Bias = 0.0, G_Gain = 1.0, G_Cont = 1.0, G_RPow = yg, G_Spow = 1.0, G_SPMid = 0.5, G_Pord = false,\
B_Bias = 0.0, B_Gain = 1.0, B_Cont = 1.0, B_RPow = yb, B_Spow = 1.0, B_SPMid = 0.5, B_Pord = false)
""")

red3=c.ShowRed("RGB32")
green3 = c.ShowGreen("RGB32")
blue3 = c.ShowBlue("RGB32")

d=c.ScriptClip("""
r = RGBDifference(red3,neutre)
g = RGBDifference(green3,neutre)
b = RGBDifference(blue3,neutre)
dr = threshold - r
dg = threshold - g
db = threshold - b
sr = 1-(threshold - r)*1/divisor_spow
sg = 1-(threshold - g)*1/divisor_spow
sb = 1-(threshold - b)*1/divisor_spow
RGBAdapt(c, \
R_Bias = 0.0, R_Gain = 1.0, R_Cont = 1.0, R_RPow = 1.0, R_Spow = sr, R_SPMid = 0.5, R_Pord = false, \
G_Bias = 0.0, G_Gain = 1.0, G_Cont = 1.0, G_RPow = 1.0, G_Spow = sg, G_SPMid = 0.5, G_Pord = false,\
B_Bias = 0.0, B_Gain = 1.0, B_Cont = 1.0, B_RPow = 1.0, B_Spow = sb, B_SPMid = 0.5, B_Pord = false)
""")

StackHorizontal(a.Subtitle("original"),b.Subtitle("linear curve"),c.Subtitle("Rpow curve"),d.Subtitle("Spow curve"),a.ConvertToYV12.ColorYUV(autowhite=true).Subtitle("AWB ColorYUV").ConvertToRGB32)




It is auto, but I have put some variable values for test.

Has this script a sense ? Has Bias and Rpow auto-tune a sense ? Has Rpow and Spow auto-tune a sense ?

For the last question, i think no, but for the other i don't know yet.

Thanks

Bernardd
24th May 2014, 22:13
Hello,

I have worked this day on RGBAdapt use for automatic white balance. I have found a new expression to tune Rpow and Spow. Perhaps is it a best expression, but i have not found it this day.

Now the script is OK for me.

AVISource("C:\.......\1970-1971-Noel-Ski début rayures et poussières amoindries.avi")

LoadPlugin("C:\..............\RGBAdapt_dll_v0.1-20140522\RGBAdapt.dll")

info = [<"info", 0, 1, 1>] # show info, no = 0, yes = 1
threshold = [<"threshold", 0, 255, 127>]
divisor_bias = [<"divisor_bias", 0.1, 1.0, 0.5>]

ConvertToRGB32(matrix="Rec601")

a=last

neutre = BlankClip(a, pixel_type="RGB32", color=$000000)

#---------------------------------------- Linear curve b with info, b1 without info

red=a.ShowRed("RGB32")
green = a.ShowGreen("RGB32")
blue = a.ShowBlue("RGB32")

b=a.ScriptClip("""
r = RGBDifference(red,neutre)
g = RGBDifference(green,neutre)
b = RGBDifference(blue,neutre)
dr = threshold - r
dg = threshold - g
db = threshold - b
dr1 = dr*divisor_bias
dg1 = dg*divisor_bias
db1 = db*divisor_bias
Subtitle("Red value : "+String(r)+"Bias : "+String(dr1),y=40)
Subtitle("Green value : "+String(b)+"Bias : "+String(dg1),y=60)
Subtitle("Blue value : "+String(b)+"Bias : "+String(db1),y=80)
RGBAdapt( \
R_Bias = dr1, R_Gain = 1.0, R_Cont = 1.0, R_RPow = 1.0, R_Spow = 1.0, R_SPMid = 0.5, R_Pord = true, \
G_Bias = dg1, G_Gain = 1.0, G_Cont = 1.0, G_RPow = 1.0, G_Spow = 1.0, G_SPMid = 0.5, G_Pord = true,\
B_Bias = db1, B_Gain = 1.0, B_Cont = 1.0, B_RPow = 1.0, B_Spow = 1.0, B_SPMid = 0.5, B_Pord = true)
""")

b1=a.ScriptClip("""
r = RGBDifference(red,neutre)
g = RGBDifference(green,neutre)
b = RGBDifference(blue,neutre)
dr = threshold - r
dg = threshold - g
db = threshold - b
dr1 = dr*divisor_bias
dg1 = dg*divisor_bias
db1 = db*divisor_bias
RGBAdapt( \
R_Bias = dr1, R_Gain = 1.0, R_Cont = 1.0, R_RPow = 1.0, R_Spow = 1.0, R_SPMid = 0.5, R_Pord = true, \
G_Bias = dg1, G_Gain = 1.0, G_Cont = 1.0, G_RPow = 1.0, G_Spow = 1.0, G_SPMid = 0.5, G_Pord = true,\
B_Bias = db1, B_Gain = 1.0, B_Cont = 1.0, B_RPow = 1.0, B_Spow = 1.0, B_SPMid = 0.5, B_Pord = true)
""")

#---------------------------------------- Rpow curve c with info, c1 without info

red2=b1.ShowRed("RGB32")
green2 = b1.ShowGreen("RGB32")
blue2 = b1.ShowBlue("RGB32")

c=b1.ScriptClip("""
r = RGBDifference(red2,neutre)
g = RGBDifference(green2,neutre)
b = RGBDifference(blue2,neutre)
dr = threshold - r
dg = threshold - g
db = threshold - b
m=(dr+dg+db)
yr = (dr < 0) ? 1+dr/100:1+dr/100
yg = (dg < 0) ? 1+dg/100:1+dg/100
yb = (db < 0) ? 1+db/100:1+db/100
Subtitle("Red value : "+String(r)+"Bias : "+String(dr)+" Rpow : "+String(yr),y=40)
Subtitle("Green value : "+String(b)+"Bias : "+String(dg)+" Rpow : "+String(yg),y=60)
Subtitle("Blue value : "+String(b)+"Bias : "+String(db)+" Rpow : "+String(yb),y=80)
RGBAdapt( \
R_Bias = 0.0, R_Gain = 1.0, R_Cont = 1.0, R_RPow = yr, R_Spow = 1.0, R_SPMid = 0.5, R_Pord = true, \
G_Bias = 0.0, G_Gain = 1.0, G_Cont = 1.0, G_RPow = yg, G_Spow = 1.0, G_SPMid = 0.5, G_Pord = true,\
B_Bias = 0.0, B_Gain = 1.0, B_Cont = 1.0, B_RPow = yb, B_Spow = 1.0, B_SPMid = 0.5, B_Pord = true)
""")

c1=b1.ScriptClip("""
r = RGBDifference(red2,neutre)
g = RGBDifference(green2,neutre)
b = RGBDifference(blue2,neutre)
dr = threshold - r
dg = threshold - g
db = threshold - b
m=(dr+dg+db)
yr = (dr < 0) ? 1+dr/100:1+dr/100
yg = (dg < 0) ? 1+dg/100:1+dg/100
yb = (db < 0) ? 1+db/100:1+db/100
RGBAdapt( \
R_Bias = 0.0, R_Gain = 1.0, R_Cont = 1.0, R_RPow = yr, R_Spow = 1.0, R_SPMid = 0.5, R_Pord = true, \
G_Bias = 0.0, G_Gain = 1.0, G_Cont = 1.0, G_RPow = yg, G_Spow = 1.0, G_SPMid = 0.5, G_Pord = true,\
B_Bias = 0.0, B_Gain = 1.0, B_Cont = 1.0, B_RPow = yb, B_Spow = 1.0, B_SPMid = 0.5, B_Pord = true)
""")

#---------------------------------------- Spow curve d with info, d1 without info

red3=c1.ShowRed("RGB32")
green3 = c1.ShowGreen("RGB32")
blue3 = c1.ShowBlue("RGB32")

d=c1.ScriptClip("""
r = RGBDifference(red3,neutre)
g = RGBDifference(green3,neutre)
b = RGBDifference(blue3,neutre)
dr = threshold - r
dg = threshold - g
db = threshold - b
sr = (dr < 0) ? 1+dr/100:1+dr/100
sg = (dg < 0) ? 1+dg/100:1+dg/100
sb = (db < 0) ? 1+db/100:1+db/100
Subtitle("Red value : "+String(r)+"Bias : "+String(dr)+" Spow : "+String(sr),y=40)
Subtitle("Green value : "+String(b)+"Bias : "+String(dg)+" Spow : "+String(sg),y=60)
Subtitle("Blue value : "+String(b)+"Bias : "+String(db)+" Spow : "+String(sb),y=80)
RGBAdapt( \
R_Bias = 0.0, R_Gain = 1.0, R_Cont = 1.0, R_RPow = 1.0, R_Spow = sr, R_SPMid = 0.5, R_Pord = false, \
G_Bias = 0.0, G_Gain = 1.0, G_Cont = 1.0, G_RPow = 1.0, G_Spow = sg, G_SPMid = 0.5, G_Pord = false,\
B_Bias = 0.0, B_Gain = 1.0, B_Cont = 1.0, B_RPow = 1.0, B_Spow = sb, B_SPMid = 0.5, B_Pord = false)
""")

d1=c1.ScriptClip("""
r = RGBDifference(red3,neutre)
g = RGBDifference(green3,neutre)
b = RGBDifference(blue3,neutre)
dr = threshold - r
dg = threshold - g
db = threshold - b
sr = (dr < 0) ? 1+dr/100:1+dr/100
sg = (dg < 0) ? 1+dg/100:1+dg/100
sb = (db < 0) ? 1+db/100:1+db/100
RGBAdapt( \
R_Bias = 0.0, R_Gain = 1.0, R_Cont = 1.0, R_RPow = 0.9, R_Spow = sr, R_SPMid = 0.5, R_Pord = false, \
G_Bias = 0.0, G_Gain = 1.0, G_Cont = 1.0, G_RPow = 0.9, G_Spow = sg, G_SPMid = 0.5, G_Pord = false,\
B_Bias = 0.0, B_Gain = 1.0, B_Cont = 1.0, B_RPow = 0.9, B_Spow = sb, B_SPMid = 0.5, B_Pord = false)
""")

(info == 1) ? \
StackHorizontal(a.Subtitle("original"),b.Subtitle("linear curve"),c.Subtitle("Rpow curve"),d.Subtitle("Spow curve"),\
a.ConvertToYV12.ColorYUV(autowhite=true).Subtitle("AWB ColorYUV").ConvertToRGB32) : \
StackHorizontal(a.Subtitle("original"),b1.Subtitle("linear curve"),c1.Subtitle("Rpow curve"),d1.Subtitle("Spow curve"),\
a.ConvertToYV12.ColorYUV(autowhite=true).Subtitle("AWB ColorYUV").ConvertToRGB32)



Thanks for the plugin. With Rpow and Spow use i have a best result that RGBAdjust and gamma use.

Bernardd
25th May 2014, 10:35
Hello StainlessS,

After night, ideas are more light, thus i have written still my script for having more accordance with your great plugin.

AVISource("C:\.......\video.avi")

LoadPlugin("C:\......\RGBAdapt_dll_v0.1-20140522\RGBAdapt.dll")

threshold = [<"threshold", 0, 255, 127>] # Middle ton for automatic white balance
strength_bias = [<"strength_bias", 0.1, 1.0, 0.5>] # Strength linear curve use
strength_Rpow = [<"Strength_Rpow", 0.1, 1.0, 0.8>] # Strength Rpow curve use
strength_Spow = [<"Strength_Spow", 0.1, 1.0, 1.0>] # Strength Spow curve use

ConvertToRGB32(matrix="Rec601")

a=last

neutre = BlankClip(a, pixel_type="RGB32", color=$000000)

#---------------------------------------- Linear curve b with info, b1 without info

red=a.ShowRed("RGB32")
green = a.ShowGreen("RGB32")
blue = a.ShowBlue("RGB32")

b=a.ScriptClip("""

#------------ RGB values calcul
r = RGBDifference(red,neutre)
g = RGBDifference(green,neutre)
b = RGBDifference(blue,neutre)

#----------- RGB correction calcul
dr = threshold - r
dg = threshold - g
db = threshold - b

#----------- RGB correction with linear curve calcul (Bias)
dr1 = dr*strength_bias
dg1 = dg*strength_bias
db1 = db*strength_bias

#----------- RGB correction with Rpow and Spow curves calcul
dr2 = dr-dr1
dg2 = dg-dg1
db2 = db-db1

#----------- RGB correction with Rpow curve calcul
yr = (dr2 < 0) ? (1+dr2/100)*strength_rpow:(1+dr2/100)*strength_rpow
yg = (dg2 < 0) ? (1+dg2/100)*strength_rpow:(1+dg2/100)*strength_rpow
yb = (db2 < 0) ? (1+db2/100)*strength_rpow:(1+db2/100)*strength_rpow

#----------- RGB correction with Spow curve calcul
sr = (dr2 < 0) ? (1+dr2/100)*strength_spow:(1+dr2/100)*strength_spow
sg = (dg2 < 0) ? (1+dg2/100)*strength_spow:(1+dg2/100)*strength_spow
sb = (db2 < 0) ? (1+db2/100)*strength_spow:(1+db2/100)*strength_spow

Subtitle("Red value : "+String(r)+"Bias : "+String(dr)+" Rpow : "+String(yr)+" Spow : "+String(sr),y=40)
Subtitle("Green value : "+String(b)+"Bias : "+String(dg)+" Rpow : "+String(yg)+" Spow : "+String(sg),y=60)
Subtitle("Blue value : "+String(b)+"Bias : "+String(db)+" Rpow : "+String(yb)+" Spow : "+String(sb), y=80)

RGBAdapt( \
R_Bias = dr1, R_Gain = 1.0, R_Cont = 1.0, R_RPow = yr, R_Spow = sr, R_SPMid = 0.5, R_Pord = false, \
G_Bias = dg1, G_Gain = 1.0, G_Cont = 1.0, G_RPow = yg, G_Spow = sg, G_SPMid = 0.5, G_Pord = false,\
B_Bias = db1, B_Gain = 1.0, B_Cont = 1.0, B_RPow = yb, B_Spow = sb, B_SPMid = 0.5, B_Pord = false)
""")

b1=a.ScriptClip("""

#------------ RGB values calcul
r = RGBDifference(red,neutre)
g = RGBDifference(green,neutre)
b = RGBDifference(blue,neutre)

#----------- RGB correction calcul
dr = threshold - r
dg = threshold - g
db = threshold - b

#----------- RGB correction with linear curve calcul (Bias)
dr1 = dr*strength_bias
dg1 = dg*strength_bias
db1 = db*strength_bias

#----------- RGB correction with Rpow and Spow curves calcul
dr2 = dr-dr1
dg2 = dg-dg1
db2 = db-db1

#----------- RGB correction with Rpow curve calcul
yr = (dr2 < 0) ? (1+dr2/100)*strength_rpow:(1+dr2/100)*strength_rpow
yg = (dg2 < 0) ? (1+dg2/100)*strength_rpow:(1+dg2/100)*strength_rpow
yb = (db2 < 0) ? (1+db2/100)*strength_rpow:(1+db2/100)*strength_rpow

#----------- RGB correction with Spow curve calcul
sr = (dr2 < 0) ? (1+dr2/100)*strength_spow:(1+dr2/100)*strength_spow
sg = (dg2 < 0) ? (1+dg2/100)*strength_spow:(1+dg2/100)*strength_spow
sb = (db2 < 0) ? (1+db2/100)*strength_spow:(1+db2/100)*strength_spow
sb = (db2 < 0) ? 1+db2/100:1+db2/100

RGBAdapt( \
R_Bias = dr1, R_Gain = 1.0, R_Cont = 1.0, R_RPow = yr, R_Spow = sr, R_SPMid = 0.5, R_Pord = false, \
G_Bias = dg1, G_Gain = 1.0, G_Cont = 1.0, G_RPow = yg, G_Spow = sg, G_SPMid = 0.5, G_Pord = false,\
B_Bias = db1, B_Gain = 1.0, B_Cont = 1.0, B_RPow = yb, B_Spow = sb, B_SPMid = 0.5, B_Pord = false)
""")

return StackHorizontal(a,b,b1)

This script has three args for tune strength of bias, rpow and spow corrections.
Thanks
Nice sunday

Bernardd
26th May 2014, 19:54
Hello StainlessS,

To day i have finished the automatic autowhite balance of RGBAdapt and i have written the automatic autowhite balance of CorlorYUV2. This two scripts below :


#AVISource("C:\..........\video.avi")
LoadPlugin("C:\..........\RGBAdapt_dll_v0.1-20140522\RGBAdapt.dll")

threshold = [<"threshold", 0, 255, 128>] # Middle ton for automatic white balance
strength_bias = [<"strength_bias", 0.1, 1.0, 0.5>] # Strength linear curve use
cont = [<"cont", 1.00, 1.50, 1.15>] # Contrast, necessary after linear curve
strength_Rpow = [<"Strength_Rpow", 0.0, 1.0, 0.5>] # Strength Rpow curve use
strength_Spow = [<"Strength_Spow", 0.0, 1.0, 0.5>] # Strength Spow curve use
Spmid = [<"Spmid", 0.1, 0.99, 0.58>] # Middle point for Spow curve use
Pord_nb = [<"Pord_nb", 0, 1, 0>]
Pord = (Pord_nb == 0) ? false : true
show_info = [<"show_info", 0, 1, 0>]
comparison = [<"comparison", 0, 1, 0>]

original=last

ConvertToRGB32(matrix="Rec601")

neutre = BlankClip(last, pixel_type="RGB32", color=$000000)
red=ShowRed("RGB32")
green = ShowGreen("RGB32")
blue = ShowBlue("RGB32")

ScriptClip("""

#------------ RGB values calcul
r = RGBDifference(red,neutre)
g = RGBDifference(green,neutre)
b = RGBDifference(blue,neutre)

#----------- RGB correction calcul
dr = threshold - r
dg = threshold - g
db = threshold - b

#----------- RGB correction with linear curve calcul (Bias)
dr1 = dr*strength_bias
dg1 = dg*strength_bias
db1 = db*strength_bias

#----------- RGB correction with Rpow and Spow curves calcul
dr2 = dr-dr1
dg2 = dg-dg1
db2 = db-db1

#----------- RGB correction with Rpow curve calcul
yr = (dr2 < 0) ? 1+(dr2*0.9/128)*strength_rpow: 1+(dr2*3/128)*strength_rpow
yg = (dg2 < 0) ? 1+(dg2*0.9/128)*strength_rpow: 1+(dg2*3/128)*strength_rpow
yb = (db2 < 0) ? 1+(db2*0.9/128)*strength_rpow: 1+(db2*3/128)*strength_rpow

#~ yr = (dr2 < 0) ? (1+dr2/128)*strength_rpow:(1+dr2*Full_range)*strength_rpow
#~ yg = (dg2 < 0) ? (1+dg2/128)*strength_rpow:(1+dg2*Full_range)*strength_rpow
#~ yb = (db2 < 0) ? (1+db2/100)*strength_rpow:(1+db2*Full_range)*strength_rpow

#----------- RGB correction with Spow curve calcul
sr = (dr2 < 0) ? 1+(dr2*0.9/128)*strength_spow: 1+(dr2*3/128)*strength_spow
sg = (dg2 < 0) ? 1+(dg2*0.9/128)*strength_spow: 1+(dg2*3/128)*strength_spow
sb = (db2 < 0) ? 1+(db2*0.9/128)*strength_spow: 1+(db2*3/128)*strength_spow

(show_info == 0)? \
RGBAdapt( \
R_Bias = dr1, R_Gain = 1.0, R_Cont = cont, R_RPow = yr, R_Spow = sr, R_SPMid = Spmid, R_Pord = Pord, \
G_Bias = dg1, G_Gain = 1.0, G_Cont = cont, G_RPow = yg, G_Spow = sg, G_SPMid = Spmid, G_Pord = Pord,\
B_Bias = db1, B_Gain = 1.0, B_Cont = cont, B_RPow = yb, B_Spow = sb, B_SPMid = Spmid, B_Pord = Pord):\
RGBAdapt( \
R_Bias = dr1, R_Gain = 1.0, R_Cont = cont, R_RPow = yr, R_Spow = sr, R_SPMid = Spmid, R_Pord = Pord, \
G_Bias = dg1, G_Gain = 1.0, G_Cont = cont, G_RPow = yg, G_Spow = sg, G_SPMid = Spmid, G_Pord = Pord,\
B_Bias = db1, B_Gain = 1.0, B_Cont = cont, B_RPow = yb, B_Spow = sb, B_SPMid = Spmid, B_Pord = Pord)\
.Subtitle("Red value : "+String(r)+" Bias : "+String(dr1)+" Rpow : "+String(yr)+" Spow : "+String(sr),y=40)\
.Subtitle("Green value : "+String(b)+" Bias : "+String(dg1)+" Rpow : "+String(yg)+" Spow : "+String(sg),y=60)\
.Subtitle("Blue value : "+String(b)+" Bias : "+String(db1)+" Rpow : "+String(yb)+" Spow : "+String(sb), y=80)

""")

ConvertToYV12(matrix="Rec601")

(comparison == 0) ? last : StackHorizontal(original,last)



#AVISource("C:\............\video.avi")

LoadPlugin("C:\............\ColorYUV2_25_dll_20120529\ColorYUV2.dll")

threshold = [<"threshold", 0, 255, 127>] # Middle ton for automatic white balance
strength_bias = [<"strength_bias", 0.1, 1.0, 0.5>] # Strength linear curve use
cont = [<"cont", -20, 60, 51.1>]
strength_Rpow = [<"Strength_Rpow", 0.1, 1.0, 0.5>] # Strength Rpow curve use
strength_Spow = [<"Strength_Spow", 0.1, 1.0, 0.5>] # Strength Spow curve use
Pord = [<"Pord_nb", 0, 1, 0>]
show_info = [<"show_info", 0, 1, 0>]
comparison = [<"comparison", 0, 1, 0>]

original=last

ScriptClip("""

#------------ YUV average value
y = AverageLuma()
u = AverageChromaU()
v = AverageChromaV()

#----------- RGB correction calcul
dy = threshold - y
du = threshold - u
dv = threshold - v

#----------- RGB correction with linear curve calcul (Bias)
dy1 = dy*strength_bias
du1 = du*strength_bias
dv1 = dv*strength_bias

#----------- RGB correction with Rpow and Spow curves calcul
dy2 = dy-dy1
du2 = du-du1
dv2 = dv-dv1

#----------- RGB correction with Rpow curve calcul
yy = dy2*strength_rpow
yu = du2*strength_rpow
yv = dv2*strength_rpow

#----------- RGB correction with Spow curve calcul
sy = dy2*strength_spow
su = du2*strength_spow
sv = dv2*strength_spow

(show_info == 0)? \
ColorYUV2(\
off_y = dy1, cont_y = cont, rpow_y = yy, spow_y = sy, pord_y = pord,\
off_u = du1, rpow_u = yu, spow_u = su, pord_u = pord,\
off_v = dv1, rpow_v = yv, spow_v = sv, pord_v = pord):\
ColorYUV2(\
off_y = dy1, cont_y = cont, rpow_y = yy, spow_y = sy, pord_y = pord,\
off_u = du1, rpow_u = yu, spow_u = su, pord_u = pord,\
off_v = dv1, rpow_v = yv, spow_v = sv, pord_v = pord)\
.Subtitle("Luma value : "+String(y)+" Bias : "+String(dy)+" Rpow : "+String(yy)+" Spow : "+String(sy),y=40)\
.Subtitle("U value : "+String(u)+" Bias : "+String(du)+" Rpow : "+String(yu)+" Spow : "+String(su),y=60)\
.Subtitle("V value : "+String(v)+" Bias : "+String(dv)+" Rpow : "+String(yv)+" Spow : "+String(sv), y=80)

""")

(comparison == 0) ? last : StackHorizontal(original,last)



I believe these scripts can be used to make automatic white balance or at less to help, with their info displays to find best args values in manual script use.

Thanks for this script and also for the graffers, with them we know that we are doing.

StainlessS
26th May 2014, 20:02
Glad that your keeping busy :)
I'm busy myself at the moment, and dont have AVSPmod installed to try your scripts (I usually just use text editor and VDMod).
If you want to look for ideas, maybe try search for AWB by Martin53 (he has not been around for a good time, told me he was
on safari several months ago, hope those crocodiles did not get him).

Bernardd
27th May 2014, 20:09
Hello StainlessS,

I do believe that automatic white balance can not give back natural colors, but only nearest. There are for film external args which give bad white balance, like sunset for example. Thus my aim is to improve few, ColorYUV automatic functions. Because sometime i get cold colors.

With your graffer, i have understood that is because ColorYUV AutoWhite use only a bias correction with a linear curve. Thus i think your ColorYUV2 and RGBAdapt plugins should be more efficiency with rpow and spow curves. I think sunset light information is more readable in light tones, thus we do not must erase them in white balance action. Spow curve is good in this case.

My scripts are not all automatic. I need to keep args to choice and tune strength of linear, rpow and spow curves actions.

This scripts use only difference between 127 and each channel average value for automatic caculation. they are now operational, for ColorYUV2, i think is finished, for RGBAdapt i search still the best formula for Rpow and Spow inputs. In colorYUV2 these args input are linear, but in RGBAdapt, i smell a log input, but i have no found the good numbers.

In the next version, i shall write my script in function style.

I hope my search do not disturb you.

Thanks

StainlessS
27th May 2014, 21:55
I think that ColorYUV AutoWhite just centers U and V using Off_u and off_v (but cant remember how it decides, maybe by pixel population).

EDIT Scratch that, probably AverageChromaU, AverageChromaV, ie make them center at 128.

EDIT: Although I would suggest might be better only to do at most half way correction as above.

Bernardd
29th May 2014, 00:28
Hello StainlessS

Gavino have given me this autowhite coloryuv calculation in this post http://forum.doom9.org/showthread.php?p=1673682#post1673682

But i think other formula is used for tune luma in autowhite. I do not find it, thus i have add contraste args in my two scripts.

Below the two scripts in function style version. In the end, after instruction " __End__", i have save the script to call the function with
AvsPmod Users Sliders.


function RGBAdapt_auto(clip clip, int "threshold", \
float "strength_bias", float "cont", \
float "strength_rpow", float "strength_spow", float "spmid",bool "pord",\
bool "show_info", bool "comparison")

{

#----------------------------------------------based on RGBADapt plugin ------------------------------------------#
# script autor : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------#

Assert(clip.IsRGB, "RGBAdapt-auto: source must be RGB")

global threshold = Default(threshold, 127) # channel value range center for calculation
global strength_bias = Default(strength_bias, 0.8) # linear curve use strength, between 0.0 and 1.0, default 0.5
global cont = Default(cont, 1.2) # adjust luma contrast, default 1.2
global strength_rpow = Default(strength_rpow,1.0) # Rpow curve use strength, between 0.0 and 4.0, default 1.0
global strength_spow = Default(strength_spow,1.0) # Spow curve use strength, between 0.0 and 4.0, default 1.0
global spmid = Default(spmid, 0.5) # Middle point for Spow curve use
global pord = Default(pord,false) # process Rpow curve before Spow curve or not (1), default 0
global show_info = Default(show_info, false) # show info or not, default false
comparison = Default(comparison, false) # show original vs processed comparison or not, default false

global neutre = BlankClip( clip,pixel_type="RGB32", color=$000000)
global red=ShowRed(clip,"RGB32")
global green = ShowGreen(clip,"RGB32")
global blue = ShowBlue(clip,"RGB32")

ScriptClip(clip, """

#------------ RGB values calcul
r = RGBDifference(red,neutre)
g = RGBDifference(green,neutre)
b = RGBDifference(blue,neutre)

#----------- RGB correction calcul
dr = threshold - r
dg = threshold - g
db = threshold - b

#----------- RGB correction with linear curve calcul (Bias)
dr1 = dr*strength_bias
dg1 = dg*strength_bias
db1 = db*strength_bias

#----------- RGB correction with Rpow and Spow curves calcul
dr2 = dr-dr1
dg2 = dg-dg1
db2 = db-db1

#----------- RGB correction with Rpow curve calcul
yr = exp((dr2/100)*strength_rpow)
yg = exp((dg2/100)*strength_rpow)
yb = exp((db2/100)*strength_rpow)
#----------- RGB correction with Spow curve calcul
sr = exp((dr2/100)*strength_spow)
sg = exp((dg2/100)*strength_spow)
sb = exp((db2/100)*strength_spow)

(show_info == false)? \
RGBAdapt( \
R_Bias = dr1, R_Gain = 1.0, R_Cont = cont, R_RPow = yr, R_Spow = sr, R_SPMid = spmid, R_Pord = pord, \
G_Bias = dg1, G_Gain = 1.0, G_Cont = cont, G_RPow = yg, G_Spow = sg, G_SPMid = spmid, G_Pord = pord,\
B_Bias = db1, B_Gain = 1.0, B_Cont = cont, B_RPow = yb, B_Spow = sb, B_SPMid = spmid, B_Pord = pord):\
RGBAdapt( \
R_Bias = dr1, R_Gain = 1.0, R_Cont = cont, R_RPow = yr, R_Spow = sr, R_SPMid = spmid, R_Pord = pord, \
G_Bias = dg1, G_Gain = 1.0, G_Cont = cont, G_RPow = yg, G_Spow = sg, G_SPMid = spmid, G_Pord = pord,\
B_Bias = db1, B_Gain = 1.0, B_Cont = cont, B_RPow = yb, B_Spow = sb, B_SPMid = spmid, B_Pord = pord)\
.Subtitle("Red value : "+String(r)+\
"\n Middle - Red Value : "+String(dr)+\
"\n Bias : "+String(dr1)+\
"\n Gamma and S correction base : "+String(dr2)+\
"\n Rpow : "+String(yr)+" Spow : "+String(sr),y=40,lsp=20)\
.Subtitle("Green value : "+String(b)+\
"\n Middle - Green Value : "+String(dg)+\
"\n Bias : "+String(dg1)+\
"\n Gamma and S correction base : "+String(dg2)+\
"\n Rpow : "+String(yg)+" Spow : "+String(sg),y=160,lsp=20)\
.Subtitle("Blue value : "+String(b)+\
"\n Middle - Blue Value : "+String(db)+\
"\n Bias : "+String(db1)+\
"\n Gamma and S correction base : "+String(db2)+\
"\n Rpow : "+String(yb)+" Spow : "+String(sb), y=280,lsp=20)

""")

(comparison == false) ? last : StackHorizontal(clip,last)

}

__End__

AVISource("C:\...............\video.avi")
LoadPlugin("C:\..........................\RGBAdapt_dll_v0.1-20140522\RGBAdapt.dll")
Import("C:\.............\RGBAdapt_auto.avsi")

threshold = [<"threshold", 0, 255, 127>]
strength_bias = [<"strength_bias", 0.0, 1.0, 0.5>]
cont = [<"cont", -3.0, 3.0, 1.2>]
strength_rpow = [<"Strength_rpow", 0.0, 4.0, 1.0>]
strength_spow = [<"Strength_spow", 0.0, 4.0, 1.0>]
spmid = [<"Spmid", 0.1, 0.99, 0.5>]
Pord_nb = [<"Pord", 0, 1, 1>]
pord = (Pord_nb == 0) ? false : true
show_info_nb = [<"show_info_nb", 0, 1, 0>]
show_info = (show_info_nb==0) ? false : true
comparison_nb = [<"comparison_nb", 0, 1, 0>]
comparison = (comparison_nb==0) ? false : true

ConvertToRGB32(matrix="Rec601")

RGBAdapt_auto(threshold = threshold, \
strength_bias = strength_bias, cont = cont, \
strength_rpow = strength_rpow, strength_spow = strength_spow, spmid = spmid, pord = pord,\
show_info = show_info, comparison = comparison)

ConvertToYV12(matrix="Rec601")



function ColorYUV2_auto(clip clip, \
bool "process_luma", int "threshold", \
float "strength_bias", float "cont", \
float "strength_Rpow", float "strength_Spow", int "pord",\
bool "show_info", bool "comparison")

{

#----------------------------------------------based on ColorYUV2 plugin ------------------------------------------- #
# script autor : StainlessS http://forum.doom9.org/showthread.php?p=1443313#post1443313 #
#--------------------------------------------------------------------------------------------------------------------#

global process_luma = Default(process_luma, true) # process or not the luma channel
global threshold = Default(threshold, 127) # channel value range center for calculation
global strength_bias = Default(strength_bias, 0.5) # linear curve use strength, between 0.0 and 1.0, default 0.5
global cont = Default(cont, 20.0) # adjust luma contrast, default 20.0
global strength_Rpow = Default(strength_Rpow,1.0) # Rpow curve use strength, between 0.0 and 4.0, default 1.0
global strength_Spow = Default(strength_Spow,1.0) # Spow curve use strength, between 0.0 and 4.0, default 1.0
global pord = Default(pord,0) # process Rpow curve before Spow curve or not (1), default 0
global show_info = Default(show_info, false) # show info or not, default false
comparison = Default(comparison, false) # show original vs processed comparison or not, default false

ScriptClip(clip, """

#------------ YUV average value
y = AverageLuma()
u = AverageChromaU()
v = AverageChromaV()

#----------- RGB correction calcul
dy = (process_luma == true) ? threshold - y : 0
du = threshold - u
dv = threshold - v

#----------- RGB correction with linear curve calcul (Bias)
dy1 = dy*strength_bias
du1 = du*strength_bias
dv1 = dv*strength_bias

#----------- RGB correction with Rpow and Spow curves calcul
dy2 = dy-dy1
du2 = du-du1
dv2 = dv-dv1

#----------- RGB correction with Rpow curve calcul
yy = dy2*strength_rpow
yu = du2*strength_rpow
yv = dv2*strength_rpow

#----------- RGB correction with Spow curve calcul
sy = dy2*strength_spow
su = du2*strength_spow
sv = dv2*strength_spow

(show_info == false)? \
ColorYUV2(\
off_y = dy1, cont_y = cont, rpow_y = yy, spow_y = sy, pord_y = pord,\
off_u = du1, rpow_u = yu, spow_u = su, pord_u = pord,\
off_v = dv1, rpow_v = yv, spow_v = sv, pord_v = pord):\
ColorYUV2(\
off_y = dy1, cont_y = cont, rpow_y = yy, spow_y = sy, pord_y = pord,\
off_u = du1, rpow_u = yu, spow_u = su, pord_u = pord,\
off_v = dv1, rpow_v = yv, spow_v = sv, pord_v = pord)\
.Subtitle("Luma value : "+String(y)+\
"\n Middle - Luma value : "+String(dy)+\
"\n Bias : "+String(dy1)+\
"\n Gamma and S correction base : "+String(dy2)+\
"\n Rpow : "+String(yy)+" Spow : "+String(sy),y=40,lsp=20)\
.Subtitle("U Chroma value : "+String(u)+\
"\n Middle - U Chroma value : "+String(du)+\
"\n Bias : "+String(du1)+\
"\n Gamma and S correction base : "+String(du2)+\
"\n Rpow : "+String(yu)+" Spow : "+String(su),y=160,lsp=20)\
.Subtitle("V value : "+String(v)+\
"\n Middle - V Chroma value : "+String(dv)+\
"\n Bias : "+String(dv1)+\
"\n Gamma and S correction base : "+String(dv2)+\
"\n Rpow : "+String(yv)+" Spow : "+String(sv),y=280,lsp=20)

""")

( comparison == false) ? last : StackHorizontal(clip,last)

}

__End__

AVISource("C:\..................\video.avi")
LoadPlugin("C:\..................\ColorYUV2_25_dll_20120529\ColorYUV2.dll")
Import("C:\...............\ColorYUV2 auto.avsi")

process_luma_nb = [<"process_luma_nb", 0, 1, 1>]
process_luma = (process_luma_nb==0) ? false : true
threshold = [<"threshold", 0, 255, 127>]
strength_bias = [<"strength_bias", 0.0, 1.0, 0.5>]
cont = [<"cont", -20, 60, 20.0>]
strength_Rpow = [<"Strength_Rpow", 0.0, 4.0, 0.0>]
strength_Spow = [<"Strength_Spow", 0.0, 4.0, 1.0>]
Pord = [<"Pord", 0, 1, 0>]
show_info_nb = [<"show_info_nb", 0, 1, 0>]
show_info = (show_info_nb==0) ? false : true
comparison_nb = [<"comparison_nb", 0, 1, 0>]
comparison = (comparison_nb==0) ? false : true

ColorYUV2_auto(last,process_luma=process_luma, threshold=threshold, \
strength_bias=strength_bias,cont=cont, \
strength_Rpow = strength_Rpow, strength_Spow=strength_Spow, pord=pord,\
show_info=show_info, comparison=comparison)


The smart ScripClip use has given to me by Gavino.
Thanks

StainlessS
29th May 2014, 01:10
AutoWhite only adjust chroma U and V, (to 127 as Gavino said, I mistakenly said 128), luma is not touched by it.
AutoGain modifies the Luma Channel.

Bernardd
2nd June 2014, 19:46
Hi !

I have observed your ColorYUV2 source and i have written an autogain tunable function.
The new script version is there :

function ColorYUV2_auto(clip clip, int "threshold", float "strength_bias",float "strength_Rpow", float "strength_Spow", int "pord",\
bool "autogain", float "luma_threshold",\
bool "show_info", bool "comparison")

{

#----------------------------------------------based on ColorYUV2 plugin ---------------------------------------------------------------------#
# script autor : StainlessS http://forum.doom9.org/showthread.php?p=1443313#post1443313 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #


global threshold = Default(threshold, 127) # channel value range center for calculation
global strength_bias = Default(strength_bias, 0.8) # linear curve use strength, between 0.0 and 1.0, default 0.5
global strength_Rpow = Default(strength_Rpow,1.0) # Rpow curve use strength, between 0.0 and 4.0, default 1.0
global strength_Spow = Default(strength_Spow,1.0) # Spow curve use strength, between 0.0 and 4.0, default 1.0
global pord = Default(pord,1) # process Rpow curve before Spow curve or not (1), default 0
global autogain = Default(autogain, false)
global luma_threshold = Default(luma_threshold, 0.35) # channel value range center for calculation
global show_info = Default(show_info, false) # show info or not, default false
comparison = Default(comparison, false) # show original vs processed comparison or not, default false

ScriptClip(clip, """

#--------------------------------------------
# Autowhite process
#--------------------------------------------

#------------ UV average values
u = AverageChromaU()
v = AverageChromaV()

#----------- UV corrections calculation
du = threshold - u
dv = threshold - v

#----------- UV corrections with linear curve calculation (Offset)
du1 = du*strength_bias
dv1 = dv*strength_bias

#----------- UV corrections range with Rpow and Spow curves calculation
du2 = du-du1
dv2 = dv-dv1

#----------- UV corrections with Rpow curve calculation
ru = du2*strength_rpow
rv = dv2*strength_rpow

#----------- UV corrections with Spow curve calculation
su = du2*strength_spow
sv = dv2*strength_spow

#--------------------------------------------
# Autogain process
#--------------------------------------------

#------------ Y max and min values

y_max_value = float(YPlaneMax(threshold = luma_threshold))
y_max = min (y_max_value, 236)
y_min_value = float(YPlaneMin(threshold = luma_threshold))
y_min = max (16, y_min_value)

#----------- Y gain correction calculation

f = (autogain == true) ? float(220/(y_max - y_min)) : 1
gy = 256*f-256

#----------- Y offset correction calculation
new_y_max = y_max * f # only for display
new_y_min = y_min * f
dy = (autogain == true) ? 16 - new_y_min : 0

(show_info == false) ? \
ColorYUV2(\
gain_y = gy, off_y = dy,\
off_u = du1, rpow_u = ru, spow_u = su, pord_u = pord,\
off_v = dv1, rpow_v = rv, spow_v = sv, pord_v = pord)\
:\
ColorYUV2(\
gain_y = gy, off_y = dy,\
off_u = du1, rpow_u = ru, spow_u = su, pord_u = pord,\
off_v = dv1, rpow_v = rv, spow_v = sv, pord_v = pord)\
.Subtitle(" U Chroma value : "+String(u)+"\n"+\
" Middle - U Chroma value : "+String(du)+"\n"+\
" Bias : "+String(du1)+"\n"+\
" Gamma and S correction base : "+String(du2)+"\n"+\
" Rpow : "+String(ru)+" Spow : "+String(su),y=40,lsp=20)\
.Subtitle(" V value : "+String(v)+"\n"+\
" Middle - V Chroma value : "+String(dv)+"\n"+\
" Bias : "+String(dv1)+"\n"+\
" Gamma and S correction base : "+String(dv2)+"\n"+\
" Rpow : "+String(rv)+" Spow : "+String(sv),y=160,lsp=20)\
.Subtitle(" Y max : "+String(y_max)+" Y min : "+String(y_min)+" Luma_Threshold : "+String(luma_threshold)+"\n"+\
" Y factor : "+String(f)+" Y gain : "+String(gy)+" Y offset : "+String(dy)+"\n"+\
" New Y max : "+String(new_y_max + dy)+" New Y min : "+String(new_y_min + dy),y=280,lsp=20)

""")

( comparison == false) ? last : StackHorizontal(clip,last)

}

__End__
# Below, call script with AvsPmod user sliders

AVISource("C:\......................\video.avi")

LoadPlugin("C:\...................\ColorYUV2_25_dll_20120529\ColorYUV2.dll")
Import("C:\.................\ColorYUV2 auto.avs")

[<separator = "AWB tunning args">]
[<separator = "No AWB is strength_bias = strength_rpow = strength_spow = 0">]
threshold = [<"threshold", 0, 255, 127>]
strength_bias = [<"strength_bias", 0.0, 1.0, 0.8>]
strength_Rpow = [<"strength_Rpow", 0.0, 4.0, 1.0>]
strength_Spow = [<"strength_Spow", 0.0, 4.0, 1.0>]
Pord = [<"Pord", 0, 1, 1>]

[<separator = "Autogain tunning args">]
autogain_nb = [<"autogain_nb", 0, 1, 0>]
luma_threshold = [<"Luma_threshold", 0.00, 1.00, 0.35>]
autogain = (autogain_nb == 0) ? false : true

[<separator = "Output choice">]
show_info_nb = [<"show_info_nb", 0, 1, 0>]
show_info = (show_info_nb==0) ? false : true
comparison_nb = [<"comparison_nb", 0, 1, 0>]
comparison = (comparison_nb==0) ? false : true

ColorYUV2_auto(last, threshold=threshold, strength_bias=strength_bias, strength_Rpow = \
strength_Rpow, strength_Spow=strength_Spow, pord=pord,\
autogain = autogain, Luma_threshold = luma_threshold,\
show_info=show_info, comparison=comparison)


The tunning args is the Avisynth internal runtime function threshold (YPlaneMax and YPlaneMin).
When autogain is too strong with overbound light i can now decrease threshold for best result.

But i have two questions.

first
Do you know if in basic autogain coloryuv function, is it a threshold for selected luma (threshold nearest 0.3) ?

secund
In my script i must define variables like global to enable their use in ScriptClip. Thus whit short script like this, only the args
for the second call function is use.

a=ColorYUV2_auto(show_info=true)
b=ColorYUV2_auto(show_info=false)
StackHorizontal(a,b)

Have you a tips ?

Gavino
2nd June 2014, 23:54
In my script i must define variables like global to enable their use in ScriptClip. Thus whit short script like this, only the args for the second call function is use.
The GRunT plugin is designed to solve this problem (and others).
It replaces the built-in run-time filters (ScriptClip, etc) with extended versions that have a couple of extra arguments, providing (among other things) a simple, natural and robust way to pass local variables into a run-time script from 'outside'.

For more details, see the description of the args parameter in the GRunT thread (and the supplied doc), which should hopefully tell you all you need to know.

StainlessS
3rd June 2014, 15:41
As Gavino says above, use Grunt for args, much nicer than standard Scriptclip.

Should this not be 235(as per rec601 Luma max)

y_max = min (y_max_value, 236)



Not sure about this line [Should 220 be 219 (235-16)]

f = (autogain == true) ? float(220/(y_max - y_min)) : 1


Maybe should be

f = (autogain == true) ? 219.0/(y_max - y_min) : 1.0


Dont like your mixed use of Int and Float, there seem to be a number of places in your script where
you will sometimes have Int and Sometimes float, with unexpected consequences.

Bernardd
3rd June 2014, 22:06
StainlessS, Gavino,
Thousand thanks, your plugins are great.

I have written my script one more once.

For ColorYUV2, i think auto white balance and autogain have a sense. With rpow and spow args, the result is less flat than a coloryuv use.
I can keep the sunset light.


function ColorYUV2_auto(clip clip, int "threshold", float "strength_bias",float "strength_Rpow", float "strength_Spow", int "pord",\
bool "autogain", float "luma_threshold",\
bool "show_info", bool "comparison")

{

#----------------------------------------------based on ColorYUV2 plugin ---------------------------------------------------------------------#
# script autor : StainlessS http://forum.doom9.org/showthread.php?p=1443313#post1443313 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #

#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script autor : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #


threshold = Default(threshold, 127) # channel value range center for calculation
strength_bias = Default(strength_bias, 0.8) # linear curve use strength, between 0.0 and 1.0, default 0.5
strength_Rpow = Default(strength_Rpow,1.0) # Rpow curve use strength, between 0.0 and 4.0, default 1.0
strength_Spow = Default(strength_Spow,1.0) # Spow curve use strength, between 0.0 and 4.0, default 1.0
pord = Default(pord,1) # process Rpow curve before Spow curve or not (1), default 0
autogain = Default(autogain, false)
luma_threshold = Default(luma_threshold, 0.35) # channel value range center for calculation
show_info = Default(show_info, false) # show info or not, default false
comparison = Default(comparison, false) # show original vs processed comparison or not, default false

ScriptClip(clip, """

#--------------------------------------------
# Autowhite process
#--------------------------------------------

#------------ UV average values
u = AverageChromaU()
v = AverageChromaV()

#----------- UV corrections calculation
du = threshold - u
dv = threshold - v

#----------- UV corrections with linear curve calculation (Offset)
du1 = du*strength_bias
dv1 = dv*strength_bias

#----------- UV corrections range with Rpow and Spow curves calculation
du2 = du-du1
dv2 = dv-dv1

#----------- UV corrections with Rpow curve calculation
ru = du2*strength_rpow
rv = dv2*strength_rpow

#----------- UV corrections with Spow curve calculation
su = du2*strength_spow
sv = dv2*strength_spow

#--------------------------------------------
# Autogain process
#--------------------------------------------

#------------ Y max and min values

y_max_value = float(YPlaneMax(threshold = luma_threshold))
y_max = min (y_max_value, 235.0)
y_min_value = float(YPlaneMin(threshold = luma_threshold))
y_min = max (16.0, y_min_value)

#----------- Y gain correction calculation

f = (autogain == true) ? float(219.0/(y_max - y_min)) : 1.0
gy = 256.0*f-256.0

#----------- Y offset correction calculation
new_y_max = y_max * f # only for display
new_y_min = y_min * f
dy = (autogain == true) ? 16.0 - new_y_min : 0.0

(show_info == false) ? \
ColorYUV2(\
gain_y = gy, off_y = dy,\
off_u = du1, rpow_u = ru, spow_u = su, pord_u = pord,\
off_v = dv1, rpow_v = rv, spow_v = sv, pord_v = pord)\
:\
ColorYUV2(\
gain_y = gy, off_y = dy,\
off_u = du1, rpow_u = ru, spow_u = su, pord_u = pord,\
off_v = dv1, rpow_v = rv, spow_v = sv, pord_v = pord)\
.Subtitle(" U Chroma value : "+String(u)+"\n"+\
" Middle - U Chroma value : "+String(du)+"\n"+\
" Bias : "+String(du1)+"\n"+\
" Gamma and S correction base : "+String(du2)+"\n"+\
" Rpow : "+String(ru)+" Spow : "+String(su),y=40,lsp=20)\
.Subtitle(" V value : "+String(v)+"\n"+\
" Middle - V Chroma value : "+String(dv)+"\n"+\
" Bias : "+String(dv1)+"\n"+\
" Gamma and S correction base : "+String(dv2)+"\n"+\
" Rpow : "+String(rv)+" Spow : "+String(sv),y=160,lsp=20)\
.Subtitle(" Y max : "+String(y_max)+" Y min : "+String(y_min)+" Luma_Threshold : "+String(luma_threshold)+"\n"+\
" Y factor : "+String(f)+" Y gain : "+String(gy)+" Y offset : "+String(dy)+"\n"+\
" New Y max : "+String(new_y_max + dy)+" New Y min : "+String(new_y_min + dy),y=280,lsp=20)

""", args = "threshold, strength_bias, strength_rpow, strength_spow, pord, autogain, luma_threshold, show_info")

( comparison == false) ? last : StackHorizontal(clip,last)

}



For RGBAdapt, i think auto white balance has no sense, because apply rule 127 - channel value to find the white is forgetting that in each channel value
is a part for luma datas. I have not found ideas to separate efficiently luma and chroma before apply auto white balance. But like this rule give some results
with a good look, i have converted my script in help script for manual white balance. The script propose a white balance start for manual search.


function RGBAdapt_half_auto(clip clip, \
float "R_bias_manu", float "R_gain", float "R_cont", float "R_rpow_manu", float "R_spow_manu", float "R_spmid", bool "R_pord",\
float "G_bias_manu", float "G_gain", float "G_cont", float "G_rpow_manu", float "G_spow_manu", float "G_spmid", bool "G_pord",\
float "B_bias_manu", float "B_gain", float "B_cont", float "B_rpow_manu", float "B_spow_manu", float "B_spmid", bool "B_pord",\
int "threshold", float "strength_bias", float "strength_rpow", float "strength_spow",\
bool "show_info", bool "comparison")

{

#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script autor : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #

#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script autor : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #

Assert(clip.IsRGB, "RGBAdapt-auto: source must be RGB")

R_bias_manu = Default(R_bias_manu, 0) # same range with original R_bias args
G_bias_manu = Default(G_bias_manu, 0) # same range with original G_bias args
B_bias_manu = Default(B_bias_manu, 0) # same range with original B_bias args

R_gain = Default(R_gain, 1) # It is original R_gain args, range -8 to 8 center 1.0
G_gain = Default(G_gain, 1) # It is original G_gain args, range -8 to 8 center 1.0
B_gain = Default(B_gain, 1) # It is original B_gain args, range -8 to 8 center 1.0

R_cont = Default(R_cont, 1) # It is original R_cont args, range -8 to 8 center 1.0
G_cont = Default(G_cont, 1) # It is original G_cont args, range -8 to 8 center 1.0
B_cont = Default(B_cont, 1) # It is original B_cont args, range -8 to 8 center 1.0

R_rpow_manu = Default(R_rpow_manu, 0) # range -0.8 to 3.0 center 0 (original R_rpow range 0.1 to 4.0 center 1.0)
G_rpow_manu = Default(G_rpow_manu, 0) # range -0.8 to 3.0 center 0 (original G_rpow range 0.1 to 4.0 center 1.0)
B_rpow_manu = Default(B_rpow_manu, 0) # range -0.8 to 3.0 center 0 (original B_rpow range 0.1 to 4.0 center 1.0)

R_spow_manu = Default(R_spow_manu, 0) # range -0.8 to 3.0 center 0 (original R_spow range 0.1 to 4.0 center 1.0)
G_spow_manu = Default(G_spow_manu, 0) # range -0.8 to 3.0 center 0 (original G_spow range 0.1 to 4.0 center 1.0)
B_spow_manu = Default(B_spow_manu, 0) # range -0.8 to 3.0 center 0 (original B_spow range 0.1 to 4.0 center 1.0)

R_spmid = Default(R_spmid, 0.5) # It is original R_spmid args, range 0.1 to 0.99 center 0.5
G_spmid = Default(G_spmid, 0.5) # It is original G_spmid args, range 0.1 to 0.99 center 0.5
B_spmid = Default(B_spmid, 0.5) # It is original B_spmid args, range 0.1 to 0.99 center 0.5

R_pord = Default(R_pord, false) # It is original R_pord args
G_pord = Default(G_pord, false) # It is original G_pord args
B_pord = Default(B_pord, false) # It is original B_pord args

threshold = Default(threshold, 127) # channel value range center for calculation
strength_bias = Default(strength_bias, 0.8) # linear curve use strength, between 0.0 and 1.0, default 0.5
strength_rpow = Default(strength_rpow,1.0) # Rpow curve use strength, between 0.0 and 4.0, default 1.0
strength_spow = Default(strength_spow,1.0) # Spow curve use strength, between 0.0 and 4.0, default 1.0

show_info = Default(show_info, false) # show info or not, default false
comparison = Default(comparison, false) # show original vs processed comparison or not, default false

neutre = BlankClip( clip,pixel_type="RGB32", color=$000000)
red=ShowRed(clip,"RGB32")
green = ShowGreen(clip,"RGB32")
blue = ShowBlue(clip,"RGB32")

ScriptClip(clip, """

#------------ RGB values calcul
r = RGBDifference(red,neutre)
g = RGBDifference(green,neutre)
b = RGBDifference(blue,neutre)

#----------- RGB correction calcul
dr = threshold - r
dg = threshold - g
db = threshold - b

#----------- RGB correction with linear curve calcul (Bias)
dr1 = dr*strength_bias + R_bias_manu
dg1 = dg*strength_bias + G_bias_manu
db1 = db*strength_bias + G_bias_manu

#----------- RGB correction with Rpow and Spow curves calcul
dr2 = dr-dr1
dg2 = dg-dg1
db2 = db-db1

#----------- RGB correction with Rpow curve calcul
yr = exp((dr2/100)*strength_rpow) + R_Rpow_manu
yg = exp((dg2/100)*strength_rpow) + G_Rpow_manu
yb = exp((db2/100)*strength_rpow) + B_Rpow_manu

#----------- RGB correction with Spow curve calcul
sr = exp((dr2/100)*strength_spow) + R_spow_manu
sg = exp((dg2/100)*strength_spow) + G_spow_manu
sb = exp((db2/100)*strength_spow) + B_spow_manu

(show_info == false)? \
RGBAdapt( \
R_Bias = dr1, R_Gain = R_gain, R_Cont = R_cont, R_RPow = yr, R_Spow = sr, R_SPMid = R_spmid, R_Pord = R_pord, \
G_Bias = dg1, G_Gain = G_gain, G_Cont = G_cont, G_RPow = yg, G_Spow = sg, G_SPMid = G_spmid, G_Pord = G_pord,\
B_Bias = db1, B_Gain = B_gain, B_Cont = B_cont, B_RPow = yb, B_Spow = sb, B_SPMid = B_spmid, B_Pord = B_pord):\
RGBAdapt( \
R_Bias = dr1, R_Gain = R_gain, R_Cont = R_cont, R_RPow = yr, R_Spow = sr, R_SPMid = R_spmid, R_Pord = R_pord, \
G_Bias = dg1, G_Gain = G_gain, G_Cont = G_cont, G_RPow = yg, G_Spow = sg, G_SPMid = G_spmid, G_Pord = G_pord,\
B_Bias = db1, B_Gain = B_gain, B_Cont = B_cont, B_RPow = yb, B_Spow = sb, B_SPMid = B_spmid, B_Pord = B_pord)\
.Subtitle("Red value : "+String(r)+\
"\n Middle - Red Value : "+String(dr)+\
"\n Bias : "+String(dr1)+\
"\n Gamma and S correction base : "+String(dr2)+\
"\n Rpow : "+String(yr)+" Spow : "+String(sr),y=40,lsp=20)\
.Subtitle("Green value : "+String(g)+\
"\n Middle - Green Value : "+String(dg)+\
"\n Bias : "+String(dg1)+\
"\n Gamma and S correction base : "+String(dg2)+\
"\n Rpow : "+String(yg)+" Spow : "+String(sg),y=160,lsp=20)\
.Subtitle("Blue value : "+String(b)+\
"\n Middle - Blue Value : "+String(db)+\
"\n Bias : "+String(db1)+\
"\n Gamma and S correction base : "+String(db2)+\
"\n Rpow : "+String(yb)+" Spow : "+String(sb), y=280,lsp=20)

""", args = "R_bias_manu, R_gain, R_cont, R_rpow_manu, R_spow_manu, R_spmid, R_pord," +\
"G_bias_manu, G_gain, G_cont, G_rpow_manu, G_spow_manu, G_spmid, G_pord,"+\
"B_bias_manu, B_gain, B_cont, B_rpow_manu, B_spow_manu, B_spmid, B_pord,"+\
"neutre, red, green, blue,"+\
"threshold, strength_bias, strength_rpow, strength_spow, show_info")


(comparison == false) ? last : StackHorizontal(clip,last)

}



Thanks to have spend your time to answer me.

StainlessS
3rd June 2014, 22:26
For RGB, I suggest take a peek at VirtualDub plugin 'White Balance' source by Jim Leonard,
I think I examined this about 8 maybe 10 years ago, think it got the highest frame pixel value of R, G and B,
and made them the same (adding difference to all pixels of adjusted channels),
and then did 'Top relative contrast' on the channels that had to be changed.

Bernardd
4th June 2014, 23:24
Hello StainlessS,

I cannot apply your proposal because i do not get the highest frame pixel value. Avisynth runtime function give only RGB difference.
It is the limit of my process. I think that my RGBAdapt_half_auto script (last version below) is a lab script, a little help for manual
white balance search.


function RGBAdapt_half_auto(clip clip, bool "same",\
float "R_gain", float "R_cont", float "R_spmid", bool "R_pord",\
float "G_gain", float "G_cont", float "G_spmid", bool "G_pord",\
float "B_gain", float "B_cont", float "B_spmid", bool "B_pord",\
float "Gain", float "Cont", float "Spmid", bool "Pord",\
int "threshold", float "strength_bias", float "strength_rpow", float "strength_spow",\
bool "show_info", bool "comparison")

{

#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script autor : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #

#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script autor : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #

Assert(clip.IsRGB, "RGBAdapt-auto: source must be RGB")

same = Default(same,false) # same correction in the three channels

R_gain = Default(R_gain, 1) # It is original R_gain args, range -8 to 8 center 1.0
G_gain = Default(G_gain, 1) # It is original G_gain args, range -8 to 8 center 1.0
B_gain = Default(B_gain, 1) # It is original B_gain args, range -8 to 8 center 1.0
Gain = Default(Gain, 0) # same range with original gain args
R_Gain = (same == false) ? R_Gain : Gain
G_Gain = (same == false) ? G_Gain : Gain
B_Gain = (same == false) ? B_Gain : Gain

R_cont = Default(R_cont, 1) # It is original R_cont args, range -8 to 8 center 1.0
G_cont = Default(G_cont, 1) # It is original G_cont args, range -8 to 8 center 1.0
B_cont = Default(B_cont, 1) # It is original B_cont args, range -8 to 8 center 1.0
Cont = Default(Cont, 0) # same range with original cont args
R_Cont = (same == false) ? R_Cont : Cont
G_Cont = (same == false) ? G_Cont : Cont
B_Cont = (same == false) ? B_Cont : Cont

R_spmid = Default(R_spmid, 0.5) # It is original R_spmid args, range 0.1 to 0.99 center 0.5
G_spmid = Default(G_spmid, 0.5) # It is original G_spmid args, range 0.1 to 0.99 center 0.5
B_spmid = Default(B_spmid, 0.5) # It is original B_spmid args, range 0.1 to 0.99 center 0.5
Spmid = Default(Spmid, 0) # same range with original Spmid args
R_spmid = (same == false) ? R_spmid : Spmid
G_spmid = (same == false) ? G_spmid : Spmid
B_spmid = (same == false) ? B_spmid : Spmid

R_pord = Default(R_pord, false) # It is original R_pord args
G_pord = Default(G_pord, false) # It is original G_pord args
B_pord = Default(B_pord, false) # It is original B_pord args
Pord = Default(Pord, 0) # same range with original Pord args
R_pord = (same == false) ? R_pord : Pord
G_pord = (same == false) ? G_pord : Pord
B_pord = (same == false) ? B_pord : Pord

threshold = Default(threshold, 127) # channel value range center for calculation
strength_bias = Default(strength_bias, 0.8) # linear curve use strength, between 0.0 and 1.0, default 0.5
strength_rpow = Default(strength_rpow,1.0) # Rpow curve use strength, between 0.0 and 4.0, default 1.0
strength_spow = Default(strength_spow,1.0) # Spow curve use strength, between 0.0 and 4.0, default 1.0

show_info = Default(show_info, false) # show info or not, default false
comparison = Default(comparison, false) # show original vs processed comparison or not, default false

neutre = BlankClip( clip,pixel_type="RGB32", color=$000000)
red=ShowRed(clip,"RGB32")
green = ShowGreen(clip,"RGB32")
blue = ShowBlue(clip,"RGB32")

ScriptClip(clip, """

#------------ RGB values calcul
r = RGBDifference(red,neutre)
g = RGBDifference(green,neutre)
b = RGBDifference(blue,neutre)

#----------- RGB correction calcul
dr = threshold - r
dg = threshold - g
db = threshold - b

#----------- RGB correction with linear curve calcul (Bias)
dr1 = dr*strength_bias
dg1 = dg*strength_bias
db1 = db*strength_bias

#----------- RGB correction with Rpow and Spow curves calcul
dr2 = dr-dr1
dg2 = dg-dg1
db2 = db-db1

#----------- RGB correction with Rpow curve calcul
yr = exp((dr2/100)*strength_rpow)
yg = exp((dg2/100)*strength_rpow)
yb = exp((db2/100)*strength_rpow)

#----------- RGB correction with Spow curve calcul
sr = exp((dr2/100)*strength_spow)
sg = exp((dg2/100)*strength_spow)
sb = exp((db2/100)*strength_spow)

(show_info == false)? \
RGBAdapt( \
R_Bias = dr1, R_Gain = R_gain, R_Cont = R_cont, R_RPow = yr, R_Spow = sr, R_SPMid = R_spmid, R_Pord = R_pord, \
G_Bias = dg1, G_Gain = G_gain, G_Cont = G_cont, G_RPow = yg, G_Spow = sg, G_SPMid = G_spmid, G_Pord = G_pord,\
B_Bias = db1, B_Gain = B_gain, B_Cont = B_cont, B_RPow = yb, B_Spow = sb, B_SPMid = B_spmid, B_Pord = B_pord):\
RGBAdapt( \
R_Bias = dr1, R_Gain = R_gain, R_Cont = R_cont, R_RPow = yr, R_Spow = sr, R_SPMid = R_spmid, R_Pord = R_pord, \
G_Bias = dg1, G_Gain = G_gain, G_Cont = G_cont, G_RPow = yg, G_Spow = sg, G_SPMid = G_spmid, G_Pord = G_pord,\
B_Bias = db1, B_Gain = B_gain, B_Cont = B_cont, B_RPow = yb, B_Spow = sb, B_SPMid = B_spmid, B_Pord = B_pord)\
.Subtitle("Red value : "+String(r)+\
"\n Middle - Red Value : "+String(dr)+\
"\n Bias : "+String(dr1)+\
"\n Gamma and S correction base : "+String(dr2)+\
"\n Rpow : "+String(yr)+" Spow : "+String(sr),y=40,lsp=20)\
.Subtitle("Green value : "+String(g)+\
"\n Middle - Green Value : "+String(dg)+\
"\n Bias : "+String(dg1)+\
"\n Gamma and S correction base : "+String(dg2)+\
"\n Rpow : "+String(yg)+" Spow : "+String(sg),y=160,lsp=20)\
.Subtitle("Blue value : "+String(b)+\
"\n Middle - Blue Value : "+String(db)+\
"\n Bias : "+String(db1)+\
"\n Gamma and S correction base : "+String(db2)+\
"\n Rpow : "+String(yb)+" Spow : "+String(sb), y=280,lsp=20)

""", args = "R_gain, R_cont,R_spmid, R_pord," +\
"G_gain, G_cont, G_spmid, G_pord,"+\
"B_gain, B_cont, B_spmid, B_pord,"+\
"Gain, Cont, Spmid, Pord, same,"+\
"neutre, red, green, blue,"+\
"threshold, strength_bias, strength_rpow, strength_spow, show_info")


(comparison == false) ? last : StackHorizontal(clip,last)

}



ColorYUV2_auto is full ops, no many args, only one dangerous args : luma_threshold which is sometime cause of bright flicker when it
is too weak.


function ColorYUV2_auto(clip clip, float "strength_bias",float "strength_Rpow", float "strength_Spow", int "pord",\
bool "autogain", float "luma_threshold", bool "show_info", bool "comparison")

{

#----------------------------------------------based on ColorYUV2 plugin ---------------------------------------------------------------------#
# script autor : StainlessS http://forum.doom9.org/showthread.php?p=1443313#post1443313 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #

#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script autor : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #


strength_bias = Default(strength_bias, 0.5) # linear curve use strength, between 0.0 and 1.0, default 0.5
strength_Rpow = Default(strength_Rpow,1.0) # Rpow curve use strength, between 0.0 and 4.0, default 1.0
strength_Spow = Default(strength_Spow,1.0) # Spow curve use strength, between 0.0 and 4.0, default 1.0
pord = Default(pord,1) # process Rpow curve before Spow curve or not (1), default 0
autogain = Default(autogain, false)
luma_threshold = Default(luma_threshold, 0.50) # selected luma value percentage for calculation, too weak can be cause of light flicker
show_info = Default(show_info, false) # show info or not, default false
comparison = Default(comparison, false) # show original vs processed comparison or not, default false

ScriptClip(clip, """

#--------------------------------------------
# Autowhite process
#--------------------------------------------

#------------ UV average values
u = AverageChromaU()
v = AverageChromaV()

#----------- UV corrections calculation
du = 127.0 - u
dv = 127.0 - v

#----------- UV corrections with linear curve calculation (Offset)
du1 = du*strength_bias
dv1 = dv*strength_bias

#----------- UV corrections range with Rpow and Spow curves calculation
du2 = du-du1
dv2 = dv-dv1

#----------- UV corrections with Rpow curve calculation
ru = du2*strength_rpow
rv = dv2*strength_rpow

#----------- UV corrections with Spow curve calculation
su = du2*strength_spow
sv = dv2*strength_spow

#--------------------------------------------
# autogain process
#--------------------------------------------

#------------ Y max and min values

y_max_value = float(YPlaneMax(threshold = luma_threshold))
y_max = min (y_max_value, 235.0)
y_min_value = float(YPlaneMin(threshold = luma_threshold))
y_min = max (16.0, y_min_value)

#----------- Y gain correction calculation

f = (autogain == true) ? float(219.0/(y_max - y_min)) : 1.0
gy = 256.0*f-256.0

#----------- Y offset correction calculation
new_y_max = y_max * f # only for display
new_y_min = y_min * f
dy = (autogain == true) ? 16.0 - new_y_min : 0.0

(show_info == false) ? \
ColorYUV2(\
gain_y = gy, off_y = dy,\
off_u = du1, rpow_u = ru, spow_u = su, pord_u = pord,\
off_v = dv1, rpow_v = rv, spow_v = sv, pord_v = pord)\
:\
ColorYUV2(\
gain_y = gy, off_y = dy,\
off_u = du1, rpow_u = ru, spow_u = su, pord_u = pord,\
off_v = dv1, rpow_v = rv, spow_v = sv, pord_v = pord)\
.Subtitle(" U Chroma value : "+String(u)+"\n"+\
" Middle - U Chroma value : "+String(du)+"\n"+\
" Bias : "+String(du1)+"\n"+\
" Gamma and S correction base : "+String(du2)+"\n"+\
" Rpow : "+String(ru)+" Spow : "+String(su),y=40,lsp=20)\
.Subtitle(" V value : "+String(v)+"\n"+\
" Middle - V Chroma value : "+String(dv)+"\n"+\
" Bias : "+String(dv1)+"\n"+\
" Gamma and S correction base : "+String(dv2)+"\n"+\
" Rpow : "+String(rv)+" Spow : "+String(sv),y=160,lsp=20)\
.Subtitle(" Y max : "+String(y_max)+" Y min : "+String(y_min)+" Luma_Threshold : "+String(luma_threshold)+"\n"+\
" Y factor : "+String(f)+" Y gain : "+String(gy)+" Y offset : "+String(dy)+"\n"+\
" New Y max : "+String(new_y_max + dy)+" New Y min : "+String(new_y_min + dy),y=280,lsp=20)

""", args = "strength_bias, strength_rpow, strength_spow, pord, autogain, luma_threshold, show_info")

( comparison == false) ? last : StackHorizontal(clip,last)

}


Thanks

StainlessS
5th June 2014, 01:36
"i do not get the highest frame pixel value"

Well, yes of course you do.

RT_RgbChanStats(clip c,int "n"=current_frame,int "delta"=0,int "x"=0,int "y"=0,int "w"=0,int "h"=0,bool "interlaced"=false,
float "threshold"=0.0,int "chan"=0,int "lo"=128,int "hi"=lo,int "flgs"=255,string "prefix"="RCS_",
float "mu"=0.0,int "d"=1,int "p"=1,int "u"=1,int "mask"=NOT_USED, int "MaskMin"=128,"MaskMax"=255)
Returns multiple results as for above single frame RGB channel sampling functions as Local Variables (prefixed with the prefix string arg).
The args up to "interlaced", are as for all other clip functions, "threshold" used only for "RT_RgbChanMin", "RT_RgbChanMax" and
"RT_RgbChanMinMaxDifference" equivalent routines with same functionality.
"lo" and "hi" are used only with the "RT_RgbChanInRange" equivalent routine with same functionality.
"mu" and "d" and "p" and "u" are used only with the "RT_RgbChanPNorm" equivalent routine with same functionality.
The new arg "Flgs" selects which results you want returned and the string "Prefix" that is prepended
to the returned Local variable names.
The actual return result is a copy of the flgs args with any non valid bits reset, ie the Local variables that were set.
Local variables are NOT altered for any function not selected in flgs.
Returns 0 if no pixels found in search area of mask within MaskMin and MaskMax.

Flgs_Bit_Number Add_To_Flgs Equivalent_Function Local_Var_Set_Excluding_Prefix_and_Chan_postfix
0 1($01) RT_RgbChanMin() "Min" (0->255)
1 2($02) RT_RgbChanMax() "Max" (0->255)
2 4($04) RT_RgbChanMinMaxDifference() "MinMaxDiff" (0->255)
3 8($08) RT_RgbChanMedian() "Med" (0->255)
4 16($10) RT_RgbChanAve() "Ave" (0.0->255.0)
5 32($20) RT_RgbChanStdev() "Stdev" (0.0->255.0)
6 64($40) RT_RgbChanInRange() "InRng" (0.0->1.0)
7 128($80) RT_RgbChanPNorm() "PNorm" (0.0->??? depends upon d and u)
The Channel Postfix is of the form "_0", where 0 is RED, 1 is GREEN and 2 is Blue, 3 is ALPHA(RGB32 ONLY), and is appended to the
base name described above. So eg RT_RgbChanMin for RED channel 0 with default Prefix is "RCS_Min_0".
RT_RgbChanstats() allows you to inquire multiple results simultaneously, with not much more overhead than calling a single individual
routine, however, you should not select sub functions that you dont need as there may be an additional unnecessary overhead.
The Default flgs=255($FF) are all bits set and so sets ALL Local vars at once.
RT_RgbChanStats(flgs=1+2+16) would set Local vars "RCS_Min_0", "RCS_Max_0" and "RCS_Ave_0" for full frame current_frame, Red Channel.

In addition to above Local Variables, RT_RgbChanStats() sets an int Local variable (where default prefix) of "RCS_PixelCount_0" being
the number of Red Channel pixels in mask area X,Y,W,H between MaskMin and MaskMax inclusive.

NOTE, RT_RgbChanStats() allows Chan to be -1, where ALL three R, and G, and B channels are processed simultaneouly for ALL functions
selected by flgs arg (ALPHA Channel is NOT processed).
A chan arg of -2 (RGB32 ONLY allowed) will additionally process the ALPHA channel as well as R+G+B.
Also Note, (where default Prefix) RCS_PixelCount_x is also set (identically) for all channels when Chan == -1 or -2.
NOTE, If no valid flg bits set (eg $FF00), then returns 0, RCS_PixelCount_x and all other variables remain as before call.
Assuming some valid flg bits, if no valid pixels were found in mask then function returns 0, and only RCS_PixelCount_x would be set
to 0, no other variables are touched (remain as before call, undefined if not previously existing).
Example usage:
ScriptClip("""
got = RT_RgbChanStats(c,mask=Mask,chan=-1,flgs=$10) # Ave
(got != 0)
\ ? RT_Debug(RT_String("AveR = %f AveG = %f AveB = %f Pixels = %d",RCS_Ave_0,RCS_Ave_1,RCS_Ave_2,RCS_PixelCount_0))
\ : RT_Debug("NO VALID PIXELS FOUND")
""")



That's the one fix for everything version, but there are of couse individual functions.

However, dont know how you do the 'top down contrast', probably mt_tools would be best bet.

EDIT: although he may have done some kind of whole clip scan, twas a long time ago, rather than single frame.
take a peek, you sounded at an earlier post as though you were a C coder.

Bernardd
5th June 2014, 22:53
Thanks StainlessS,
It is for me a new world. I have need time for understand. I should come back if i find a solution.
Thanks, RGBAdapt is a great plugin to manual search and find perfect color.

Bernardd
10th June 2014, 18:47
Hi StainlessS,

Without use RT_RgbChanStats, i have found a effective solution with difference between clip in RGB and clip in greyscale.
Auto white balance with RGBAdapt or ColorYUV2 are now ok.
Because i have not the same start datas, autogain functions have not the same approach in this two last script versions.


function RGBAdapt_half_auto(clip clip, bool "awb", bool "autogain", \
float "R_bias_manu", float "R_gain_manu", float "R_cont_manu", float "R_rpow_manu", float "R_spow_manu", float "R_spmid", bool "R_pord",\
float "G_bias_manu", float "G_gain_manu", float "G_cont_manu", float "G_rpow_manu", float "G_spow_manu", float "G_spmid", bool "G_pord",\
float "B_bias_manu", float "B_gain_manu", float "B_cont_manu", float "B_rpow_manu", float "B_spow_manu", float "B_spmid", bool "B_pord",\
float "strength_bias", float "strength_rpow", float "strength_spow", float "strength_autogain",\
bool "show_info", bool "comparison")

{

#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#

#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #

Assert(clip.IsRGB, "RGBAdapt-auto: source must be RGB")

awb = Default(awb,false) # Auto white balance
awb_nb = (awb == false) ? 0 : 1
autogain = Default(autogain, false) # Autogain

R_bias_manu = Default(R_bias_manu, 0) # same range with original R_bias args
G_bias_manu = Default(G_bias_manu, 0) # same range with original G_bias args
B_bias_manu = Default(B_bias_manu, 0) # same range with original B_bias args

R_gain_manu = Default(R_gain_manu, 1) # It is original R_gain args, range -8 to 8 center 1.0
G_gain_manu = Default(G_gain_manu, 1) # It is original G_gain args, range -8 to 8 center 1.0
B_gain_manu = Default(B_gain_manu, 1) # It is original B_gain args, range -8 to 8 center 1.0

R_cont_manu = Default(R_cont_manu, 1) # It is original R_cont args, range -8 to 8 center 1.0
G_cont_manu = Default(G_cont_manu, 1) # It is original G_cont args, range -8 to 8 center 1.0
B_cont_manu = Default(B_cont_manu, 1) # It is original B_cont args, range -8 to 8 center 1.0

R_rpow_manu = Default(R_rpow_manu, 0) # range -0.8 to 3.0 center 0 (original R_rpow range 0.1 to 4.0 center 1.0)
G_rpow_manu = Default(G_rpow_manu, 0) # range -0.8 to 3.0 center 0 (original G_rpow range 0.1 to 4.0 center 1.0)
B_rpow_manu = Default(B_rpow_manu, 0) # range -0.8 to 3.0 center 0 (original B_rpow range 0.1 to 4.0 center 1.0)

R_spow_manu = Default(R_spow_manu, 0) # range -0.8 to 3.0 center 0 (original R_spow range 0.1 to 4.0 center 1.0)
G_spow_manu = Default(G_spow_manu, 0) # range -0.8 to 3.0 center 0 (original G_spow range 0.1 to 4.0 center 1.0)
B_spow_manu = Default(B_spow_manu, 0) # range -0.8 to 3.0 center 0 (original B_spow range 0.1 to 4.0 center 1.0)

R_spmid = Default(R_spmid, 0.5) # It is original R_spmid args, range 0.1 to 0.99 center 0.5
G_spmid = Default(G_spmid, 0.5) # It is original G_spmid args, range 0.1 to 0.99 center 0.5
B_spmid = Default(B_spmid, 0.5) # It is original B_spmid args, range 0.1 to 0.99 center 0.5

R_pord = Default(R_pord, false) # It is original R_pord args
G_pord = Default(G_pord, false) # It is original G_pord args
B_pord = Default(B_pord, false) # It is original B_pord args

strength_bias = Default(strength_bias, 0.8) # linear curve use strength, between 0.0 and 1.0, default 0.5
strength_rpow = Default(strength_rpow,1.0) # Rpow curve use strength, between 0.0 and 4.0, default 1.0
strength_spow = Default(strength_spow,1.0) # Spow curve use strength, between 0.0 and 4.0, default 1.0
strength_autogain = Default(strength_autogain,0.1) # Spow curve use strength, between 0.0 and 4.0, default 1.0

show_info = Default(show_info, false) # show info or not, default false
comparison = Default(comparison, false) # show original vs processed comparison or not, default false

neutre = BlankClip( clip,pixel_type="RGB32", color=$000000)
luma = Greyscale(clip, matrix="Rec601")
red=ShowRed(clip,"RGB32")
green = ShowGreen(clip,"RGB32")
blue = ShowBlue(clip,"RGB32")

ScriptClip(clip, """

#------------ RGB values calcul

r_luma = RGBDifference(luma, neutre)
g_luma = RGBDifference(luma,neutre)
b_luma = RGBDifference(luma,neutre)
r = RGBDifference(neutre, red)
g = RGBDifference(neutre,green)
b = RGBDifference(neutre,blue)

#----------- RGB correction calcul
dr = r_luma-r
dg = g_luma-g
db = b_luma-b

#----------- RGB correction with linear curve calcul (Bias)
dr1_calcul = dr * strength_bias * awb_nb + R_bias_manu
dr1_low_limit = Max (dr1_calcul, -512)
dr1 = Min (512, dr1_low_limit)
dg1_calcul = dg * strength_bias * awb_nb + G_bias_manu
dg1_low_limit = Max (dg1_calcul, -512)
dg1 = Min (512, dg1_low_limit)
db1_calcul = db * strength_bias * awb_nb + B_bias_manu
db1_low_limit = Max (db1_calcul, -512)
db1 = Min (512, db1_low_limit)

#----------- RGB correction with Rpow and Spow curves calcul
dr2 = (dr - dr * strength_bias) * awb_nb
dg2 = (dg - dg * strength_bias) * awb_nb
db2 = (db - db * strength_bias) * awb_nb

#----------- RGB correction with Rpow curve calcul
yr_calcul = exp((dr2/100) * strength_rpow) + R_Rpow_manu
yr_low_limit = Max (yr_calcul, 0.1)
yr = Min (4.0, yr_low_limit)
yg_calcul = exp((dg2/100) * strength_rpow) + G_Rpow_manu
yg_low_limit = Max (yg_calcul, 0.1)
yg = Min (4.0, yg_low_limit)
yb_calcul = exp((db2/100) * strength_rpow) + B_Rpow_manu
yb_low_limit = Max (yb_calcul, 0.1)
yb = Min (4.0, yb_low_limit)

#----------- RGB correction with Spow curve calcul
sr_calcul = exp((dr2/100) * strength_spow) + R_spow_manu
sr_low_limit = Max (sr_calcul, 0.1)
sr = Min (4.0, sr_low_limit)
sg_calcul = exp((dg2/100) * strength_spow) + G_spow_manu
sg_low_limit = Max (sg_calcul, 0.1)
sg = Min (4.0, sg_low_limit)
sb_calcul = exp((db2/100) * strength_spow) + B_spow_manu
sb_low_limit = Max (sb_calcul, 0.1)
sb = Min (4.0, sb_low_limit)

#----------- RGB autogain
f = (autogain ==true ) ? (r+g+b)/(r_luma+g_luma+b_luma) :0

gr_calcul = R_gain_manu + f * strength_autogain/2
gr_low_limit = Max (gr_calcul, -8.0)
gr = Min (8.0, gr_low_limit)
gg_calcul = G_gain_manu + f * strength_autogain/2
gg_low_limit = Max (gg_calcul, -8.0)
gg = Min (8.0, gg_low_limit)
gb_calcul = B_gain_manu + f * strength_autogain/2
gb_low_limit = Max (gb_calcul, -8.0)
gb = Min (8.0, gb_low_limit)

cr_calcul = R_cont_manu + f * strength_autogain
cr_low_limit = Max (cr_calcul, -8.0)
cr = Min (8.0, cr_low_limit)
cg_calcul = G_cont_manu + f * strength_autogain
cg_low_limit = Max (cg_calcul, -8.0)
cg = Min (8.0, cg_low_limit)
cb_calcul = B_cont_manu + f * strength_autogain
cb_low_limit = Max (cb_calcul, -8.0)
cb = Min (8.0, cb_low_limit)


(show_info == false)? \
RGBAdapt( \
R_Bias = dr1, R_Gain = gr, R_Cont = cr, R_RPow = yr, R_Spow = sr, R_SPMid = R_spmid, R_Pord = R_pord, \
G_Bias = dg1, G_Gain = gg, G_Cont = cg, G_RPow = yg, G_Spow = sg, G_SPMid = G_spmid, G_Pord = G_pord,\
B_Bias = db1, B_Gain = gb, B_Cont = cb, B_RPow = yb, B_Spow = sb, B_SPMid = B_spmid, B_Pord = B_pord):\
RGBAdapt( \
R_Bias = dr1, R_Gain = gr, R_Cont = cr, R_RPow = yr, R_Spow = sr, R_SPMid = R_spmid, R_Pord = R_pord, \
G_Bias = dg1, G_Gain = gg, G_Cont = cg, G_RPow = yg, G_Spow = sg, G_SPMid = G_spmid, G_Pord = G_pord,\
B_Bias = db1, B_Gain = gb, B_Cont = cb, B_RPow = yb, B_Spow = sb, B_SPMid = B_spmid, B_Pord = B_pord)\
.Subtitle("Red value : "+String(r)+\
"\n Middle - Red Value : "+String(dr)+\
"\n Bias : "+String(dr1)+\
"\n Gamma and S correction base : "+String(dr2)+\
"\n Rpow : "+String(yr)+" Spow : "+String(sr),y=40,lsp=20)\
.Subtitle("Green value : "+String(g)+\
"\n Middle - Green Value : "+String(dg)+\
"\n Bias : "+String(dg1)+\
"\n Gamma and S correction base : "+String(dg2)+\
"\n Rpow : "+String(yg)+" Spow : "+String(sg),y=160,lsp=20)\
.Subtitle("Blue value : "+String(b)+\
"\n Middle - Blue Value : "+String(db)+\
"\n Bias : "+String(db1)+\
"\n Gamma and S correction base : "+String(db2)+\
"\n Rpow : "+String(yb)+" Spow : "+String(sb), y=280,lsp=20)\
.Subtitle("Greyscale Value : "+String(r_luma)+" Contrast gain : "+String(f), y=400,lsp=20)

""", args = "R_bias_manu, R_gain_manu, R_cont_manu, R_rpow_manu, R_spow_manu, R_spmid, R_pord," +\
"G_bias_manu, G_gain_manu, G_cont_manu, G_rpow_manu, G_spow_manu, G_spmid, G_pord,"+\
"B_bias_manu, B_gain_manu, B_cont_manu, B_rpow_manu, B_spow_manu, B_spmid, B_pord,"+\
"neutre, red, green, blue,luma,"+\
"awb_nb, autogain,"+\
"strength_bias, strength_rpow, strength_spow, strength_autogain,"+\
"show_info")


(comparison == false) ? last : StackHorizontal(clip,last)

}




function ColorYUV2_auto(clip clip, float "strength_bias",float "strength_Rpow", float "strength_Spow", int "pord",\
float "luma_threshold", float "strength_autogain", bool "show_info", bool "comparison")

{

#----------------------------------------------based on ColorYUV2 plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1443313#post1443313 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #

#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #


strength_bias = Default(strength_bias, 0.5) # linear curve use strength, between 0.0 and 1.0, default 0.5
strength_Rpow = Default(strength_Rpow,1.0) # Rpow curve use strength, between 0.0 and 4.0, default 1.0
strength_Spow = Default(strength_Spow,1.0) # Spow curve use strength, between 0.0 and 4.0, default 1.0
pord = Default(pord,1) # process Rpow curve before Spow curve or not (1), default 0

luma_threshold = Default(luma_threshold, 0.50)
strength_autogain = Default(strength_autogain,1.0) # Spow curve use strength, between 0.0 and 4.0, default 1.0 # selected luma value percentage for calculation, too weak can be cause of light flicker

show_info = Default(show_info, false) # show info or not, default false
comparison = Default(comparison, false) # show original vs processed comparison or not, default false

ScriptClip(clip, """

#--------------------------------------------
# Autowhite process
#--------------------------------------------

#------------ UV average values
u = AverageChromaU()
v = AverageChromaV()

#----------- UV corrections calculation
du = 127.0 - u
dv = 127.0 - v

#----------- UV corrections with linear curve calculation (Offset)
du1 = du*strength_bias
dv1 = dv*strength_bias

#----------- UV corrections range with Rpow and Spow curves calculation
du2 = du-du1
dv2 = dv-dv1

#----------- UV corrections with Rpow curve calculation
ru = du2*strength_rpow
rv = dv2*strength_rpow

#----------- UV corrections with Spow curve calculation
su = du2*strength_spow
sv = dv2*strength_spow

#--------------------------------------------
# autogain process
#--------------------------------------------

#------------ Y max and min values

y_max_value = float(YPlaneMax(threshold = luma_threshold))
y_max = min (y_max_value, 235.0)
y_min_value = float(YPlaneMin(threshold = luma_threshold))
y_min = max (16.0, y_min_value)

#----------- Y gain correction calculation

f = float(219.0/(y_max - y_min)) #(autogain == true) ? : 1.0
gy = (256.0*f-256.0)*strength_autogain

#----------- Y offset correction calculation
new_y_max = y_max * f # only for display
new_y_min = y_min * f
dy = (16.0 - new_y_min)*strength_autogain

(show_info == false) ? \
ColorYUV2(\
gain_y = gy, off_y = dy,\
off_u = du1, rpow_u = ru, spow_u = su, pord_u = pord,\
off_v = dv1, rpow_v = rv, spow_v = sv, pord_v = pord)\
:\
ColorYUV2(\
gain_y = gy, off_y = dy,\
off_u = du1, rpow_u = ru, spow_u = su, pord_u = pord,\
off_v = dv1, rpow_v = rv, spow_v = sv, pord_v = pord)\
.Subtitle(" U Chroma value : "+String(u)+"\n"+\
" Middle - U Chroma value : "+String(du)+"\n"+\
" Bias : "+String(du1)+"\n"+\
" Gamma and S correction base : "+String(du2)+"\n"+\
" Rpow : "+String(ru)+" Spow : "+String(su),y=40,lsp=20)\
.Subtitle(" V value : "+String(v)+"\n"+\
" Middle - V Chroma value : "+String(dv)+"\n"+\
" Bias : "+String(dv1)+"\n"+\
" Gamma and S correction base : "+String(dv2)+"\n"+\
" Rpow : "+String(rv)+" Spow : "+String(sv),y=160,lsp=20)\
.Subtitle(" Y max : "+String(y_max)+" Y min : "+String(y_min)+"\n"+\
" luma_threshold : "+String(luma_threshold)+ " strength_autogain : "+String(strength_autogain)+"\n"+\
" Y factor : "+String(f)+" Y gain : "+String(gy)+" Y offset : "+String(dy)+"\n"+\
" New Y max : "+String(new_y_max + dy)+" New Y min : "+String(new_y_min + dy),y=280,lsp=20)

""", args = "strength_bias, strength_rpow, strength_spow, pord, luma_threshold, strength_autogain, show_info")

( comparison == false) ? last : StackHorizontal(clip,last)

}


Auto white balance with RGBAdapt seem a little best auto white balance with ColorYUV. Perhaps it is because the args ranges are not the same, and so
i do not compare the same strength action. Perhaps it is because my RGBAdapt script has not 16-235 range limitation, before convertTo YV12.

Do you agree my analysis or is it something i have not understood ?

Thanks

Bernardd
18th June 2014, 21:20
Hi Stainless,

You can find below my last script version of RGBAdapt auto. The script purpose is to have automatic white balance function and if the result is no good to have manual tuning input.


function RGBAdapt_awb_auto(clip clip, bool "awb",\
float "R_bias_manu", float "R_gain", float "R_cont", float "R_rpow_manu", float "R_spow_manu", float "R_spmid", bool "R_pord",\
float "G_bias_manu", float "G_gain", float "G_cont", float "G_rpow_manu", float "G_spow_manu", float "G_spmid", bool "G_pord",\
float "B_bias_manu", float "B_gain", float "B_cont", float "B_rpow_manu", float "B_spow_manu", float "B_spmid", bool "B_pord",\
float "strength_bias", float "strength_rpow", float "strength_spow",\
bool "show_info", bool "comparison")

{

#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #

#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #

test = isRGB(clip)
(test == false) ? ConvertToRGB32(clip, matrix="Rec601") : clip

clip = last

awb = Default(awb,true) # auto white balance mode
awb_nb = (awb == false) ? 0 : 1

R_bias_manu = Default(R_bias_manu, 0) # same range with original R_bias args
G_bias_manu = Default(G_bias_manu, 0) # same range with original G_bias args
B_bias_manu = Default(B_bias_manu, 0) # same range with original B_bias args

R_gain = Default(R_gain, 1) # it is original original R_gain args, range -8 to 8 center 1.0
G_gain = Default(G_gain, 1) # it is original original G_gain args, range -8 to 8 center 1.0
B_gain = Default(B_gain, 1) # it is original original B_gain args, range -8 to 8 center 1.0

R_cont = Default(R_cont, 1) # it is original original R_cont args, range -8 to 8 center 1.0
G_cont = Default(G_cont, 1) # it is original original G_cont args, range -8 to 8 center 1.0
B_cont = Default(B_cont, 1) # it is original original B_cont args, range -8 to 8 center 1.0

R_rpow_manu = Default(R_rpow_manu, 0) # range -0.9 to 3.0 center 0 (original R_rpow range 0.1 to 4.0 center 1.0)
G_rpow_manu = Default(G_rpow_manu, 0) # range -0.9 to 3.0 center 0 (original G_rpow range 0.1 to 4.0 center 1.0)
B_rpow_manu = Default(B_rpow_manu, 0) # range -0.9 to 3.0 center 0 (original B_rpow range 0.1 to 4.0 center 1.0)

R_spow_manu = Default(R_spow_manu, 0) # range -0.9 to 3.0 center 0 (original R_spow range 0.1 to 4.0 center 1.0)
G_spow_manu = Default(G_spow_manu, 0) # range -0.9 to 3.0 center 0 (original G_spow range 0.1 to 4.0 center 1.0)
B_spow_manu = Default(B_spow_manu, 0) # range -0.9 to 3.0 center 0 (original B_spow range 0.1 to 4.0 center 1.0)

R_spmid = Default(R_spmid, 0.5) # it is original R_spmid args, range 0.1 to 0.99 center 0.5
G_spmid = Default(G_spmid, 0.5) # it is original G_spmid args, range 0.1 to 0.99 center 0.5
B_spmid = Default(B_spmid, 0.5) # it is original B_spmid args, range 0.1 to 0.99 center 0.5

R_pord = Default(R_pord, false) # it is original R_pord args
G_pord = Default(G_pord, false) # it is original G_pord args
B_pord = Default(B_pord, false) # it is original B_pord args

strength_bias = Default(strength_bias, 0.8) # linear curve use strength, between 0.0 and 1.0, default 0.8
strength_rpow = Default(strength_rpow,1.0) # rpow curve use strength, between -4.0 and 4.0, default 1.0
strength_spow = Default(strength_spow,1.0) # spow curve use strength, between -4.0 and 4.0, default 1.0

show_info = Default(show_info, false) # show info or not, default false
comparison = Default(comparison, false) # show original vs processed comparison or not, default false

neutre = BlankClip( clip,pixel_type="RGB32", color=$000000)
luma = Greyscale(clip, matrix="Rec601")
red=ShowRed(clip,"RGB32")
green = ShowGreen(clip,"RGB32")
blue = ShowBlue(clip,"RGB32")

ScriptClip(clip, """

#------------ RGB values calcul

luma_value = RGBDifference(luma, neutre)
r = RGBDifference(neutre, red)
g = RGBDifference(neutre,green)
b = RGBDifference(neutre,blue)

#----------- RGB correction calcul
dr = luma_value-r
dg = luma_value-g
db = luma_value-b

#----------- RGB correction with linear curve calcul (Bias)
dr1_calcul = dr * strength_bias * awb_nb + R_bias_manu
dr1_low_limit = Max (dr1_calcul, -512)
dr1 = Min (512, dr1_low_limit)
dg1_calcul = dg * strength_bias * awb_nb + G_bias_manu
dg1_low_limit = Max (dg1_calcul, -512)
dg1 = Min (512, dg1_low_limit)
db1_calcul = db * strength_bias * awb_nb + B_bias_manu
db1_low_limit = Max (db1_calcul, -512)
db1 = Min (512, db1_low_limit)

#----------- RGB correction with Rpow and Spow curves calcul
dr2 = (dr - dr * strength_bias) * awb_nb
dg2 = (dg - dg * strength_bias) * awb_nb
db2 = (db - db * strength_bias) * awb_nb

#----------- RGB correction with Rpow curve calcul
yr_calcul = pow((1+dr2 * strength_rpow/128),(1+dr2 * strength_rpow/128)) + R_Rpow_manu # exp((dr2/100) * strength_rpow) + R_Rpow_manu
yr_low_limit = Max (yr_calcul, 0.1)
yr = Min (4.0, yr_low_limit)
yg_calcul = pow((1+dg2 * strength_rpow/128),(1+dg2 * strength_rpow/128)) + G_Rpow_manu # exp((dg2/100) * strength_rpow) + G_Rpow_manu
yg_low_limit = Max (yg_calcul, 0.1)
yg = Min (4.0, yg_low_limit)
yb_calcul = pow((1+db2 * strength_rpow/128),(1+db2 * strength_rpow/128)) + B_Rpow_manu # exp((db2/100) * strength_rpow) + B_Rpow_manu
yb_low_limit = Max (yb_calcul, 0.1)
yb = Min (4.0, yb_low_limit)

#----------- RGB correction with Spow curve calcul
sr_calcul = pow((1+dr2 * strength_spow/128),(1+dr2 * strength_spow/128)) + R_Spow_manu # exp((dr2/100) * strength_spow) + R_spow_manu
sr_low_limit = Max (sr_calcul, 0.1)
sr = Min (4.0, sr_low_limit)
sg_calcul = pow((1+dg2 * strength_spow/128),(1+dg2 * strength_spow/128)) + G_Spow_manu # exp((dg2/100) * strength_spow) + G_spow_manu
sg_low_limit = Max (sg_calcul, 0.1)
sg = Min (4.0, sg_low_limit)
sb_calcul = pow((1+db2 * strength_spow/128),(1+db2 * strength_spow/128)) + B_Spow_manu # exp((db2/100) * strength_spow) + B_spow_manu
sb_low_limit = Max (sb_calcul, 0.1)
sb = Min (4.0, sb_low_limit)


(show_info == false)? \
RGBAdapt( \
R_Bias = dr1, R_Gain = R_Gain, R_Cont = R_Cont, R_RPow = yr, R_Spow = sr, R_SPMid = R_spmid, R_Pord = R_pord, \
G_Bias = dg1, G_Gain = G_Gain, G_Cont = G_Cont, G_RPow = yg, G_Spow = sg, G_SPMid = G_spmid, G_Pord = G_pord,\
B_Bias = db1, B_Gain = B_Gain, B_Cont = B_Cont, B_RPow = yb, B_Spow = sb, B_SPMid = B_spmid, B_Pord = B_pord)\
:\
RGBAdapt( \
R_Bias = dr1, R_Gain = R_Gain, R_Cont = R_Cont, R_RPow = yr, R_Spow = sr, R_SPMid = R_spmid, R_Pord = R_pord, \
G_Bias = dg1, G_Gain = G_Gain, G_Cont = G_Cont, G_RPow = yg, G_Spow = sg, G_SPMid = G_spmid, G_Pord = G_pord,\
B_Bias = db1, B_Gain = B_Gain, B_Cont = B_Cont, B_RPow = yb, B_Spow = sb, B_SPMid = B_spmid, B_Pord = B_pord)\
.Subtitle("Red value : "+String(r)+\
"\n Middle - Red Value : "+String(dr)+\
"\n Bias : "+String(dr1)+\
"\n Gamma and S correction base : "+String(dr2)+\
"\n Rpow : "+String(yr)+" Spow : "+String(sr),y=40,lsp=20)\
.Subtitle("Green value : "+String(g)+\
"\n Middle - Green Value : "+String(dg)+\
"\n Bias : "+String(dg1)+\
"\n Gamma and S correction base : "+String(dg2)+\
"\n Rpow : "+String(yg)+" Spow : "+String(sg),y=160,lsp=20)\
.Subtitle("Blue value : "+String(b)+\
"\n Middle - Blue Value : "+String(db)+\
"\n Bias : "+String(db1)+\
"\n Gamma and S correction base : "+String(db2)+\
"\n Rpow : "+String(yb)+" Spow : "+String(sb), y=280,lsp=20)

""", args = "R_bias_manu, R_gain, R_cont, R_rpow_manu, R_spow_manu, R_spmid, R_pord," +\
"G_bias_manu, G_gain, G_cont, G_rpow_manu, G_spow_manu, G_spmid, G_pord,"+\
"B_bias_manu, B_gain, B_cont, B_rpow_manu, B_spow_manu, B_spmid, B_pord,"+\
"neutre, red, green, blue,luma,"+\
"awb_nb, strength_bias, strength_rpow, strength_spow,"+\
"show_info")


(comparison == false) ? last : StackHorizontal(clip,last)

(test == false) ? ConvertToYV12(last, matrix="Rec601") : last

}


I have erased the automatic gain function, because it was experimental and other plugins exist for that.

In this script, i have added six args :
strength bias, to tune automatic white balance with linear curve,
strength rpow, to tune automatic white balance with rpow curve,
strength spow, to tune automatic white balance with spow curve,
abw, to fast enable or no automatic white balance,
show_info, to display automatic args values,
and comparison, to display original vs filtered comparison.

To stay in accordance with your plugin, original bias args are now named bias_manu, rpow rpow_manu and spow spow_manu. With these new args and your original args we can make white balance search around automatic white balance output.

The automatic white balance default principe is to make the job at 80% with bias curve and to finish with rpow and spow actions.
Thus we minimize automatic white balance effects in highest and lowest luma tones, and for me we keep sunset or night colors.

strength bias values are in 0.0 and 0.1 range. 0.0 mean automatic white balance only with rpow and spow curves. 1.0 mean automatic white balance only with linear curve, in this case the result is like colorYUV autowhite function.

rpow and spow inputs are not linear, thus i use x^x curves for translate the linear difference between 127 and channel value datas. rpow and spow values are in -4.0 and 4.0 range
with default 1.0. I do not know if this automatic rpow or spow curves use have a mathematical sense, but with 1.0 values for this two args i find result good for me. I have a white balance effects more strong for light midtones as dark midtones and very little for the upper and lower tones.
0.0 mean no use rpow or spow curves. I have limited their values range at -4 to 4, because i have observed we can efficiently modify white balance with this args before start a manual job with the RGBAdapt original args.

For automatic white balance with rpow and spow curves use, we can process with my ColorYUV2 auto script proposal, but i believe it more easier to work in RGB when the automatic result is not satisfactory. I think RGBAdapt is thus better for find the automatic white balance start before a manual search.

Thanks for your great plugins.

Bernardd
24th June 2014, 18:41
Hi StainlessS,

I come back with my two automatic use of your plugins. I believe that i have solved the problem of assymetric inputs for rpow and spow args. For example -50 and 50 with
ColorYUV2 and 0,5 and 1,5 with RGBAdapt do not give symetric curves.

For coloryuv2, if difference between channel value and 127 is negative i apply "this difference" like pow args and i apply "1/this difference" in other case.
For RGBAdapt, if difference between channel value and 127 is negative i apply "1+ this difference" like pow args and i apply "1/(1 - this difference)" in other case.

Thus i hope automatic functions with rpow and spow args are more logical.

Below the last versions of this two scripts.


function ColorYUV2_auto(clip clip, float "strength_bias",float "strength_Rpow", float "strength_Spow", int "pord",\
float "luma_threshold", float "strength_autogain", bool "show_info", bool "comparison")

{

#----------------------------------------------based on ColorYUV2 plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1443313#post1443313 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #

#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #


strength_bias = Default(strength_bias, 0.5) # linear curve use strength, between 0.0 and 1.0, default 0.5
strength_Rpow = Default(strength_Rpow,1.0) # Rpow curve use strength, between -4.0 and 4.0, default 1.0
strength_Spow = Default(strength_Spow,1.0) # Spow curve use strength, between -4.0 and 4.0, default 1.0
pord = Default(pord,0) # process Rpow curve before Spow curve or not (1), default 0

luma_threshold = Default(luma_threshold, 0.50) # selected luma value percentage for calculation, too weak can be cause of light flicker
strength_autogain = Default(strength_autogain,1.0) # autogain strength, between 0.0 and 1.0, default 1.0

show_info = Default(show_info, false) # show info or not, default false
comparison = Default(comparison, false) # show original vs processed comparison or not, default false

ScriptClip(clip, """

#--------------------------------------------
# Autowhite process
#--------------------------------------------

#------------ UV average values
u = AverageChromaU()
v = AverageChromaV()

#----------- UV corrections calculation
du = 127.0 - u
dv = 127.0 - v

#----------- UV corrections with linear curve calculation (Offset)
du1 = du*strength_bias
dv1 = dv*strength_bias

#----------- UV corrections range with Rpow and Spow curves calculation
du2 = du-du1
dv2 = dv-dv1

#----------- UV corrections with Rpow curve calculation
ru = (du2 <= 0) ? du2*strength_rpow : 1*strength_rpow/du2
rv = (dv2 <= 0) ? dv2*strength_rpow : 1*strength_rpow/dv2

#----------- UV corrections with Spow curve calculation
su = (du2 <= 0) ? du2*strength_spow : 1*strength_spow/du2
sv = (dv2 <= 0) ? dv2*strength_spow : 1*strength_spow/dv2

#--------------------------------------------
# autogain process
#--------------------------------------------

#------------ Y max and min values

y_max_value = float(YPlaneMax(threshold = luma_threshold))
y_max = min (y_max_value, 235.0)
y_min_value = float(YPlaneMin(threshold = luma_threshold))
y_min = max (16.0, y_min_value)

#----------- Y gain correction calculation

f = float(219.0/(y_max - y_min)) #(autogain == true) ? : 1.0
gy = (256.0*f-256.0)*strength_autogain

#----------- Y offset correction calculation
new_y_max = y_max * f # only for display
new_y_min = y_min * f
dy = (16.0 - new_y_min)*strength_autogain

(show_info == false) ? \
ColorYUV2(\
gain_y = gy, off_y = dy,\
off_u = du1, rpow_u = ru, spow_u = su, pord_u = pord,\
off_v = dv1, rpow_v = rv, spow_v = sv, pord_v = pord)\
:\
ColorYUV2(\
gain_y = gy, off_y = dy,\
off_u = du1, rpow_u = ru, spow_u = su, pord_u = pord,\
off_v = dv1, rpow_v = rv, spow_v = sv, pord_v = pord)\
.Subtitle(" U Chroma value : "+String(u)+"\n"+\
" Middle - U Chroma value : "+String(du)+"\n"+\
" Bias : "+String(du1)+"\n"+\
" Gamma and S correction base : "+String(du2)+"\n"+\
" Rpow : "+String(ru)+" Spow : "+String(su),y=40,lsp=20)\
.Subtitle(" V value : "+String(v)+"\n"+\
" Middle - V Chroma value : "+String(dv)+"\n"+\
" Bias : "+String(dv1)+"\n"+\
" Gamma and S correction base : "+String(dv2)+"\n"+\
" Rpow : "+String(rv)+" Spow : "+String(sv),y=160,lsp=20)\
.Subtitle(" Y max : "+String(y_max)+" Y min : "+String(y_min)+"\n"+\
" luma_threshold : "+String(luma_threshold)+ " strength_autogain : "+String(strength_autogain)+"\n"+\
" Y factor : "+String(f)+" Y gain : "+String(gy)+" Y offset : "+String(dy)+"\n"+\
" New Y max : "+String(new_y_max + dy)+" New Y min : "+String(new_y_min + dy),y=280,lsp=20)

""", args = "strength_bias, strength_rpow, strength_spow, pord, luma_threshold, strength_autogain, show_info")

( comparison == false) ? last : StackHorizontal(clip,last)

}



function RGBAdapt_awb_auto(clip clip, bool "awb",\
float "R_bias_manu", float "R_gain", float "R_cont", float "R_rpow_manu", float "R_spow_manu", float "R_spmid", bool "R_pord",\
float "G_bias_manu", float "G_gain", float "G_cont", float "G_rpow_manu", float "G_spow_manu", float "G_spmid", bool "G_pord",\
float "B_bias_manu", float "B_gain", float "B_cont", float "B_rpow_manu", float "B_spow_manu", float "B_spmid", bool "B_pord",\
float "strength_bias", float "strength_rpow", float "strength_spow",\
bool "show_info", bool "comparison")

{

#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #

#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #

test = isRGB(clip)
(test == false) ? ConvertToRGB32(clip, matrix="Rec601") : clip

clip = last

awb = Default(awb,true) # auto white balance mode
awb_nb = (awb == false) ? 0 : 1

R_bias_manu = Default(R_bias_manu, 0) # same range with original R_bias args
G_bias_manu = Default(G_bias_manu, 0) # same range with original G_bias args
B_bias_manu = Default(B_bias_manu, 0) # same range with original B_bias args

R_gain = Default(R_gain, 1) # it is original original R_gain args, range -8 to 8 center 1.0
G_gain = Default(G_gain, 1) # it is original original G_gain args, range -8 to 8 center 1.0
B_gain = Default(B_gain, 1) # it is original original B_gain args, range -8 to 8 center 1.0

R_cont = Default(R_cont, 1) # it is original original R_cont args, range -8 to 8 center 1.0
G_cont = Default(G_cont, 1) # it is original original G_cont args, range -8 to 8 center 1.0
B_cont = Default(B_cont, 1) # it is original original B_cont args, range -8 to 8 center 1.0

R_rpow_manu = Default(R_rpow_manu, 0) # range -0.9 to 3.0 center 0 (original R_rpow range 0.1 to 4.0 center 1.0)
G_rpow_manu = Default(G_rpow_manu, 0) # range -0.9 to 3.0 center 0 (original G_rpow range 0.1 to 4.0 center 1.0)
B_rpow_manu = Default(B_rpow_manu, 0) # range -0.9 to 3.0 center 0 (original B_rpow range 0.1 to 4.0 center 1.0)

R_spow_manu = Default(R_spow_manu, 0) # range -0.9 to 3.0 center 0 (original R_spow range 0.1 to 4.0 center 1.0)
G_spow_manu = Default(G_spow_manu, 0) # range -0.9 to 3.0 center 0 (original G_spow range 0.1 to 4.0 center 1.0)
B_spow_manu = Default(B_spow_manu, 0) # range -0.9 to 3.0 center 0 (original B_spow range 0.1 to 4.0 center 1.0)

R_spmid = Default(R_spmid, 0.5) # it is original R_spmid args, range 0.1 to 0.99 center 0.5
G_spmid = Default(G_spmid, 0.5) # it is original G_spmid args, range 0.1 to 0.99 center 0.5
B_spmid = Default(B_spmid, 0.5) # it is original B_spmid args, range 0.1 to 0.99 center 0.5

R_pord = Default(R_pord, false) # it is original R_pord args
G_pord = Default(G_pord, false) # it is original G_pord args
B_pord = Default(B_pord, false) # it is original B_pord args

strength_bias = Default(strength_bias, 0.8) # linear curve use strength, between 0.0 and 1.0, default 0.8
strength_rpow = Default(strength_rpow,1.0) # rpow curve use strength, between -4.0 and 4.0, default 1.0
strength_spow = Default(strength_spow,1.0) # spow curve use strength, between -4.0 and 4.0, default 1.0

show_info = Default(show_info, false) # show info or not, default false
comparison = Default(comparison, false) # show original vs processed comparison or not, default false

neutre = BlankClip( clip,pixel_type="RGB32", color=$000000)
luma = Greyscale(clip, matrix="Rec601")
red=ShowRed(clip,"RGB32")
green = ShowGreen(clip,"RGB32")
blue = ShowBlue(clip,"RGB32")

ScriptClip(clip, """

#------------ RGB values calcul

luma_value = RGBDifference(luma, neutre)
r = RGBDifference(neutre, red)
g = RGBDifference(neutre,green)
b = RGBDifference(neutre,blue)

#----------- RGB correction calcul
dr = luma_value-r
dg = luma_value-g
db = luma_value-b

#----------- RGB correction with linear curve calcul (Bias)
dr1_calcul = dr * strength_bias * awb_nb + R_bias_manu
dr1_low_limit = Max (dr1_calcul, -512)
dr1 = Min (512, dr1_low_limit)
dg1_calcul = dg * strength_bias * awb_nb + G_bias_manu
dg1_low_limit = Max (dg1_calcul, -512)
dg1 = Min (512, dg1_low_limit)
db1_calcul = db * strength_bias * awb_nb + B_bias_manu
db1_low_limit = Max (db1_calcul, -512)
db1 = Min (512, db1_low_limit)

#----------- RGB correction with Rpow and Spow curves calcul
dr2 = (dr - dr * strength_bias) * awb_nb
dg2 = (dg - dg * strength_bias) * awb_nb
db2 = (db - db * strength_bias) * awb_nb

#----------- RGB correction with Rpow curve calcul
yr_calcul = (dr2 < 0) ? 1+dr2 * strength_rpow/128 + R_Rpow_manu : 1/(1-dr2 * strength_rpow/128) + R_Rpow_manu
yr_low_limit = Max (yr_calcul, 0.1)
yr = Min (4.0, yr_low_limit)
yg_calcul = (dg2 < 0) ? 1+dg2 * strength_rpow/128 + G_Rpow_manu : 1/(1-dg2 * strength_rpow/128) + G_Rpow_manu
yg_low_limit = Max (yg_calcul, 0.1)
yg = Min (4.0, yg_low_limit)
yb_calcul = (db2 < 0) ? 1+db2 * strength_rpow/128 + B_Rpow_manu : 1/(1-db2 * strength_rpow/128) + B_Rpow_manu
yb_low_limit = Max (yb_calcul, 0.1)
yb = Min (4.0, yb_low_limit)

#----------- RGB correction with Spow curve calcul
sr_calcul = (dr2 < 0) ? 1+dr2 * strength_spow/128 + R_Spow_manu : 1/(1-dr2 * strength_spow/128) + R_Spow_manu
sr_low_limit = Max (sr_calcul, 0.1)
sr = Min (4.0, sr_low_limit)
sg_calcul = (dg2 < 0) ? 1+dg2 * strength_spow/128 + G_Spow_manu : 1/(1-dg2 * strength_spow/128) + G_Spow_manu
sg_low_limit = Max (sg_calcul, 0.1)
sg = Min (4.0, sg_low_limit)
sb_calcul = (db2 < 0) ? 1+db2 * strength_spow/128 + B_Spow_manu : 1/(1-db2 * strength_spow/128) + B_Spow_manu
sb_low_limit = Max (sb_calcul, 0.1)
sb = Min (4.0, sb_low_limit)


(show_info == false)? \
RGBAdapt( \
R_Bias = dr1, R_Gain = R_Gain, R_Cont = R_Cont, R_RPow = yr, R_Spow = sr, R_SPMid = R_spmid, R_Pord = R_pord, \
G_Bias = dg1, G_Gain = G_Gain, G_Cont = G_Cont, G_RPow = yg, G_Spow = sg, G_SPMid = G_spmid, G_Pord = G_pord,\
B_Bias = db1, B_Gain = B_Gain, B_Cont = B_Cont, B_RPow = yb, B_Spow = sb, B_SPMid = B_spmid, B_Pord = B_pord)\
:\
RGBAdapt( \
R_Bias = dr1, R_Gain = R_Gain, R_Cont = R_Cont, R_RPow = yr, R_Spow = sr, R_SPMid = R_spmid, R_Pord = R_pord, \
G_Bias = dg1, G_Gain = G_Gain, G_Cont = G_Cont, G_RPow = yg, G_Spow = sg, G_SPMid = G_spmid, G_Pord = G_pord,\
B_Bias = db1, B_Gain = B_Gain, B_Cont = B_Cont, B_RPow = yb, B_Spow = sb, B_SPMid = B_spmid, B_Pord = B_pord)\
.Subtitle("Red value : "+String(r)+\
"\n Middle - Red Value : "+String(dr)+\
"\n Bias : "+String(dr1)+\
"\n Gamma and S correction base : "+String(dr2)+\
"\n Rpow : "+String(yr)+" Spow : "+String(sr),y=40,lsp=20)\
.Subtitle("Green value : "+String(g)+\
"\n Middle - Green Value : "+String(dg)+\
"\n Bias : "+String(dg1)+\
"\n Gamma and S correction base : "+String(dg2)+\
"\n Rpow : "+String(yg)+" Spow : "+String(sg),y=160,lsp=20)\
.Subtitle("Blue value : "+String(b)+\
"\n Middle - Blue Value : "+String(db)+\
"\n Bias : "+String(db1)+\
"\n Gamma and S correction base : "+String(db2)+\
"\n Rpow : "+String(yb)+" Spow : "+String(sb), y=280,lsp=20)

""", args = "R_bias_manu, R_gain, R_cont, R_rpow_manu, R_spow_manu, R_spmid, R_pord," +\
"G_bias_manu, G_gain, G_cont, G_rpow_manu, G_spow_manu, G_spmid, G_pord,"+\
"B_bias_manu, B_gain, B_cont, B_rpow_manu, B_spow_manu, B_spmid, B_pord,"+\
"neutre, red, green, blue,luma,"+\
"awb_nb, strength_bias, strength_rpow, strength_spow,"+\
"show_info")


(comparison == false) ? last : StackHorizontal(clip,last)

(test == false) ? ConvertToYV12(last, matrix="Rec601") : last

}

Bernardd
11th May 2015, 19:44
Hello,

I have rewritten my script to make automatic white balance with RGBAdapt plugin.
Now, i think it is possible to have a good result with this script.

The script have eleven settings :
two booleans to select the display, "show_info" and "comparison"
nine to tune the automatic white balance process
in this nine, four are most interest
"linear_gamma_mix" to mix linear curve correction process and rpow and spow curves correction process, default value 0 (no linear curve correction process)
"spmid" to tune the inflexion point of spow curve , default value 0.5
"pord" to compute the spow curve calcul before or no the rpow curve, default value false
"gamma" to tune the gamma factor, , default value 2.2
the four other are more interest than the first settings with bad videos
"red_gamma_increase" to increase the calulated red gamma value around gamma value given before, default value 0.0
"green_gamma_increase" to increase the calulated green gamma value around gamma value given before, default value 0.0
"blue_gamma_increase" to increase the calulated blue gamma value around gamma value given before, default value 0.0
"gain" and "cont" to increase or decrease the gain and cont, default value 1.0

The script need to load GRunT.dll and RGBAdapt.dll. The script has two functions. The first to diplay comparison, the second to automatic white balance process.

This script run in rgb color mode, i do not know if convert yuv to rgb and return is a good thing. I should apreciate advice.


function RGBAdapt_auto_awb(clip clip, bool "show_info", bool "comparison", \
float "linear_gamma_mix", float "spmid", bool "pord",\
float "gamma", float "red_gamma_increase", float "green_gamma_increase", float "blue_gamma_increase",\
float "gain", float "cont")

{
show_info = Default(show_info, false) # show info or not, default false
comparison = Default(comparison, false) # show info or not, default false

gamma = Default(gamma, 2.2) # gamma value defintion for calcul between 1.0 and 10.0, default 2.2
red_gamma_increase = Default(red_gamma_increase, 0.0) # red gamma value adjust between 0.0 and 0.0, default 0.0
green_gamma_increase = Default(green_gamma_increase, 0.0) # green gamma value adjust between 1.0 and 4.0, default 0.0
blue_gamma_increase = Default(blue_gamma_increase, 0.0) # blue gamma value adjust between 1.0 and 4.0, default 0.0
linear_gamma_mix = Default(linear_gamma_mix, 0.5) # linear curve use strength, between 0.0 and 1.0, default 0.5
spmid = Default(spmid, 0.5) # it is original Channel_spmid args, range 0.1 to 0.99 center 0.5
pord = Default(pord, false) # it is original Channel_pord args
gain = Default(gain, 1.0) # it is calculated gain stength args, range -9.0 to 8.0, center 0.0
cont = Default(cont, 1.0) # it is calculated cont stength args, range -9.0 to 8.0, center 0.0



Classic_awb = ColorYUV(clip.convertToYV12, autowhite = true)

RGBAdapt_bias =RGBAdapt_auto_awb_process( clip, show_info = show_info, \
linear_gamma_mix = linear_gamma_mix, spmid = 0.5, pord = false,\
gamma = 1.0, red_gamma_increase = 0.0, green_gamma_increase = 0.0, blue_gamma_increase = 0.0, gain = 0.0, cont =0.0)

RGBAdapt_bias_rpow_spow_default =RGBAdapt_auto_awb_process( clip, show_info = show_info, \
linear_gamma_mix = linear_gamma_mix, spmid = 0.5, pord = false,\
gamma = 2.2, red_gamma_increase = 0.0, green_gamma_increase = 0.0, blue_gamma_increase = 0.0, gain = 0.0, cont = 0.0)

RGBAdapt_bias_rpow_spow =RGBAdapt_auto_awb_process( clip, show_info = show_info, \
linear_gamma_mix = linear_gamma_mix, spmid = spmid, pord = pord,\
gamma = 2.2, red_gamma_increase = 0.0, green_gamma_increase = 0.0, blue_gamma_increase = 0.0, gain = 0.0, cont = 0.0)

RGBAdapt_bias_rpow_spow_gamma =RGBAdapt_auto_awb_process( clip, show_info = show_info, \
linear_gamma_mix = linear_gamma_mix, spmid = spmid, pord = pord,\
gamma = gamma, red_gamma_increase = red_gamma_increase, green_gamma_increase = green_gamma_increase, blue_gamma_increase = blue_gamma_increase, gain = 0.0, cont = 0.0)

RGBAdapt_awb =RGBAdapt_auto_awb_process( clip, show_info = show_info, \
linear_gamma_mix = linear_gamma_mix, spmid = spmid, pord = pord,\
gamma = gamma, red_gamma_increase = red_gamma_increase, green_gamma_increase = green_gamma_increase, blue_gamma_increase = blue_gamma_increase, gain = gain, cont = cont)

(comparison == false) ? RGBAdapt_awb : Stackvertical(StackHorizontal(RGBAdapt_bias.Subtitle("AWB with " +string(round(float(linear_gamma_mix)* 100)) +" %"+" of only bias "), \
RGBAdapt_bias_rpow_spow_default.Subtitle("AWB with "+string(round(float(linear_gamma_mix) * 100)) +" %"+" of bias and "+" spmid = 0.5 and pord = false"),\
RGBAdapt_bias_rpow_spow.Subtitle("AWB with "+string(round(float(linear_gamma_mix) * 100)) +" %"+" of bias and "+" spmid = " + String(spmid) + " and pord = " +string(pord))),\
StackHorizontal(Classic_awb.Subtitle("Classic AWB (ColorYUV - autogain)"),clip.Subtitle("original"), \
RGBAdapt_bias_rpow_spow_gamma.Subtitle("AWB with gamma tune\n" + "on ground : " + String(gamma) + " and increase\n" + \
"in red channel" + String(red_gamma_increase) + " in green : " + String(green_gamma_increase) + " in blue : " +String(blue_gamma_increase),\
lsp = 10)),\
StackHorizontal(clip.BlankClip(color=$000000), clip.BlankClip(color=$000000), RGBAdapt_awb.Subtitle("AWB with gain tune : " + String(gain) + "and cont tune : " + String(cont))))
}


function RGBAdapt_auto_awb_process(clip clip, bool "show_info", \
float "linear_gamma_mix", float "spmid", bool "pord",\
float "gamma", float "red_gamma_increase", float "green_gamma_increase", float "blue_gamma_increase", \
float "gain", float "cont")
{

#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #

#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #

test = isRGB(clip)
(test == false) ? ConvertToRGB24(clip, matrix="Rec601") : clip

clip = last

neutre = BlankClip( clip,pixel_type="RGB24", color=$000000)

luma = clip.Greyscale( matrix="Rec601")

red=ShowRed(clip,"RGB24")
green = ShowGreen(clip,"RGB24")
blue = ShowBlue(clip,"RGB24")

ScriptClip(clip, """

#------------ RGB values calcul

luma_value = RGBDifference(luma, neutre)

g = RGBDifference(green, neutre)
r = RGBDifference(red, neutre)
b = RGBDifference(blue,neutre)

#----------- RGB correction calcul

dr = (luma_value - r)
dg = (luma_value - g)
db = (luma_value - b)

#----------- RGB correction with linear curve calcul (Bias)

dr1_calcul = dr * linear_gamma_mix
dr1_low_limit = Max (dr1_calcul, -512)
dr1 = Min (512, dr1_low_limit)

dg1_calcul = dg * linear_gamma_mix
dg1_low_limit = Max (dg1_calcul, -512)
dg1 = Min (512, dg1_low_limit)

db1_calcul = db * linear_gamma_mix
db1_low_limit = Max (db1_calcul, -512)
db1 = Min (512, db1_low_limit)

#---------- Remaining RGB correction with gamma curves(rpow, spow)after linear curve process

dr2 = dr - dr * linear_gamma_mix
dg2 = dg - dg * linear_gamma_mix
db2 = db - db * linear_gamma_mix

#--------- Auto gamma calcul

red_gamma_increase = gamma + abs(dr2/128)*(1+0.299) + red_gamma_increase
green_gamma_increase = gamma + abs(dg2/128)*(1+0.587) + green_gamma_increase
blue_gamma_increase = gamma + abs(db2/128)*(1+0.114) + blue_gamma_increase

#----------- RGB correction with Rpow curve calcul

yr_calcul = pow(red_gamma_increase,dr2/128)
yr_low_limit = Max (yr_calcul, 0.1)
yr = Min (4.0, yr_low_limit)
yg_calcul = pow(green_gamma_increase,dg2/128)
yg_low_limit = Max (yg_calcul, 0.1)
yg = Min (4.0, yg_low_limit)
yb_calcul = pow(blue_gamma_increase,db2/128)
yb_low_limit = Max (yb_calcul, 0.1)
yb = Min (4.0, yb_low_limit)

#----------- RGB correction with Spow curve calcul

sr_calcul = pow(red_gamma_increase,dr2/128)
sr_low_limit = Max (sr_calcul, 0.1)
sr = Min (4.0, sr_low_limit)
sg_calcul = pow(green_gamma_increase,dg2/128)
sg_low_limit = Max (sg_calcul, 0.1)
sg = Min (4.0, sg_low_limit)
sb_calcul = pow(blue_gamma_increase,db2/128)
sb_low_limit = Max (sb_calcul, 0.1)
sb = Min (4.0, sb_low_limit)

#---------- Gain

gain_r = r/(r-(yr+sr)*gain)
gain_g = g/(g-(yg+sg)*gain)
gain_b = b/(b-(yb+sb)*gain)

cont_r = r/(r-(yr+sr)*cont)
cont_g = g/(g-(yg+sg)*cont)
cont_b = b/(b-(yb+sb)*cont)

#---------- RGBAdapt use

output_video = RGBAdapt( \
R_Bias = dr1, R_Gain = gain_r, R_Cont = cont_r, R_RPow = yr, R_Spow = sr, R_SPMid = spmid, R_Pord = pord, \
G_Bias = dg1, G_Gain = gain_g, G_Cont = cont_g, G_RPow = yg, G_Spow = sg, G_SPMid = spmid, G_Pord = pord,\
B_Bias = db1, B_Gain = gain_b, B_Cont = cont_b, B_RPow = yb, B_Spow = sb, B_SPMid = spmid, B_Pord = pord)

#-------- displayed info or no

(show_info == false)? output_video : output_video.Subtitle("Red value : "+String(r)+\
"\n Middle - Red Value : "+String(dr)+" somme : "+String(dr+dg+db)+\
"\n Bias : "+String(dr1)+\
"\n Rpow and Spow correction base : "+String(dr2)+\
"\n Rpow : "+String(yr)+" Spow : "+String(sr)+" Gamma : "+String(red_gamma_increase),y=40,lsp=20)\
.Subtitle("Green value : "+String(g)+\
"\n Middle - Green Value : "+String(dg)+\
"\n Bias : "+String(dg1)+\
"\n Gamma and S correction base : "+String(dg2)+\
"\n Rpow : "+String(yg)+" Spow : "+String(sg)+" Gamma : "+String(green_gamma_increase),y=160,lsp=20)\
.Subtitle("Blue value : "+String(b)+\
"\n Middle - Blue Value : "+String(db)+\
"\n Bias : "+String(db1)+\
"\n Gamma and S correction base : "+String(db2)+\
"\n Rpow : "+String(yb)+" Spow : "+String(sb)+" Gamma : "+String(blue_gamma_increase), y=280,lsp=20)

""", args = "show_info, neutre, red, green, blue,luma,"+\
"linear_gamma_mix, spmid, pord,"+\
"gamma, red_gamma_increase, green_gamma_increase, blue_gamma_increase,gain, cont")

(test == false) ? ConvertToYV12(last, matrix="Rec601") : last

}

Bernardd
11th May 2015, 19:56
In attachment one script output example.

StainlessS
11th May 2015, 20:29
Bernardd, very nice job :)

I've just tried it on an 80's clip with a quite pronounced color cast (sometimes yellow, sometimes magenta) and it did a great job with default settings.

Only one suggestion eg.
gamma = Default(gamma, 2.2) # gamma value defintion for calcul between 1.0 and 10.0, default 2.2
might best be
gamma = Float(Default(gamma, 2.2)) # gamma value defintion for calcul between 1.0 and 10.0, default 2.2

To avoid mistakes where user supplies int instead of float, same for other float args.

Nice work, keep it up :)

(keeping a copy of that for myself :) )

EDIT: I have had so many clips where this script would have come in very handy.

Bernardd
11th May 2015, 21:49
Hi StainlessS,

Thanks first for RGBAdapt.

Thanks for writter advice, i shall amend my script with float label.

StainlessS
11th May 2015, 22:14
Bernardd,
You need to detect black frames and not make mid gray.
Also, seems to screw up on fade to black, produces RGBAdapt error message from inside Scriptclip:-

RGBAdapt: Invalid B_Gain(-8.0 -> 8.0) {-9.923378}
([ScriptClip ], line 82).


Produces an error and then a white flash as fade from black to video again.

Probably have to be careful when white too.

EDIT: Just checked with another clip where starts fade in from black, same error.

EDIT:
Here gain_g overflows range -8.0 -> 8.0
gain_g = g/(g-(yg+sg)*gain)


00000007 3.55045724 Test: gain_g=0.000000 g=0.000000 yg=1.000000 sg=1.000000 gain=1.000000
00000008 12.14557266 Test: gain_g=0.000000 g=0.000000 yg=1.000000 sg=1.000000 gain=1.000000
00000009 22.18893433 Test: gain_g=0.000000 g=0.000000 yg=1.000000 sg=1.000000 gain=1.000000
00000010 26.50687408 Test: gain_g=-0.014609 g=0.028798 yg=1.000000 sg=1.000000 gain=1.000000
00000011 28.18403816 Test: gain_g=-0.019549 g=0.038351 yg=1.000069 sg=1.000069 gain=1.000000
00000012 29.58735466 Test: gain_g=-0.960002 g=0.979514 yg=0.999919 sg=0.999919 gain=1.000000
00000013 32.45030975 Test: gain_g=-2.584577 g=1.441373 yg=0.999527 sg=0.999527 gain=1.000000
00000014 34.04193497 Test: gain_g=-2.736397 g=1.464258 yg=0.999681 sg=0.999681 gain=1.000000
00000015 35.24155426 Test: gain_g=-10.906834 g=1.830961 yg=0.999417 sg=0.999417 gain=1.000000 # This frame produces error


EDIT: This prevents the problems with both gain and cont args to RGBAdapt

cont_r = Max(Min(gain_r,8.0),-8.0)
cont_g = Max(Min(cont_g,8.0),-8.0)
cont_b = Max(Min(cont_b,8.0),-8.0)

gain_r = Max(Min(gain_r,8.0),-8.0)
gain_g = Max(Min(gain_g,8.0),-8.0)
gain_b = Max(Min(gain_b,8.0),-8.0)

However fade to and from black still produces flashes [as also does ColorYUV(AutoGain=true) on same clip].

EDIT: You might also want to add this

Assert(linear_gamma_mix>=0.0 && linear_gamma_mix <= 1.0,"RGBAdapt_auto_awb: linear_gamma_mix 0.0 -> 1.0")
Assert(spmid>=0.01 && spmid <= 0.99,"RGBAdapt_auto_awb: spmid 0.01 -> 0.99")
Assert(gamma>=0.1 && gamma <= 4.0,"RGBAdapt_auto_awb: gamma 0.1 -> 4.0")
Assert(red_gamma_increase>=0.0 && red_gamma_increase <= 4.0,"RGBAdapt_auto_awb: red_gamma_increase 0.0 -> 4.0")
Assert(green_gamma_increase>=0.0 && green_gamma_increase <= 4.0,"RGBAdapt_auto_awb: green_gamma_increase 0.0 -> 4.0")
Assert(blue_gamma_increase>=0.0 && blue_gamma_increase <= 4.0,"RGBAdapt_auto_awb: blue_gamma_increase 0.0 -> 4.0")
Assert(gain>=-8.0 && gain <= 8.0,"RGBAdapt_auto_awb: gain -8.0 -> 8.0")
Assert(cont>=-8.0 && gain <= 8.0,"RGBAdapt_auto_awb: gain -8.0 -> 8.0")

Dont know what your limits for red_gamma_increase etc should be.

Also, check your comments on arg ranges.

Bernardd
13th May 2015, 22:14
Hi Stainless,

Bizarre is this overflow problem with the gain for images with a transition. In accordance with your recommendations, I have eliminated the error by adding conditions max and min. But there remains the possibility of obtaining one or a few images with aberrant colors.
The only solution now is to manually reduce the gain .

Without solving the problem , however, I modified the formula of gain and cont to reflect corrections bias. On bad video, the result is a little better when you mix corrections linear curves and gamma .

I have amended the scripts by following your recommendations on the values ​​of parameter inputs . I duplicated the definition of variables in both functions , to allow use of the second function independently of the first.

Thank you very much for correcting my scripts.

The new version is in bellow post

Bernardd
13th May 2015, 22:19
New script version. First function to call the second and choice display.


function RGBAdapt_auto_awb(clip clip, bool "show_info", bool "comparison", \
float "linear_gamma_mix", float "spmid", bool "pord",\
float "gamma", float "red_gamma_increase", float "green_gamma_increase", float "blue_gamma_increase",\
float "gain", float "cont")

{

show_info = Default(show_info, false) # show info or not, default false
comparison = Default(comparison, false) # show info or not, default false


linear_gamma_mix = Default(linear_gamma_mix, 0.5) # linear curve use strength, between 0.0 and 1.0, default 0.5
Assert(linear_gamma_mix>=0.0 && linear_gamma_mix <= 1.0,"RGBAdapt_auto_awb: linear_gamma_mix 0.0 -> 1.0")
spmid = Default(spmid, 0.5) # it is original RGBADapt Channel_spmid args, range 0.1 to 0.99 center 0.5
Assert(spmid>=0.01 && spmid <= 0.99,"RGBAdapt_auto_awb: spmid 0.01 -> 0.99")
pord = Default(pord, false) # it is original RGBADapt Channel_pord args

gamma = Default(gamma, 2.2) # gamma value defintion for calcul between 1.0 and 7.0, default 2.2, neutral value 1.0
Assert(gamma>=1.0 && gamma <= 7.0,"RGBAdapt_auto_awb: gamma 1.0 -> 7.0")
red_gamma_increase = Default(red_gamma_increase, 0.0) # red gamma value adjust between 0.0 and 7.0, default = neutral = 0.0
Assert(red_gamma_increase>=0.0 && red_gamma_increase <= 7.0,"RGBAdapt_auto_awb: red_gamma_increase 0.0 -> 7.0")
green_gamma_increase = Default(green_gamma_increase, 0.0) # green gamma value adjust between 0.0 and 7.0, default = neutral = 0.0
Assert(green_gamma_increase>=0.0 && green_gamma_increase <= 7.0,"RGBAdapt_auto_awb: green_gamma_increase 0.0 -> 7.0")
blue_gamma_increase = Default(blue_gamma_increase, 0.0) # blue gamma value adjust between 0.0 and 7.0, default = neutral = 0.0
Assert(blue_gamma_increase>=0.0 && blue_gamma_increase <=7.0,"RGBAdapt_auto_awb: blue_gamma_increase 0.0 -> 7.0")

gain = Default(gain, 1.0) # it is calculated gain stength args, range -8.0 to 8.0, center 0.0
Assert(gain>=-8.0 && gain <= 8.0,"RGBAdapt_auto_awb: gain -8.0 -> 8.0")
cont = Default(cont, 1.0) # it is calculated cont stength args, range -8.0 to 8.0, center 0.0
Assert(cont>=-8.0 && gain <= 8.0,"RGBAdapt_auto_awb: gain -8.0 -> 8.0")

Classic_awb = ColorYUV(clip.convertToYV12, autowhite = true)

RGBAdapt_bias =RGBAdapt_auto_awb_process( clip, show_info = show_info, \
linear_gamma_mix = linear_gamma_mix, spmid = 0.5, pord = false,\
gamma = 1.0, red_gamma_increase = 0.0, green_gamma_increase = 0.0, blue_gamma_increase = 0.0, gain = 0.0, cont =0.0)

RGBAdapt_bias_rpow_spow_default =RGBAdapt_auto_awb_process( clip, show_info = show_info, \
linear_gamma_mix = linear_gamma_mix, spmid = 0.5, pord = false,\
gamma = 2.2, red_gamma_increase = 0.0, green_gamma_increase = 0.0, blue_gamma_increase = 0.0, gain = 0.0, cont = 0.0)

RGBAdapt_bias_rpow_spow =RGBAdapt_auto_awb_process( clip, show_info = show_info, \
linear_gamma_mix = linear_gamma_mix, spmid = spmid, pord = pord,\
gamma = 2.2, red_gamma_increase = 0.0, green_gamma_increase = 0.0, blue_gamma_increase = 0.0, gain = 0.0, cont = 0.0)

RGBAdapt_bias_rpow_spow_gamma =RGBAdapt_auto_awb_process( clip, show_info = show_info, \
linear_gamma_mix = linear_gamma_mix, spmid = spmid, pord = pord,\
gamma = gamma, red_gamma_increase = red_gamma_increase, green_gamma_increase = green_gamma_increase, blue_gamma_increase = blue_gamma_increase, gain = 0.0, cont = 0.0)

RGBAdapt_awb =RGBAdapt_auto_awb_process( clip, show_info = show_info, \
linear_gamma_mix = linear_gamma_mix, spmid = spmid, pord = pord,\
gamma = gamma, red_gamma_increase = red_gamma_increase, green_gamma_increase = green_gamma_increase, blue_gamma_increase = blue_gamma_increase, gain = gain, cont = cont)

(comparison == false) ? RGBAdapt_awb : Stackvertical(StackHorizontal(RGBAdapt_bias.Subtitle("Balance avec " +string(round(float(linear_gamma_mix)* 100)) +" %"+" de bias seul "), \
RGBAdapt_bias_rpow_spow_default.Subtitle("Balance avec "+string(round(float(linear_gamma_mix) * 100)) +" %"+" de bias et "+" spmid = 0.5 et pord = false"),\
RGBAdapt_bias_rpow_spow.Subtitle("Balance avec "+string(round(float(linear_gamma_mix) * 100)) +" %"+" de bias et "+" spmid = " + String(spmid) + " et pord = " +string(pord))),\
StackHorizontal(Classic_awb.Subtitle("Balance auto classique (ColorYUV - autogain)"),clip.Subtitle("original"), \
RGBAdapt_bias_rpow_spow_gamma.Subtitle("Balance avec ajustage du gamma\n" + "de base : " + String(gamma) + " et une augmentation\n" + \
"dans le rouge de" + String(red_gamma_increase) + " vert : " + String(green_gamma_increase) + " bleu : " +String(blue_gamma_increase),\
lsp = 10)),\
StackHorizontal(clip.BlankClip(color=$000000), clip.BlankClip(color=$000000), RGBAdapt_awb.Subtitle("Balance avec ajustage de gain : " + String(gain) + "et de cont : " + String(cont))))
}

Bernardd
13th May 2015, 22:22
New script version. Second function to get a tuned automatic white balance.


function RGBAdapt_auto_awb_process(clip clip, bool "show_info", \
float "linear_gamma_mix", float "spmid", bool "pord",\
float "gamma", float "red_gamma_increase", float "green_gamma_increase", float "blue_gamma_increase", \
float "gain", float "cont")
{

#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #

#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #

test = isRGB(clip)
(test == false) ? ConvertToRGB24(clip, matrix="Rec601") : clip

clip = last

show_info = Default(show_info, false) # show info or not, default false

linear_gamma_mix = Default(linear_gamma_mix, 0.5) # linear curve use strength, between 0.0 and 1.0, default 0.5
Assert(linear_gamma_mix>=0.0 && linear_gamma_mix <= 1.0,"RGBAdapt_auto_awb: linear_gamma_mix 0.0 -> 1.0")
spmid = Default(spmid, 0.5) # it is original RGBADapt Channel_spmid args, range 0.1 to 0.99 center 0.5
Assert(spmid>=0.01 && spmid <= 0.99,"RGBAdapt_auto_awb: spmid 0.01 -> 0.99")
pord = Default(pord, false) # it is original RGBADapt Channel_pord args

gamma = Default(gamma, 2.2) # gamma value defintion for calcul between 1.0 and 7.0, default 2.2, neutral value 1.0
Assert(gamma>=1.0 && gamma <= 7.0,"RGBAdapt_auto_awb: gamma 1.0 -> 7.0")
red_gamma_increase = Default(red_gamma_increase, 0.0) # red gamma value adjust between 0.0 and 7.0, default = neutral = 0.0
Assert(red_gamma_increase>=0.0 && red_gamma_increase <= 7.0,"RGBAdapt_auto_awb: red_gamma_increase 0.0 -> 7.0")
green_gamma_increase = Default(green_gamma_increase, 0.0) # green gamma value adjust between 0.0 and 7.0, default = neutral = 0.0
Assert(green_gamma_increase>=0.0 && green_gamma_increase <= 7.0,"RGBAdapt_auto_awb: green_gamma_increase 0.0 -> 7.0")
blue_gamma_increase = Default(blue_gamma_increase, 0.0) # blue gamma value adjust between 0.0 and 7.0, default = neutral = 0.0
Assert(blue_gamma_increase>=0.0 && blue_gamma_increase <=7.0,"RGBAdapt_auto_awb: blue_gamma_increase 0.0 -> 7.0")

gain = Default(gain, 1.0) # it is calculated gain stength args, range -8.0 to 8.0, center 0.0
Assert(gain>=-8.0 && gain <= 8.0,"RGBAdapt_auto_awb: gain -8.0 -> 8.0")
cont = Default(cont, 1.0) # it is calculated cont stength args, range -8.0 to 8.0, center 0.0
Assert(cont>=-8.0 && gain <= 8.0,"RGBAdapt_auto_awb: gain -8.0 -> 8.0")

neutre = BlankClip( clip,pixel_type="RGB24", color=$000000)

luma = clip.Greyscale( matrix="Rec601")

red=ShowRed(clip,"RGB24")
green = ShowGreen(clip,"RGB24")
blue = ShowBlue(clip,"RGB24")

ScriptClip(clip, """

#------------ RGB values calcul

luma_value = RGBDifference(luma, neutre)

g = RGBDifference(green, neutre)
r = RGBDifference(red, neutre)
b = RGBDifference(blue,neutre)

#----------- RGB correction calcul

dr = (luma_value - r)
dg = (luma_value - g)
db = (luma_value - b)

#----------- RGB correction with linear curve calcul (Bias)

dr1_calcul = dr * linear_gamma_mix
dr1_low_limit = Max (dr1_calcul, -512)
dr1 = Min (512, dr1_low_limit)

dg1_calcul = dg * linear_gamma_mix
dg1_low_limit = Max (dg1_calcul, -512)
dg1 = Min (512, dg1_low_limit)

db1_calcul = db * linear_gamma_mix
db1_low_limit = Max (db1_calcul, -512)
db1 = Min (512, db1_low_limit)

#---------- Remaining RGB correction with gamma curves(rpow, spow)after linear curve process

dr2 = dr - dr * linear_gamma_mix
dg2 = dg - dg * linear_gamma_mix
db2 = db - db * linear_gamma_mix

#--------- Auto gamma calcul

red_gamma_increase = gamma + abs(dr2/128)*(1+0.299) + red_gamma_increase
green_gamma_increase = gamma + abs(dg2/128)*(1+0.587) + green_gamma_increase
blue_gamma_increase = gamma + abs(db2/128)*(1+0.114) + blue_gamma_increase

#----------- RGB correction with Rpow curve calcul

yr_calcul = pow(red_gamma_increase,dr2/128)
yr_low_limit = Max (yr_calcul, 0.1)
yr = Min (4.0, yr_low_limit)
yg_calcul = pow(green_gamma_increase,dg2/128)
yg_low_limit = Max (yg_calcul, 0.1)
yg = Min (4.0, yg_low_limit)
yb_calcul = pow(blue_gamma_increase,db2/128)
yb_low_limit = Max (yb_calcul, 0.1)
yb = Min (4.0, yb_low_limit)

#----------- RGB correction with Spow curve calcul

sr_calcul = pow(red_gamma_increase,dr2/128)
sr_low_limit = Max (sr_calcul, 0.1)
sr = Min (4.0, sr_low_limit)
sg_calcul = pow(green_gamma_increase,dg2/128)
sg_low_limit = Max (sg_calcul, 0.1)
sg = Min (4.0, sg_low_limit)
sb_calcul = pow(blue_gamma_increase,db2/128)
sb_low_limit = Max (sb_calcul, 0.1)
sb = Min (4.0, sb_low_limit)

#---------- Gain

gain_r = r/(r-(abs(dr1/128)+yr+sr)*gain)
gain_r = Max(Min(gain_r,8.0),-8.0)
gain_g = g/(g-(abs(dg1/128)+yg+sg)*gain)
gain_g = Max(Min(gain_g,8.0),-8.0)
gain_b = b/(b-(abs(db1/128)+yb+sb)*gain)
gain_b = Max(Min(gain_b,8.0),-8.0)

cont_r = r/(r-(abs(dr1/128)+yr+sr)*cont)
cont_r = Max(Min(gain_r,8.0),-8.0)
cont_g = g/(g-(abs(dg1/128)+yg+sg)*cont)
cont_g = Max(Min(cont_g,8.0),-8.0)
cont_b = b/(b-(abs(db1/128)+yb+sb)*cont)
cont_b = Max(Min(cont_b,8.0),-8.0)

#---------- RGBAdapt use

output_video = RGBAdapt( \
R_Bias = dr1, R_Gain = gain_r, R_Cont = cont_r, R_RPow = yr, R_Spow = sr, R_SPMid = spmid, R_Pord = pord, \
G_Bias = dg1, G_Gain = gain_g, G_Cont = cont_g, G_RPow = yg, G_Spow = sg, G_SPMid = spmid, G_Pord = pord,\
B_Bias = db1, B_Gain = gain_b, B_Cont = cont_b, B_RPow = yb, B_Spow = sb, B_SPMid = spmid, B_Pord = pord)

#-------- displayed info or no

(show_info == false)? output_video : output_video.Subtitle("Red value : "+String(r)+\
"\n Middle - Red Value : "+String(dr)+" somme : "+String(dr+dg+db)+\
"\n Bias : "+String(dr1)+\
"\n Rpow and Spow correction base : "+String(dr2)+\
"\n Rpow : "+String(yr)+" Spow : "+String(sr)+" Gamma : "+String(red_gamma_increase),y=40,lsp=20)\
.Subtitle("Green value : "+String(g)+\
"\n Middle - Green Value : "+String(dg)+\
"\n Bias : "+String(dg1)+\
"\n Gamma and S correction base : "+String(dg2)+\
"\n Rpow : "+String(yg)+" Spow : "+String(sg)+" Gamma : "+String(green_gamma_increase),y=160,lsp=20)\
.Subtitle("Blue value : "+String(b)+\
"\n Middle - Blue Value : "+String(db)+\
"\n Bias : "+String(db1)+\
"\n Gamma and S correction base : "+String(db2)+\
"\n Rpow : "+String(yb)+" Spow : "+String(sb)+" Gamma : "+String(blue_gamma_increase), y=280,lsp=20)

""", args = "show_info, neutre, red, green, blue,luma,"+\
"linear_gamma_mix, spmid, pord,"+\
"gamma, red_gamma_increase, green_gamma_increase, blue_gamma_increase,gain, cont")

(test == false) ? ConvertToYV12(last, matrix="Rec601") : last

}

Bernardd
17th May 2015, 12:49
Hi StainlessS

I apology, in my last post i have written a mistake on channel gamma increase. These variables are twice written. But it was not a big problem.
I have studied gain and cont problems with few video frames. I think that the gain overflow result of some pixels, which are maximum or minimum for channel values and this pixels are few and do not weight on medium channel values, used in script formulas.
Avisynth have not runtimefunction working in RGB with threshold like the YPlaneMax familiy. So i have deleted gain and cont lines. In the same time, i have simplified channel gamma formulas.
Thus this last version is more simple and theorical.


function RGBAdapt_auto_awb(clip clip, bool "show_info", bool "comparison",\
float "linear_gamma_mix", float "spmid", bool "pord",\
float "gamma", float "red_gamma_increase", float "green_gamma_increase", float "blue_gamma_increase")
{

show_info = Default(show_info, false) # show info or not, default false
comparison = Default(comparison, false) # show info or not, default false

linear_gamma_mix = Default(linear_gamma_mix, 0.5) # linear curve use strength, between 0.0 and 1.0, default 0.5
Assert(linear_gamma_mix>=0.0 && linear_gamma_mix <= 1.0,"RGBAdapt_auto_awb: linear_gamma_mix 0.0 -> 1.0")
spmid = Default(spmid, 0.5) # it is original RGBADapt Channel_spmid args, range 0.1 to 0.99 center 0.5
Assert(spmid>=0.01 && spmid <= 0.99,"RGBAdapt_auto_awb: spmid 0.01 -> 0.99")
pord = Default(pord, false) # it is original RGBADapt Channel_pord args

gamma = Default(gamma, 2.2) # gamma value defintion for calcul between 1.0 and 7.0, default 2.2, neutral value 1.0
Assert(gamma>=1.0 && gamma <= 7.0,"RGBAdapt_auto_awb: gamma 1.0 -> 7.0")
red_gamma_increase = Default(red_gamma_increase, 0.0) # red gamma value adjust between 0.0 and 7.0, default = neutral = 0.0
Assert(red_gamma_increase>=0.0 && red_gamma_increase <= 7.0,"RGBAdapt_auto_awb: red_gamma_increase 0.0 -> 7.0")
green_gamma_increase = Default(green_gamma_increase, 0.0) # green gamma value adjust between 0.0 and 7.0, default = neutral = 0.0
Assert(green_gamma_increase>=0.0 && green_gamma_increase <= 7.0,"RGBAdapt_auto_awb: green_gamma_increase 0.0 -> 7.0")
blue_gamma_increase = Default(blue_gamma_increase, 0.0) # blue gamma value adjust between 0.0 and 7.0, default = neutral = 0.0
Assert(blue_gamma_increase>=0.0 && blue_gamma_increase <=7.0,"RGBAdapt_auto_awb: blue_gamma_increase 0.0 -> 7.0")

Classic_awb = ColorYUV(clip.convertToYV12, autowhite = true)

RGBAdapt_bias =RGBAdapt_auto_awb_process( clip, show_info = show_info, \
linear_gamma_mix = linear_gamma_mix, spmid = 0.5, pord = false,\
gamma = 1.0, red_gamma_increase = 0.0, green_gamma_increase = 0.0, blue_gamma_increase = 0.0)

RGBAdapt_bias_rpow_spow_default =RGBAdapt_auto_awb_process( clip, show_info = show_info, \
linear_gamma_mix = linear_gamma_mix, spmid = 0.5, pord = false,\
gamma = 2.2, red_gamma_increase = 0.0, green_gamma_increase = 0.0, blue_gamma_increase = 0.0)

RGBAdapt_bias_rpow_spow =RGBAdapt_auto_awb_process( clip, show_info = show_info, \
linear_gamma_mix = linear_gamma_mix, spmid = spmid, pord = pord,\
gamma = 2.2, red_gamma_increase = 0.0, green_gamma_increase = 0.0, blue_gamma_increase = 0.0)

RGBAdapt_bias_rpow_spow_gamma =RGBAdapt_auto_awb_process( clip, show_info = show_info, \
linear_gamma_mix = linear_gamma_mix, spmid = spmid, pord = pord,\
gamma = gamma, red_gamma_increase = red_gamma_increase, green_gamma_increase = green_gamma_increase, blue_gamma_increase = blue_gamma_increase)

RGBAdapt_awb =RGBAdapt_auto_awb_process( clip, show_info = show_info, \
linear_gamma_mix = linear_gamma_mix, spmid = spmid, pord = pord,\
gamma = gamma, red_gamma_increase = red_gamma_increase, green_gamma_increase = green_gamma_increase, blue_gamma_increase = blue_gamma_increase)

(comparison == false) ? RGBAdapt_awb : Stackvertical(StackHorizontal(RGBAdapt_bias.Subtitle("AWB with " +string(round(float(linear_gamma_mix)* 100)) +" %"+" of only bias "), \
RGBAdapt_bias_rpow_spow_default.Subtitle("AWB with "+string(round(float(linear_gamma_mix) * 100)) +" %"+" of bias and "+" spmid = 0.5, pord = false and gamma = 2.2"),\
RGBAdapt_bias_rpow_spow.Subtitle("AWB with "+string(round(float(linear_gamma_mix) * 100)) +" %"+" of bias and "+" spmid = " + String(spmid) + " , pord = " +string(pord)+ " and gamma = 2.2")),\
StackHorizontal(Classic_awb.Subtitle("Classix AWB (ColorYUV - autogain)"),clip.Subtitle("original"), \
RGBAdapt_bias_rpow_spow_gamma.Subtitle("AWB with tunned gamma\n" + "of ground : " + String(gamma) + " and with increase\n" + \
"in red channel" + String(red_gamma_increase) + " green : " + String(green_gamma_increase) + " blue : " +String(blue_gamma_increase),\
lsp = 10)))
}

function RGBAdapt_auto_awb_process(clip clip, bool "show_info", \
float "linear_gamma_mix", float "spmid", bool "pord",\
float "gamma", float "red_gamma_increase", float "green_gamma_increase", float "blue_gamma_increase")
{

#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #

#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #

test = isRGB(clip)
(test == false) ? ConvertToRGB24(clip, matrix="Rec601") : clip

clip = last

neutre = BlankClip( clip,pixel_type="RGB24", color=$000000)

red=ShowRed(clip,"RGB24")
green = ShowGreen(clip,"RGB24")
blue = ShowBlue(clip,"RGB24")

ScriptClip(clip, """

#------------ RGB values calcul

r = RGBDifference(red, neutre)
g = RGBDifference(green, neutre)
b = RGBDifference(blue,neutre)
middle_value = (r+g+b)/3

#----------- RGB correction calcul

dr = (middle_value - r)
dg = (middle_value - g)
db = (middle_value - b)

#----------- RGB correction with linear curve calcul (Bias)

dr1_calcul = dr * linear_gamma_mix
dr1_low_limit = Max (dr1_calcul, -512)
dr1 = Min (512, dr1_low_limit)

dg1_calcul = dg * linear_gamma_mix
dg1_low_limit = Max (dg1_calcul, -512)
dg1 = Min (512, dg1_low_limit)

db1_calcul = db * linear_gamma_mix
db1_low_limit = Max (db1_calcul, -512)
db1 = Min (512, db1_low_limit)

#---------- Remaining RGB correction with gamma curves(rpow, spow)after linear curve process

dr2 = dr - dr * linear_gamma_mix
dg2 = dg - dg * linear_gamma_mix
db2 = db - db * linear_gamma_mix

#--------- Auto gamma calcul

red_gamma = gamma + red_gamma_increase
green_gamma = gamma + green_gamma_increase
blue_gamma = gamma + blue_gamma_increase

#----------- RGB correction with Rpow curve calcul

yr_calcul = pow(red_gamma,dr2/128)
yr_low_limit = Max (yr_calcul, 0.1)
yr = Min (4.0, yr_low_limit)
yg_calcul = pow(green_gamma,dg2/128)
yg_low_limit = Max (yg_calcul, 0.1)
yg = Min (4.0, yg_low_limit)
yb_calcul = pow(blue_gamma,db2/128)
yb_low_limit = Max (yb_calcul, 0.1)
yb = Min (4.0, yb_low_limit)

#----------- RGB correction with Spow curve calcul

sr_calcul = pow(red_gamma,dr2/128)
sr_low_limit = Max (sr_calcul, 0.1)
sr = Min (4.0, sr_low_limit)
sg_calcul = pow(green_gamma,dg2/128)
sg_low_limit = Max (sg_calcul, 0.1)
sg = Min (4.0, sg_low_limit)
sb_calcul = pow(blue_gamma,db2/128)
sb_low_limit = Max (sb_calcul, 0.1)
sb = Min (4.0, sb_low_limit)

#---------- RGBAdapt use

output_video = RGBAdapt( \
R_Bias = dr1, R_Gain = 1.0, R_Cont = 1.0, R_RPow = yr, R_Spow = sr, R_SPMid = spmid, R_Pord = pord, \
G_Bias = dg1, G_Gain = 1.0, G_Cont = 1.0, G_RPow = yg, G_Spow = sg, G_SPMid = spmid, G_Pord = pord,\
B_Bias = db1, B_Gain = 1.0, B_Cont = 1.0, B_RPow = yb, B_Spow = sb, B_SPMid = spmid, B_Pord = pord)

#-------- displayed info or no

(show_info == false)? output_video : output_video.Subtitle("Red value : "+String(r)+" Middle_value "+String(middle_value)+\
"\nMiddle - Red Values Diff : "+String(dr)+\
"\nBias : "+String(dr1)+\
"\nRpow and Spow correction base : "+String(dr2)+" Gamma : "+String(gamma)+\
"\n Rpow : "+String(yr)+" Spow : "+String(sr)+" Red Gamma increase : "+String(red_gamma_increase),y=40,lsp=20)\
.Subtitle("Green value : "+String(g)+\
"\nMiddle - Green Values Diff : "+String(dg)+\
"\nBias : "+String(dg1)+\
"\nRpow and Spow correction base : "+String(dg2)+" Gamma : "+String(gamma)+\
"\n Rpow : "+String(yg)+" Spow : "+String(sg)+" Green Gamma increase : "+String(green_gamma_increase),y=160,lsp=20)\
.Subtitle("Blue value : "+String(b)+\
"\nMiddle - Blue Values Diff : "+String(db)+\
"\nBias : "+String(db1)+\
"\nRpow and Spow correction base : "+String(db2)+" Gamma : "+String(gamma)+\
"\nRpow : "+String(yb)+" Spow : "+String(sb)+" Blue Gamma increase : "+String(blue_gamma_increase), y=280,lsp=20)

""", args = "show_info, neutre, red, green, blue,"+\
"linear_gamma_mix, spmid, pord,"+\
"gamma, red_gamma_increase, green_gamma_increase, blue_gamma_increase")

(test == false) ? ConvertToYV12(last, matrix="Rec601") : last

}

StainlessS
17th May 2015, 18:07
Avisynth have not runtimefunction working in RGB with threshold like the YPlaneMax familiy

I guess you could extract RGB channels to Y8/YV12-Y and process using eg YPlaneMax, OR below would work but would mean an extra plugin requirement
(there are also single function versions instead of the multi-function one below).


RT_RgbChanStats(clip c,int "n"=current_frame,int "delta"=0,int "x"=0,int "y"=0,int "w"=0,int "h"=0,bool "interlaced"=false,
float "threshold"=0.0,int "chan"=0,int "lo"=128,int "hi"=lo,int "flgs"=255,string "prefix"="RCS_",
float "mu"=0.0,int "d"=1,int "p"=1,int "u"=1,int "mask"=NOT_USED, int "MaskMin"=128,"MaskMax"=255)
Returns multiple results as for above single frame RGB channel sampling functions as Local Variables (prefixed with the prefix string arg).
The args up to "interlaced", are as for all other clip functions, "threshold" used only for "RT_RgbChanMin", "RT_RgbChanMax" and
"RT_RgbChanMinMaxDifference" equivalent routines with same functionality.
"lo" and "hi" are used only with the "RT_RgbChanInRange" equivalent routine with same functionality.
"mu" and "d" and "p" and "u" are used only with the "RT_RgbChanPNorm" equivalent routine with same functionality.
The new arg "Flgs" selects which results you want returned and the string "Prefix" that is prepended
to the returned Local variable names.
The actual return result is a copy of the flgs args with any non valid bits reset, ie the Local variables that were set.
Local variables are NOT altered for any function not selected in flgs.
Returns 0 if no pixels found in search area of mask within MaskMin and MaskMax.

Flgs_Bit_Number Add_To_Flgs Equivalent_Function Local_Var_Set_Excluding_Prefix_and_Chan_postfix
0 1($01) RT_RgbChanMin() "Min" (0->255)
1 2($02) RT_RgbChanMax() "Max" (0->255)
2 4($04) RT_RgbChanMinMaxDifference() "MinMaxDiff" (0->255)
3 8($08) RT_RgbChanMedian() "Med" (0->255)
4 16($10) RT_RgbChanAve() "Ave" (0.0->255.0)
5 32($20) RT_RgbChanStdev() "Stdev" (0.0->255.0)
6 64($40) RT_RgbChanInRange() "InRng" (0.0->1.0)
7 128($80) RT_RgbChanPNorm() "PNorm" (0.0->??? depends upon d and u)
The Channel Postfix is of the form "_0", where 0 is RED, 1 is GREEN and 2 is Blue, 3 is ALPHA(RGB32 ONLY), and is appended to the
base name described above. So eg RT_RgbChanMin for RED channel 0 with default Prefix is "RCS_Min_0".
RT_RgbChanstats() allows you to inquire multiple results simultaneously, with not much more overhead than calling a single individual
routine, however, you should not select sub functions that you dont need as there may be an additional unnecessary overhead.
The Default flgs=255($FF) are all bits set and so sets ALL Local vars at once.
RT_RgbChanStats(flgs=1+2+16) would set Local vars "RCS_Min_0", "RCS_Max_0" and "RCS_Ave_0" for full frame current_frame, Red Channel.

In addition to above Local Variables, RT_RgbChanStats() sets an int Local variable (where default prefix) of "RCS_PixelCount_0" being
the number of Red Channel pixels in mask area X,Y,W,H between MaskMin and MaskMax inclusive.

NOTE, RT_RgbChanStats() allows Chan to be -1, where ALL three R, and G, and B channels are processed simultaneouly for ALL functions
selected by flgs arg (ALPHA Channel is NOT processed).
A chan arg of -2 (RGB32 ONLY allowed) will additionally process the ALPHA channel as well as R+G+B.
Also Note, (where default Prefix) RCS_PixelCount_x is also set (identically) for all channels when Chan == -1 or -2.
NOTE, If no valid flg bits set (eg $FF00), then returns 0, RCS_PixelCount_x and all other variables remain as before call.
Assuming some valid flg bits, if no valid pixels were found in mask then function returns 0, and only RCS_PixelCount_x would be set
to 0, no other variables are touched (remain as before call, undefined if not previously existing).
Example usage:
ScriptClip("""
got = RT_RgbChanStats(c,mask=Mask,chan=-1,flgs=$10) # Ave
(got != 0)
\ ? RT_Debug(RT_String("AveR = %f AveG = %f AveB = %f Pixels = %d",RCS_Ave_0,RCS_Ave_1,RCS_Ave_2,RCS_PixelCount_0))
\ : RT_Debug("NO VALID PIXELS FOUND")
""")



EDIT: And one of the single function versions

RT_RgbChanMax(clip c,int "n"=current_frame,int "delta"=0,int "x"=0,int "y"=0,int "w"=0,int "h"=0,
bool "interlaced"=false,float "threshold"=0.0,
int "chan"=0,int "mask"=NOT_USED, int "MaskMin"=128,"MaskMax"=255)
Return int -1, if no valid pixels in Mask clip.
Returns int maximum value (0 -> 255) in frame(n+delta) for area x,y,w,h, and selected Chan channel (0=R,1=G,2=B, RGB32 3=ALPHA)
Threshold is a percentage, stating how many percent of the pixels are allowed above maximum (ignore extreme pixels ie noise).
Threshold is % of valid mask pixels processed. The threshold is optional and defaults to 0.0.


and a bit more

The compiletime/runtime clip functions share some common characteristics.
The 'n' and (where used) 'n2' args are the optional frame numbers and default to 'current_frame' if not specified.
The x,y,w,h, coords specify the source rectangle under scrutiny and are specified as for Crop(), the default 0,0,0,0 is full frame.
If 'interlaced' is true, then every other line is ommited from the scan, so if eg x=0,y=1, then scanlines 1,3,5,7 etc are scanned,
if eg x=0,y=4 then scanlines 4,6,8,10 etc are scanned. The 'h' coord specifies the full height scan ie same whether interlaced is true
or false, although it will not matter if the 'h' coord is specified as eg odd or even, internally the height 'h' is reduced by 1 when
interlaced=true and 'h' is even.

Optional mask clip Planar ONLY [v2.6 colorpspaces OK]
The Planar mask clip, governs which pixels are processed by the functions. Where a luma pixel in selected area of the the mask clip is
in range "MaskMin" to "MaskMax" inclusive, then those pixels will be processed.
Mask MUST, be same dimensions and have at least the same number of frames as clip c.
Calling without mask OR with MaskMin=0,MaskMax=255 will effectively ignore the mask and scan full x,y,w,h area.

The Chan arg specifies which R or G or B channel to process [the multi-functional RT_RgbChanStats() function also allows a Chan arg of -1,
which processes R and G and B simulaneously for all functions selected by flgs arg, also allowed is chan arg of -2 which additionally
processes the ALPHA channel if RGB32 but throws an error if RGB24].
Default Chan is 0 (Red), 1 = Green, 2=Blue channel and 3=ALPHA channel when RGB32 ONLY else error.

Bernardd
17th May 2015, 23:14
Stainlesss thank you ,

Today, i do not know really good whether to mix AWB function and Autogain function, because these are two problems with some different entry datas. To make autogain, there are several plugins, including SmoothAdjust, which has an interframe analysis.

I fear also lose data during convertions YUV to RGB and back.

But your development ideas worth exploring. So I left for a year of study.

Thanks

Bernardd
27th May 2015, 18:38
Hello,

I have written a new version of RGBAdapt half automatic use script. It use now Average Luma, AverageChromaU and AverageChromaV values like inputs. The RGB values are done with these formulas
r = y + 2*(v-128)*(1-Kr)
g = y - 2*(u-128)*(1-Kb)*Kb/Kg - 2*(v-128)*(1-Kr)*Kr/Kg
b = y + 2*(u-128)*(1-Kb)

The RGBAdapt white balance with only bias is not the same but very near from ColorYUV white balance. I need advice to explain that. Perhaps are the formulas no good for Rec 601 conversion ?

But this formulas give some good results, the RGBAdapt gamma curve automatic white balance is perhaps a good alternative to CorlorYUV autowhite.




function RGBAdapt_auto_awb(clip clip, bool "show_info", bool "comparison", bool "matrix", float "linear_gamma_mix", float "spmid", bool "pord", float "gamma")

{

standart = (matrix == false) ? "Rec601" : "Rec709"

show_info = Default(show_info, false) # show info or not, default false
comparison = Default(comparison, false) # show info or not, default false
matrix = Default(matrix, false) # Color standart, false = Rec 601, true = Rec 709

linear_gamma_mix = Default(linear_gamma_mix, 0.5) # linear curve use strength, between 0.0 and 1.0, default 0.5
Assert(linear_gamma_mix>=0.0 && linear_gamma_mix <= 1.0,"RGBAdapt_auto_awb: linear_gamma_mix 0.0 -> 1.0")
spmid = Default(spmid, 0.5) # it is original RGBADapt Channel_spmid args, range 0.1 to 0.99 center 0.5
Assert(spmid>=0.01 && spmid <= 0.99,"RGBAdapt_auto_awb: spmid 0.01 -> 0.99")
pord = Default(pord, false) # it is original RGBADapt Channel_pord args

gamma = Default(gamma, 2.2) # gamma value defintion for calcul between 1.0 and 15.0, default 2.2, neutral value 1.0
Assert(gamma>=0.1 && gamma <= 15.0,"RGBAdapt_auto_awb: gamma 1.0 -> 15.0")

clip_yuv = ( isYV12(clip)== false) ? ConvertToYV12(clip, matrix=standart) : clip

Classic_awb = ColorYUV(clip_yuv, autowhite = true).ColorYUV( analyze = true)

Classic_awb = (isYV12(clip) == false) ? ConvertToRGB(Classic_awb, matrix=standart) : Classic_awb

RGBAdapt_bias =RGBAdapt_auto_awb_process( clip, show_info = show_info, matrix = matrix, linear_gamma_mix = linear_gamma_mix, spmid = 0.5, pord = false, gamma = 1.0)#.ColorYUV( analyze = true)

RGBAdapt_bias_rpow_spow_default =RGBAdapt_auto_awb_process( clip, show_info = show_info, matrix = matrix, linear_gamma_mix = linear_gamma_mix, spmid = 0.5, pord = false, gamma = 2.2)

RGBAdapt_bias_rpow_spow =RGBAdapt_auto_awb_process( clip, show_info = show_info, matrix = matrix, linear_gamma_mix = linear_gamma_mix, spmid = spmid, pord = pord, gamma = 2.2)

RGBAdapt_bias_rpow_spow_gamma =RGBAdapt_auto_awb_process( clip, show_info = show_info, matrix = matrix, linear_gamma_mix = linear_gamma_mix, spmid = spmid, pord = pord, gamma = gamma)

(comparison == false) ? RGBAdapt_bias_rpow_spow_gamma : Stackvertical(StackHorizontal(RGBAdapt_bias.Subtitle("Balance avec " +string(round(float(linear_gamma_mix)* 100)) +" %"+" de bias seul et gamma = 1.0"), \
RGBAdapt_bias_rpow_spow_default.Subtitle("Balance avec "+string(round(float(linear_gamma_mix) * 100)) +" %"+" de bias et "+" spmid = 0.5, pord = false et gamma = 2.2"),\
RGBAdapt_bias_rpow_spow.Subtitle("Balance avec "+string(round(float(linear_gamma_mix) * 100)) +" %"+" de bias et "+" spmid = " + String(spmid) + " , pord = " +string(pord)+ " et gamma = 2.2")),\
StackHorizontal(Classic_awb.Subtitle("Balance auto classique (ColorYUV - autogain)"),clip.Subtitle("original"), \
RGBAdapt_bias_rpow_spow_gamma.Subtitle("Balance avec ajustage du gamma" + "de base : " + String(gamma))))
}

function RGBAdapt_auto_awb_process(clip clip, bool "show_info", bool "matrix", float "linear_gamma_mix", float "spmid", bool "pord", float "gamma")
{

#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #

#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #

standart = (matrix == false) ? "Rec601" : "Rec709"

show_info = Default(show_info, false) # show info or not, default false
matrix = Default(matrix, false) # Color standart, false = Rec 601, true = Rec 709

linear_gamma_mix = Default(linear_gamma_mix, 0.5) # linear curve use strength, between 0.0 and 1.0, default 0.5
Assert(linear_gamma_mix>=0.0 && linear_gamma_mix <= 1.0,"RGBAdapt_auto_awb: linear_gamma_mix 0.0 -> 1.0")
spmid = Default(spmid, 0.5) # it is original RGBADapt Channel_spmid args, range 0.1 to 0.99 center 0.5
Assert(spmid>=0.01 && spmid <= 0.99,"RGBAdapt_auto_awb: spmid 0.01 -> 0.99")
pord = Default(pord, false) # it is original RGBADapt Channel_pord args

gamma = Default(gamma, 2.2) # gamma value defintion for calcul between 1.0 and 15.0, default 2.2, neutral value 1.0
Assert(gamma>=0.1 && gamma <= 15.0,"RGBAdapt_auto_awb: gamma 1.0 -> 15.0")

ScriptClip(clip, """

clip = last

#------------ Color matrix input
standart = (matrix == false) ? "Rec601" : "Rec709"
Kr = (matrix == false) ? 0.299 : 0.2126
Kg = (matrix == false) ? 0.587 : 0.7152
Kb = (matrix == false) ? 0.114 : 0.0722

#------------ YUV values extraction

(isYV12(clip) == false) ? ConvertToYV12(clip, matrix=standart) : clip

y = AverageLuma()
u = AverageChromaU()
v = AverageChromaV()

#------------ RGB values calcul

r = y + 2*(v-128)*(1-Kr)
g = y - 2*(u-128)*(1-Kb)*Kb/Kg - 2*(v-128)*(1-Kr)*Kr/Kg
b = y + 2*(u-128)*(1-Kb)

#----------- RGB corrections calcul

dr = - 2*(v-128)*(1-Kr) # in YUV range correction is 128 - channel value, in RGB range correction is luma - channel value
db = - 2*(u-128)*(1-Kb)
dg = - db*Kb/Kg - dr*Kr/Kg

#----------- RGB correction with classic linear curve calcul (Bias)

dr1 = dr * linear_gamma_mix
dg1 = dg * linear_gamma_mix
db1 = db * linear_gamma_mix

#---------- Remaining RGB correction after classic linear curve process

dr2 = dr - dr * linear_gamma_mix
dg2 = dg - dg * linear_gamma_mix
db2 = db - db * linear_gamma_mix

#----------- RGB correction with Rpow curve calcul

yr = pow(gamma,dr2/128)
yr = Min (4.0, Max (yr, 0.1))
yg = pow(gamma,dg2/128)
yg = Min (4.0, Max (yg, 0.1))
yb = pow(gamma,db2/128)
yb = Min (4.0, Max (yb, 0.1))

#----------- RGB correction with Spow curve calcul

sr = pow(gamma,dr2/128)
sr = Min (4.0, Max (sr, 0.1))
sg = pow(gamma,dg2/128)
sg = Min (4.0, Max (sg, 0.1))
sb = pow(gamma,db2/128)
sb = Min (4.0, Max (sb, 0.1))

#--------- Gain

gain_r = kr*dr/(r)
gain_g = (-db/(b))*Kb/Kg - (dr/(r))*Kr/Kg
gain_b = kb*db/(b)
cont_r = 0
cont_g = 0
cont_b = 0

#---------- RGBAdapt use

(isRGB(clip) == false) ? ConvertToRGB24(last, matrix=standart) : clip

output_video = RGBAdapt( \
R_Bias = dr1, R_Gain = 1.0 + gain_r, R_Cont = 1.0 + cont_r, R_RPow = yr, R_Spow = sr, R_SPMid = spmid, R_Pord = pord, \
G_Bias = dg1, G_Gain = 1.0 + gain_g, G_Cont = 1.0 + cont_g, G_RPow = yg, G_Spow = sg, G_SPMid = spmid, G_Pord = pord,\
B_Bias = db1, B_Gain = 1.0 + gain_b, B_Cont = 1.0 + cont_b, B_RPow = yb, B_Spow = sb, B_SPMid = spmid, B_Pord = pord)

output_video = (isRGB(clip) == false) ? ConvertToYV12(output_video, matrix=standart) : output_video


#-------- displayed info or no

(show_info == false)? output_video : output_video.Subtitle("Red value : "+String(r)+" Luma value "+String(y)+\
"\nMiddle - Red Values Diff : "+String(dr)+\
"\nClassic linear correction : "+String(dr1)+\
"\nSmart luma chroma correction base : "+String(dr2)+\
"\ngain : " + String(gain_r) + " Rpow : "+String(yr)+" Spow : "+String(sr),y=40,lsp=20)\
.Subtitle("Green value : "+String(g)+\
"\nMiddle - Green Values Diff : "+String(dg)+\
"\nClassic linear correction : "+String(dg1)+\
"\nSmart luma chroma correction base : "+String(dg2)+\
"\ngain : " + String(gain_g) + " Rpow : "+String(yg)+" Spow : "+String(sg),y=160,lsp=20)\
.Subtitle("Blue value : "+String(b)+\
"\nMiddle - Blue Values Diff : "+String(db)+\
"\nClassic linear correction : "+String(db1)+\
"\nSmart luma chroma correction base : "+String(db2)+\
"\ngain : " + String(gain_b) + " Rpow : "+String(yb)+" Spow : "+String(sb)+ " Gamma : "+String(gamma), y=280,lsp=20)

""", args = "show_info, matrix,linear_gamma_mix, spmid, pord, gamma, standart")

}

StainlessS
27th May 2015, 20:13
Hi Bernardd.

Your script is not working correctly, try a 16->235 range clip with good distribution between those limits, and after your script do a

Histogram(mode="levels")

and you will see a compressed range, about 16+8 -> 235-8.
Remember your average Y is based off 16 (TV levels) and RGB off 0.
(previous script was likewise compressed range result, but looked quite good).

Have made a few changes to your script, I hate trying to read un-formated code so I have formatted.
Have added missing Float() to float default args.
Commented out one standart line, not necessary (and moved standart comparison till after Default matrix processing).
Changed

standart = (matrix == false) ? "Rec601" : "Rec709"

TO

standart = (!matrix) ? "Rec601" : "Rec709"


Line wrapped some lines to appear better on D9.

Here:

Function RGBAdapt_auto_awb(clip clip, bool "show_info", bool "comparison", bool "matrix", float "linear_gamma_mix",
\ float "spmid", bool "pord", float "gamma")
{
show_info = Default(show_info, false) # show info or not, default false
comparison = Default(comparison, false) # show info or not, default false
matrix = Default(matrix, false) # Color standart, false = Rec 601, true = Rec 709

linear_gamma_mix = Float(Default(linear_gamma_mix, 0.5)) # linear curve use strength, between 0.0 and 1.0, default 0.5
Assert(linear_gamma_mix>=0.0 && linear_gamma_mix <= 1.0,"RGBAdapt_auto_awb: linear_gamma_mix 0.0 -> 1.0")
spmid = Float(Default(spmid, 0.5)) # it is original RGBADapt Channel_spmid args, range 0.1 to 0.99 center 0.5
Assert(spmid>=0.01 && spmid <= 0.99,"RGBAdapt_auto_awb: spmid 0.01 -> 0.99")
pord = Default(pord, false) # it is original RGBADapt Channel_pord args

gamma = Float(Default(gamma, 2.2)) # gamma value defintion for calcul between 1.0 and 15.0, default 2.2, neutral value 1.0
Assert(gamma>=0.1 && gamma <= 15.0,"RGBAdapt_auto_awb: gamma 1.0 -> 15.0")

standart = (!matrix) ? "Rec601" : "Rec709"

clip_yuv = ( isYV12(clip)== false) ? ConvertToYV12(clip, matrix=standart) : clip

Classic_awb = ColorYUV(clip_yuv, autowhite = true).ColorYUV( analyze = true)

Classic_awb = (isYV12(clip) == false) ? ConvertToRGB(Classic_awb, matrix=standart) : Classic_awb

RGBAdapt_bias =RGBAdapt_auto_awb_process(clip, show_info=show_info, matrix=matrix, linear_gamma_mix=linear_gamma_mix, spmid=0.5,
\ pord=false,gamma=1.0) #.ColorYUV( analyze = true)

RGBAdapt_bias_rpow_spow_default =RGBAdapt_auto_awb_process( clip, show_info=show_info, matrix=matrix, linear_gamma_mix=linear_gamma_mix,
\ spmid=0.5, pord=false, gamma=2.2)

RGBAdapt_bias_rpow_spow =RGBAdapt_auto_awb_process( clip, show_info=show_info, matrix=matrix, linear_gamma_mix=linear_gamma_mix,
\ spmid=spmid, pord=pord, gamma=2.2)

RGBAdapt_bias_rpow_spow_gamma =RGBAdapt_auto_awb_process( clip, show_info=show_info, matrix=matrix, linear_gamma_mix=linear_gamma_mix,
\ spmid=spmid, pord=pord, gamma=gamma)

(comparison == false)
\ ? RGBAdapt_bias_rpow_spow_gamma
\ : Stackvertical(StackHorizontal(RGBAdapt_bias.Subtitle("Balance avec " +string(round(float(linear_gamma_mix)* 100)) +
\ " %"+" de bias seul et gamma = 1.0"),
\ RGBAdapt_bias_rpow_spow_default.Subtitle("Balance avec "+string(round(float(linear_gamma_mix) * 100)) +
\ " %"+" de bias et "+" spmid = 0.5, pord = false et gamma = 2.2"),
\ RGBAdapt_bias_rpow_spow.Subtitle("Balance avec "+string(round(float(linear_gamma_mix) * 100)) +
\ " %"+" de bias et "+" spmid = " + String(spmid) + " , pord = " +string(pord)+ " et gamma = 2.2")),
\ StackHorizontal(Classic_awb.Subtitle("Balance auto classique (ColorYUV - autogain)"),clip.Subtitle("original"),
\ RGBAdapt_bias_rpow_spow_gamma.Subtitle("Balance avec ajustage du gamma" + "de base : " + String(gamma))))
}

Function RGBAdapt_auto_awb_process(clip clip, bool "show_info", bool "matrix", float "linear_gamma_mix", float "spmid",
\ bool "pord", float "gamma")
{
#----------------------------------------------based on RGBADapt plugin ------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.ph...86#post1681286 #
#---------------------------------------------------------------------------------------------------------------------------------- #

#---------------------------------------------- need GRunT plugin ------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.ph...83#post1157083 #
#---------------------------------------------------------------------------------------------------------------------------------- #

show_info = Default(show_info, false) # show info or not, default false
matrix = Default(matrix, false) # Color standart, false = Rec 601, true = Rec 709
linear_gamma_mix = Float(Default(linear_gamma_mix, 0.5)) # linear curve use strength, between 0.0 and 1.0, default 0.5
Assert(linear_gamma_mix>=0.0 && linear_gamma_mix <= 1.0,"RGBAdapt_auto_awb: linear_gamma_mix 0.0 -> 1.0")
spmid = Float(Default(spmid, 0.5)) # it is original RGBADapt Channel_spmid args, range 0.1 to 0.99 center 0.5
Assert(spmid>=0.01 && spmid <= 0.99,"RGBAdapt_auto_awb: spmid 0.01 -> 0.99")
pord = Default(pord, false) # it is original RGBADapt Channel_pord args
gamma = Float(Default(gamma, 2.2)) # gamma value defintion for calcul between 1.0 and 15.0, default 2.2, neutral value 1.0
Assert(gamma>=0.1 && gamma <= 15.0,"RGBAdapt_auto_awb: gamma 1.0 -> 15.0")

standart = (!matrix) ? "Rec601" : "Rec709"

ScriptClip(clip, """

clip = last

#------------ Color matrix input
# standart = (matrix == false) ? "Rec601" : "Rec709"

Kr = (matrix == false) ? 0.299 : 0.2126
Kg = (matrix == false) ? 0.587 : 0.7152
Kb = (matrix == false) ? 0.114 : 0.0722

#------------ YUV values extraction

(isYV12(clip) == false) ? ConvertToYV12(clip, matrix=standart) : clip

y = AverageLuma()
u = AverageChromaU()
v = AverageChromaV()

#------------ RGB values calcul

r = y + 2*(v-128)*(1-Kr)
g = y - 2*(u-128)*(1-Kb)*Kb/Kg - 2*(v-128)*(1-Kr)*Kr/Kg
b = y + 2*(u-128)*(1-Kb)

#----------- RGB corrections calcul

dr = - 2*(v-128)*(1-Kr) # in YUV range correction is 128 - channel value, in RGB range correction is luma - channel value
db = - 2*(u-128)*(1-Kb)
dg = - db*Kb/Kg - dr*Kr/Kg

#----------- RGB correction with classic linear curve calcul (Bias)

dr1 = dr * linear_gamma_mix
dg1 = dg * linear_gamma_mix
db1 = db * linear_gamma_mix

#---------- Remaining RGB correction after classic linear curve process

dr2 = dr - dr * linear_gamma_mix
dg2 = dg - dg * linear_gamma_mix
db2 = db - db * linear_gamma_mix

#----------- RGB correction with Rpow curve calcul

yr = pow(gamma,dr2/128)
yr = Min (4.0, Max (yr, 0.1))
yg = pow(gamma,dg2/128)
yg = Min (4.0, Max (yg, 0.1))
yb = pow(gamma,db2/128)
yb = Min (4.0, Max (yb, 0.1))

#----------- RGB correction with Spow curve calcul

sr = pow(gamma,dr2/128)
sr = Min (4.0, Max (sr, 0.1))
sg = pow(gamma,dg2/128)
sg = Min (4.0, Max (sg, 0.1))
sb = pow(gamma,db2/128)
sb = Min (4.0, Max (sb, 0.1))

#--------- Gain

gain_r = kr*dr/(r)
gain_g = (-db/(b))*Kb/Kg - (dr/(r))*Kr/Kg
gain_b = kb*db/(b)
cont_r = 0
cont_g = 0
cont_b = 0

#---------- RGBAdapt use

(isRGB(clip) == false) ? ConvertToRGB24(last, matrix=standart) : clip

output_video = RGBAdapt(
\ R_Bias = dr1, R_Gain = 1.0 + gain_r, R_Cont = 1.0 + cont_r, R_RPow = yr, R_Spow = sr, R_SPMid = spmid, R_Pord = pord,
\ G_Bias = dg1, G_Gain = 1.0 + gain_g, G_Cont = 1.0 + cont_g, G_RPow = yg, G_Spow = sg, G_SPMid = spmid, G_Pord = pord,
\ B_Bias = db1, B_Gain = 1.0 + gain_b, B_Cont = 1.0 + cont_b, B_RPow = yb, B_Spow = sb, B_SPMid = spmid, B_Pord = pord)

output_video = (isRGB(clip) == false) ? ConvertToYV12(output_video, matrix=standart) : output_video

#-------- displayed info or no

(show_info == false)
\ ? output_video
\ : output_video.Subtitle("Red value : "+String(r)+" Luma value "+String(y)+
\ "\nMiddle - Red Values Diff : "+String(dr)+
\ "\nClassic linear correction : "+String(dr1)+
\ "\nSmart luma chroma correction base : "+String(dr2)+
\ "\ngain : " + String(gain_r) + " Rpow : "+String(yr)+" Spow : "+String(sr),y=40,lsp=20)
\ .Subtitle("Green value : "+String(g)+
\ "\nMiddle - Green Values Diff : "+String(dg)+
\ "\nClassic linear correction : "+String(dg1)+
\ "\nSmart luma chroma correction base : "+String(dg2)+
\ "\ngain : " + String(gain_g) + " Rpow : "+String(yg)+" Spow : "+String(sg),y=160,lsp=20)
\ .Subtitle("Blue value : "+String(b)+
\ "\nMiddle - Blue Values Diff : "+String(db)+
\ "\nClassic linear correction : "+String(db1)+
\ "\nSmart luma chroma correction base : "+String(db2)+
\ "\ngain : " + String(gain_b) + " Rpow : "+String(yb)+" Spow : "+String(sb)+ " Gamma : "+String(gamma), y=280,lsp=20)

""", args = "show_info, matrix,linear_gamma_mix, spmid, pord, gamma, standart")
}

Bernardd
27th May 2015, 21:46
Hi StainlessS,

You have a great script writter eye. Sorry for the bug ; standart comparison before Default matrix processing. I apologize
You have a great expert process eye. I try to change matrix choice in PC601 an PC709. I do not observe compressed range. Do you approve this solution ?

StainlessS
27th May 2015, 22:33
I apologize

Dont be silly, no apologies at all necessary.

There were I think another couple of (xxx == false) comparisons that I forgot to point out, -> (!xxx).

Dont know what the solution to YUV RGB matching would be best, my maths is rubbish and would take me quite some time to figure
out exactly what your script is doing and how best to correct. There are many other on-site that would be able to point you in right direction there.
(I tried doing a ColorYUV(levels="TV->PC) beforehand and it still produced similar compressed results).

As it happens, I am trying to correct a clip right now, tried your script, abandoned. Tried AutoAdjust, abandoned (yours was better).
and now using Martin53 AWB(), best of all, using that.

Good luck, hope you get it sorted.

Bernardd
1st June 2015, 18:34
Hi StainlessS,

Luma compressed range is not a bug result by my script. RGBAdapt in accordance with RGBAdjust give this result. I have tried, in RGBAdjust, increase any arg, like bias for example, the luma spectre move to right and is compressed.

The luma variation must be compensated with a second pass.

StainlessS
1st June 2015, 19:27
The luma variation must be compensated with a second pass.

OK, thank you.

I think cont args in RgbAdapt could allow for luma range adjustment but I dont really understand your mixture of YUV and RGB.
I would like to see Martin53 (or someone else) take his AWB script and perfect it, hope he comes back one day (armed with his new CPP skill set).
I think AWB also produces luma compressed range.

Gavino
1st June 2015, 22:46
I have written a new version of RGBAdapt half automatic use script. It use now Average Luma, AverageChromaU and AverageChromaV values like inputs. The RGB values are done with these formulas
r = y + 2*(v-128)*(1-Kr)
g = y - 2*(u-128)*(1-Kb)*Kb/Kg - 2*(v-128)*(1-Kr)*Kr/Kg
b = y + 2*(u-128)*(1-Kb)
Your script is not working correctly, try a 16->235 range clip with good distribution between those limits, and after your script [...] you will see a compressed range, about 16+8 -> 235-8.
Remember your average Y is based off 16 (TV levels) and RGB off 0.
Bernardd's formulas assume conversion to RGB [0,255] from YUV [0,255].
If converting from the standard luma [16,235] and chroma [16,240], they need to be:
r = (y-16)*255.0/219 + 2*(v-128)*255.0/224*(1-Kr)
g = (y-16)*255.0/219 - 2*(u-128)*255.0/224*(1-Kb)*Kb/Kg - 2*(v-128)*255.0/224*(1-Kr)*Kr/Kg
b = (y-16)*255.0/219 + 2*(u-128)*255.0/224*(1-Kb)

For example, see http://avisynth.nl/index.php/Color_conversions.

StainlessS
2nd June 2015, 02:56
Thank you big G

I think I could have got the "(y-16)*255.0/219" bit, but the "255.0/224*" stuff would have taken some eons longer.

Dont be such a stranger :)

Bernardd
2nd June 2015, 19:40
Thanks Gavino,

I have tried the yuv [16,235] <-> rgb [0,255] formulas, copied on Avisynth web page, but i did not know that 255 is not 255.0, like this short script show it. Thus i have not took this formula the last time.

ScriptClip( """

Kr = 0.299
Kg = 0.587
Kb = 0.114

y = AverageLuma()
u = AverageChromaU()
v = AverageChromaV()

r_255 = (255/219)*y + (255/112)*v*(1-Kr) - (255*16/219 + 255*128/112*(1-Kr))
g_255 = (255/219)*y - (255/112)*u*(1-Kb)*Kb/Kg - (255/112)*v*(1-Kr)*Kr/Kg - (255*16/219 - 255/112*128*(1-Kb)*Kb/Kg - 255/112*128*(1-Kr)*Kr/Kg)
b_255 = (255/219)*y + (255/112)*u*(1-Kb) - (255*16/219 + 255*128/112*(1-Kb))

r_255_0 = (255.0/219)*y + (255.0/112)*v*(1-Kr) - (255.0*16/219 + 255.0*128/112*(1-Kr))
g_255_0 = (255.0/219)*y - (255.0/112)*u*(1-Kb)*Kb/Kg - (255.0/112)*v*(1-Kr)*Kr/Kg - (255.0*16/219 - 255.0/112*128*(1-Kb)*Kb/Kg - 255.0/112*128*(1-Kr)*Kr/Kg)
b_255_0 = (255.0/219)*y + (255.0/112)*u*(1-Kb) - (255.0*16/219 + 255.0*128/112*(1-Kb))

Subtitle( "Red value 255 : "+String(r_255) + " Red value 255.0 : "+String(r_255_0) +\
"\nGreen value 255 : "+String(g_255) + " Green value 255.0 : "+String(g_255_0) +\
"\nBlue value 255 : "+String(b_255) + " Blue value 255.0 : "+String(b_255_0) \
,y=40,lsp=20) """)

Now i understand, why StainlessS has added missing Float() in my script.

StainlessS
2nd June 2015, 23:42
Now i understand, why StainlessS has added missing Float() in my script.

That was from Gavino too, I just copy him :)

Bernardd
11th June 2015, 19:02
Hello,

I have written this script to show my problem. I do not understand why RGBAdjust (working only with bias args) give a picture with look of coloryuv white balance,
but whith differents luma an chroma values. I need advice.

Thanks


ScriptClip( """

#------------ Color matrix input

Kr = 0.299
Kg = 0.587
Kb = 0.114

#------------ YUV values extraction

y = AverageLuma()
u = AverageChromaU()
v = AverageChromaV()

#------------ RGB values calculation

r = (y-16)*255.0/219 + 2*(v-128)*255.0/224*(1-Kr)
g = (y-16)*255.0/219 - 2*(u-128)*255.0/224*(1-Kb)*Kb/Kg - 2*(v-128)*255.0/224*(1-Kr)*Kr/Kg
b = (y-16)*255.0/219 + 2*(u-128)*255.0/224*(1-Kb)

#----------- AWB corrections calcul

du = 128-u # in YUV range, correction is 128 subtract YUV channel value
dv = 128-v

#--------- Chroma values after automatic white balance

u_awb = u + du
v_awb = v + dv

#-------- RGB values for AWB chroma values

r_awb = (y-16)*255.0/219 + 2*(v_awb-128)*255.0/224*(1-Kr)
g_awb = (y-16)*255.0/219 - 2*(u_awb-128)*255.0/224*(1-Kb)*Kb/Kg - 2*(v_awb-128)*255.0/224*(1-Kr)*Kr/Kg
b_awb = (y-16)*255.0/219 + 2*(u_awb-128)*255.0/224*(1-Kb)

#------- For display target AWB Chroma values

y_awb = (Kr*219/255.0)*r_awb + (Kg*219/255.0)*g_awb + (Kb*219/255.0)*b_awb + 16
v_awb = 112.0/255.0*r_awb - Kg*112.0/255.0*g_awb/(1-Kr) - Kb*112.0/255.0*b_awb/(1-Kr) + 128.0
u_awb = - Kr*112.0/255.0*r_awb/(1-Kb) - Kg*112.0/255.0*g_awb/(1-Kb) + 112.0/255.0*b_awb + 128.0

#------ AWB RGB correction calculation

dr = r_awb - r
dg = g_awb - g
db = b_awb - b

#------ RGBAdjust bias use

ConvertToRGB(matrix = "REC601")

RGBAdjust(rb = dr, gb = dg, bb = db)

ConvertToYV12(last, matrix = "Rec601")

#------- For display output AWB Chroma values

y_out = AverageLuma(last)
u_out = AverageChromaU(last)
v_out = AverageChromaV(last)
Subtitle("target luma awb : " + string(y_awb)+ " target chroma u awb : " + string(u_awb)+ " target chroma v awb : " + string(v_awb)+\
"\nluma-output : " + string(y_out)+ " chroma u output : " + string(u_out)+ " chroma v output : " + string(v_out),lsp=20)
return last
""")

StainlessS
11th June 2015, 21:06
I imagine that it's mainly because of the colorspace conversions (16->235 -> 0->255 -> 16->235), ie
ConvertToRGB(matrix = "REC601") and ConvertToYV12(last, matrix = "Rec601")
EDIT: Precision loss, pixel values are integer (also, Even though RGBAdjust takes float Bias args, cannot adjust pixels by fractional amount).

I've added a line and commented out a couple (and changed order a little bit)


ScriptClip( """

#------------ Color matrix input

Kr = 0.299
Kg = 0.587
Kb = 0.114

#------------ YUV values extraction

y = AverageLuma()
u = AverageChromaU()
v = AverageChromaV()

#----------- AWB corrections calcul

du = 128-u # in YUV range, correction is 128 subtract YUV channel value
dv = 128-v

#--------- Chroma values after automatic white balance

y_awb = y # ssS, Same as original
u_awb = u + du
v_awb = v + dv

#-------- RGB values for AWB chroma values

r_awb = (y-16)*255.0/219 + 2*(v_awb-128)*255.0/224*(1-Kr)
g_awb = (y-16)*255.0/219 - 2*(u_awb-128)*255.0/224*(1-Kb)*Kb/Kg - 2*(v_awb-128)*255.0/224*(1-Kr)*Kr/Kg
b_awb = (y-16)*255.0/219 + 2*(u_awb-128)*255.0/224*(1-Kb)

#------- For display target AWB Chroma values

# ssS, unnecessary colorspace conversion back to what it was before (above awb->rgb->awb)
#y_awb = (Kr*219/255.0)*r_awb + (Kg*219/255.0)*g_awb + (Kb*219/255.0)*b_awb + 16
#v_awb = 112.0/255.0*r_awb - Kg*112.0/255.0*g_awb/(1-Kr) - Kb*112.0/255.0*b_awb/(1-Kr) + 128.0
#u_awb = - Kr*112.0/255.0*r_awb/(1-Kb) - Kg*112.0/255.0*g_awb/(1-Kb) + 112.0/255.0*b_awb + 128.0

#------------ RGB values calculation

r = (y-16)*255.0/219 + 2*(v-128)*255.0/224*(1-Kr)
g = (y-16)*255.0/219 - 2*(u-128)*255.0/224*(1-Kb)*Kb/Kg - 2*(v-128)*255.0/224*(1-Kr)*Kr/Kg
b = (y-16)*255.0/219 + 2*(u-128)*255.0/224*(1-Kb)


#------ AWB RGB correction calculation

dr = r_awb - r
dg = g_awb - g
db = b_awb - b

#------ RGBAdjust bias use

ConvertToRGB(matrix = "REC601")

RGBAdjust(rb = dr, gb = dg, bb = db)

ConvertToYV12(last, matrix = "Rec601")

#------- For display output AWB Chroma values

y_out = AverageLuma(last)
u_out = AverageChromaU(last)
v_out = AverageChromaV(last)
Subtitle("target luma awb : " + string(y_awb)+ " target chroma u awb : " + string(u_awb)+ " target chroma v awb : " + string(v_awb)+\
"\nluma-output : " + string(y_out)+ " chroma u output : " + string(u_out)+ " chroma v output : " + string(v_out),lsp=20)
return last
""")

return last


EDIT: Also, there are some legal range YUV TV Levels (eg $10F0F0 fully chroma saturated BLACK) that cannot be converted into RGB,
and of course out of range YUV TV levels colors too, eg $000000.

EDIT: Two page thread that is quite interesting: http://forum.doom9.org/showthread.php?t=92944

Bernardd
12th June 2015, 18:24
Hi StainlessS,

Color space conversion can not explain the whole problem. I have modified my script to display output RGB channel values without ConvertToYV12.
RGBAdjust use a channel standard deviation and thus apply a bias is not a simple value copy. RGB color space action is not easy. But RGBADjust and RGBAdapt work well.


ScriptClip( """

#------------ Color matrix input

Kr = 0.299
Kg = 0.587
Kb = 0.114

#------------ YUV values extraction

y = AverageLuma()
u = AverageChromaU()
v = AverageChromaV()

#----------- AWB corrections calcul

du = 128-u # in YUV range, correction is 128 subtract YUV channel value
dv = 128-v

#--------- Chroma values after automatic white balance

y_awb = y # ssS, Same as original
u_awb = u + du
v_awb = v + dv

#-------- RGB values for AWB chroma values

r_awb = (y-16)*255.0/219 + 2*(v_awb-128)*255.0/224*(1-Kr)
g_awb = (y-16)*255.0/219 - 2*(u_awb-128)*255.0/224*(1-Kb)*Kb/Kg - 2*(v_awb-128)*255.0/224*(1-Kr)*Kr/Kg
b_awb = (y-16)*255.0/219 + 2*(u_awb-128)*255.0/224*(1-Kb)

#------- For display target AWB Chroma values

# ssS, unnecessary colorspace conversion back to what it was before (above awb->rgb->awb)
#y_awb = (Kr*219/255.0)*r_awb + (Kg*219/255.0)*g_awb + (Kb*219/255.0)*b_awb + 16
#v_awb = 112.0/255.0*r_awb - Kg*112.0/255.0*g_awb/(1-Kr) - Kb*112.0/255.0*b_awb/(1-Kr) + 128.0
#u_awb = - Kr*112.0/255.0*r_awb/(1-Kb) - Kg*112.0/255.0*g_awb/(1-Kb) + 112.0/255.0*b_awb + 128.0

#------------ RGB values calculation

r = (y-16)*255.0/219 + 2*(v-128)*255.0/224*(1-Kr)
g = (y-16)*255.0/219 - 2*(u-128)*255.0/224*(1-Kb)*Kb/Kg - 2*(v-128)*255.0/224*(1-Kr)*Kr/Kg
b = (y-16)*255.0/219 + 2*(u-128)*255.0/224*(1-Kb)


#------ AWB RGB correction calculation

dr = r_awb - r
dg = g_awb - g
db = b_awb - b

#------ RGBAdjust bias use

ConvertToRGB(matrix = "REC601")

RGBAdjust(rb = dr, gb = dg, bb = db, analyze = false)

output_video = last

#------ For display AWB RGB correction after RGBAdjust

black = BlankClip(output_video, pixel_type="RGB32", color=$000000)
red = ShowRed(output_video,pixel_type="RGB32")
green = ShowGreen(output_video,pixel_type="RGB32")
blue = ShowBlue(output_video,pixel_type="RGB32")
red_out = RGBDifference(red, black)
green_out = RGBDifference(green, black)
blue_out = RGBDifference(blue, black)
dr_out = red_out - r
dg_out = green_out - g
db_out = blue_out - b

ConvertToYV12(last, matrix = "Rec601")

#------- For display output AWB Chroma values

y_out = AverageLuma(last)
u_out = AverageChromaU(last)
v_out = AverageChromaV(last)
Subtitle("Input Red awb value : "+String(r)+" Input Green awb value : "+String(g)+" Input Blue awb value : "+String(b)+\
"\nTarget Red awb value : "+String(r_awb)+" Target Green awb value : "+String(g_awb)+" Target Blue awb value : "+String(b_awb)+\
"\nOutput Red awb value : "+String(red_out)+" Output Green awb value : "+String(green_out)+" Output Blue awb value : "+String(blue_out)\
,lsp=20)
return last
""")

StainlessS
13th June 2015, 06:42
Each pixel could be up to 0.5 in error for both of the colorspace conversions and also up to 0.5 in error for the RgbAdjust step.
What is the biggest discrepancy you are seeing ?

I'm currently knocking up an RgbAdapt graffer thing, will post when done.

EDIT: For RgbAdjust step, each and every pixel will suffer the same error (Bias float rounded to int before addition, for the each channel).

RGBAdjust use a channel standard deviation and thus apply a bias is not a simple value copy.

Is a simple addition

New_R = Min(Max(Old_R + Round(Bias_R),0),255)

Bernardd
13th June 2015, 09:23
Hi StainlesS,

I have seen some differences for bias application, that i cannot explain with round error.
I believe find the reason : channel standard deviation. But your answer i understand it is a mistake.
I have written this short script to illustrate what i have seen.
With a BlanckClip as video, channel standard deviation = 0, 100% of bias is in output.
With any of my life videos, channel standard deviation > 0, only X % of bias is in input.
I have only seen that with big bias. Thus in this example a bias value is 100.

I do not know the rule, but it is good. With AWB bias computed in YUV color space and converted in RGB color space
the RGB output picture look is very near the UV output picture look.


BlankClip( pixel_type="RGB32", color=$808080)
# AViSource("C:\your video.avi")
# ConvertToRGB(matrix="Rec601", interlaced=false) #If neccesary
a = RGBAdjust(analyze=true)
b = RGBAdjust(rb=100, analyze=false)
StackHorizontal(a,b.RGBAdjust( analyze=true))

StainlessS
13th June 2015, 21:56
@Bernardd

Can I clarify earlier post, When setting Bias only and other args at default, then be equivalent to

New_R = Min(Max(Old_R + Round(Bias_R),0),255)


Here is the Lut creator (for RgbAdapt_Graffer) in VB6

Private Sub Make_Lut(Lutix As Long)
' Lutix, 0 = Blue, 1 = Green, 2 = Red
Dim x As Long, i As Long, Bias As Double, Gain As Double, Cont As Double, RPow As Double, Spow As Double, v As Double, Lin As Long
Dim rGam As Double, sGam As Double, SPMid As Double
Dim pord As Boolean, Val As Long
Bias = Lut_Bias(Lutix)
Gain = Lut_Gain(Lutix)
Cont = Lut_Cont(Lutix)
RPow = Lut_RPow(Lutix)
Spow = Lut_SPow(Lutix)
pord = Lut_Pord(Lutix)
SPMid = Lut_SPMid(Lutix)
If RPow < 0.1 Then RPow = 0.1
rGam = 1# / RPow
If rGam < 0.004 Then rGam = 0.004

sGam = 1# / Spow

Bias = Bias / 256#
For i = 0 To 255
v = i / 255#
v = (v * Gain) + ((v - 0.5) * Cont + 0.5) - v + Bias
If (rGam <> 1# Or sGam <> 1#) Then
If (pord = False) Then
If (rGam <> 1#) Then ' Here, rpow 1st
If (v > 0#) Then ' avoid error
v = v ^ rGam
End If
End If
If (sGam <> 1#) Then
v = v - SPMid
If (v < 0#) Then ' bottom half
v = -v ' abs(), spin right way up
v = v / SPMid ' Make in range 0 -> 1.0
v = v ^ sGam ' spow
v = v * SPMid ' Back to original range
v = -v ' spin upside down again
Else
v = v / (1# - SPMid) ' Make in range 0 -> 1.0
v = v ^ sGam ' spow
v = v * (1# - SPMid) ' Back to range 0 -> 0.5
End If
v = v + SPMid
End If
Else
If (sGam <> 1#) Then ' Here Spow 1st
v = v - SPMid
If (v < 0#) Then ' bottom half
v = -v ' abs(), spin right way up
v = v / SPMid ' Make in range 0 -> 1.0
v = v ^ sGam ' spow
v = v * SPMid ' Back to range 0 -> 0.5
v = -v ' spin upside down again
Else
v = v / (1# - SPMid) ' Make in range 0 -> 1.0
v = v ^ sGam ' spow
v = v * (1# - SPMid) ' Back to range 0 -> 0.5
End If
v = v + SPMid
End If
If (rGam <> 1#) Then
If (v > 0#) Then ' avoid error
v = v ^ rGam ' rpow
End If
End If
End If
' Avoid possible overflow due to multiple powers
If (v > 1#) Then
v = 1#
ElseIf v < 0# Then
v = 0#
End If
End If
v = (v * 255#) + 0.5
Val = Int(v) ' Round towards -ve infinity
If (Val > 255) Then
Val = 255
ElseIf Val < 0 Then
Val = 0
End If
Lut(Lutix, i) = Val
Next i
End Sub


And here for RgbAdjust Graffer in VB 6 (direct conversion from the dll CPP EDIT: Avisynth source not dll).
Where 'off' is equivalent to Bias.

Private Sub Make_Lut(Lutix As Long)
Dim i As Long
Dim off As Double, gain As Double, gamma As Double
Dim v As Double
off = Lut_off(Lutix)
gain = Lut_gain(Lutix)
gamma = 1# / Lut_gamma(Lutix)
If gamma < 0.004 Then gamma = 0.004
For i = 0 To 255
v = (off + i * gain) / 255#
v = IIf(v < 0#, 0#, IIf(v > 1#, 1#, v))
Lut(Lutix, i) = Int((v ^ gamma) * 255# + 0.5)
Next i
End Sub


@All

RgbAdapt() zip updated 13 june 2015, Added RgbAdapt_Graffer executable to demo plugin.
Dll not updated from v0.1. See 1st post.

Fish:
https://s20.postimg.org/owf34mw71/Fish_zpstbhjpckn.jpg (https://postimg.org/image/fbvghr6ux/)

Frog: Showing Line=2, ie bubbles rather than straight line graph [EDIT: Shows big jump for both red and green in LUT].
https://s20.postimg.org/owf34mw71/Fish_zpstbhjpckn.jpg (https://postimg.org/image/fbvghr6ux/)

EDIT: I should have moused over the graphic for both jpg's to show Before and After RGB colors under the mouse.
Zip includes Graffer source in VB6.

Fish2b showing Full Grid and Before & After Colors.
https://s20.postimg.org/3pbcgmjjx/Fish2b_zpszyoh8qz6.jpg (https://postimg.org/image/d9uz3i8vt/)

EDIT: The 'Copy To Clipboard' button copies the RgbAdapt() function call together with arguments.
The Left half of frame is corrected (After and Right Half Before).
You can see my Windows 95 RedTile's, :eek:

EDIT: And with full frame modified [Half Screen unticked]:
https://s20.postimg.org/l3vkowgot/Fish_Full_Frame_zpslkwfahkm.jpg (https://postimg.org/image/r4t9lz3ax/)

Bernardd
15th June 2015, 21:44
Hi StainlessS

I have read RGBAdapt source in the past, but it is difficult for me to understand formulas in vb6. Thus now with "lut" i can not say if it is a variable or a instruction. If you have internet page to learn,thank you.

Your graffer is a nice tool. Perhaps, it will be a few better with display of RGB values before and after. But I have used it to analyse my manual process. I make iteration.

Thus i propose this new version, which add linear correction to gamma correction. Linear correction is based on the output of gamma correction.


function RGBAdapt_auto_awb_process(clip clip, bool "show_info", bool "matrix", float "linear_gamma_mix", float "spmid", bool "pord", float "gamma")
{

#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #

#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #

standard = (matrix == false) ? "Rec601" : "Rec709"

show_info = Default(show_info, false) # show info or not, default false
matrix = Default(matrix, false) # Color standard, false = Rec 601, true = Rec 709

linear_gamma_mix = Default(linear_gamma_mix, 0.5) # linear curve use strength, between 0.0 and 1.0, default 0.5
Assert(linear_gamma_mix>=0.0 && linear_gamma_mix <= 1.0,"RGBAdapt_auto_awb: linear_gamma_mix 0.0 -> 1.0")
spmid = Default(spmid, 0.5) # it is original RGBADapt Channel_spmid args, range 0.1 to 0.99 center 0.5
Assert(spmid>=0.01 && spmid <= 0.99,"RGBAdapt_auto_awb: spmid 0.01 -> 0.99")
pord = Default(pord, false) # it is original RGBADapt Channel_pord args

gamma = Default(gamma, 2.2) # gamma value defintion for calcul between 1.0 and 15.0, default 2.2, neutral value 1.0
Assert(gamma>=0.1 && gamma <= 15.0,"RGBAdapt_auto_awb: gamma 1.0 -> 15.0")

ScriptClip(clip, """

clip = last

#------------ Color matrix input

standard = (!matrix) ? "REC601" : "REC709"
Kr = (matrix == false) ? 0.299 : 0.2126
Kg = (matrix == false) ? 0.587 : 0.7152
Kb = (matrix == false) ? 0.114 : 0.0722

#------------ YUV values extraction

(!isYV12(clip)) ? ConvertToYV12(clip, matrix=standard) : clip

y = AverageLuma()
u = AverageChromaU()
v = AverageChromaV()

#---------- Automatic white balance corrections calcul

du = 128-u # in YUV range, correction is 128 subtract YUV channel value
dv = 128-v

u_awb = u + du
v_awb = v + dv

#------------ YUV values to RGB values

#-------- original values
r = (y-16)*255.0/219 + 2*(v-128)*255.0/224*(1-Kr)
g = (y-16)*255.0/219 - 2*(u-128)*255.0/224*(1-Kb)*Kb/Kg - 2*(v-128)*255.0/224*(1-Kr)*Kr/Kg
b = (y-16)*255.0/219 + 2*(u-128)*255.0/224*(1-Kb)

#-------- AWB target RGB values

r_awb = (y-16)*255.0/219 + 2*(v_awb-128)*255.0/224*(1-Kr)
g_awb = (y-16)*255.0/219 - 2*(u_awb-128)*255.0/224*(1-Kb)*Kb/Kg - 2*(v_awb-128)*255.0/224*(1-Kr)*Kr/Kg
b_awb = (y-16)*255.0/219 + 2*(u_awb-128)*255.0/224*(1-Kb)

#----------- RGB corrections calcul

dr = r_awb - r
dg = g_awb - g
db = b_awb - b

#----------- Linear curve correction range (Bias)

dr_linear = dr * linear_gamma_mix
dg_linear = dg * linear_gamma_mix
db_linear = db * linear_gamma_mix

#---------- Remaining RGB correction after classic linear curve process

dr_gamma = dr - dr_linear
dg_gamma = dg - dg_linear
db_gamma = db - db_linear

#----------- RGB correction with Rpow curve calcul

yr = pow(gamma,dr_gamma/128)
yr = Min (4.0, Max (yr, 0.1))
yg = pow(gamma,dg_gamma/128)
yg = Min (4.0, Max (yg, 0.1))
yb = pow(gamma,db_gamma/128)
yb = Min (4.0, Max (yb, 0.1))

#----------- RGB correction with Spow curve calcul

sr = pow(gamma,dr_gamma/128)
sr = Min (4.0, Max (sr, 0.1))
sg = pow(gamma,dg_gamma/128)
sg = Min (4.0, Max (sg, 0.1))
sb = pow(gamma,db_gamma/128)
sb = Min (4.0, Max (sb, 0.1))

#---------- RGBAdapt use

(!isRGB(clip)) ? ConvertToRGB24(last, matrix=standard) : clip

#---------- first pass : process only with gamma curves

output_video = RGBAdapt( \
R_Bias = 0, R_Gain = 1.0, R_Cont = 1.0, R_RPow = yr, R_Spow = sr, R_SPMid = spmid, R_Pord = pord,\
G_Bias = 0, G_Gain = 1.0, G_Cont = 1.0, G_RPow = yg, G_Spow = sg, G_SPMid = spmid, G_Pord = pord,\
B_Bias = 0, B_Gain = 1.0, B_Cont = 1.0, B_RPow = yb, B_Spow = sb, B_SPMid = spmid, B_Pord = pord)

#--------- first pass output RGB values extraction

black = BlankClip(output_video, pixel_type="RGB32", color=$000000)
red = ShowRed(output_video,pixel_type="RGB32")
green = ShowGreen(output_video,pixel_type="RGB32")
blue = ShowBlue(output_video,pixel_type="RGB32")
red_out = RGBDifference(red, black)
green_out = RGBDifference(green, black)
blue_out = RGBDifference(blue, black)

#------- Difference between AWB target RGB values and first pass output RGB values

dr_out = (r_awb - red_out)*(1-kr) # experiment say necessary to insert luma channel factors
dg_out = (g_awb - green_out)*(1-kg)
db_out = (b_awb - blue_out)*(1-kb)

output_video = RGBAdapt( \
R_Bias = dr_linear + dr_out*(1 -linear_gamma_mix), R_Gain = 1.0, R_Cont = 1.0, R_RPow = yr, R_Spow = sr, R_SPMid = spmid, R_Pord = pord,\
G_Bias = dg_linear + dg_out*(1 -linear_gamma_mix), G_Gain = 1.0, G_Cont = 1.0, G_RPow = yg, G_Spow = sg, G_SPMid = spmid, G_Pord = pord,\
B_Bias = db_linear + db_out*(1 -linear_gamma_mix), B_Gain = 1.0, B_Cont = 1.0, B_RPow = yb, B_Spow = sb, B_SPMid = spmid, B_Pord = pord)

output_video = RGBAdjust(output_video,analyze=false)
output_video = (!isRGB(clip)) ? ConvertToYV12(output_video, matrix=standard) : output_video

#-------- displayed info or no

(!show_info)? output_video : output_video.Subtitle("Red value : "+String(r)+" Target Red awb value : "+String(r_awb)+\
"\nRed Values Diff : "+String(dr)+\
"\nClassic AWB linear correction : "+String(dr_linear)+\
"\nGamma curves correction base : "+String(dr_gamma)+\
"\nRpow : "+String(yr)+" Spow : "+String(sr)+" last linear adjust : "+String(dr_out)+\
"\nOutput Red value : "+String(red_out),y=40,lsp=20)\
.Subtitle("Green value : "+String(g)+" Target Green awb value : "+String(g_awb)+\
"\nGreen Values Diff : "+String(dg)+\
"\nClassic AWB linear correction : "+String(dg_linear)+\
"\nGamma curves correction base : "+String(dg_gamma)+\
"\nRpow : "+String(yg)+" Spow : "+String(sg)+" last linear adjust : "+String(dg_out)+\
"\nOutput Green value : "+String(green_out),y=190,lsp=20)\
.Subtitle("Blue value : "+String(b)+" Target Blue awb value : "+String(b_awb)+\
"\nBlue Values Diff : "+String(db)+\
"\nClassic AWB linear correction : "+String(db_linear)+\
"\nGamma curves correction base : "+String(db_gamma)+\
"\nRpow : "+String(yb)+" Spow : "+String(sb)+" last linear adjust : "+String(db_out)+\
"\nOutput Blue value : "+String(blue_out), y=340,lsp=20)\
.Subtitle("Luma value "+String(y)+" Gamma : "+String(gamma), y=500)
""", args = "show_info, matrix,linear_gamma_mix, spmid, pord, gamma, standard")

}

StainlessS
16th June 2015, 11:15
A LUT (Look Up Table) is just an array that is pre-prepared, where you LATER get the modified color using the
original channel value as an index into the table. EDIT: Lutix is just the RGB channel number, 0=B, 1=G, R=2.
It is quicker to set up a 3*256 pre-calculated array than to do the calculations on each and every pixel for each
channel.

I screwed up the display of 'Before' and 'After' colors, I forgot that RGB is upside down when I added that.
Added two little boxes show the actual color as well as Hex values.
Have added 4 more arguments for each channel, IMin, OMin, IMax, and OMax (all 0->255, IMin <= IMax).
Any INPUT value less than IMin will be mapped to OMin, and values greater than IMax will be mapped to
OMax. Only input values that do not comply with above are processed as usual.
This allows for weird shaped LUT to eg create masks.
Made a few more changes to the Graffer, will update a bit later today (I think)
EDIT: Both Graffer and dll pending update.


EDIT:
Previously posted RgbAdjust Graffer in VB 6 converted from Avisynth CPP source, with comments
Where 'off' is equivalent to Bias (in RgbAdapt). [EDIT: Actually its called eg rb rather than off or R_Bias in RgbAdjust,
Off is just what I called it in the RgbAdjust graffer code].

Private Sub Make_Lut(Lutix As Long)
Dim i As Long
Dim off As Double, gain As Double, gamma As Double
Dim v As Double
off = Lut_off(Lutix) # Below just getting Off(bias) Gain and Gamma args
gain = Lut_gain(Lutix)
gamma = 1# / Lut_gamma(Lutix)
If gamma < 0.004 Then gamma = 0.004
For i = 0 To 255 # Process 0 to 255 in the LUT array
v = (off + i * gain) / 255# # apply Gain and Bias and range 0.0 -> 1.0
v = IIf(v < 0#, 0#, IIf(v > 1#, 1#, v)) # This is just a Min(Max()) 0.0 -> 1.0 operation, 1# just means a Double Float ie same as 1.0
Lut(Lutix, i) = Int((v ^ gamma) * 255# + 0.5) # Apply Gamma, range 0 -> 255, store in LUT array for Lutix chan(2 dim array, 3x256)
Next i
End Sub


Later will use something like

NEW_R = RED_LUT(OLD_R) # where OLD_R is original Red channel value


Where Gamma and Gain at default 1.0 (ie no effect), same result as

New_R = Min(Max(Round(Old_R + Bias_R),0),255)


And because OLD_R is an integer, so is same as

New_R = Min(Max(Old_R + Round(Bias_R),0),255)